s3:share_mode_lock: consistently debug share_mode_entry records
[Samba.git] / source3 / locking / share_mode_lock.c
bloba1a7b9793cfa7831f13449004c15bf8bc71b255c
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 "locking/proto.h"
42 #include "smbd/globals.h"
43 #include "dbwrap/dbwrap.h"
44 #include "dbwrap/dbwrap_open.h"
45 #include "dbwrap/dbwrap_private.h"
46 #include "../libcli/security/security.h"
47 #include "serverid.h"
48 #include "messages.h"
49 #include "util_tdb.h"
50 #include "../librpc/gen_ndr/ndr_open_files.h"
51 #include "source3/lib/dbwrap/dbwrap_watch.h"
52 #include "locking/leases_db.h"
53 #include "../lib/util/memcache.h"
54 #include "lib/util/tevent_ntstatus.h"
55 #include "g_lock.h"
57 #undef DBGC_CLASS
58 #define DBGC_CLASS DBGC_LOCKING
60 #define NO_LOCKING_COUNT (-1)
62 /* the locking database handle */
63 static struct g_lock_ctx *lock_ctx;
65 static bool locking_init_internal(bool read_only)
67 struct db_context *backend;
68 char *db_path;
70 brl_init(read_only);
72 if (lock_ctx != NULL) {
73 return True;
76 db_path = lock_path(talloc_tos(), "locking.tdb");
77 if (db_path == NULL) {
78 return false;
81 backend = db_open(NULL, db_path,
82 SMB_OPEN_DATABASE_TDB_HASH_SIZE,
83 TDB_DEFAULT|
84 TDB_VOLATILE|
85 TDB_CLEAR_IF_FIRST|
86 TDB_INCOMPATIBLE_HASH|
87 TDB_SEQNUM,
88 read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
89 DBWRAP_LOCK_ORDER_NONE,
90 DBWRAP_FLAG_NONE);
91 TALLOC_FREE(db_path);
92 if (!backend) {
93 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
94 return False;
97 lock_ctx = g_lock_ctx_init_backend(
98 NULL, global_messaging_context(), &backend);
99 if (lock_ctx == NULL) {
100 TALLOC_FREE(backend);
101 return false;
103 g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1);
105 if (!posix_locking_init(read_only)) {
106 TALLOC_FREE(lock_ctx);
107 return False;
110 return True;
113 bool locking_init(void)
115 return locking_init_internal(false);
118 bool locking_init_readonly(void)
120 return locking_init_internal(true);
123 /*******************************************************************
124 Deinitialize the share_mode management.
125 ******************************************************************/
127 bool locking_end(void)
129 brl_shutdown();
130 TALLOC_FREE(lock_ctx);
131 return true;
134 /*******************************************************************
135 Form a static locking key for a dev/inode pair.
136 ******************************************************************/
138 static TDB_DATA locking_key(const struct file_id *id)
140 return make_tdb_data((const uint8_t *)id, sizeof(*id));
143 /*******************************************************************
144 Share mode cache utility functions that store/delete/retrieve
145 entries from memcache.
147 For now share the statcache (global cache) memory space. If
148 a lock record gets orphaned (which shouldn't happen as we're
149 using the same locking_key data as lookup) it will eventually
150 fall out of the cache via the normal LRU trim mechanism. If
151 necessary we can always make this a separate (smaller) cache.
152 ******************************************************************/
154 static DATA_BLOB memcache_key(const struct file_id *id)
156 return data_blob_const((const void *)id, sizeof(*id));
159 static void share_mode_memcache_store(struct share_mode_data *d)
161 const DATA_BLOB key = memcache_key(&d->id);
162 struct file_id_buf idbuf;
164 DBG_DEBUG("stored entry for file %s epoch %"PRIx64" key %s\n",
165 d->base_name,
166 d->unique_content_epoch,
167 file_id_str_buf(d->id, &idbuf));
169 /* Ensure everything stored in the cache is pristine. */
170 d->modified = false;
171 d->fresh = false;
174 * Ensure the memory going into the cache
175 * doesn't have a destructor so it can be
176 * cleanly evicted by the memcache LRU
177 * mechanism.
179 talloc_set_destructor(d, NULL);
181 /* Cache will own d after this call. */
182 memcache_add_talloc(NULL,
183 SHARE_MODE_LOCK_CACHE,
184 key,
185 &d);
189 * NB. We use ndr_pull_hyper on a stack-created
190 * struct ndr_pull with no talloc allowed, as we
191 * need this to be really fast as an ndr-peek into
192 * the first 10 bytes of the blob.
195 static enum ndr_err_code get_share_mode_blob_header(
196 const uint8_t *buf, size_t buflen, uint64_t *pepoch, uint16_t *pflags)
198 struct ndr_pull ndr = {
199 .data = discard_const_p(uint8_t, buf),
200 .data_size = buflen,
202 NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pepoch));
203 NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
204 return NDR_ERR_SUCCESS;
207 struct fsp_update_share_mode_flags_state {
208 enum ndr_err_code ndr_err;
209 uint16_t share_mode_flags;
212 static void fsp_update_share_mode_flags_fn(
213 const uint8_t *buf,
214 size_t buflen,
215 bool *modified_dependent,
216 void *private_data)
218 struct fsp_update_share_mode_flags_state *state = private_data;
219 uint64_t seq;
221 state->ndr_err = get_share_mode_blob_header(
222 buf, buflen, &seq, &state->share_mode_flags);
225 static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
227 struct fsp_update_share_mode_flags_state state = {0};
228 int seqnum = g_lock_seqnum(lock_ctx);
229 NTSTATUS status;
231 if (seqnum == fsp->share_mode_flags_seqnum) {
232 return NT_STATUS_OK;
235 status = share_mode_do_locked(
236 fsp->file_id, fsp_update_share_mode_flags_fn, &state);
237 if (!NT_STATUS_IS_OK(status)) {
238 DBG_DEBUG("share_mode_do_locked returned %s\n",
239 nt_errstr(status));
240 return status;
243 if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
244 DBG_DEBUG("get_share_mode_blob_header returned %s\n",
245 ndr_errstr(state.ndr_err));
246 return ndr_map_error2ntstatus(state.ndr_err);
249 fsp->share_mode_flags_seqnum = seqnum;
250 fsp->share_mode_flags = state.share_mode_flags;
252 return NT_STATUS_OK;
255 bool file_has_read_lease(struct files_struct *fsp)
257 NTSTATUS status;
259 status = fsp_update_share_mode_flags(fsp);
260 if (!NT_STATUS_IS_OK(status)) {
261 /* Safe default for leases */
262 return true;
265 return (fsp->share_mode_flags & SHARE_MODE_LEASE_READ) != 0;
268 static int share_mode_data_nofree_destructor(struct share_mode_data *d)
270 return -1;
273 static struct share_mode_data *share_mode_memcache_fetch(
274 TALLOC_CTX *mem_ctx,
275 const TDB_DATA id_key,
276 const uint8_t *buf,
277 size_t buflen)
279 enum ndr_err_code ndr_err;
280 struct share_mode_data *d;
281 uint64_t unique_content_epoch;
282 uint16_t flags;
283 void *ptr;
284 struct file_id id;
285 struct file_id_buf idbuf;
286 DATA_BLOB key;
288 /* Ensure this is a locking_key record. */
289 if (id_key.dsize != sizeof(id)) {
290 return NULL;
293 memcpy(&id, id_key.dptr, id_key.dsize);
294 key = memcache_key(&id);
296 ptr = memcache_lookup_talloc(NULL,
297 SHARE_MODE_LOCK_CACHE,
298 key);
299 if (ptr == NULL) {
300 DBG_DEBUG("failed to find entry for key %s\n",
301 file_id_str_buf(id, &idbuf));
302 return NULL;
304 /* sequence number key is at start of blob. */
305 ndr_err = get_share_mode_blob_header(
306 buf, buflen, &unique_content_epoch, &flags);
307 if (ndr_err != NDR_ERR_SUCCESS) {
308 /* Bad blob. Remove entry. */
309 DBG_DEBUG("bad blob %u key %s\n",
310 (unsigned int)ndr_err,
311 file_id_str_buf(id, &idbuf));
312 memcache_delete(NULL,
313 SHARE_MODE_LOCK_CACHE,
314 key);
315 return NULL;
318 d = (struct share_mode_data *)ptr;
319 if (d->unique_content_epoch != unique_content_epoch) {
320 DBG_DEBUG("epoch changed (cached %"PRIx64") (new %"PRIx64") "
321 "for key %s\n",
322 d->unique_content_epoch,
323 unique_content_epoch,
324 file_id_str_buf(id, &idbuf));
325 /* Cache out of date. Remove entry. */
326 memcache_delete(NULL,
327 SHARE_MODE_LOCK_CACHE,
328 key);
329 return NULL;
332 /* Move onto mem_ctx. */
333 d = talloc_move(mem_ctx, &ptr);
336 * Now we own d, prevent the cache from freeing it
337 * when we delete the entry.
339 talloc_set_destructor(d, share_mode_data_nofree_destructor);
341 /* Remove from the cache. We own it now. */
342 memcache_delete(NULL,
343 SHARE_MODE_LOCK_CACHE,
344 key);
346 /* And reset the destructor to none. */
347 talloc_set_destructor(d, NULL);
349 DBG_DEBUG("fetched entry for file %s epoch %"PRIx64" key %s\n",
350 d->base_name,
351 d->unique_content_epoch,
352 file_id_str_buf(id, &idbuf));
354 return d;
358 * 132 is the sizeof an ndr-encoded struct share_mode_entry_buf.
359 * Reading/writing entries will immediately error out if this
360 * size differs (push/pull is done without allocs).
363 struct share_mode_entry_buf {
364 uint8_t buf[132];
366 #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))
368 static bool share_mode_entry_put(
369 const struct share_mode_entry *e,
370 struct share_mode_entry_buf *dst)
372 DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
373 enum ndr_err_code ndr_err;
375 if (DEBUGLEVEL>=10) {
376 DBG_DEBUG("share_mode_entry:\n");
377 NDR_PRINT_DEBUG(share_mode_entry, discard_const_p(void, e));
380 ndr_err = ndr_push_struct_into_fixed_blob(
381 &blob,
383 (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
384 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
385 DBG_WARNING("ndr_push_share_mode_entry failed: %s\n",
386 ndr_errstr(ndr_err));
387 return false;
390 return true;
393 static bool share_mode_entry_get(
394 const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
396 enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
397 DATA_BLOB blob = {
398 .data = discard_const_p(uint8_t, ptr),
399 .length = SHARE_MODE_ENTRY_SIZE,
402 ndr_err = ndr_pull_struct_blob_all_noalloc(
403 &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
404 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
405 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
406 return false;
408 return true;
412 * locking.tdb records consist of
414 * uint32_t share_mode_data_len
415 * uint8_t [share_mode_data] This is struct share_mode_data in NDR
417 * 0 [SHARE_MODE_ENTRY_SIZE] Sorted array of share modes,
418 * 1 [SHARE_MODE_ENTRY_SIZE] filling up the rest of the data in the
419 * 2 [SHARE_MODE_ENTRY_SIZE] g_lock.c maintained record in locking.tdb
422 struct locking_tdb_data {
423 const uint8_t *share_mode_data_buf;
424 size_t share_mode_data_len;
425 const uint8_t *share_entries;
426 size_t num_share_entries;
429 static bool locking_tdb_data_get(
430 struct locking_tdb_data *data, const uint8_t *buf, size_t buflen)
432 uint32_t share_mode_data_len, share_entries_len;
434 if (buflen == 0) {
435 *data = (struct locking_tdb_data) { 0 };
436 return true;
438 if (buflen < sizeof(uint32_t)) {
439 return false;
442 share_mode_data_len = PULL_LE_U32(buf, 0);
444 buf += sizeof(uint32_t);
445 buflen -= sizeof(uint32_t);
447 if (buflen < share_mode_data_len) {
448 return false;
451 share_entries_len = buflen - share_mode_data_len;
453 if ((share_entries_len % SHARE_MODE_ENTRY_SIZE) != 0) {
454 return false;
457 *data = (struct locking_tdb_data) {
458 .share_mode_data_buf = buf,
459 .share_mode_data_len = share_mode_data_len,
460 .share_entries = buf + share_mode_data_len,
461 .num_share_entries = share_entries_len / SHARE_MODE_ENTRY_SIZE,
464 return true;
467 struct locking_tdb_data_fetch_state {
468 TALLOC_CTX *mem_ctx;
469 uint8_t *data;
470 size_t datalen;
473 static void locking_tdb_data_fetch_fn(
474 struct server_id exclusive,
475 size_t num_shared,
476 struct server_id *shared,
477 const uint8_t *data,
478 size_t datalen,
479 void *private_data)
481 struct locking_tdb_data_fetch_state *state = private_data;
482 state->datalen = datalen;
483 state->data = talloc_memdup(state->mem_ctx, data, datalen);
486 static NTSTATUS locking_tdb_data_fetch(
487 TDB_DATA key, TALLOC_CTX *mem_ctx, struct locking_tdb_data **ltdb)
489 struct locking_tdb_data_fetch_state state = { 0 };
490 struct locking_tdb_data *result = NULL;
491 NTSTATUS status;
492 bool ok;
494 result = talloc_zero(mem_ctx, struct locking_tdb_data);
495 if (result == NULL) {
496 return NT_STATUS_NO_MEMORY;
498 state.mem_ctx = result;
500 status = g_lock_dump(lock_ctx, key, locking_tdb_data_fetch_fn, &state);
502 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
504 * Just return an empty record
506 goto done;
508 if (!NT_STATUS_IS_OK(status)) {
509 DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
510 return status;
512 if (state.datalen == 0) {
513 goto done;
516 ok = locking_tdb_data_get(result, state.data, state.datalen);
517 if (!ok) {
518 DBG_DEBUG("locking_tdb_data_get failed for %zu bytes\n",
519 state.datalen);
520 TALLOC_FREE(result);
521 return NT_STATUS_INTERNAL_DB_CORRUPTION;
524 done:
525 *ltdb = result;
526 return NT_STATUS_OK;
529 static NTSTATUS locking_tdb_data_store(
530 TDB_DATA key,
531 const struct locking_tdb_data *ltdb,
532 const TDB_DATA *share_mode_dbufs,
533 size_t num_share_mode_dbufs)
535 uint8_t share_mode_data_len_buf[4];
536 TDB_DATA dbufs[num_share_mode_dbufs+3];
537 NTSTATUS status;
539 if ((ltdb->share_mode_data_len == 0) &&
540 (ltdb->num_share_entries == 0) &&
541 (num_share_mode_dbufs == 0)) {
543 * Nothing to write
545 status = g_lock_write_data(lock_ctx, key, NULL, 0);
546 if (!NT_STATUS_IS_OK(status)) {
547 DBG_DEBUG("g_lock_writev_data() failed: %s\n",
548 nt_errstr(status));
550 return status;
553 PUSH_LE_U32(share_mode_data_len_buf, 0, ltdb->share_mode_data_len);
555 dbufs[0] = (TDB_DATA) {
556 .dptr = share_mode_data_len_buf,
557 .dsize = sizeof(share_mode_data_len_buf),
559 dbufs[1] = (TDB_DATA) {
560 .dptr = discard_const_p(uint8_t, ltdb->share_mode_data_buf),
561 .dsize = ltdb->share_mode_data_len,
564 if (ltdb->num_share_entries > SIZE_MAX/SHARE_MODE_ENTRY_SIZE) {
565 /* overflow */
566 return NT_STATUS_BUFFER_OVERFLOW;
568 dbufs[2] = (TDB_DATA) {
569 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
570 .dsize = ltdb->num_share_entries * SHARE_MODE_ENTRY_SIZE,
573 if (num_share_mode_dbufs != 0) {
574 memcpy(&dbufs[3],
575 share_mode_dbufs,
576 num_share_mode_dbufs * sizeof(TDB_DATA));
579 status = g_lock_writev_data(lock_ctx, key, dbufs, ARRAY_SIZE(dbufs));
580 if (!NT_STATUS_IS_OK(status)) {
581 DBG_DEBUG("g_lock_writev_data() failed: %s\n",
582 nt_errstr(status));
584 return status;
587 /*******************************************************************
588 Get all share mode entries for a dev/inode pair.
589 ********************************************************************/
591 static struct share_mode_data *parse_share_modes(
592 TALLOC_CTX *mem_ctx,
593 const TDB_DATA key,
594 const uint8_t *buf,
595 size_t buflen)
597 struct share_mode_data *d;
598 enum ndr_err_code ndr_err;
599 DATA_BLOB blob;
601 /* See if we already have a cached copy of this key. */
602 d = share_mode_memcache_fetch(mem_ctx, key, buf, buflen);
603 if (d != NULL) {
604 return d;
607 d = talloc(mem_ctx, struct share_mode_data);
608 if (d == NULL) {
609 DEBUG(0, ("talloc failed\n"));
610 goto fail;
613 blob = (DATA_BLOB) {
614 .data = discard_const_p(uint8_t, buf),
615 .length = buflen,
617 ndr_err = ndr_pull_struct_blob_all(
618 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
619 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
620 DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
621 ndr_errstr(ndr_err));
622 goto fail;
625 if (DEBUGLEVEL >= 10) {
626 DEBUG(10, ("parse_share_modes:\n"));
627 NDR_PRINT_DEBUG(share_mode_data, d);
631 * We have a non-zero locking.tdb record that was correctly
632 * parsed. This means a share_entries.tdb entry exists,
633 * otherwise we'd have paniced before in
634 * share_mode_data_store()
636 d->have_share_modes = true;
638 return d;
639 fail:
640 TALLOC_FREE(d);
641 return NULL;
644 /*******************************************************************
645 If modified, store the share_mode_data back into the database.
646 ********************************************************************/
648 static NTSTATUS share_mode_data_store(struct share_mode_data *d)
650 TDB_DATA key = locking_key(&d->id);
651 struct locking_tdb_data *ltdb = NULL;
652 DATA_BLOB blob = { 0 };
653 NTSTATUS status;
655 if (!d->modified) {
656 DBG_DEBUG("not modified\n");
657 return NT_STATUS_OK;
660 if (DEBUGLEVEL >= 10) {
661 DBG_DEBUG("\n");
662 NDR_PRINT_DEBUG(share_mode_data, d);
665 d->unique_content_epoch = generate_unique_u64(d->unique_content_epoch);
667 status = locking_tdb_data_fetch(key, d, &ltdb);
668 if (!NT_STATUS_IS_OK(status)) {
669 return status;
672 if (ltdb->num_share_entries != 0) {
673 enum ndr_err_code ndr_err;
675 ndr_err = ndr_push_struct_blob(
676 &blob,
677 ltdb,
679 (ndr_push_flags_fn_t)ndr_push_share_mode_data);
680 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
681 DBG_DEBUG("ndr_push_share_mode_data failed: %s\n",
682 ndr_errstr(ndr_err));
683 TALLOC_FREE(ltdb);
684 return ndr_map_error2ntstatus(ndr_err);
688 ltdb->share_mode_data_buf = blob.data;
689 ltdb->share_mode_data_len = blob.length;
691 status = locking_tdb_data_store(key, ltdb, NULL, 0);
692 TALLOC_FREE(ltdb);
693 return status;
696 /*******************************************************************
697 Allocate a new share_mode_data struct, mark it unmodified.
698 fresh is set to note that currently there is no database entry.
699 ********************************************************************/
701 static struct share_mode_data *fresh_share_mode_lock(
702 TALLOC_CTX *mem_ctx, const char *servicepath,
703 const struct smb_filename *smb_fname,
704 const struct timespec *old_write_time)
706 struct share_mode_data *d;
708 if ((servicepath == NULL) || (smb_fname == NULL) ||
709 (old_write_time == NULL)) {
710 return NULL;
713 d = talloc_zero(mem_ctx, struct share_mode_data);
714 if (d == NULL) {
715 goto fail;
717 d->unique_content_epoch = generate_unique_u64(0);
719 d->base_name = talloc_strdup(d, smb_fname->base_name);
720 if (d->base_name == NULL) {
721 goto fail;
723 if (smb_fname->stream_name != NULL) {
724 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
725 if (d->stream_name == NULL) {
726 goto fail;
729 d->servicepath = talloc_strdup(d, servicepath);
730 if (d->servicepath == NULL) {
731 goto fail;
733 d->old_write_time = full_timespec_to_nt_time(old_write_time);
734 d->flags = SHARE_MODE_SHARE_DELETE |
735 SHARE_MODE_SHARE_WRITE |
736 SHARE_MODE_SHARE_READ;
737 d->modified = false;
738 d->fresh = true;
739 return d;
740 fail:
741 DEBUG(0, ("talloc failed\n"));
742 TALLOC_FREE(d);
743 return NULL;
747 * Key that's locked with g_lock
749 static uint8_t share_mode_lock_key_data[sizeof(struct file_id)];
750 static TDB_DATA share_mode_lock_key = {
751 .dptr = share_mode_lock_key_data,
752 .dsize = sizeof(share_mode_lock_key_data),
754 static size_t share_mode_lock_key_refcount = 0;
757 * We can only ever have one share mode locked. Use a static
758 * share_mode_data pointer that is shared by multiple nested
759 * share_mode_lock structures, explicitly refcounted.
761 static struct share_mode_data *static_share_mode_data = NULL;
762 static size_t static_share_mode_data_refcount = 0;
764 /*******************************************************************
765 Either fetch a share mode from the database, or allocate a fresh
766 one if the record doesn't exist.
767 ********************************************************************/
769 struct get_static_share_mode_data_state {
770 TALLOC_CTX *mem_ctx;
771 struct file_id id;
772 const char *servicepath;
773 const struct smb_filename *smb_fname;
774 const struct timespec *old_write_time;
775 NTSTATUS status;
778 static void get_static_share_mode_data_fn(
779 struct server_id exclusive,
780 size_t num_shared,
781 struct server_id *shared,
782 const uint8_t *data,
783 size_t datalen,
784 void *private_data)
786 struct get_static_share_mode_data_state *state = private_data;
787 TDB_DATA key = locking_key(&state->id);
788 struct share_mode_data *d = NULL;
789 struct locking_tdb_data ltdb = { 0 };
791 if (datalen != 0) {
792 bool ok;
794 ok = locking_tdb_data_get(&ltdb, data, datalen);
795 if (!ok) {
796 DBG_DEBUG("locking_tdb_data_get failed\n");
797 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
798 return;
802 if (ltdb.share_mode_data_len == 0) {
803 if (state->smb_fname == NULL) {
804 state->status = NT_STATUS_NOT_FOUND;
805 return;
807 d = fresh_share_mode_lock(
808 state->mem_ctx,
809 state->servicepath,
810 state->smb_fname,
811 state->old_write_time);
812 if (d == NULL) {
813 state->status = NT_STATUS_NO_MEMORY;
814 return;
816 } else {
817 d = parse_share_modes(
818 lock_ctx,
819 key,
820 ltdb.share_mode_data_buf,
821 ltdb.share_mode_data_len);
822 if (d == NULL) {
823 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
824 return;
828 d->id = state->id;
829 static_share_mode_data = d;
832 static NTSTATUS get_static_share_mode_data(
833 struct file_id id,
834 const char *servicepath,
835 const struct smb_filename *smb_fname,
836 const struct timespec *old_write_time)
838 struct get_static_share_mode_data_state state = {
839 .mem_ctx = lock_ctx,
840 .id = id,
841 .servicepath = servicepath,
842 .smb_fname = smb_fname,
843 .old_write_time = old_write_time,
845 NTSTATUS status;
847 SMB_ASSERT(static_share_mode_data == NULL);
849 status = g_lock_dump(
850 lock_ctx,
851 share_mode_lock_key,
852 get_static_share_mode_data_fn,
853 &state);
854 if (!NT_STATUS_IS_OK(status)) {
855 DBG_DEBUG("g_lock_dump failed: %s\n",
856 nt_errstr(status));
857 return status;
859 if (!NT_STATUS_IS_OK(state.status)) {
860 DBG_DEBUG("get_static_share_mode_data_fn failed: %s\n",
861 nt_errstr(state.status));
862 return state.status;
865 return NT_STATUS_OK;
868 /*******************************************************************
869 Get a share_mode_lock, Reference counted to allow nested calls.
870 ********************************************************************/
872 static int share_mode_lock_destructor(struct share_mode_lock *lck);
874 struct share_mode_lock *get_share_mode_lock(
875 TALLOC_CTX *mem_ctx,
876 struct file_id id,
877 const char *servicepath,
878 const struct smb_filename *smb_fname,
879 const struct timespec *old_write_time)
881 TDB_DATA key = locking_key(&id);
882 struct share_mode_lock *lck = NULL;
883 NTSTATUS status;
884 int cmp;
886 lck = talloc(mem_ctx, struct share_mode_lock);
887 if (lck == NULL) {
888 DEBUG(1, ("talloc failed\n"));
889 return NULL;
892 if (static_share_mode_data != NULL) {
893 if (!file_id_equal(&static_share_mode_data->id, &id)) {
894 DEBUG(1, ("Can not lock two share modes "
895 "simultaneously\n"));
896 goto fail;
898 goto done;
901 if (share_mode_lock_key_refcount == 0) {
902 status = g_lock_lock(
903 lock_ctx,
904 key,
905 G_LOCK_WRITE,
906 (struct timeval) { .tv_sec = 3600 });
907 if (!NT_STATUS_IS_OK(status)) {
908 DBG_DEBUG("g_lock_lock failed: %s\n",
909 nt_errstr(status));
910 goto fail;
912 memcpy(share_mode_lock_key_data, key.dptr, key.dsize);
915 cmp = tdb_data_cmp(share_mode_lock_key, key);
916 if (cmp != 0) {
917 DBG_WARNING("Can not lock two share modes simultaneously\n");
918 goto fail;
921 SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
922 share_mode_lock_key_refcount += 1;
924 SMB_ASSERT(static_share_mode_data_refcount == 0);
926 status = get_static_share_mode_data(
928 servicepath,
929 smb_fname,
930 old_write_time);
931 if (!NT_STATUS_IS_OK(status)) {
932 DBG_DEBUG("get_static_share_mode_data failed: %s\n",
933 nt_errstr(status));
934 share_mode_lock_key_refcount -= 1;
935 goto fail;
937 done:
938 static_share_mode_data_refcount += 1;
939 lck->data = static_share_mode_data;
941 talloc_set_destructor(lck, share_mode_lock_destructor);
943 return lck;
944 fail:
945 TALLOC_FREE(lck);
946 if (share_mode_lock_key_refcount == 0) {
947 status = g_lock_unlock(lock_ctx, share_mode_lock_key);
948 if (!NT_STATUS_IS_OK(status)) {
949 DBG_ERR("g_lock_unlock failed: %s\n",
950 nt_errstr(status));
953 return NULL;
956 static int share_mode_lock_destructor(struct share_mode_lock *lck)
958 NTSTATUS status;
960 SMB_ASSERT(static_share_mode_data_refcount > 0);
961 static_share_mode_data_refcount -= 1;
963 if (static_share_mode_data_refcount > 0) {
964 return 0;
967 status = share_mode_data_store(static_share_mode_data);
968 if (!NT_STATUS_IS_OK(status)) {
969 DBG_ERR("share_mode_data_store failed: %s\n",
970 nt_errstr(status));
971 smb_panic("Could not store share mode data\n");
974 SMB_ASSERT(share_mode_lock_key_refcount > 0);
975 share_mode_lock_key_refcount -= 1;
977 if (share_mode_lock_key_refcount == 0) {
978 status = g_lock_unlock(lock_ctx, share_mode_lock_key);
979 if (!NT_STATUS_IS_OK(status)) {
980 DBG_ERR("g_lock_unlock failed: %s\n",
981 nt_errstr(status));
982 smb_panic("Could not unlock share mode\n");
986 if (static_share_mode_data->have_share_modes) {
988 * This is worth keeping. Without share modes,
989 * share_mode_data_store above has left nothing in the
990 * database.
992 share_mode_memcache_store(static_share_mode_data);
993 static_share_mode_data = NULL;
994 } else {
996 * The next opener of this file will find an empty
997 * locking.tdb record. Don't store the share_mode_data
998 * in the memcache, fresh_share_mode_lock() will
999 * generate a fresh seqnum anyway, obsoleting the
1000 * cache entry.
1002 TALLOC_FREE(static_share_mode_data);
1005 return 0;
1008 struct share_mode_do_locked_state {
1009 TDB_DATA key;
1010 void (*fn)(const uint8_t *buf,
1011 size_t buflen,
1012 bool *modified_dependent,
1013 void *private_data);
1014 void *private_data;
1017 static void share_mode_do_locked_fn(
1018 struct server_id exclusive,
1019 size_t num_shared,
1020 struct server_id *shared,
1021 const uint8_t *data,
1022 size_t datalen,
1023 void *private_data)
1025 struct share_mode_do_locked_state *state = private_data;
1026 bool modified_dependent = false;
1027 struct locking_tdb_data ltdb = { 0 };
1028 bool ok;
1030 ok = locking_tdb_data_get(
1031 &ltdb, discard_const_p(uint8_t, data), datalen);
1032 if (!ok) {
1033 DBG_WARNING("locking_tdb_data_get failed\n");
1034 return;
1037 state->fn(ltdb.share_mode_data_buf,
1038 ltdb.share_mode_data_len,
1039 &modified_dependent,
1040 state->private_data);
1042 if (modified_dependent) {
1043 g_lock_wake_watchers(lock_ctx, state->key);
1047 NTSTATUS share_mode_do_locked(
1048 struct file_id id,
1049 void (*fn)(const uint8_t *buf,
1050 size_t buflen,
1051 bool *modified_dependent,
1052 void *private_data),
1053 void *private_data)
1055 TDB_DATA key = locking_key(&id);
1056 size_t data_refcount, key_refcount;
1057 struct share_mode_do_locked_state state = {
1058 .key = key, .fn = fn, .private_data = private_data,
1060 NTSTATUS status;
1062 if (share_mode_lock_key_refcount == 0) {
1063 status = g_lock_lock(
1064 lock_ctx,
1065 key,
1066 G_LOCK_WRITE,
1067 (struct timeval) { .tv_sec = 3600 });
1068 if (!NT_STATUS_IS_OK(status)) {
1069 DBG_DEBUG("g_lock_lock failed: %s\n",
1070 nt_errstr(status));
1071 return status;
1073 memcpy(share_mode_lock_key_data, key.dptr, key.dsize);
1076 SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
1077 share_mode_lock_key_refcount += 1;
1079 key_refcount = share_mode_lock_key_refcount;
1080 data_refcount = static_share_mode_data_refcount;
1082 status = g_lock_dump(
1083 lock_ctx, key, share_mode_do_locked_fn, &state);
1084 if (!NT_STATUS_IS_OK(status)) {
1085 DBG_DEBUG("g_lock_dump failed: %s\n",
1086 nt_errstr(status));
1089 SMB_ASSERT(data_refcount == static_share_mode_data_refcount);
1090 SMB_ASSERT(key_refcount == share_mode_lock_key_refcount);
1091 share_mode_lock_key_refcount -= 1;
1093 if (share_mode_lock_key_refcount == 0) {
1094 status = g_lock_unlock(lock_ctx, key);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 DBG_DEBUG("g_lock_unlock failed: %s\n",
1097 nt_errstr(status));
1101 return status;
1104 static void share_mode_wakeup_waiters_fn(
1105 const uint8_t *buf,
1106 size_t buflen,
1107 bool *modified_dependent,
1108 void *private_data)
1110 *modified_dependent = true;
1113 NTSTATUS share_mode_wakeup_waiters(struct file_id id)
1115 return share_mode_do_locked(id, share_mode_wakeup_waiters_fn, NULL);
1118 bool share_mode_have_entries(struct share_mode_lock *lck)
1120 return lck->data->have_share_modes;
1123 struct share_mode_watch_state {
1124 bool blockerdead;
1125 struct server_id blocker;
1128 static void share_mode_watch_done(struct tevent_req *subreq);
1130 struct tevent_req *share_mode_watch_send(
1131 TALLOC_CTX *mem_ctx,
1132 struct tevent_context *ev,
1133 struct file_id id,
1134 struct server_id blocker)
1136 TDB_DATA key = locking_key(&id);
1137 struct tevent_req *req = NULL, *subreq = NULL;
1138 struct share_mode_watch_state *state = NULL;
1140 req = tevent_req_create(
1141 mem_ctx, &state, struct share_mode_watch_state);
1142 if (req == NULL) {
1143 return NULL;
1146 subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker);
1147 if (tevent_req_nomem(subreq, req)) {
1148 return tevent_req_post(req, ev);
1150 tevent_req_set_callback(subreq, share_mode_watch_done, req);
1151 return req;
1154 static void share_mode_watch_done(struct tevent_req *subreq)
1156 struct tevent_req *req = tevent_req_callback_data(
1157 subreq, struct tevent_req);
1158 struct share_mode_watch_state *state = tevent_req_data(
1159 req, struct share_mode_watch_state);
1160 NTSTATUS status;
1162 status = g_lock_watch_data_recv(
1163 subreq, &state->blockerdead, &state->blocker);
1164 if (tevent_req_nterror(req, status)) {
1165 return;
1167 tevent_req_done(req);
1170 NTSTATUS share_mode_watch_recv(
1171 struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
1173 struct share_mode_watch_state *state = tevent_req_data(
1174 req, struct share_mode_watch_state);
1175 NTSTATUS status;
1177 if (tevent_req_is_nterror(req, &status)) {
1178 return status;
1180 if (blockerdead != NULL) {
1181 *blockerdead = state->blockerdead;
1183 if (blocker != NULL) {
1184 *blocker = state->blocker;
1186 return NT_STATUS_OK;
1189 struct fetch_share_mode_unlocked_state {
1190 TALLOC_CTX *mem_ctx;
1191 TDB_DATA key;
1192 struct share_mode_lock *lck;
1195 static void fetch_share_mode_unlocked_parser(
1196 struct server_id exclusive,
1197 size_t num_shared,
1198 struct server_id *shared,
1199 const uint8_t *data,
1200 size_t datalen,
1201 void *private_data)
1203 struct fetch_share_mode_unlocked_state *state = private_data;
1204 struct locking_tdb_data ltdb = { 0 };
1206 if (datalen != 0) {
1207 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1208 if (!ok) {
1209 DBG_DEBUG("locking_tdb_data_get failed\n");
1210 return;
1214 if (ltdb.share_mode_data_len == 0) {
1215 /* Likely a ctdb tombstone record, ignore it */
1216 return;
1219 state->lck = talloc(state->mem_ctx, struct share_mode_lock);
1220 if (state->lck == NULL) {
1221 DEBUG(0, ("talloc failed\n"));
1222 return;
1225 state->lck->data = parse_share_modes(
1226 state->lck,
1227 state->key,
1228 ltdb.share_mode_data_buf,
1229 ltdb.share_mode_data_len);
1230 if (state->lck->data == NULL) {
1231 DBG_DEBUG("parse_share_modes failed\n");
1232 TALLOC_FREE(state->lck);
1236 /*******************************************************************
1237 Get a share_mode_lock without locking the database or reference
1238 counting. Used by smbstatus to display existing share modes.
1239 ********************************************************************/
1241 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
1242 struct file_id id)
1244 struct fetch_share_mode_unlocked_state state = {
1245 .mem_ctx = mem_ctx,
1246 .key = locking_key(&id),
1248 NTSTATUS status;
1250 status = g_lock_dump(
1251 lock_ctx, state.key, fetch_share_mode_unlocked_parser, &state);
1252 if (!NT_STATUS_IS_OK(status)) {
1253 DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
1254 return NULL;
1256 return state.lck;
1259 struct fetch_share_mode_state {
1260 struct file_id id;
1261 struct share_mode_lock *lck;
1262 NTSTATUS status;
1265 static void fetch_share_mode_fn(
1266 struct server_id exclusive,
1267 size_t num_shared,
1268 struct server_id *shared,
1269 const uint8_t *data,
1270 size_t datalen,
1271 void *private_data);
1272 static void fetch_share_mode_done(struct tevent_req *subreq);
1275 * @brief Get a share_mode_lock without locking or refcounting
1277 * This can be used in a clustered Samba environment where the async dbwrap
1278 * request is sent over a socket to the local ctdbd. If the send queue is full
1279 * and the caller was issuing multiple async dbwrap requests in a loop, the
1280 * caller knows it's probably time to stop sending requests for now and try
1281 * again later.
1283 * @param[in] mem_ctx The talloc memory context to use.
1285 * @param[in] ev The event context to work on.
1287 * @param[in] id The file id for the locking.tdb key
1289 * @param[out] queued This boolean out parameter tells the caller whether the
1290 * async request is blocked in a full send queue:
1292 * false := request is dispatched
1294 * true := send queue is full, request waiting to be
1295 * dispatched
1297 * @return The new async request, NULL on error.
1299 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
1300 struct tevent_context *ev,
1301 struct file_id id,
1302 bool *queued)
1304 struct tevent_req *req = NULL, *subreq = NULL;
1305 struct fetch_share_mode_state *state = NULL;
1307 *queued = false;
1309 req = tevent_req_create(mem_ctx, &state,
1310 struct fetch_share_mode_state);
1311 if (req == NULL) {
1312 return NULL;
1314 state->id = id;
1316 subreq = g_lock_dump_send(
1317 state,
1319 lock_ctx,
1320 locking_key(&id),
1321 fetch_share_mode_fn,
1322 state);
1323 if (tevent_req_nomem(subreq, req)) {
1324 return tevent_req_post(req, ev);
1326 tevent_req_set_callback(subreq, fetch_share_mode_done, req);
1327 return req;
1330 static void fetch_share_mode_fn(
1331 struct server_id exclusive,
1332 size_t num_shared,
1333 struct server_id *shared,
1334 const uint8_t *data,
1335 size_t datalen,
1336 void *private_data)
1338 struct fetch_share_mode_state *state = talloc_get_type_abort(
1339 private_data, struct fetch_share_mode_state);
1340 struct locking_tdb_data ltdb = { 0 };
1342 if (datalen != 0) {
1343 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1344 if (!ok) {
1345 DBG_DEBUG("locking_tdb_data_get failed\n");
1346 return;
1350 if (ltdb.share_mode_data_len == 0) {
1351 /* Likely a ctdb tombstone record, ignore it */
1352 return;
1355 state->lck = talloc(state, struct share_mode_lock);
1356 if (state->lck == NULL) {
1357 DBG_WARNING("talloc failed\n");
1358 state->status = NT_STATUS_NO_MEMORY;
1359 return;
1362 state->lck->data = parse_share_modes(
1363 state->lck,
1364 locking_key(&state->id),
1365 ltdb.share_mode_data_buf,
1366 ltdb.share_mode_data_len);
1367 if (state->lck->data == NULL) {
1368 DBG_DEBUG("parse_share_modes failed\n");
1369 TALLOC_FREE(state->lck);
1373 static void fetch_share_mode_done(struct tevent_req *subreq)
1375 struct tevent_req *req = tevent_req_callback_data(
1376 subreq, struct tevent_req);
1377 struct fetch_share_mode_state *state = tevent_req_data(
1378 req, struct fetch_share_mode_state);
1379 NTSTATUS status;
1381 status = g_lock_dump_recv(subreq);
1382 TALLOC_FREE(subreq);
1383 if (tevent_req_nterror(req, status)) {
1384 return;
1386 if (tevent_req_nterror(req, state->status)) {
1387 return;
1389 tevent_req_done(req);
1392 NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
1393 TALLOC_CTX *mem_ctx,
1394 struct share_mode_lock **_lck)
1396 struct fetch_share_mode_state *state = tevent_req_data(
1397 req, struct fetch_share_mode_state);
1398 struct share_mode_lock *lck = NULL;
1400 NTSTATUS status;
1402 if (tevent_req_is_nterror(req, &status)) {
1403 tevent_req_received(req);
1404 return status;
1407 if (state->lck == NULL) {
1408 tevent_req_received(req);
1409 return NT_STATUS_NOT_FOUND;
1412 lck = talloc_move(mem_ctx, &state->lck);
1414 if (DEBUGLEVEL >= 10) {
1415 DBG_DEBUG("share_mode_data:\n");
1416 NDR_PRINT_DEBUG(share_mode_data, lck->data);
1419 *_lck = lck;
1420 tevent_req_received(req);
1421 return NT_STATUS_OK;
1424 struct share_mode_forall_state {
1425 TDB_DATA key;
1426 int (*fn)(struct file_id fid,
1427 const struct share_mode_data *data,
1428 void *private_data);
1429 void *private_data;
1432 static void share_mode_forall_dump_fn(
1433 struct server_id exclusive,
1434 size_t num_shared,
1435 struct server_id *shared,
1436 const uint8_t *data,
1437 size_t datalen,
1438 void *private_data)
1440 struct share_mode_forall_state *state = private_data;
1441 struct file_id fid;
1442 struct locking_tdb_data ltdb = { 0 };
1443 bool ok;
1444 struct share_mode_data *d;
1446 if (state->key.dsize != sizeof(fid)) {
1447 DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize);
1448 return;
1450 memcpy(&fid, state->key.dptr, sizeof(fid));
1452 ok = locking_tdb_data_get(&ltdb, data, datalen);
1453 if (!ok) {
1454 DBG_DEBUG("locking_tdb_data_get() failed\n");
1455 return;
1458 d = parse_share_modes(
1459 talloc_tos(),
1460 state->key,
1461 ltdb.share_mode_data_buf,
1462 ltdb.share_mode_data_len);
1463 if (d == NULL) {
1464 DBG_DEBUG("parse_share_modes() failed\n");
1465 return;
1468 state->fn(fid, d, state->private_data);
1469 TALLOC_FREE(d);
1472 static int share_mode_forall_fn(TDB_DATA key, void *private_data)
1474 struct share_mode_forall_state *state = private_data;
1475 NTSTATUS status;
1477 state->key = key;
1479 status = g_lock_dump(
1480 lock_ctx, key, share_mode_forall_dump_fn, private_data);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 DBG_DEBUG("g_lock_dump failed: %s\n",
1483 nt_errstr(status));
1485 return 0;
1488 int share_mode_forall(int (*fn)(struct file_id fid,
1489 const struct share_mode_data *data,
1490 void *private_data),
1491 void *private_data)
1493 struct share_mode_forall_state state = {
1494 .fn = fn,
1495 .private_data = private_data
1497 int ret;
1499 if (lock_ctx == NULL) {
1500 return 0;
1503 ret = g_lock_locks(
1504 lock_ctx, share_mode_forall_fn, &state);
1505 if (ret < 0) {
1506 DBG_DEBUG("g_lock_locks failed\n");
1508 return ret;
1511 struct share_entry_forall_state {
1512 struct file_id fid;
1513 const struct share_mode_data *data;
1514 int (*fn)(struct file_id fid,
1515 const struct share_mode_data *data,
1516 const struct share_mode_entry *entry,
1517 void *private_data);
1518 void *private_data;
1519 int ret;
1522 static bool share_entry_traverse_walker(
1523 struct share_mode_entry *e,
1524 bool *modified,
1525 void *private_data)
1527 struct share_entry_forall_state *state = private_data;
1529 state->ret = state->fn(
1530 state->fid, state->data, e, state->private_data);
1531 return (state->ret != 0);
1534 static int share_entry_traverse_fn(struct file_id fid,
1535 const struct share_mode_data *data,
1536 void *private_data)
1538 struct share_entry_forall_state *state = private_data;
1539 struct share_mode_lock lck = {
1540 .data = discard_const_p(struct share_mode_data, data)
1542 bool ok;
1544 state->fid = fid;
1545 state->data = data;
1547 ok = share_mode_forall_entries(
1548 &lck, share_entry_traverse_walker, state);
1549 if (!ok) {
1550 DBG_DEBUG("share_mode_forall_entries failed\n");
1551 return false;
1554 return state->ret;
1557 /*******************************************************************
1558 Call the specified function on each entry under management by the
1559 share mode system.
1560 ********************************************************************/
1562 int share_entry_forall(int (*fn)(struct file_id fid,
1563 const struct share_mode_data *data,
1564 const struct share_mode_entry *entry,
1565 void *private_data),
1566 void *private_data)
1568 struct share_entry_forall_state state = {
1569 .fn = fn, .private_data = private_data };
1571 return share_mode_forall(share_entry_traverse_fn, &state);
1574 struct cleanup_disconnected_state {
1575 struct share_mode_lock *lck;
1576 uint64_t open_persistent_id;
1577 size_t num_disconnected;
1578 bool found_connected;
1581 static bool cleanup_disconnected_lease(struct share_mode_entry *e,
1582 void *private_data)
1584 struct cleanup_disconnected_state *state = private_data;
1585 NTSTATUS status;
1587 status = leases_db_del(
1588 &e->client_guid, &e->lease_key, &state->lck->data->id);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 DBG_DEBUG("leases_db_del failed: %s\n",
1592 nt_errstr(status));
1595 return false;
1598 static bool share_mode_find_connected_fn(
1599 struct share_mode_entry *e,
1600 bool *modified,
1601 void *private_data)
1603 struct cleanup_disconnected_state *state = private_data;
1604 struct share_mode_data *d = state->lck->data;
1605 bool disconnected;
1607 disconnected = server_id_is_disconnected(&e->pid);
1608 if (!disconnected) {
1609 struct file_id_buf tmp1;
1610 struct server_id_buf tmp2;
1611 DBG_INFO("file (file-id='%s', servicepath='%s', "
1612 "base_name='%s%s%s') "
1613 "is used by server %s ==> do not cleanup\n",
1614 file_id_str_buf(d->id, &tmp1),
1615 d->servicepath,
1616 d->base_name,
1617 (d->stream_name == NULL)
1618 ? "" : "', stream_name='",
1619 (d->stream_name == NULL)
1620 ? "" : d->stream_name,
1621 server_id_str_buf(e->pid, &tmp2));
1622 state->found_connected = true;
1623 return true;
1626 if (state->open_persistent_id != e->share_file_id) {
1627 struct file_id_buf tmp;
1628 DBG_INFO("entry for file "
1629 "(file-id='%s', servicepath='%s', "
1630 "base_name='%s%s%s') "
1631 "has share_file_id %"PRIu64" but expected "
1632 "%"PRIu64"==> do not cleanup\n",
1633 file_id_str_buf(d->id, &tmp),
1634 d->servicepath,
1635 d->base_name,
1636 (d->stream_name == NULL)
1637 ? "" : "', stream_name='",
1638 (d->stream_name == NULL)
1639 ? "" : d->stream_name,
1640 e->share_file_id,
1641 state->open_persistent_id);
1642 state->found_connected = true;
1643 return true;
1646 state->num_disconnected += 1;
1648 return false;
1651 bool share_mode_cleanup_disconnected(struct file_id fid,
1652 uint64_t open_persistent_id)
1654 struct cleanup_disconnected_state state = {
1655 .open_persistent_id = open_persistent_id
1657 struct share_mode_data *data;
1658 bool ret = false;
1659 TALLOC_CTX *frame = talloc_stackframe();
1660 struct file_id_buf idbuf;
1661 bool ok;
1663 state.lck = get_existing_share_mode_lock(frame, fid);
1664 if (state.lck == NULL) {
1665 DBG_INFO("Could not fetch share mode entry for %s\n",
1666 file_id_str_buf(fid, &idbuf));
1667 goto done;
1669 data = state.lck->data;
1671 ok = share_mode_forall_entries(
1672 state.lck, share_mode_find_connected_fn, &state);
1673 if (!ok) {
1674 DBG_DEBUG("share_mode_forall_entries failed\n");
1675 goto done;
1677 if (state.found_connected) {
1678 DBG_DEBUG("Found connected entry\n");
1679 goto done;
1682 ok = share_mode_forall_leases(
1683 state.lck, cleanup_disconnected_lease, &state);
1684 if (!ok) {
1685 DBG_DEBUG("failed to clean up leases associated "
1686 "with file (file-id='%s', servicepath='%s', "
1687 "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
1688 "==> do not cleanup\n",
1689 file_id_str_buf(fid, &idbuf),
1690 data->servicepath,
1691 data->base_name,
1692 (data->stream_name == NULL)
1693 ? "" : "', stream_name='",
1694 (data->stream_name == NULL)
1695 ? "" : data->stream_name,
1696 open_persistent_id);
1699 ok = brl_cleanup_disconnected(fid, open_persistent_id);
1700 if (!ok) {
1701 DBG_DEBUG("failed to clean up byte range locks associated "
1702 "with file (file-id='%s', servicepath='%s', "
1703 "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
1704 "==> do not cleanup\n",
1705 file_id_str_buf(fid, &idbuf),
1706 data->servicepath,
1707 data->base_name,
1708 (data->stream_name == NULL)
1709 ? "" : "', stream_name='",
1710 (data->stream_name == NULL)
1711 ? "" : data->stream_name,
1712 open_persistent_id);
1713 goto done;
1716 DBG_DEBUG("cleaning up %zu entries for file "
1717 "(file-id='%s', servicepath='%s', "
1718 "base_name='%s%s%s') "
1719 "from open_persistent_id %"PRIu64"\n",
1720 state.num_disconnected,
1721 file_id_str_buf(fid, &idbuf),
1722 data->servicepath,
1723 data->base_name,
1724 (data->stream_name == NULL)
1725 ? "" : "', stream_name='",
1726 (data->stream_name == NULL)
1727 ? "" : data->stream_name,
1728 open_persistent_id);
1730 data->have_share_modes = false;
1731 data->modified = true;
1734 * This is a temporary reproducer for the origin of
1735 * https://bugzilla.samba.org/show_bug.cgi?id=14428
1736 * "PANIC: assert failed in get_lease_type()"
1738 * This will be removed again once the bug is demonstrated
1739 * and fixed.
1741 TALLOC_FREE(state.lck);
1742 state.lck = get_existing_share_mode_lock(frame, fid);
1743 if (state.lck != NULL) {
1744 DBG_ERR("Reproduced BUG#14428\n");
1747 ret = true;
1748 done:
1749 talloc_free(frame);
1750 return ret;
1753 static int share_mode_entry_cmp(
1754 struct server_id pid1,
1755 uint64_t share_file_id1,
1756 struct server_id pid2,
1757 uint64_t share_file_id2)
1759 int cmp;
1761 cmp = server_id_cmp(&pid1, &pid2);
1762 if (cmp != 0) {
1763 return cmp;
1765 if (share_file_id1 != share_file_id2) {
1766 return (share_file_id1 < share_file_id2) ? -1 : 1;
1768 return 0;
1771 static size_t share_mode_entry_find(
1772 const uint8_t *data,
1773 size_t num_share_modes,
1774 struct server_id pid,
1775 uint64_t share_file_id,
1776 struct share_mode_entry *e,
1777 bool *match)
1779 ssize_t left, right, middle;
1781 *match = false;
1783 if (num_share_modes == 0) {
1784 return 0;
1787 left = 0;
1788 right = (num_share_modes-1);
1790 while (left <= right) {
1791 const uint8_t *middle_ptr = NULL;
1792 int cmp;
1793 bool ok;
1795 middle = left + ((right - left) / 2);
1796 middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
1798 DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
1799 left,
1800 right,
1801 middle,
1802 middle_ptr);
1804 ok = share_mode_entry_get(middle_ptr, e);
1805 if (!ok) {
1806 DBG_DEBUG("share_mode_entry_get failed\n");
1807 return 0;
1810 cmp = share_mode_entry_cmp(
1811 e->pid, e->share_file_id, pid, share_file_id);
1812 if (cmp == 0) {
1813 *match = true;
1814 return middle;
1817 if (cmp < 0) {
1818 right = middle-1;
1819 } else {
1820 left = middle+1;
1824 return left;
1827 bool set_share_mode(struct share_mode_lock *lck,
1828 struct files_struct *fsp,
1829 uid_t uid,
1830 uint64_t mid,
1831 uint16_t op_type,
1832 uint32_t share_access,
1833 uint32_t access_mask)
1835 struct share_mode_data *d = lck->data;
1836 TDB_DATA key = locking_key(&d->id);
1837 struct server_id my_pid = messaging_server_id(
1838 fsp->conn->sconn->msg_ctx);
1839 struct locking_tdb_data *ltdb = NULL;
1840 size_t idx;
1841 struct share_mode_entry e = { .pid.pid = 0 };
1842 struct share_mode_entry_buf e_buf;
1843 NTSTATUS status;
1844 bool ok, found;
1846 TDB_DATA dbufs[3];
1847 size_t num_dbufs = 0;
1849 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
1852 nt_errstr(status));
1853 return false;
1855 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
1857 idx = share_mode_entry_find(
1858 ltdb->share_entries,
1859 ltdb->num_share_entries,
1860 my_pid,
1861 fsp->fh->gen_id,
1863 &found);
1864 if (found) {
1865 DBG_WARNING("Found duplicate share mode\n");
1866 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1867 goto done;
1870 e = (struct share_mode_entry) {
1871 .pid = my_pid,
1872 .share_access = share_access,
1873 .private_options = fsp->fh->private_options,
1874 .access_mask = access_mask,
1875 .op_mid = mid,
1876 .op_type = op_type,
1877 .time.tv_sec = fsp->open_time.tv_sec,
1878 .time.tv_usec = fsp->open_time.tv_usec,
1879 .share_file_id = fsp->fh->gen_id,
1880 .uid = (uint32_t)uid,
1881 .flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1882 SHARE_MODE_FLAG_POSIX_OPEN : 0,
1883 .name_hash = fsp->name_hash,
1886 if (op_type == LEASE_OPLOCK) {
1887 const struct GUID *client_guid = fsp_client_guid(fsp);
1888 e.client_guid = *client_guid;
1889 e.lease_key = fsp->lease->lease.lease_key;
1892 ok = share_mode_entry_put(&e, &e_buf);
1893 if (!ok) {
1894 DBG_DEBUG("share_mode_entry_put failed\n");
1895 status = NT_STATUS_INTERNAL_ERROR;
1896 goto done;
1899 DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
1901 if (idx > 0) {
1902 dbufs[num_dbufs] = (TDB_DATA) {
1903 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
1904 .dsize = idx * SHARE_MODE_ENTRY_SIZE,
1906 num_dbufs += 1;
1909 dbufs[num_dbufs] = (TDB_DATA) {
1910 .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
1912 num_dbufs += 1;
1914 if (idx < ltdb->num_share_entries) {
1915 size_t num_after_idx = (ltdb->num_share_entries-idx);
1916 dbufs[num_dbufs] = (TDB_DATA) {
1917 .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
1918 idx * SHARE_MODE_ENTRY_SIZE,
1919 .dsize = num_after_idx * SHARE_MODE_ENTRY_SIZE,
1921 num_dbufs += 1;
1925 size_t i;
1926 for (i=0; i<num_dbufs; i++) {
1927 DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
1929 dbufs[i].dptr,
1930 dbufs[i].dsize);
1934 if (num_dbufs == 1) {
1936 * Storing a fresh record with just one share entry
1938 d->have_share_modes = true;
1939 d->modified = true;
1943 * If there was any existing data in
1944 * ltdb->share_entries, it's now been
1945 * moved and we've split it into:
1947 * num_dbufs = 3
1948 * dbufs[0] -> old sorted data less than new_entry
1949 * dbufs[1] -> new_share_mode_entry
1950 * dbufs[2] -> old sorted_data greater than new entry.
1952 * So the old data inside ltdb->share_entries is
1953 * no longer valid.
1955 * If we're storing a brand new entry the
1956 * dbufs look like:
1958 * num_dbufs = 1
1959 * dbufs[0] -> new_share_mode_entry
1961 * Either way we must set ltdb->share_entries = NULL
1962 * and ltdb->num_share_entries = 0 so that
1963 * locking_tdb_data_store() doesn't use it to
1964 * store any data. It's no longer there.
1967 ltdb->share_entries = NULL;
1968 ltdb->num_share_entries = 0;
1970 status = locking_tdb_data_store(key, ltdb, dbufs, num_dbufs);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
1973 nt_errstr(status));
1975 done:
1976 TALLOC_FREE(ltdb);
1977 return NT_STATUS_IS_OK(status);
1980 static bool share_mode_for_one_entry(
1981 bool (*fn)(struct share_mode_entry *e,
1982 bool *modified,
1983 void *private_data),
1984 void *private_data,
1985 size_t *i,
1986 uint8_t *data,
1987 size_t *num_share_modes,
1988 bool *writeback)
1990 DATA_BLOB blob = {
1991 .data = data + (*i) * SHARE_MODE_ENTRY_SIZE,
1992 .length = SHARE_MODE_ENTRY_SIZE,
1994 struct share_mode_entry e = {.pid.pid=0};
1995 enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
1996 bool modified = false;
1997 bool stop = false;
1998 struct server_id e_pid;
1999 uint64_t e_share_file_id;
2001 ndr_err = ndr_pull_struct_blob_all_noalloc(
2002 &blob,
2004 (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
2005 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2006 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
2007 *i += 1;
2008 return false;
2010 if (DEBUGLEVEL >= 10) {
2011 DBG_DEBUG("entry[%zu]:\n", *i);
2012 NDR_PRINT_DEBUG(share_mode_entry, &e);
2015 e_pid = e.pid;
2016 e_share_file_id = e.share_file_id;
2018 stop = fn(&e, &modified, private_data);
2020 DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2022 (int)modified,
2023 (int)e.stale);
2025 if (e.stale) {
2026 if (DEBUGLEVEL>=10) {
2027 DBG_DEBUG("share_mode_entry:\n");
2028 NDR_PRINT_DEBUG(share_mode_entry, &e);
2031 if (*i < *num_share_modes) {
2032 memmove(blob.data,
2033 blob.data + SHARE_MODE_ENTRY_SIZE,
2034 (*num_share_modes - *i - 1) *
2035 SHARE_MODE_ENTRY_SIZE);
2037 *num_share_modes -= 1;
2038 *writeback = true;
2039 return stop;
2042 if (modified) {
2043 if (DEBUGLEVEL>=10) {
2044 DBG_DEBUG("share_mode_entry:\n");
2045 NDR_PRINT_DEBUG(share_mode_entry, &e);
2049 * Make sure sorting order is kept intact
2051 SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
2052 SMB_ASSERT(e_share_file_id == e.share_file_id);
2054 ndr_err = ndr_push_struct_into_fixed_blob(
2055 &blob,
2057 (ndr_push_flags_fn_t)
2058 ndr_push_share_mode_entry);
2059 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2060 DBG_WARNING("ndr_push_share_mode_entry "
2061 "failed: %s\n",
2062 ndr_errstr(ndr_err));
2064 * Not much we can do, just ignore it
2067 *i += 1;
2068 *writeback = true;
2069 return stop;
2072 if (stop) {
2073 return true;
2076 *i += 1;
2077 return false;
2080 bool share_mode_forall_entries(
2081 struct share_mode_lock *lck,
2082 bool (*fn)(struct share_mode_entry *e,
2083 bool *modified,
2084 void *private_data),
2085 void *private_data)
2087 struct share_mode_data *d = lck->data;
2088 TDB_DATA key = locking_key(&d->id);
2089 struct locking_tdb_data *ltdb = NULL;
2090 uint8_t *share_entries = NULL;
2091 size_t num_share_entries;
2092 bool writeback = false;
2093 NTSTATUS status;
2094 bool stop = false;
2095 size_t i;
2097 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2098 if (!NT_STATUS_IS_OK(status)) {
2099 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2100 nt_errstr(status));
2101 return false;
2103 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2105 num_share_entries = ltdb->num_share_entries;
2106 share_entries = discard_const_p(uint8_t, ltdb->share_entries);
2108 i = 0;
2109 while (i<num_share_entries) {
2110 stop = share_mode_for_one_entry(
2112 private_data,
2114 share_entries,
2115 &num_share_entries,
2116 &writeback);
2117 if (stop) {
2118 break;
2122 DBG_DEBUG("num_share_entries=%zu, writeback=%d\n",
2123 num_share_entries,
2124 (int)writeback);
2126 if (!writeback) {
2127 return true;
2130 if ((ltdb->num_share_entries != 0 ) && (num_share_entries == 0)) {
2132 * This routine wiped all share entries
2134 d->have_share_modes = false;
2135 d->modified = true;
2138 ltdb->num_share_entries = num_share_entries;
2139 ltdb->share_entries = share_entries;
2141 status = locking_tdb_data_store(key, ltdb, NULL, 0);
2142 if (!NT_STATUS_IS_OK(status)) {
2143 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2144 nt_errstr(status));
2145 return false;
2148 return true;
2151 struct share_mode_count_entries_state {
2152 size_t num_share_modes;
2153 NTSTATUS status;
2156 static void share_mode_count_entries_fn(
2157 struct server_id exclusive,
2158 size_t num_shared,
2159 struct server_id *shared,
2160 const uint8_t *data,
2161 size_t datalen,
2162 void *private_data)
2164 struct share_mode_count_entries_state *state = private_data;
2165 struct locking_tdb_data ltdb = { 0 };
2166 bool ok;
2168 ok = locking_tdb_data_get(&ltdb, data, datalen);
2169 if (!ok) {
2170 DBG_WARNING("locking_tdb_data_get failed for %zu\n", datalen);
2171 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2172 return;
2174 state->num_share_modes = ltdb.num_share_entries;
2175 state->status = NT_STATUS_OK;
2178 NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
2180 struct share_mode_count_entries_state state = {
2181 .status = NT_STATUS_NOT_FOUND,
2183 NTSTATUS status;
2185 status = g_lock_dump(
2186 lock_ctx,
2187 locking_key(&fid),
2188 share_mode_count_entries_fn,
2189 &state);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 DBG_DEBUG("g_lock_dump failed: %s\n",
2192 nt_errstr(status));
2193 return status;
2195 if (!NT_STATUS_IS_OK(state.status)) {
2196 DBG_DEBUG("share_mode_count_entries_fn failed: %s\n",
2197 nt_errstr(state.status));
2198 return state.status;
2201 *num_share_modes = state.num_share_modes;
2202 return NT_STATUS_OK;
2205 static bool share_mode_entry_do(
2206 struct share_mode_lock *lck,
2207 struct server_id pid,
2208 uint64_t share_file_id,
2209 void (*fn)(struct share_mode_entry *e,
2210 size_t num_share_modes,
2211 bool *modified,
2212 void *private_data),
2213 void *private_data)
2215 struct share_mode_data *d = lck->data;
2216 TDB_DATA key = locking_key(&d->id);
2217 struct locking_tdb_data *ltdb = NULL;
2218 size_t idx;
2219 bool found = false;
2220 bool modified;
2221 struct share_mode_entry e;
2222 uint8_t *e_ptr = NULL;
2223 bool have_share_modes;
2224 NTSTATUS status;
2225 bool ret = false;
2227 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2228 if (!NT_STATUS_IS_OK(status)) {
2229 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2230 nt_errstr(status));
2231 return false;
2233 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2235 idx = share_mode_entry_find(
2236 ltdb->share_entries,
2237 ltdb->num_share_entries,
2238 pid,
2239 share_file_id,
2241 &found);
2242 if (!found) {
2243 DBG_WARNING("Did not find share mode entry for %"PRIu64"\n",
2244 share_file_id);
2245 goto done;
2248 if (DEBUGLEVEL>=10) {
2249 DBG_DEBUG("entry[%zu]:\n", idx);
2250 NDR_PRINT_DEBUG(share_mode_entry, &e);
2253 fn(&e, ltdb->num_share_entries, &modified, private_data);
2255 DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2256 idx,
2257 (int)modified,
2258 (int)e.stale);
2260 if (!e.stale && !modified) {
2261 ret = true;
2262 goto done;
2265 e_ptr = discard_const_p(uint8_t, ltdb->share_entries) +
2266 idx * SHARE_MODE_ENTRY_SIZE;
2268 if (e.stale) {
2270 * Move the rest down one entry
2272 size_t behind = ltdb->num_share_entries - idx - 1;
2273 if (behind != 0) {
2274 memmove(e_ptr,
2275 e_ptr + SHARE_MODE_ENTRY_SIZE,
2276 behind * SHARE_MODE_ENTRY_SIZE);
2278 ltdb->num_share_entries -= 1;
2280 if (DEBUGLEVEL>=10) {
2281 DBG_DEBUG("share_mode_entry:\n");
2282 NDR_PRINT_DEBUG(share_mode_entry, &e);
2284 } else {
2285 struct share_mode_entry_buf buf;
2286 bool ok;
2288 if (ltdb->num_share_entries != 1) {
2290 * Make sure the sorting order stays intact
2292 SMB_ASSERT(server_id_equal(&e.pid, &pid));
2293 SMB_ASSERT(e.share_file_id == share_file_id);
2296 ok = share_mode_entry_put(&e, &buf);
2297 if (!ok) {
2298 DBG_DEBUG("share_mode_entry_put failed\n");
2299 goto done;
2301 memcpy(e_ptr, buf.buf, SHARE_MODE_ENTRY_SIZE);
2304 status = locking_tdb_data_store(key, ltdb, NULL, 0);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2307 nt_errstr(status));
2308 goto done;
2311 have_share_modes = (ltdb->num_share_entries != 0);
2312 if (d->have_share_modes != have_share_modes) {
2313 d->have_share_modes = have_share_modes;
2314 d->modified = true;
2317 ret = true;
2318 done:
2319 TALLOC_FREE(ltdb);
2320 return ret;
2323 struct del_share_mode_state {
2324 bool ok;
2327 static void del_share_mode_fn(
2328 struct share_mode_entry *e,
2329 size_t num_share_modes,
2330 bool *modified,
2331 void *private_data)
2333 struct del_share_mode_state *state = private_data;
2334 e->stale = true;
2335 state->ok = true;
2338 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
2340 struct del_share_mode_state state = { .ok = false };
2341 bool ok;
2343 ok = share_mode_entry_do(
2344 lck,
2345 messaging_server_id(fsp->conn->sconn->msg_ctx),
2346 fsp->fh->gen_id,
2347 del_share_mode_fn,
2348 &state);
2349 if (!ok) {
2350 DBG_DEBUG("share_mode_entry_do failed\n");
2351 return false;
2353 if (!state.ok) {
2354 DBG_DEBUG("del_share_mode_fn failed\n");
2355 return false;
2357 return true;
2360 struct remove_share_oplock_state {
2361 bool ok;
2364 static void remove_share_oplock_fn(
2365 struct share_mode_entry *e,
2366 size_t num_share_modes,
2367 bool *modified,
2368 void *private_data)
2370 struct remove_share_oplock_state *state = private_data;
2372 e->op_type = NO_OPLOCK;
2373 *modified = true;
2374 state->ok = true;
2377 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2379 struct remove_share_oplock_state state = { .ok = false };
2380 bool ok;
2382 ok = share_mode_entry_do(
2383 lck,
2384 messaging_server_id(fsp->conn->sconn->msg_ctx),
2385 fsp->fh->gen_id,
2386 remove_share_oplock_fn,
2387 &state);
2388 if (!ok) {
2389 DBG_DEBUG("share_mode_entry_do failed\n");
2390 return false;
2392 if (!state.ok) {
2393 DBG_DEBUG("remove_share_oplock_fn failed\n");
2394 return false;
2397 if (fsp->oplock_type == LEASE_OPLOCK) {
2398 remove_lease_if_stale(
2399 lck,
2400 fsp_client_guid(fsp),
2401 &fsp->lease->lease.lease_key);
2404 share_mode_wakeup_waiters(fsp->file_id);
2406 return true;
2409 struct downgrade_share_oplock_state {
2410 bool ok;
2413 static void downgrade_share_oplock_fn(
2414 struct share_mode_entry *e,
2415 size_t num_share_modes,
2416 bool *modified,
2417 void *private_data)
2419 struct downgrade_share_oplock_state *state = private_data;
2421 e->op_type = LEVEL_II_OPLOCK;
2422 *modified = true;
2423 state->ok = true;
2426 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2428 struct downgrade_share_oplock_state state = { .ok = false };
2429 bool ok;
2431 ok = share_mode_entry_do(
2432 lck,
2433 messaging_server_id(fsp->conn->sconn->msg_ctx),
2434 fsp->fh->gen_id,
2435 downgrade_share_oplock_fn,
2436 &state);
2437 if (!ok) {
2438 DBG_DEBUG("share_mode_entry_do failed\n");
2439 return false;
2441 if (!state.ok) {
2442 DBG_DEBUG("downgrade_share_oplock_fn failed\n");
2443 return false;
2446 lck->data->flags |= SHARE_MODE_LEASE_READ;
2447 lck->data->modified = true;
2449 return true;
2452 struct mark_share_mode_disconnected_state {
2453 uint64_t open_persistent_id;
2454 bool ok;
2457 static void mark_share_mode_disconnected_fn(
2458 struct share_mode_entry *e,
2459 size_t num_share_modes,
2460 bool *modified,
2461 void *private_data)
2463 struct mark_share_mode_disconnected_state *state = private_data;
2465 if (num_share_modes != 1) {
2466 state->ok = false;
2467 return;
2470 server_id_set_disconnected(&e->pid);
2471 e->share_file_id = state->open_persistent_id;
2472 *modified = true;
2473 state->ok = true;
2476 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
2477 struct files_struct *fsp)
2479 struct mark_share_mode_disconnected_state state;
2480 bool ok;
2482 if (fsp->op == NULL) {
2483 return false;
2485 if (!fsp->op->global->durable) {
2486 return false;
2489 state = (struct mark_share_mode_disconnected_state) {
2490 .open_persistent_id = fsp->op->global->open_persistent_id,
2493 ok = share_mode_entry_do(
2494 lck,
2495 messaging_server_id(fsp->conn->sconn->msg_ctx),
2496 fsp->fh->gen_id,
2497 mark_share_mode_disconnected_fn,
2498 &state);
2499 if (!ok) {
2500 DBG_DEBUG("share_mode_entry_do failed\n");
2501 return false;
2503 if (!state.ok) {
2504 DBG_DEBUG("mark_share_mode_disconnected_fn failed\n");
2505 return false;
2508 lck->data->modified = true;
2509 return true;
2512 bool reset_share_mode_entry(
2513 struct share_mode_lock *lck,
2514 struct server_id old_pid,
2515 uint64_t old_share_file_id,
2516 struct server_id new_pid,
2517 uint64_t new_mid,
2518 uint64_t new_share_file_id)
2520 struct share_mode_data *d = lck->data;
2521 TDB_DATA key = locking_key(&d->id);
2522 struct locking_tdb_data *ltdb = NULL;
2523 struct share_mode_entry e;
2524 struct share_mode_entry_buf e_buf;
2525 NTSTATUS status;
2526 bool ret = false;
2527 bool ok;
2529 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2530 if (!NT_STATUS_IS_OK(status)) {
2531 DBG_DEBUG("locking_tdb_data_fetch failed: %s\n",
2532 nt_errstr(status));
2533 return false;
2536 if (ltdb->num_share_entries != 1) {
2537 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2538 goto done;
2541 ok = share_mode_entry_get(ltdb->share_entries, &e);
2542 if (!ok) {
2543 DBG_WARNING("share_mode_entry_get failed\n");
2544 goto done;
2547 ret = share_mode_entry_cmp(
2548 old_pid, old_share_file_id, e.pid, e.share_file_id);
2549 if (ret != 0) {
2550 struct server_id_buf tmp1, tmp2;
2551 DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
2552 "got pid=%s, file_id=%"PRIu64"\n",
2553 server_id_str_buf(old_pid, &tmp1),
2554 old_share_file_id,
2555 server_id_str_buf(e.pid, &tmp2),
2556 e.share_file_id);
2557 goto done;
2560 e.pid = new_pid;
2561 e.op_mid = new_mid;
2562 e.share_file_id = new_share_file_id;
2564 ok = share_mode_entry_put(&e, &e_buf);
2565 if (!ok) {
2566 DBG_WARNING("share_mode_entry_put failed\n");
2567 goto done;
2570 ltdb->share_entries = e_buf.buf;
2572 status = locking_tdb_data_store(key, ltdb, NULL, 0);
2573 if (!NT_STATUS_IS_OK(status)) {
2574 DBG_DEBUG("locking_tdb_data_store failed: %s\n",
2575 nt_errstr(status));
2576 goto done;
2579 d->have_share_modes = true;
2580 ret = true;
2581 done:
2582 TALLOC_FREE(ltdb);
2583 return true;