s3: libsmb: In cli_qpathinfo_send() (SMBtrans2:TRANSACT2_QPATHINFO) check for DFS...
[Samba.git] / source3 / locking / share_mode_lock.c
blob75912ec5dc86127580810ad945f9a561508385b5
1 /*
2 Unix SMB/CIFS implementation.
3 Locking functions
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Jeremy Allison 1992-2006
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 Revision History:
23 12 aug 96: Erik.Devriendt@te6.siemens.be
24 added support for shared memory implementation of share mode locking
26 May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 locking to deal with multiple share modes per open file.
29 September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 support.
32 rewritten completely to use new tdb code. Tridge, Dec '99
34 Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35 Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
38 #include "includes.h"
39 #include "system/filesys.h"
40 #include "lib/util/server_id.h"
41 #include "share_mode_lock.h"
42 #include "share_mode_lock_private.h"
43 #include "locking/proto.h"
44 #include "smbd/globals.h"
45 #include "dbwrap/dbwrap.h"
46 #include "dbwrap/dbwrap_open.h"
47 #include "dbwrap/dbwrap_private.h"
48 #include "../libcli/security/security.h"
49 #include "serverid.h"
50 #include "messages.h"
51 #include "util_tdb.h"
52 #include "../librpc/gen_ndr/ndr_open_files.h"
53 #include "source3/lib/dbwrap/dbwrap_watch.h"
54 #include "locking/leases_db.h"
55 #include "../lib/util/memcache.h"
56 #include "lib/util/tevent_ntstatus.h"
57 #include "g_lock.h"
58 #include "smbd/fd_handle.h"
59 #include "lib/global_contexts.h"
61 #undef DBGC_CLASS
62 #define DBGC_CLASS DBGC_LOCKING
64 #define NO_LOCKING_COUNT (-1)
66 /* the locking database handle */
67 static struct g_lock_ctx *lock_ctx;
69 static bool locking_init_internal(bool read_only)
71 struct db_context *backend;
72 char *db_path;
74 brl_init(read_only);
76 if (lock_ctx != NULL) {
77 return True;
80 db_path = lock_path(talloc_tos(), "locking.tdb");
81 if (db_path == NULL) {
82 return false;
85 backend = db_open(NULL, db_path,
86 SMB_OPEN_DATABASE_TDB_HASH_SIZE,
87 TDB_DEFAULT|
88 TDB_VOLATILE|
89 TDB_CLEAR_IF_FIRST|
90 TDB_INCOMPATIBLE_HASH|
91 TDB_SEQNUM,
92 read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
93 DBWRAP_LOCK_ORDER_NONE,
94 DBWRAP_FLAG_NONE);
95 TALLOC_FREE(db_path);
96 if (!backend) {
97 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
98 return False;
101 lock_ctx = g_lock_ctx_init_backend(
102 NULL, global_messaging_context(), &backend);
103 if (lock_ctx == NULL) {
104 TALLOC_FREE(backend);
105 return false;
107 g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1);
109 if (!posix_locking_init(read_only)) {
110 TALLOC_FREE(lock_ctx);
111 return False;
114 return True;
117 bool locking_init(void)
119 return locking_init_internal(false);
122 bool locking_init_readonly(void)
124 return locking_init_internal(true);
127 /*******************************************************************
128 Deinitialize the share_mode management.
129 ******************************************************************/
131 bool locking_end(void)
133 brl_shutdown();
134 TALLOC_FREE(lock_ctx);
135 return true;
138 /*******************************************************************
139 Form a static locking key for a dev/inode pair.
140 ******************************************************************/
142 static TDB_DATA locking_key(const struct file_id *id)
144 return make_tdb_data((const uint8_t *)id, sizeof(*id));
147 /*******************************************************************
148 Share mode cache utility functions that store/delete/retrieve
149 entries from memcache.
151 For now share the statcache (global cache) memory space. If
152 a lock record gets orphaned (which shouldn't happen as we're
153 using the same locking_key data as lookup) it will eventually
154 fall out of the cache via the normal LRU trim mechanism. If
155 necessary we can always make this a separate (smaller) cache.
156 ******************************************************************/
158 static DATA_BLOB memcache_key(const struct file_id *id)
160 return data_blob_const((const void *)id, sizeof(*id));
163 static void share_mode_memcache_store(struct share_mode_data *d)
165 const DATA_BLOB key = memcache_key(&d->id);
166 struct file_id_buf idbuf;
168 DBG_DEBUG("stored entry for file %s epoch %"PRIx64" key %s\n",
169 d->base_name,
170 d->unique_content_epoch,
171 file_id_str_buf(d->id, &idbuf));
173 /* Ensure everything stored in the cache is pristine. */
174 d->modified = false;
175 d->fresh = false;
178 * Ensure the memory going into the cache
179 * doesn't have a destructor so it can be
180 * cleanly evicted by the memcache LRU
181 * mechanism.
183 talloc_set_destructor(d, NULL);
185 /* Cache will own d after this call. */
186 memcache_add_talloc(NULL,
187 SHARE_MODE_LOCK_CACHE,
188 key,
189 &d);
193 * NB. We use ndr_pull_hyper on a stack-created
194 * struct ndr_pull with no talloc allowed, as we
195 * need this to be really fast as an ndr-peek into
196 * the first 10 bytes of the blob.
199 static enum ndr_err_code get_share_mode_blob_header(
200 const uint8_t *buf, size_t buflen, uint64_t *pepoch, uint16_t *pflags)
202 struct ndr_pull ndr = {
203 .data = discard_const_p(uint8_t, buf),
204 .data_size = buflen,
206 NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pepoch));
207 NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
208 return NDR_ERR_SUCCESS;
211 struct fsp_update_share_mode_flags_state {
212 enum ndr_err_code ndr_err;
213 uint16_t share_mode_flags;
216 static void fsp_update_share_mode_flags_fn(
217 const uint8_t *buf,
218 size_t buflen,
219 bool *modified_dependent,
220 void *private_data)
222 struct fsp_update_share_mode_flags_state *state = private_data;
223 uint64_t seq;
225 state->ndr_err = get_share_mode_blob_header(
226 buf, buflen, &seq, &state->share_mode_flags);
229 static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
231 struct fsp_update_share_mode_flags_state state = {0};
232 int seqnum = g_lock_seqnum(lock_ctx);
233 NTSTATUS status;
235 if (seqnum == fsp->share_mode_flags_seqnum) {
236 return NT_STATUS_OK;
239 status = share_mode_do_locked(
240 fsp->file_id, fsp_update_share_mode_flags_fn, &state);
241 if (!NT_STATUS_IS_OK(status)) {
242 DBG_DEBUG("share_mode_do_locked returned %s\n",
243 nt_errstr(status));
244 return status;
247 if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
248 DBG_DEBUG("get_share_mode_blob_header returned %s\n",
249 ndr_errstr(state.ndr_err));
250 return ndr_map_error2ntstatus(state.ndr_err);
253 fsp->share_mode_flags_seqnum = seqnum;
254 fsp->share_mode_flags = state.share_mode_flags;
256 return NT_STATUS_OK;
259 bool file_has_read_lease(struct files_struct *fsp)
261 NTSTATUS status;
263 status = fsp_update_share_mode_flags(fsp);
264 if (!NT_STATUS_IS_OK(status)) {
265 /* Safe default for leases */
266 return true;
269 return (fsp->share_mode_flags & SHARE_MODE_LEASE_READ) != 0;
272 static int share_mode_data_nofree_destructor(struct share_mode_data *d)
274 return -1;
277 static struct share_mode_data *share_mode_memcache_fetch(
278 TALLOC_CTX *mem_ctx,
279 struct file_id id,
280 const uint8_t *buf,
281 size_t buflen)
283 const DATA_BLOB key = memcache_key(&id);
284 enum ndr_err_code ndr_err;
285 struct share_mode_data *d;
286 uint64_t unique_content_epoch;
287 uint16_t flags;
288 void *ptr;
289 struct file_id_buf idbuf;
291 ptr = memcache_lookup_talloc(NULL,
292 SHARE_MODE_LOCK_CACHE,
293 key);
294 if (ptr == NULL) {
295 DBG_DEBUG("failed to find entry for key %s\n",
296 file_id_str_buf(id, &idbuf));
297 return NULL;
299 /* sequence number key is at start of blob. */
300 ndr_err = get_share_mode_blob_header(
301 buf, buflen, &unique_content_epoch, &flags);
302 if (ndr_err != NDR_ERR_SUCCESS) {
303 /* Bad blob. Remove entry. */
304 DBG_DEBUG("bad blob %u key %s\n",
305 (unsigned int)ndr_err,
306 file_id_str_buf(id, &idbuf));
307 memcache_delete(NULL,
308 SHARE_MODE_LOCK_CACHE,
309 key);
310 return NULL;
313 d = (struct share_mode_data *)ptr;
314 if (d->unique_content_epoch != unique_content_epoch) {
315 DBG_DEBUG("epoch changed (cached %"PRIx64") (new %"PRIx64") "
316 "for key %s\n",
317 d->unique_content_epoch,
318 unique_content_epoch,
319 file_id_str_buf(id, &idbuf));
320 /* Cache out of date. Remove entry. */
321 memcache_delete(NULL,
322 SHARE_MODE_LOCK_CACHE,
323 key);
324 return NULL;
327 /* Move onto mem_ctx. */
328 d = talloc_move(mem_ctx, &ptr);
331 * Now we own d, prevent the cache from freeing it
332 * when we delete the entry.
334 talloc_set_destructor(d, share_mode_data_nofree_destructor);
336 /* Remove from the cache. We own it now. */
337 memcache_delete(NULL,
338 SHARE_MODE_LOCK_CACHE,
339 key);
341 /* And reset the destructor to none. */
342 talloc_set_destructor(d, NULL);
344 DBG_DEBUG("fetched entry for file %s epoch %"PRIx64" key %s\n",
345 d->base_name,
346 d->unique_content_epoch,
347 file_id_str_buf(id, &idbuf));
349 return d;
353 * 132 is the sizeof an ndr-encoded struct share_mode_entry_buf.
354 * Reading/writing entries will immediately error out if this
355 * size differs (push/pull is done without allocs).
358 struct share_mode_entry_buf {
359 uint8_t buf[132];
361 #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))
363 static bool share_mode_entry_put(
364 const struct share_mode_entry *e,
365 struct share_mode_entry_buf *dst)
367 DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
368 enum ndr_err_code ndr_err;
370 if (DEBUGLEVEL>=10) {
371 DBG_DEBUG("share_mode_entry:\n");
372 NDR_PRINT_DEBUG(share_mode_entry, discard_const_p(void, e));
375 ndr_err = ndr_push_struct_into_fixed_blob(
376 &blob,
378 (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
379 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
380 DBG_WARNING("ndr_push_share_mode_entry failed: %s\n",
381 ndr_errstr(ndr_err));
382 return false;
385 return true;
388 static bool share_mode_entry_get(
389 const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
391 enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
392 DATA_BLOB blob = {
393 .data = discard_const_p(uint8_t, ptr),
394 .length = SHARE_MODE_ENTRY_SIZE,
397 ndr_err = ndr_pull_struct_blob_all_noalloc(
398 &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
399 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
400 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
401 return false;
403 return true;
407 * locking.tdb records consist of
409 * uint32_t share_mode_data_len
410 * uint8_t [share_mode_data] This is struct share_mode_data in NDR
412 * 0 [SHARE_MODE_ENTRY_SIZE] Sorted array of share modes,
413 * 1 [SHARE_MODE_ENTRY_SIZE] filling up the rest of the data in the
414 * 2 [SHARE_MODE_ENTRY_SIZE] g_lock.c maintained record in locking.tdb
417 struct locking_tdb_data {
418 const uint8_t *share_mode_data_buf;
419 size_t share_mode_data_len;
420 const uint8_t *share_entries;
421 size_t num_share_entries;
424 static bool locking_tdb_data_get(
425 struct locking_tdb_data *data, const uint8_t *buf, size_t buflen)
427 uint32_t share_mode_data_len, share_entries_len;
429 if (buflen == 0) {
430 *data = (struct locking_tdb_data) { 0 };
431 return true;
433 if (buflen < sizeof(uint32_t)) {
434 return false;
437 share_mode_data_len = PULL_LE_U32(buf, 0);
439 buf += sizeof(uint32_t);
440 buflen -= sizeof(uint32_t);
442 if (buflen < share_mode_data_len) {
443 return false;
446 share_entries_len = buflen - share_mode_data_len;
448 if ((share_entries_len % SHARE_MODE_ENTRY_SIZE) != 0) {
449 return false;
452 *data = (struct locking_tdb_data) {
453 .share_mode_data_buf = buf,
454 .share_mode_data_len = share_mode_data_len,
455 .share_entries = buf + share_mode_data_len,
456 .num_share_entries = share_entries_len / SHARE_MODE_ENTRY_SIZE,
459 return true;
462 struct locking_tdb_data_fetch_state {
463 TALLOC_CTX *mem_ctx;
464 uint8_t *data;
465 size_t datalen;
468 static void locking_tdb_data_fetch_fn(
469 struct server_id exclusive,
470 size_t num_shared,
471 const struct server_id *shared,
472 const uint8_t *data,
473 size_t datalen,
474 void *private_data)
476 struct locking_tdb_data_fetch_state *state = private_data;
477 state->datalen = datalen;
478 state->data = talloc_memdup(state->mem_ctx, data, datalen);
481 static NTSTATUS locking_tdb_data_fetch(
482 TDB_DATA key, TALLOC_CTX *mem_ctx, struct locking_tdb_data **ltdb)
484 struct locking_tdb_data_fetch_state state = { 0 };
485 struct locking_tdb_data *result = NULL;
486 NTSTATUS status;
487 bool ok;
489 result = talloc_zero(mem_ctx, struct locking_tdb_data);
490 if (result == NULL) {
491 return NT_STATUS_NO_MEMORY;
493 state.mem_ctx = result;
495 status = g_lock_dump(lock_ctx, key, locking_tdb_data_fetch_fn, &state);
497 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
499 * Just return an empty record
501 goto done;
503 if (!NT_STATUS_IS_OK(status)) {
504 DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
505 return status;
507 if (state.datalen == 0) {
508 goto done;
511 ok = locking_tdb_data_get(result, state.data, state.datalen);
512 if (!ok) {
513 DBG_DEBUG("locking_tdb_data_get failed for %zu bytes\n",
514 state.datalen);
515 TALLOC_FREE(result);
516 return NT_STATUS_INTERNAL_DB_CORRUPTION;
519 done:
520 *ltdb = result;
521 return NT_STATUS_OK;
524 static NTSTATUS locking_tdb_data_store(
525 TDB_DATA key,
526 const struct locking_tdb_data *ltdb,
527 const TDB_DATA *share_mode_dbufs,
528 size_t num_share_mode_dbufs)
530 uint8_t share_mode_data_len_buf[4];
531 TDB_DATA dbufs[num_share_mode_dbufs+3];
532 NTSTATUS status;
534 if ((ltdb->share_mode_data_len == 0) &&
535 (ltdb->num_share_entries == 0) &&
536 (num_share_mode_dbufs == 0)) {
538 * Nothing to write
540 status = g_lock_write_data(lock_ctx, key, NULL, 0);
541 if (!NT_STATUS_IS_OK(status)) {
542 DBG_DEBUG("g_lock_writev_data() failed: %s\n",
543 nt_errstr(status));
545 return status;
548 PUSH_LE_U32(share_mode_data_len_buf, 0, ltdb->share_mode_data_len);
550 dbufs[0] = (TDB_DATA) {
551 .dptr = share_mode_data_len_buf,
552 .dsize = sizeof(share_mode_data_len_buf),
554 dbufs[1] = (TDB_DATA) {
555 .dptr = discard_const_p(uint8_t, ltdb->share_mode_data_buf),
556 .dsize = ltdb->share_mode_data_len,
559 if (ltdb->num_share_entries > SIZE_MAX/SHARE_MODE_ENTRY_SIZE) {
560 /* overflow */
561 return NT_STATUS_BUFFER_OVERFLOW;
563 dbufs[2] = (TDB_DATA) {
564 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
565 .dsize = ltdb->num_share_entries * SHARE_MODE_ENTRY_SIZE,
568 if (num_share_mode_dbufs != 0) {
569 memcpy(&dbufs[3],
570 share_mode_dbufs,
571 num_share_mode_dbufs * sizeof(TDB_DATA));
574 status = g_lock_writev_data(lock_ctx, key, dbufs, ARRAY_SIZE(dbufs));
575 if (!NT_STATUS_IS_OK(status)) {
576 DBG_DEBUG("g_lock_writev_data() failed: %s\n",
577 nt_errstr(status));
579 return status;
582 /*******************************************************************
583 Get all share mode entries for a dev/inode pair.
584 ********************************************************************/
586 static struct share_mode_data *parse_share_modes(
587 TALLOC_CTX *mem_ctx,
588 struct file_id id,
589 const uint8_t *buf,
590 size_t buflen)
592 struct share_mode_data *d;
593 enum ndr_err_code ndr_err;
594 DATA_BLOB blob;
596 /* See if we already have a cached copy of this key. */
597 d = share_mode_memcache_fetch(mem_ctx, id, buf, buflen);
598 if (d != NULL) {
599 return d;
602 d = talloc(mem_ctx, struct share_mode_data);
603 if (d == NULL) {
604 DEBUG(0, ("talloc failed\n"));
605 goto fail;
608 blob = (DATA_BLOB) {
609 .data = discard_const_p(uint8_t, buf),
610 .length = buflen,
612 ndr_err = ndr_pull_struct_blob_all(
613 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
614 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
615 DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
616 ndr_errstr(ndr_err));
617 goto fail;
620 if (DEBUGLEVEL >= 10) {
621 DEBUG(10, ("parse_share_modes:\n"));
622 NDR_PRINT_DEBUG(share_mode_data, d);
625 return d;
626 fail:
627 TALLOC_FREE(d);
628 return NULL;
631 /*******************************************************************
632 If modified, store the share_mode_data back into the database.
633 ********************************************************************/
635 static NTSTATUS share_mode_data_store(
636 struct share_mode_data *d, bool *have_share_entries)
638 TDB_DATA key = locking_key(&d->id);
639 struct locking_tdb_data *ltdb = NULL;
640 DATA_BLOB blob = { 0 };
641 NTSTATUS status;
643 if (!d->modified) {
644 DBG_DEBUG("not modified\n");
645 return NT_STATUS_OK;
648 if (DEBUGLEVEL >= 10) {
649 DBG_DEBUG("\n");
650 NDR_PRINT_DEBUG(share_mode_data, d);
653 d->unique_content_epoch = generate_unique_u64(d->unique_content_epoch);
655 status = locking_tdb_data_fetch(key, d, &ltdb);
656 if (!NT_STATUS_IS_OK(status)) {
657 return status;
660 if (ltdb->num_share_entries != 0) {
661 enum ndr_err_code ndr_err;
663 ndr_err = ndr_push_struct_blob(
664 &blob,
665 ltdb,
667 (ndr_push_flags_fn_t)ndr_push_share_mode_data);
668 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
669 DBG_DEBUG("ndr_push_share_mode_data failed: %s\n",
670 ndr_errstr(ndr_err));
671 TALLOC_FREE(ltdb);
672 return ndr_map_error2ntstatus(ndr_err);
675 *have_share_entries = true;
678 ltdb->share_mode_data_buf = blob.data;
679 ltdb->share_mode_data_len = blob.length;
681 status = locking_tdb_data_store(key, ltdb, NULL, 0);
682 TALLOC_FREE(ltdb);
683 return status;
686 /*******************************************************************
687 Allocate a new share_mode_data struct, mark it unmodified.
688 fresh is set to note that currently there is no database entry.
689 ********************************************************************/
691 static struct share_mode_data *fresh_share_mode_lock(
692 TALLOC_CTX *mem_ctx, const char *servicepath,
693 const struct smb_filename *smb_fname,
694 const struct timespec *old_write_time)
696 struct share_mode_data *d;
698 if ((servicepath == NULL) || (smb_fname == NULL) ||
699 (old_write_time == NULL)) {
700 return NULL;
703 d = talloc_zero(mem_ctx, struct share_mode_data);
704 if (d == NULL) {
705 goto fail;
707 d->unique_content_epoch = generate_unique_u64(0);
709 d->base_name = talloc_strdup(d, smb_fname->base_name);
710 if (d->base_name == NULL) {
711 goto fail;
713 if (smb_fname->stream_name != NULL) {
714 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
715 if (d->stream_name == NULL) {
716 goto fail;
719 d->servicepath = talloc_strdup(d, servicepath);
720 if (d->servicepath == NULL) {
721 goto fail;
723 d->old_write_time = full_timespec_to_nt_time(old_write_time);
724 d->flags = SHARE_MODE_SHARE_DELETE |
725 SHARE_MODE_SHARE_WRITE |
726 SHARE_MODE_SHARE_READ;
727 d->modified = false;
728 d->fresh = true;
729 return d;
730 fail:
731 DEBUG(0, ("talloc failed\n"));
732 TALLOC_FREE(d);
733 return NULL;
737 * Key that's locked with g_lock
739 static uint8_t share_mode_lock_key_data[sizeof(struct file_id)];
740 static TDB_DATA share_mode_lock_key = {
741 .dptr = share_mode_lock_key_data,
742 .dsize = sizeof(share_mode_lock_key_data),
744 static size_t share_mode_lock_key_refcount = 0;
747 * We can only ever have one share mode locked. Use a static
748 * share_mode_data pointer that is shared by multiple nested
749 * share_mode_lock structures, explicitly refcounted.
751 static struct share_mode_data *static_share_mode_data = NULL;
752 static size_t static_share_mode_data_refcount = 0;
754 /*******************************************************************
755 Either fetch a share mode from the database, or allocate a fresh
756 one if the record doesn't exist.
757 ********************************************************************/
759 struct get_static_share_mode_data_state {
760 TALLOC_CTX *mem_ctx;
761 struct file_id id;
762 const char *servicepath;
763 const struct smb_filename *smb_fname;
764 const struct timespec *old_write_time;
765 NTSTATUS status;
768 static void get_static_share_mode_data_fn(
769 struct server_id exclusive,
770 size_t num_shared,
771 const struct server_id *shared,
772 const uint8_t *data,
773 size_t datalen,
774 void *private_data)
776 struct get_static_share_mode_data_state *state = private_data;
777 struct share_mode_data *d = NULL;
778 struct locking_tdb_data ltdb = { 0 };
780 if (datalen != 0) {
781 bool ok;
783 ok = locking_tdb_data_get(&ltdb, data, datalen);
784 if (!ok) {
785 DBG_DEBUG("locking_tdb_data_get failed\n");
786 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
787 return;
791 if (ltdb.share_mode_data_len == 0) {
792 if (state->smb_fname == NULL) {
793 state->status = NT_STATUS_NOT_FOUND;
794 return;
796 d = fresh_share_mode_lock(
797 state->mem_ctx,
798 state->servicepath,
799 state->smb_fname,
800 state->old_write_time);
801 if (d == NULL) {
802 state->status = NT_STATUS_NO_MEMORY;
803 return;
805 } else {
806 d = parse_share_modes(
807 lock_ctx,
808 state->id,
809 ltdb.share_mode_data_buf,
810 ltdb.share_mode_data_len);
811 if (d == NULL) {
812 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
813 return;
817 d->id = state->id;
818 static_share_mode_data = d;
821 static NTSTATUS get_static_share_mode_data(
822 struct file_id id,
823 const char *servicepath,
824 const struct smb_filename *smb_fname,
825 const struct timespec *old_write_time)
827 struct get_static_share_mode_data_state state = {
828 .mem_ctx = lock_ctx,
829 .id = id,
830 .servicepath = servicepath,
831 .smb_fname = smb_fname,
832 .old_write_time = old_write_time,
834 NTSTATUS status;
836 SMB_ASSERT(static_share_mode_data == NULL);
838 status = g_lock_dump(
839 lock_ctx,
840 share_mode_lock_key,
841 get_static_share_mode_data_fn,
842 &state);
843 if (!NT_STATUS_IS_OK(status)) {
844 DBG_DEBUG("g_lock_dump failed: %s\n",
845 nt_errstr(status));
846 return status;
848 if (!NT_STATUS_IS_OK(state.status)) {
849 DBG_DEBUG("get_static_share_mode_data_fn failed: %s\n",
850 nt_errstr(state.status));
851 return state.status;
854 return NT_STATUS_OK;
857 /*******************************************************************
858 Get a share_mode_lock, Reference counted to allow nested calls.
859 ********************************************************************/
861 static int share_mode_lock_destructor(struct share_mode_lock *lck);
863 struct share_mode_lock *get_share_mode_lock(
864 TALLOC_CTX *mem_ctx,
865 struct file_id id,
866 const char *servicepath,
867 const struct smb_filename *smb_fname,
868 const struct timespec *old_write_time)
870 TDB_DATA key = locking_key(&id);
871 struct share_mode_lock *lck = NULL;
872 NTSTATUS status;
873 int cmp;
875 lck = talloc(mem_ctx, struct share_mode_lock);
876 if (lck == NULL) {
877 DEBUG(1, ("talloc failed\n"));
878 return NULL;
881 if (static_share_mode_data != NULL) {
882 if (!file_id_equal(&static_share_mode_data->id, &id)) {
883 struct file_id_buf existing;
884 struct file_id_buf requested;
886 DBG_ERR("Can not lock two share modes "
887 "simultaneously: existing %s requested %s\n",
888 file_id_str_buf(static_share_mode_data->id, &existing),
889 file_id_str_buf(id, &requested));
891 smb_panic(__location__);
892 goto fail;
894 goto done;
897 if (share_mode_lock_key_refcount == 0) {
898 status = g_lock_lock(
899 lock_ctx,
900 key,
901 G_LOCK_WRITE,
902 (struct timeval) { .tv_sec = 3600 });
903 if (!NT_STATUS_IS_OK(status)) {
904 DBG_DEBUG("g_lock_lock failed: %s\n",
905 nt_errstr(status));
906 goto fail;
908 memcpy(share_mode_lock_key_data, key.dptr, key.dsize);
911 cmp = tdb_data_cmp(share_mode_lock_key, key);
912 if (cmp != 0) {
913 DBG_WARNING("Can not lock two share modes simultaneously\n");
914 smb_panic(__location__);
915 goto fail;
918 SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
919 share_mode_lock_key_refcount += 1;
921 SMB_ASSERT(static_share_mode_data_refcount == 0);
923 status = get_static_share_mode_data(
925 servicepath,
926 smb_fname,
927 old_write_time);
928 if (!NT_STATUS_IS_OK(status)) {
929 DBG_DEBUG("get_static_share_mode_data failed: %s\n",
930 nt_errstr(status));
931 share_mode_lock_key_refcount -= 1;
932 goto fail;
934 done:
935 static_share_mode_data_refcount += 1;
936 lck->data = static_share_mode_data;
938 talloc_set_destructor(lck, share_mode_lock_destructor);
940 if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
941 struct file_id_buf returned;
943 DBG_DEBUG("Returning %s (data_refcount=%zu key_refcount=%zu)\n",
944 file_id_str_buf(id, &returned),
945 static_share_mode_data_refcount,
946 share_mode_lock_key_refcount);
949 return lck;
950 fail:
951 TALLOC_FREE(lck);
952 if (share_mode_lock_key_refcount == 0) {
953 status = g_lock_unlock(lock_ctx, share_mode_lock_key);
954 if (!NT_STATUS_IS_OK(status)) {
955 DBG_ERR("g_lock_unlock failed: %s\n",
956 nt_errstr(status));
959 return NULL;
962 static int share_mode_lock_destructor(struct share_mode_lock *lck)
964 bool have_share_entries = false;
965 NTSTATUS status;
967 SMB_ASSERT(static_share_mode_data_refcount > 0);
968 static_share_mode_data_refcount -= 1;
970 if (static_share_mode_data_refcount > 0) {
971 return 0;
974 status = share_mode_data_store(
975 static_share_mode_data, &have_share_entries);
976 if (!NT_STATUS_IS_OK(status)) {
977 DBG_ERR("share_mode_data_store failed: %s\n",
978 nt_errstr(status));
979 smb_panic("Could not store share mode data\n");
982 SMB_ASSERT(share_mode_lock_key_refcount > 0);
983 share_mode_lock_key_refcount -= 1;
985 if (share_mode_lock_key_refcount == 0) {
986 status = g_lock_unlock(lock_ctx, share_mode_lock_key);
987 if (!NT_STATUS_IS_OK(status)) {
988 DBG_ERR("g_lock_unlock failed: %s\n",
989 nt_errstr(status));
990 smb_panic("Could not unlock share mode\n");
994 if (have_share_entries) {
996 * This is worth keeping. Without share modes,
997 * share_mode_data_store above has left nothing in the
998 * database.
1000 share_mode_memcache_store(static_share_mode_data);
1001 static_share_mode_data = NULL;
1004 TALLOC_FREE(static_share_mode_data);
1005 return 0;
1008 /*******************************************************************
1009 Fetch a share mode where we know one MUST exist. This call reference
1010 counts it internally to allow for nested lock fetches.
1011 ********************************************************************/
1013 struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
1014 const struct file_id id)
1016 return get_share_mode_lock(mem_ctx, id, NULL, NULL, NULL);
1019 struct share_mode_do_locked_state {
1020 TDB_DATA key;
1021 void (*fn)(const uint8_t *buf,
1022 size_t buflen,
1023 bool *modified_dependent,
1024 void *private_data);
1025 void *private_data;
1028 static void share_mode_do_locked_fn(
1029 struct server_id exclusive,
1030 size_t num_shared,
1031 const struct server_id *shared,
1032 const uint8_t *data,
1033 size_t datalen,
1034 void *private_data)
1036 struct share_mode_do_locked_state *state = private_data;
1037 bool modified_dependent = false;
1038 struct locking_tdb_data ltdb = { 0 };
1039 bool ok;
1041 ok = locking_tdb_data_get(
1042 &ltdb, discard_const_p(uint8_t, data), datalen);
1043 if (!ok) {
1044 DBG_WARNING("locking_tdb_data_get failed\n");
1045 return;
1048 state->fn(ltdb.share_mode_data_buf,
1049 ltdb.share_mode_data_len,
1050 &modified_dependent,
1051 state->private_data);
1053 if (modified_dependent) {
1054 g_lock_wake_watchers(lock_ctx, state->key);
1058 NTSTATUS share_mode_do_locked(
1059 struct file_id id,
1060 void (*fn)(const uint8_t *buf,
1061 size_t buflen,
1062 bool *modified_dependent,
1063 void *private_data),
1064 void *private_data)
1066 TDB_DATA key = locking_key(&id);
1067 size_t data_refcount, key_refcount;
1068 struct share_mode_do_locked_state state = {
1069 .key = key, .fn = fn, .private_data = private_data,
1071 NTSTATUS status;
1073 if (share_mode_lock_key_refcount == 0) {
1074 status = g_lock_lock(
1075 lock_ctx,
1076 key,
1077 G_LOCK_WRITE,
1078 (struct timeval) { .tv_sec = 3600 });
1079 if (!NT_STATUS_IS_OK(status)) {
1080 DBG_DEBUG("g_lock_lock failed: %s\n",
1081 nt_errstr(status));
1082 return status;
1084 memcpy(share_mode_lock_key_data, key.dptr, key.dsize);
1087 SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
1088 share_mode_lock_key_refcount += 1;
1090 key_refcount = share_mode_lock_key_refcount;
1091 data_refcount = static_share_mode_data_refcount;
1093 status = g_lock_dump(
1094 lock_ctx, key, share_mode_do_locked_fn, &state);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 DBG_DEBUG("g_lock_dump failed: %s\n",
1097 nt_errstr(status));
1100 SMB_ASSERT(data_refcount == static_share_mode_data_refcount);
1101 SMB_ASSERT(key_refcount == share_mode_lock_key_refcount);
1102 share_mode_lock_key_refcount -= 1;
1104 if (share_mode_lock_key_refcount == 0) {
1105 status = g_lock_unlock(lock_ctx, key);
1106 if (!NT_STATUS_IS_OK(status)) {
1107 DBG_DEBUG("g_lock_unlock failed: %s\n",
1108 nt_errstr(status));
1112 return status;
1115 static void share_mode_wakeup_waiters_fn(
1116 const uint8_t *buf,
1117 size_t buflen,
1118 bool *modified_dependent,
1119 void *private_data)
1121 *modified_dependent = true;
1124 NTSTATUS share_mode_wakeup_waiters(struct file_id id)
1126 return share_mode_do_locked(id, share_mode_wakeup_waiters_fn, NULL);
1129 NTTIME share_mode_changed_write_time(struct share_mode_lock *lck)
1131 return lck->data->changed_write_time;
1134 const char *share_mode_servicepath(struct share_mode_lock *lck)
1136 return lck->data->servicepath;
1139 char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1141 struct share_mode_data *d = lck->data;
1142 bool has_stream = (d->stream_name != NULL);
1143 char *fname = NULL;
1145 fname = talloc_asprintf(
1146 mem_ctx,
1147 "%s%s%s",
1148 d->base_name,
1149 has_stream ? ":" : "",
1150 has_stream ? d->stream_name : "");
1151 return fname;
1154 char *share_mode_data_dump(
1155 TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1157 struct ndr_print *p = talloc(mem_ctx, struct ndr_print);
1158 char *ret = NULL;
1160 if (p == NULL) {
1161 return NULL;
1164 *p = (struct ndr_print) {
1165 .print = ndr_print_string_helper,
1166 .depth = 1,
1167 .private_data = talloc_strdup(mem_ctx, ""),
1170 if (p->private_data == NULL) {
1171 TALLOC_FREE(p);
1172 return NULL;
1175 ndr_print_share_mode_data(p, "SHARE_MODE_DATA", lck->data);
1177 ret = p->private_data;
1179 TALLOC_FREE(p);
1181 return ret;
1184 void share_mode_flags_get(
1185 struct share_mode_lock *lck,
1186 uint32_t *access_mask,
1187 uint32_t *share_mode,
1188 uint32_t *lease_type)
1190 uint16_t flags = lck->data->flags;
1192 if (access_mask != NULL) {
1193 *access_mask =
1194 ((flags & SHARE_MODE_ACCESS_READ) ?
1195 FILE_READ_DATA : 0) |
1196 ((flags & SHARE_MODE_ACCESS_WRITE) ?
1197 FILE_WRITE_DATA : 0) |
1198 ((flags & SHARE_MODE_ACCESS_DELETE) ?
1199 DELETE_ACCESS : 0);
1201 if (share_mode != NULL) {
1202 *share_mode =
1203 ((flags & SHARE_MODE_SHARE_READ) ?
1204 FILE_SHARE_READ : 0) |
1205 ((flags & SHARE_MODE_SHARE_WRITE) ?
1206 FILE_SHARE_WRITE : 0) |
1207 ((flags & SHARE_MODE_SHARE_DELETE) ?
1208 FILE_SHARE_DELETE : 0);
1210 if (lease_type != NULL) {
1211 *lease_type =
1212 ((flags & SHARE_MODE_LEASE_READ) ?
1213 SMB2_LEASE_READ : 0) |
1214 ((flags & SHARE_MODE_LEASE_WRITE) ?
1215 SMB2_LEASE_WRITE : 0) |
1216 ((flags & SHARE_MODE_LEASE_HANDLE) ?
1217 SMB2_LEASE_HANDLE : 0);
1221 void share_mode_flags_set(
1222 struct share_mode_lock *lck,
1223 uint32_t access_mask,
1224 uint32_t share_mode,
1225 uint32_t lease_type,
1226 bool *modified)
1228 struct share_mode_data *d = lck->data;
1229 uint16_t flags = 0;
1231 flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
1232 SHARE_MODE_ACCESS_READ : 0;
1233 flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
1234 SHARE_MODE_ACCESS_WRITE : 0;
1235 flags |= (access_mask & (DELETE_ACCESS)) ?
1236 SHARE_MODE_ACCESS_DELETE : 0;
1238 flags |= (share_mode & FILE_SHARE_READ) ?
1239 SHARE_MODE_SHARE_READ : 0;
1240 flags |= (share_mode & FILE_SHARE_WRITE) ?
1241 SHARE_MODE_SHARE_WRITE : 0;
1242 flags |= (share_mode & FILE_SHARE_DELETE) ?
1243 SHARE_MODE_SHARE_DELETE : 0;
1245 flags |= (lease_type & SMB2_LEASE_READ) ?
1246 SHARE_MODE_LEASE_READ : 0;
1247 flags |= (lease_type & SMB2_LEASE_WRITE) ?
1248 SHARE_MODE_LEASE_WRITE : 0;
1249 flags |= (lease_type & SMB2_LEASE_HANDLE) ?
1250 SHARE_MODE_LEASE_HANDLE : 0;
1252 if (d->flags == flags) {
1253 return;
1256 if (modified != NULL) {
1257 *modified = true;
1259 d->flags = flags;
1260 d->modified = true;
1263 struct share_mode_watch_state {
1264 bool blockerdead;
1265 struct server_id blocker;
1268 static void share_mode_watch_done(struct tevent_req *subreq);
1270 struct tevent_req *share_mode_watch_send(
1271 TALLOC_CTX *mem_ctx,
1272 struct tevent_context *ev,
1273 struct share_mode_lock *lck,
1274 struct server_id blocker)
1276 TDB_DATA key = locking_key(&lck->data->id);
1277 struct tevent_req *req = NULL, *subreq = NULL;
1278 struct share_mode_watch_state *state = NULL;
1280 req = tevent_req_create(
1281 mem_ctx, &state, struct share_mode_watch_state);
1282 if (req == NULL) {
1283 return NULL;
1286 subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker);
1287 if (tevent_req_nomem(subreq, req)) {
1288 return tevent_req_post(req, ev);
1290 tevent_req_set_callback(subreq, share_mode_watch_done, req);
1291 return req;
1294 static void share_mode_watch_done(struct tevent_req *subreq)
1296 struct tevent_req *req = tevent_req_callback_data(
1297 subreq, struct tevent_req);
1298 struct share_mode_watch_state *state = tevent_req_data(
1299 req, struct share_mode_watch_state);
1300 NTSTATUS status;
1302 status = g_lock_watch_data_recv(
1303 subreq, &state->blockerdead, &state->blocker);
1304 if (tevent_req_nterror(req, status)) {
1305 return;
1307 tevent_req_done(req);
1310 NTSTATUS share_mode_watch_recv(
1311 struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
1313 struct share_mode_watch_state *state = tevent_req_data(
1314 req, struct share_mode_watch_state);
1315 NTSTATUS status;
1317 if (tevent_req_is_nterror(req, &status)) {
1318 return status;
1320 if (blockerdead != NULL) {
1321 *blockerdead = state->blockerdead;
1323 if (blocker != NULL) {
1324 *blocker = state->blocker;
1326 return NT_STATUS_OK;
1329 struct fetch_share_mode_unlocked_state {
1330 TALLOC_CTX *mem_ctx;
1331 struct file_id id;
1332 struct share_mode_lock *lck;
1335 static void fetch_share_mode_unlocked_parser(
1336 struct server_id exclusive,
1337 size_t num_shared,
1338 const struct server_id *shared,
1339 const uint8_t *data,
1340 size_t datalen,
1341 void *private_data)
1343 struct fetch_share_mode_unlocked_state *state = private_data;
1344 struct locking_tdb_data ltdb = { 0 };
1346 if (datalen != 0) {
1347 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1348 if (!ok) {
1349 DBG_DEBUG("locking_tdb_data_get failed\n");
1350 return;
1354 if (ltdb.share_mode_data_len == 0) {
1355 /* Likely a ctdb tombstone record, ignore it */
1356 return;
1359 state->lck = talloc(state->mem_ctx, struct share_mode_lock);
1360 if (state->lck == NULL) {
1361 DEBUG(0, ("talloc failed\n"));
1362 return;
1365 state->lck->data = parse_share_modes(
1366 state->lck,
1367 state->id,
1368 ltdb.share_mode_data_buf,
1369 ltdb.share_mode_data_len);
1370 if (state->lck->data == NULL) {
1371 DBG_DEBUG("parse_share_modes failed\n");
1372 TALLOC_FREE(state->lck);
1376 /*******************************************************************
1377 Get a share_mode_lock without locking the database or reference
1378 counting. Used by smbstatus to display existing share modes.
1379 ********************************************************************/
1381 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
1382 struct file_id id)
1384 struct fetch_share_mode_unlocked_state state = {
1385 .mem_ctx = mem_ctx,
1386 .id = id,
1388 TDB_DATA key = locking_key(&id);
1389 NTSTATUS status;
1391 status = g_lock_dump(
1392 lock_ctx, key, fetch_share_mode_unlocked_parser, &state);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
1395 return NULL;
1397 return state.lck;
1400 struct fetch_share_mode_state {
1401 struct file_id id;
1402 struct share_mode_lock *lck;
1403 NTSTATUS status;
1406 static void fetch_share_mode_fn(
1407 struct server_id exclusive,
1408 size_t num_shared,
1409 const struct server_id *shared,
1410 const uint8_t *data,
1411 size_t datalen,
1412 void *private_data);
1413 static void fetch_share_mode_done(struct tevent_req *subreq);
1416 * @brief Get a share_mode_lock without locking or refcounting
1418 * This can be used in a clustered Samba environment where the async dbwrap
1419 * request is sent over a socket to the local ctdbd. If the send queue is full
1420 * and the caller was issuing multiple async dbwrap requests in a loop, the
1421 * caller knows it's probably time to stop sending requests for now and try
1422 * again later.
1424 * @param[in] mem_ctx The talloc memory context to use.
1426 * @param[in] ev The event context to work on.
1428 * @param[in] id The file id for the locking.tdb key
1430 * @param[out] queued This boolean out parameter tells the caller whether the
1431 * async request is blocked in a full send queue:
1433 * false := request is dispatched
1435 * true := send queue is full, request waiting to be
1436 * dispatched
1438 * @return The new async request, NULL on error.
1440 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
1441 struct tevent_context *ev,
1442 struct file_id id,
1443 bool *queued)
1445 struct tevent_req *req = NULL, *subreq = NULL;
1446 struct fetch_share_mode_state *state = NULL;
1448 *queued = false;
1450 req = tevent_req_create(mem_ctx, &state,
1451 struct fetch_share_mode_state);
1452 if (req == NULL) {
1453 return NULL;
1455 state->id = id;
1457 subreq = g_lock_dump_send(
1458 state,
1460 lock_ctx,
1461 locking_key(&id),
1462 fetch_share_mode_fn,
1463 state);
1464 if (tevent_req_nomem(subreq, req)) {
1465 return tevent_req_post(req, ev);
1467 tevent_req_set_callback(subreq, fetch_share_mode_done, req);
1468 return req;
1471 static void fetch_share_mode_fn(
1472 struct server_id exclusive,
1473 size_t num_shared,
1474 const struct server_id *shared,
1475 const uint8_t *data,
1476 size_t datalen,
1477 void *private_data)
1479 struct fetch_share_mode_state *state = talloc_get_type_abort(
1480 private_data, struct fetch_share_mode_state);
1481 struct locking_tdb_data ltdb = { 0 };
1483 if (datalen != 0) {
1484 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1485 if (!ok) {
1486 DBG_DEBUG("locking_tdb_data_get failed\n");
1487 return;
1491 if (ltdb.share_mode_data_len == 0) {
1492 /* Likely a ctdb tombstone record, ignore it */
1493 return;
1496 state->lck = talloc(state, struct share_mode_lock);
1497 if (state->lck == NULL) {
1498 DBG_WARNING("talloc failed\n");
1499 state->status = NT_STATUS_NO_MEMORY;
1500 return;
1503 state->lck->data = parse_share_modes(
1504 state->lck,
1505 state->id,
1506 ltdb.share_mode_data_buf,
1507 ltdb.share_mode_data_len);
1508 if (state->lck->data == NULL) {
1509 DBG_DEBUG("parse_share_modes failed\n");
1510 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1511 TALLOC_FREE(state->lck);
1512 return;
1516 static void fetch_share_mode_done(struct tevent_req *subreq)
1518 struct tevent_req *req = tevent_req_callback_data(
1519 subreq, struct tevent_req);
1520 struct fetch_share_mode_state *state = tevent_req_data(
1521 req, struct fetch_share_mode_state);
1522 NTSTATUS status;
1524 status = g_lock_dump_recv(subreq);
1525 TALLOC_FREE(subreq);
1526 if (tevent_req_nterror(req, status)) {
1527 return;
1529 if (tevent_req_nterror(req, state->status)) {
1530 return;
1532 tevent_req_done(req);
1535 NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
1536 TALLOC_CTX *mem_ctx,
1537 struct share_mode_lock **_lck)
1539 struct fetch_share_mode_state *state = tevent_req_data(
1540 req, struct fetch_share_mode_state);
1541 struct share_mode_lock *lck = NULL;
1543 NTSTATUS status;
1545 if (tevent_req_is_nterror(req, &status)) {
1546 tevent_req_received(req);
1547 return status;
1550 if (state->lck == NULL) {
1551 tevent_req_received(req);
1552 return NT_STATUS_NOT_FOUND;
1555 lck = talloc_move(mem_ctx, &state->lck);
1557 if (DEBUGLEVEL >= 10) {
1558 DBG_DEBUG("share_mode_data:\n");
1559 NDR_PRINT_DEBUG(share_mode_data, lck->data);
1562 *_lck = lck;
1563 tevent_req_received(req);
1564 return NT_STATUS_OK;
1567 struct share_mode_forall_state {
1568 TDB_DATA key;
1569 int (*fn)(struct file_id fid,
1570 const struct share_mode_data *data,
1571 void *private_data);
1572 void *private_data;
1575 static void share_mode_forall_dump_fn(
1576 struct server_id exclusive,
1577 size_t num_shared,
1578 const struct server_id *shared,
1579 const uint8_t *data,
1580 size_t datalen,
1581 void *private_data)
1583 struct share_mode_forall_state *state = private_data;
1584 struct file_id fid;
1585 struct locking_tdb_data ltdb = { 0 };
1586 bool ok;
1587 struct share_mode_data *d;
1589 if (state->key.dsize != sizeof(fid)) {
1590 DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize);
1591 return;
1593 memcpy(&fid, state->key.dptr, sizeof(fid));
1595 ok = locking_tdb_data_get(&ltdb, data, datalen);
1596 if (!ok) {
1597 DBG_DEBUG("locking_tdb_data_get() failed\n");
1598 return;
1601 d = parse_share_modes(
1602 talloc_tos(),
1603 fid,
1604 ltdb.share_mode_data_buf,
1605 ltdb.share_mode_data_len);
1606 if (d == NULL) {
1607 DBG_DEBUG("parse_share_modes() failed\n");
1608 return;
1611 state->fn(fid, d, state->private_data);
1612 TALLOC_FREE(d);
1615 static int share_mode_forall_fn(TDB_DATA key, void *private_data)
1617 struct share_mode_forall_state *state = private_data;
1618 NTSTATUS status;
1620 state->key = key;
1622 status = g_lock_dump(
1623 lock_ctx, key, share_mode_forall_dump_fn, private_data);
1624 if (!NT_STATUS_IS_OK(status)) {
1625 DBG_DEBUG("g_lock_dump failed: %s\n",
1626 nt_errstr(status));
1628 return 0;
1631 int share_mode_forall(int (*fn)(struct file_id fid,
1632 const struct share_mode_data *data,
1633 void *private_data),
1634 void *private_data)
1636 struct share_mode_forall_state state = {
1637 .fn = fn,
1638 .private_data = private_data
1640 int ret;
1642 if (lock_ctx == NULL) {
1643 return 0;
1646 ret = g_lock_locks(
1647 lock_ctx, share_mode_forall_fn, &state);
1648 if (ret < 0) {
1649 DBG_DEBUG("g_lock_locks failed\n");
1651 return ret;
1654 struct share_entry_forall_state {
1655 struct file_id fid;
1656 const struct share_mode_data *data;
1657 int (*fn)(struct file_id fid,
1658 const struct share_mode_data *data,
1659 const struct share_mode_entry *entry,
1660 void *private_data);
1661 void *private_data;
1662 int ret;
1665 static bool share_entry_traverse_walker(
1666 struct share_mode_entry *e,
1667 bool *modified,
1668 void *private_data)
1670 struct share_entry_forall_state *state = private_data;
1672 state->ret = state->fn(
1673 state->fid, state->data, e, state->private_data);
1674 return (state->ret != 0);
1677 static int share_entry_traverse_fn(struct file_id fid,
1678 const struct share_mode_data *data,
1679 void *private_data)
1681 struct share_entry_forall_state *state = private_data;
1682 struct share_mode_lock lck = {
1683 .data = discard_const_p(struct share_mode_data, data)
1685 bool ok;
1687 state->fid = fid;
1688 state->data = data;
1690 ok = share_mode_forall_entries(
1691 &lck, share_entry_traverse_walker, state);
1692 if (!ok) {
1693 DBG_DEBUG("share_mode_forall_entries failed\n");
1694 return false;
1697 return state->ret;
1700 /*******************************************************************
1701 Call the specified function on each entry under management by the
1702 share mode system.
1703 ********************************************************************/
1705 int share_entry_forall(int (*fn)(struct file_id fid,
1706 const struct share_mode_data *data,
1707 const struct share_mode_entry *entry,
1708 void *private_data),
1709 void *private_data)
1711 struct share_entry_forall_state state = {
1712 .fn = fn, .private_data = private_data };
1714 return share_mode_forall(share_entry_traverse_fn, &state);
1717 static int share_mode_entry_cmp(
1718 struct server_id pid1,
1719 uint64_t share_file_id1,
1720 struct server_id pid2,
1721 uint64_t share_file_id2)
1723 int cmp;
1725 cmp = server_id_cmp(&pid1, &pid2);
1726 if (cmp != 0) {
1727 return cmp;
1729 if (share_file_id1 != share_file_id2) {
1730 return (share_file_id1 < share_file_id2) ? -1 : 1;
1732 return 0;
1735 static size_t share_mode_entry_find(
1736 const uint8_t *data,
1737 size_t num_share_modes,
1738 struct server_id pid,
1739 uint64_t share_file_id,
1740 struct share_mode_entry *e,
1741 bool *match)
1743 ssize_t left, right, middle;
1745 *match = false;
1747 if (num_share_modes == 0) {
1748 return 0;
1751 left = 0;
1752 right = (num_share_modes-1);
1754 while (left <= right) {
1755 const uint8_t *middle_ptr = NULL;
1756 int cmp;
1757 bool ok;
1759 middle = left + ((right - left) / 2);
1760 middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
1762 DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
1763 left,
1764 right,
1765 middle,
1766 middle_ptr);
1768 ok = share_mode_entry_get(middle_ptr, e);
1769 if (!ok) {
1770 DBG_DEBUG("share_mode_entry_get failed\n");
1771 return 0;
1774 cmp = share_mode_entry_cmp(
1775 e->pid, e->share_file_id, pid, share_file_id);
1776 if (cmp == 0) {
1777 *match = true;
1778 return middle;
1781 if (cmp < 0) {
1782 right = middle-1;
1783 } else {
1784 left = middle+1;
1788 return left;
1791 bool set_share_mode(struct share_mode_lock *lck,
1792 struct files_struct *fsp,
1793 uid_t uid,
1794 uint64_t mid,
1795 uint16_t op_type,
1796 const struct smb2_lease_key *lease_key,
1797 uint32_t share_access,
1798 uint32_t access_mask)
1800 struct share_mode_data *d = lck->data;
1801 TDB_DATA key = locking_key(&d->id);
1802 struct server_id my_pid = messaging_server_id(
1803 fsp->conn->sconn->msg_ctx);
1804 struct locking_tdb_data *ltdb = NULL;
1805 size_t idx;
1806 struct share_mode_entry e = { .pid.pid = 0 };
1807 struct share_mode_entry_buf e_buf;
1808 NTSTATUS status;
1809 bool ok, found;
1811 TDB_DATA dbufs[3];
1812 size_t num_dbufs = 0;
1814 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
1817 nt_errstr(status));
1818 return false;
1820 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
1822 idx = share_mode_entry_find(
1823 ltdb->share_entries,
1824 ltdb->num_share_entries,
1825 my_pid,
1826 fh_get_gen_id(fsp->fh),
1828 &found);
1829 if (found) {
1830 DBG_WARNING("Found duplicate share mode\n");
1831 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1832 goto done;
1835 e = (struct share_mode_entry) {
1836 .pid = my_pid,
1837 .share_access = share_access,
1838 .private_options = fh_get_private_options(fsp->fh),
1839 .access_mask = access_mask,
1840 .op_mid = mid,
1841 .op_type = op_type,
1842 .time.tv_sec = fsp->open_time.tv_sec,
1843 .time.tv_usec = fsp->open_time.tv_usec,
1844 .share_file_id = fh_get_gen_id(fsp->fh),
1845 .uid = (uint32_t)uid,
1846 .flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1847 SHARE_MODE_FLAG_POSIX_OPEN : 0,
1848 .name_hash = fsp->name_hash,
1851 if (op_type == LEASE_OPLOCK) {
1852 const struct GUID *client_guid = fsp_client_guid(fsp);
1853 e.client_guid = *client_guid;
1854 e.lease_key = *lease_key;
1857 ok = share_mode_entry_put(&e, &e_buf);
1858 if (!ok) {
1859 DBG_DEBUG("share_mode_entry_put failed\n");
1860 status = NT_STATUS_INTERNAL_ERROR;
1861 goto done;
1864 DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
1866 if (idx > 0) {
1867 dbufs[num_dbufs] = (TDB_DATA) {
1868 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
1869 .dsize = idx * SHARE_MODE_ENTRY_SIZE,
1871 num_dbufs += 1;
1874 dbufs[num_dbufs] = (TDB_DATA) {
1875 .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
1877 num_dbufs += 1;
1879 if (idx < ltdb->num_share_entries) {
1880 size_t num_after_idx = (ltdb->num_share_entries-idx);
1881 dbufs[num_dbufs] = (TDB_DATA) {
1882 .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
1883 idx * SHARE_MODE_ENTRY_SIZE,
1884 .dsize = num_after_idx * SHARE_MODE_ENTRY_SIZE,
1886 num_dbufs += 1;
1890 size_t i;
1891 for (i=0; i<num_dbufs; i++) {
1892 DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
1894 dbufs[i].dptr,
1895 dbufs[i].dsize);
1899 if (num_dbufs == 1) {
1901 * Storing a fresh record with just one share entry
1903 d->modified = true;
1907 * If there was any existing data in
1908 * ltdb->share_entries, it's now been
1909 * moved and we've split it into:
1911 * num_dbufs = 3
1912 * dbufs[0] -> old sorted data less than new_entry
1913 * dbufs[1] -> new_share_mode_entry
1914 * dbufs[2] -> old sorted_data greater than new entry.
1916 * So the old data inside ltdb->share_entries is
1917 * no longer valid.
1919 * If we're storing a brand new entry the
1920 * dbufs look like:
1922 * num_dbufs = 1
1923 * dbufs[0] -> new_share_mode_entry
1925 * Either way we must set ltdb->share_entries = NULL
1926 * and ltdb->num_share_entries = 0 so that
1927 * locking_tdb_data_store() doesn't use it to
1928 * store any data. It's no longer there.
1931 ltdb->share_entries = NULL;
1932 ltdb->num_share_entries = 0;
1934 status = locking_tdb_data_store(key, ltdb, dbufs, num_dbufs);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
1937 nt_errstr(status));
1939 done:
1940 TALLOC_FREE(ltdb);
1941 return NT_STATUS_IS_OK(status);
1944 static bool share_mode_for_one_entry(
1945 bool (*fn)(struct share_mode_entry *e,
1946 bool *modified,
1947 void *private_data),
1948 void *private_data,
1949 size_t *i,
1950 uint8_t *data,
1951 size_t *num_share_modes,
1952 bool *writeback)
1954 DATA_BLOB blob = {
1955 .data = data + (*i) * SHARE_MODE_ENTRY_SIZE,
1956 .length = SHARE_MODE_ENTRY_SIZE,
1958 struct share_mode_entry e = {.pid.pid=0};
1959 enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
1960 bool modified = false;
1961 bool stop = false;
1962 struct server_id e_pid;
1963 uint64_t e_share_file_id;
1965 ndr_err = ndr_pull_struct_blob_all_noalloc(
1966 &blob,
1968 (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
1969 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1970 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
1971 *i += 1;
1972 return false;
1974 if (DEBUGLEVEL >= 10) {
1975 DBG_DEBUG("entry[%zu]:\n", *i);
1976 NDR_PRINT_DEBUG(share_mode_entry, &e);
1979 e_pid = e.pid;
1980 e_share_file_id = e.share_file_id;
1982 stop = fn(&e, &modified, private_data);
1984 DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
1986 (int)modified,
1987 (int)e.stale);
1989 if (e.stale) {
1990 if (DEBUGLEVEL>=10) {
1991 DBG_DEBUG("share_mode_entry:\n");
1992 NDR_PRINT_DEBUG(share_mode_entry, &e);
1995 if (*i < *num_share_modes) {
1996 memmove(blob.data,
1997 blob.data + SHARE_MODE_ENTRY_SIZE,
1998 (*num_share_modes - *i - 1) *
1999 SHARE_MODE_ENTRY_SIZE);
2001 *num_share_modes -= 1;
2002 *writeback = true;
2003 return stop;
2006 if (modified) {
2007 if (DEBUGLEVEL>=10) {
2008 DBG_DEBUG("share_mode_entry:\n");
2009 NDR_PRINT_DEBUG(share_mode_entry, &e);
2013 * Make sure sorting order is kept intact
2015 SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
2016 SMB_ASSERT(e_share_file_id == e.share_file_id);
2018 ndr_err = ndr_push_struct_into_fixed_blob(
2019 &blob,
2021 (ndr_push_flags_fn_t)
2022 ndr_push_share_mode_entry);
2023 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2024 DBG_WARNING("ndr_push_share_mode_entry "
2025 "failed: %s\n",
2026 ndr_errstr(ndr_err));
2028 * Not much we can do, just ignore it
2031 *i += 1;
2032 *writeback = true;
2033 return stop;
2036 if (stop) {
2037 return true;
2040 *i += 1;
2041 return false;
2044 bool share_mode_forall_entries(
2045 struct share_mode_lock *lck,
2046 bool (*fn)(struct share_mode_entry *e,
2047 bool *modified,
2048 void *private_data),
2049 void *private_data)
2051 struct share_mode_data *d = lck->data;
2052 TDB_DATA key = locking_key(&d->id);
2053 struct locking_tdb_data *ltdb = NULL;
2054 uint8_t *share_entries = NULL;
2055 size_t num_share_entries;
2056 bool writeback = false;
2057 NTSTATUS status;
2058 bool stop = false;
2059 size_t i;
2061 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2062 if (!NT_STATUS_IS_OK(status)) {
2063 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2064 nt_errstr(status));
2065 return false;
2067 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2069 num_share_entries = ltdb->num_share_entries;
2070 share_entries = discard_const_p(uint8_t, ltdb->share_entries);
2072 i = 0;
2073 while (i<num_share_entries) {
2074 stop = share_mode_for_one_entry(
2076 private_data,
2078 share_entries,
2079 &num_share_entries,
2080 &writeback);
2081 if (stop) {
2082 break;
2086 DBG_DEBUG("num_share_entries=%zu, writeback=%d\n",
2087 num_share_entries,
2088 (int)writeback);
2090 if (!writeback) {
2091 return true;
2094 if ((ltdb->num_share_entries != 0 ) && (num_share_entries == 0)) {
2096 * This routine wiped all share entries, let
2097 * share_mode_data_store() delete the record
2099 d->modified = true;
2102 ltdb->num_share_entries = num_share_entries;
2103 ltdb->share_entries = share_entries;
2105 status = locking_tdb_data_store(key, ltdb, NULL, 0);
2106 if (!NT_STATUS_IS_OK(status)) {
2107 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2108 nt_errstr(status));
2109 return false;
2112 return true;
2115 struct share_mode_count_entries_state {
2116 size_t num_share_modes;
2117 NTSTATUS status;
2120 static void share_mode_count_entries_fn(
2121 struct server_id exclusive,
2122 size_t num_shared,
2123 const struct server_id *shared,
2124 const uint8_t *data,
2125 size_t datalen,
2126 void *private_data)
2128 struct share_mode_count_entries_state *state = private_data;
2129 struct locking_tdb_data ltdb = { 0 };
2130 bool ok;
2132 ok = locking_tdb_data_get(&ltdb, data, datalen);
2133 if (!ok) {
2134 DBG_WARNING("locking_tdb_data_get failed for %zu\n", datalen);
2135 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2136 return;
2138 state->num_share_modes = ltdb.num_share_entries;
2139 state->status = NT_STATUS_OK;
2142 NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
2144 struct share_mode_count_entries_state state = {
2145 .status = NT_STATUS_NOT_FOUND,
2147 NTSTATUS status;
2149 status = g_lock_dump(
2150 lock_ctx,
2151 locking_key(&fid),
2152 share_mode_count_entries_fn,
2153 &state);
2154 if (!NT_STATUS_IS_OK(status)) {
2155 DBG_DEBUG("g_lock_dump failed: %s\n",
2156 nt_errstr(status));
2157 return status;
2159 if (!NT_STATUS_IS_OK(state.status)) {
2160 DBG_DEBUG("share_mode_count_entries_fn failed: %s\n",
2161 nt_errstr(state.status));
2162 return state.status;
2165 *num_share_modes = state.num_share_modes;
2166 return NT_STATUS_OK;
2169 static bool share_mode_entry_do(
2170 struct share_mode_lock *lck,
2171 struct server_id pid,
2172 uint64_t share_file_id,
2173 void (*fn)(struct share_mode_entry *e,
2174 size_t num_share_modes,
2175 bool *modified,
2176 void *private_data),
2177 void *private_data)
2179 struct share_mode_data *d = lck->data;
2180 TDB_DATA key = locking_key(&d->id);
2181 struct locking_tdb_data *ltdb = NULL;
2182 size_t idx;
2183 bool found = false;
2184 bool modified = false;
2185 struct share_mode_entry e;
2186 uint8_t *e_ptr = NULL;
2187 NTSTATUS status;
2188 bool ret = false;
2190 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2193 nt_errstr(status));
2194 return false;
2196 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2198 idx = share_mode_entry_find(
2199 ltdb->share_entries,
2200 ltdb->num_share_entries,
2201 pid,
2202 share_file_id,
2204 &found);
2205 if (!found) {
2206 DBG_WARNING("Did not find share mode entry for %"PRIu64"\n",
2207 share_file_id);
2208 goto done;
2211 if (DEBUGLEVEL>=10) {
2212 DBG_DEBUG("entry[%zu]:\n", idx);
2213 NDR_PRINT_DEBUG(share_mode_entry, &e);
2216 fn(&e, ltdb->num_share_entries, &modified, private_data);
2218 DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2219 idx,
2220 (int)modified,
2221 (int)e.stale);
2223 if (!e.stale && !modified) {
2224 ret = true;
2225 goto done;
2228 e_ptr = discard_const_p(uint8_t, ltdb->share_entries) +
2229 idx * SHARE_MODE_ENTRY_SIZE;
2231 if (e.stale) {
2233 * Move the rest down one entry
2235 size_t behind = ltdb->num_share_entries - idx - 1;
2236 if (behind != 0) {
2237 memmove(e_ptr,
2238 e_ptr + SHARE_MODE_ENTRY_SIZE,
2239 behind * SHARE_MODE_ENTRY_SIZE);
2241 ltdb->num_share_entries -= 1;
2243 if (ltdb->num_share_entries == 0) {
2245 * Tell share_mode_lock_destructor() to delete
2246 * the whole record
2248 d->modified = true;
2251 if (DEBUGLEVEL>=10) {
2252 DBG_DEBUG("share_mode_entry:\n");
2253 NDR_PRINT_DEBUG(share_mode_entry, &e);
2255 } else {
2256 struct share_mode_entry_buf buf;
2257 bool ok;
2259 if (ltdb->num_share_entries != 1) {
2261 * Make sure the sorting order stays intact
2263 SMB_ASSERT(server_id_equal(&e.pid, &pid));
2264 SMB_ASSERT(e.share_file_id == share_file_id);
2267 ok = share_mode_entry_put(&e, &buf);
2268 if (!ok) {
2269 DBG_DEBUG("share_mode_entry_put failed\n");
2270 goto done;
2272 memcpy(e_ptr, buf.buf, SHARE_MODE_ENTRY_SIZE);
2275 status = locking_tdb_data_store(key, ltdb, NULL, 0);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2278 nt_errstr(status));
2279 goto done;
2282 ret = true;
2283 done:
2284 TALLOC_FREE(ltdb);
2285 return ret;
2288 struct del_share_mode_state {
2289 bool ok;
2292 static void del_share_mode_fn(
2293 struct share_mode_entry *e,
2294 size_t num_share_modes,
2295 bool *modified,
2296 void *private_data)
2298 struct del_share_mode_state *state = private_data;
2299 e->stale = true;
2300 state->ok = true;
2303 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
2305 struct del_share_mode_state state = { .ok = false };
2306 bool ok;
2308 ok = share_mode_entry_do(
2309 lck,
2310 messaging_server_id(fsp->conn->sconn->msg_ctx),
2311 fh_get_gen_id(fsp->fh),
2312 del_share_mode_fn,
2313 &state);
2314 if (!ok) {
2315 DBG_DEBUG("share_mode_entry_do failed\n");
2316 return false;
2318 if (!state.ok) {
2319 DBG_DEBUG("del_share_mode_fn failed\n");
2320 return false;
2322 return true;
2325 struct remove_share_oplock_state {
2326 bool ok;
2329 static void remove_share_oplock_fn(
2330 struct share_mode_entry *e,
2331 size_t num_share_modes,
2332 bool *modified,
2333 void *private_data)
2335 struct remove_share_oplock_state *state = private_data;
2337 e->op_type = NO_OPLOCK;
2338 *modified = true;
2339 state->ok = true;
2342 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2344 struct remove_share_oplock_state state = { .ok = false };
2345 bool ok;
2347 ok = share_mode_entry_do(
2348 lck,
2349 messaging_server_id(fsp->conn->sconn->msg_ctx),
2350 fh_get_gen_id(fsp->fh),
2351 remove_share_oplock_fn,
2352 &state);
2353 if (!ok) {
2354 DBG_DEBUG("share_mode_entry_do failed\n");
2355 return false;
2357 if (!state.ok) {
2358 DBG_DEBUG("remove_share_oplock_fn failed\n");
2359 return false;
2362 if (fsp->oplock_type == LEASE_OPLOCK) {
2363 remove_lease_if_stale(
2364 lck,
2365 fsp_client_guid(fsp),
2366 &fsp->lease->lease.lease_key);
2369 share_mode_wakeup_waiters(fsp->file_id);
2371 return true;
2374 struct downgrade_share_oplock_state {
2375 bool ok;
2378 static void downgrade_share_oplock_fn(
2379 struct share_mode_entry *e,
2380 size_t num_share_modes,
2381 bool *modified,
2382 void *private_data)
2384 struct downgrade_share_oplock_state *state = private_data;
2386 e->op_type = LEVEL_II_OPLOCK;
2387 *modified = true;
2388 state->ok = true;
2391 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2393 struct downgrade_share_oplock_state state = { .ok = false };
2394 bool ok;
2396 ok = share_mode_entry_do(
2397 lck,
2398 messaging_server_id(fsp->conn->sconn->msg_ctx),
2399 fh_get_gen_id(fsp->fh),
2400 downgrade_share_oplock_fn,
2401 &state);
2402 if (!ok) {
2403 DBG_DEBUG("share_mode_entry_do failed\n");
2404 return false;
2406 if (!state.ok) {
2407 DBG_DEBUG("downgrade_share_oplock_fn failed\n");
2408 return false;
2411 lck->data->flags |= SHARE_MODE_LEASE_READ;
2412 lck->data->modified = true;
2414 return true;
2417 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
2418 struct files_struct *fsp)
2420 struct server_id disconnected_pid = { .pid = 0 };
2421 bool ok;
2423 if (fsp->op == NULL) {
2424 return false;
2426 if (!fsp->op->global->durable) {
2427 return false;
2430 server_id_set_disconnected(&disconnected_pid);
2432 ok = reset_share_mode_entry(
2433 lck,
2434 messaging_server_id(fsp->conn->sconn->msg_ctx),
2435 fh_get_gen_id(fsp->fh),
2436 disconnected_pid,
2437 UINT64_MAX,
2438 fsp->op->global->open_persistent_id);
2440 return ok;
2443 bool reset_share_mode_entry(
2444 struct share_mode_lock *lck,
2445 struct server_id old_pid,
2446 uint64_t old_share_file_id,
2447 struct server_id new_pid,
2448 uint64_t new_mid,
2449 uint64_t new_share_file_id)
2451 struct share_mode_data *d = lck->data;
2452 TDB_DATA key = locking_key(&d->id);
2453 struct locking_tdb_data *ltdb = NULL;
2454 struct share_mode_entry e;
2455 struct share_mode_entry_buf e_buf;
2456 NTSTATUS status;
2457 bool ret = false;
2458 bool ok;
2460 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2461 if (!NT_STATUS_IS_OK(status)) {
2462 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2463 nt_errstr(status));
2464 return false;
2467 if (ltdb->num_share_entries != 1) {
2468 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2469 goto done;
2472 ok = share_mode_entry_get(ltdb->share_entries, &e);
2473 if (!ok) {
2474 DBG_WARNING("share_mode_entry_get failed\n");
2475 goto done;
2478 ret = share_mode_entry_cmp(
2479 old_pid, old_share_file_id, e.pid, e.share_file_id);
2480 if (ret != 0) {
2481 struct server_id_buf tmp1, tmp2;
2482 DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
2483 "got pid=%s, file_id=%"PRIu64"\n",
2484 server_id_str_buf(old_pid, &tmp1),
2485 old_share_file_id,
2486 server_id_str_buf(e.pid, &tmp2),
2487 e.share_file_id);
2488 goto done;
2491 e.pid = new_pid;
2492 if (new_mid != UINT64_MAX) {
2493 e.op_mid = new_mid;
2495 e.share_file_id = new_share_file_id;
2497 ok = share_mode_entry_put(&e, &e_buf);
2498 if (!ok) {
2499 DBG_WARNING("share_mode_entry_put failed\n");
2500 goto done;
2503 ltdb->share_entries = e_buf.buf;
2505 status = locking_tdb_data_store(key, ltdb, NULL, 0);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2508 nt_errstr(status));
2509 goto done;
2512 d->modified = true;
2513 ret = true;
2514 done:
2515 TALLOC_FREE(ltdb);
2516 return true;