gp: Move GNOME admx templates
[Samba.git] / source3 / locking / share_mode_lock.c
blob84497f42145dbd67bb2b2049b2356b6951b5f639
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 "lib/util/time_basic.h"
40 #include "system/filesys.h"
41 #include "lib/util/server_id.h"
42 #include "share_mode_lock_private.h"
43 struct share_mode_lock {
44 struct file_id id;
45 struct share_mode_data *cached_data;
47 #define SHARE_MODE_ENTRY_PREPARE_STATE_LCK_SPACE 1
48 #include "share_mode_lock.h"
49 #include "locking/proto.h"
50 #include "smbd/globals.h"
51 #include "dbwrap/dbwrap.h"
52 #include "dbwrap/dbwrap_open.h"
53 #include "dbwrap/dbwrap_private.h"
54 #include "../libcli/security/security.h"
55 #include "serverid.h"
56 #include "messages.h"
57 #include "util_tdb.h"
58 #include "../librpc/gen_ndr/ndr_open_files.h"
59 #include "source3/lib/dbwrap/dbwrap_watch.h"
60 #include "locking/leases_db.h"
61 #include "../lib/util/memcache.h"
62 #include "lib/util/tevent_ntstatus.h"
63 #include "g_lock.h"
64 #include "smbd/fd_handle.h"
65 #include "lib/global_contexts.h"
67 #undef DBGC_CLASS
68 #define DBGC_CLASS DBGC_LOCKING
70 #define DBG_GET_SHARE_MODE_LOCK(__status, ...) \
71 DBG_PREFIX( \
72 NT_STATUS_EQUAL(__status, NT_STATUS_NOT_FOUND) ? \
73 DBGLVL_DEBUG : DBGLVL_ERR, \
74 (__VA_ARGS__))
76 /* the locking database handle */
77 static struct g_lock_ctx *lock_ctx;
78 static struct g_lock_lock_cb_state *current_share_mode_glck = NULL;
80 static bool share_mode_g_lock_within_cb(TDB_DATA key);
82 static NTSTATUS share_mode_g_lock_dump(TDB_DATA key,
83 void (*fn)(struct server_id exclusive,
84 size_t num_shared,
85 const struct server_id *shared,
86 const uint8_t *data,
87 size_t datalen,
88 void *private_data),
89 void *private_data)
91 if (share_mode_g_lock_within_cb(key)) {
92 return g_lock_lock_cb_dump(current_share_mode_glck,
93 fn, private_data);
96 return g_lock_dump(lock_ctx, key, fn, private_data);
99 static NTSTATUS share_mode_g_lock_writev(TDB_DATA key,
100 const TDB_DATA *dbufs,
101 size_t num_dbufs)
103 if (share_mode_g_lock_within_cb(key)) {
104 return g_lock_lock_cb_writev(current_share_mode_glck,
105 dbufs, num_dbufs);
108 return g_lock_writev_data(lock_ctx, key, dbufs, num_dbufs);
111 static bool locking_init_internal(bool read_only)
113 struct db_context *backend;
114 char *db_path;
116 brl_init(read_only);
118 if (lock_ctx != NULL) {
119 return True;
122 db_path = lock_path(talloc_tos(), "locking.tdb");
123 if (db_path == NULL) {
124 return false;
127 backend = db_open(NULL, db_path,
128 SMB_OPEN_DATABASE_TDB_HASH_SIZE,
129 TDB_DEFAULT|
130 TDB_VOLATILE|
131 TDB_CLEAR_IF_FIRST|
132 TDB_INCOMPATIBLE_HASH|
133 TDB_SEQNUM,
134 read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
135 DBWRAP_LOCK_ORDER_NONE,
136 DBWRAP_FLAG_NONE);
137 TALLOC_FREE(db_path);
138 if (!backend) {
139 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
140 return False;
143 lock_ctx = g_lock_ctx_init_backend(
144 NULL, global_messaging_context(), &backend);
145 if (lock_ctx == NULL) {
146 TALLOC_FREE(backend);
147 return false;
149 g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1);
151 if (!posix_locking_init(read_only)) {
152 TALLOC_FREE(lock_ctx);
153 return False;
156 return True;
159 bool locking_init(void)
161 return locking_init_internal(false);
164 bool locking_init_readonly(void)
166 return locking_init_internal(true);
169 /*******************************************************************
170 Deinitialize the share_mode management.
171 ******************************************************************/
173 bool locking_end(void)
175 brl_shutdown();
176 TALLOC_FREE(lock_ctx);
177 return true;
180 /*******************************************************************
181 Form a static locking key for a dev/inode pair.
182 ******************************************************************/
184 static TDB_DATA locking_key(const struct file_id *id)
186 return make_tdb_data((const uint8_t *)id, sizeof(*id));
189 /*******************************************************************
190 Share mode cache utility functions that store/delete/retrieve
191 entries from memcache.
193 For now share the statcache (global cache) memory space. If
194 a lock record gets orphaned (which shouldn't happen as we're
195 using the same locking_key data as lookup) it will eventually
196 fall out of the cache via the normal LRU trim mechanism. If
197 necessary we can always make this a separate (smaller) cache.
198 ******************************************************************/
200 static DATA_BLOB memcache_key(const struct file_id *id)
202 return data_blob_const((const void *)id, sizeof(*id));
205 static void share_mode_memcache_store(struct share_mode_data *d)
207 const DATA_BLOB key = memcache_key(&d->id);
208 struct file_id_buf idbuf;
210 DBG_DEBUG("stored entry for file %s epoch %"PRIx64" key %s\n",
211 d->base_name,
212 d->unique_content_epoch,
213 file_id_str_buf(d->id, &idbuf));
215 /* Ensure everything stored in the cache is pristine. */
216 SMB_ASSERT(!d->modified);
217 SMB_ASSERT(!d->not_stored);
220 * Ensure the memory going into the cache
221 * doesn't have a destructor so it can be
222 * cleanly evicted by the memcache LRU
223 * mechanism.
225 talloc_set_destructor(d, NULL);
227 /* Cache will own d after this call. */
228 memcache_add_talloc(NULL,
229 SHARE_MODE_LOCK_CACHE,
230 key,
231 &d);
235 * NB. We use ndr_pull_hyper on a stack-created
236 * struct ndr_pull with no talloc allowed, as we
237 * need this to be really fast as an ndr-peek into
238 * the first 10 bytes of the blob.
241 static enum ndr_err_code get_share_mode_blob_header(
242 const uint8_t *buf, size_t buflen, uint64_t *pepoch, uint16_t *pflags)
244 struct ndr_pull ndr = {
245 .data = discard_const_p(uint8_t, buf),
246 .data_size = buflen,
248 NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pepoch));
249 NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
250 return NDR_ERR_SUCCESS;
253 static int share_mode_data_nofree_destructor(struct share_mode_data *d)
255 return -1;
258 static struct share_mode_data *share_mode_memcache_fetch(
259 TALLOC_CTX *mem_ctx,
260 struct file_id id,
261 const uint8_t *buf,
262 size_t buflen)
264 const DATA_BLOB key = memcache_key(&id);
265 enum ndr_err_code ndr_err;
266 struct share_mode_data *d;
267 uint64_t unique_content_epoch;
268 uint16_t flags;
269 void *ptr;
270 struct file_id_buf idbuf;
272 ptr = memcache_lookup_talloc(NULL,
273 SHARE_MODE_LOCK_CACHE,
274 key);
275 if (ptr == NULL) {
276 DBG_DEBUG("failed to find entry for key %s\n",
277 file_id_str_buf(id, &idbuf));
278 return NULL;
280 /* sequence number key is at start of blob. */
281 ndr_err = get_share_mode_blob_header(
282 buf, buflen, &unique_content_epoch, &flags);
283 if (ndr_err != NDR_ERR_SUCCESS) {
284 /* Bad blob. Remove entry. */
285 DBG_DEBUG("bad blob %u key %s\n",
286 (unsigned int)ndr_err,
287 file_id_str_buf(id, &idbuf));
288 memcache_delete(NULL,
289 SHARE_MODE_LOCK_CACHE,
290 key);
291 return NULL;
294 d = (struct share_mode_data *)ptr;
295 if (d->unique_content_epoch != unique_content_epoch) {
296 DBG_DEBUG("epoch changed (cached %"PRIx64") (new %"PRIx64") "
297 "for key %s\n",
298 d->unique_content_epoch,
299 unique_content_epoch,
300 file_id_str_buf(id, &idbuf));
301 /* Cache out of date. Remove entry. */
302 memcache_delete(NULL,
303 SHARE_MODE_LOCK_CACHE,
304 key);
305 return NULL;
308 /* Move onto mem_ctx. */
309 d = talloc_move(mem_ctx, &ptr);
312 * Now we own d, prevent the cache from freeing it
313 * when we delete the entry.
315 talloc_set_destructor(d, share_mode_data_nofree_destructor);
317 /* Remove from the cache. We own it now. */
318 memcache_delete(NULL,
319 SHARE_MODE_LOCK_CACHE,
320 key);
322 /* And reset the destructor to none. */
323 talloc_set_destructor(d, NULL);
325 DBG_DEBUG("fetched entry for file %s epoch %"PRIx64" key %s\n",
326 d->base_name,
327 d->unique_content_epoch,
328 file_id_str_buf(id, &idbuf));
330 return d;
334 * 132 is the sizeof an ndr-encoded struct share_mode_entry_buf.
335 * Reading/writing entries will immediately error out if this
336 * size differs (push/pull is done without allocs).
339 struct share_mode_entry_buf {
340 uint8_t buf[132];
342 #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))
344 static bool share_mode_entry_put(
345 const struct share_mode_entry *e,
346 struct share_mode_entry_buf *dst)
348 DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
349 enum ndr_err_code ndr_err;
351 if (DEBUGLEVEL>=10) {
352 DBG_DEBUG("share_mode_entry:\n");
353 NDR_PRINT_DEBUG(share_mode_entry, discard_const_p(void, e));
356 ndr_err = ndr_push_struct_into_fixed_blob(
357 &blob,
359 (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
360 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
361 DBG_WARNING("ndr_push_share_mode_entry failed: %s\n",
362 ndr_errstr(ndr_err));
363 return false;
366 return true;
369 static bool share_mode_entry_get(
370 const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
372 enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
373 DATA_BLOB blob = {
374 .data = discard_const_p(uint8_t, ptr),
375 .length = SHARE_MODE_ENTRY_SIZE,
378 ndr_err = ndr_pull_struct_blob_all_noalloc(
379 &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
380 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
381 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
382 return false;
384 return true;
388 * locking.tdb records consist of
390 * uint32_t share_mode_data_len
391 * uint8_t [share_mode_data] This is struct share_mode_data in NDR
393 * 0 [SHARE_MODE_ENTRY_SIZE] Sorted array of share modes,
394 * 1 [SHARE_MODE_ENTRY_SIZE] filling up the rest of the data in the
395 * 2 [SHARE_MODE_ENTRY_SIZE] g_lock.c maintained record in locking.tdb
398 struct locking_tdb_data {
399 const uint8_t *share_mode_data_buf;
400 size_t share_mode_data_len;
401 const uint8_t *share_entries;
402 size_t num_share_entries;
405 static bool locking_tdb_data_get(
406 struct locking_tdb_data *data, const uint8_t *buf, size_t buflen)
408 uint32_t share_mode_data_len, share_entries_len;
410 if (buflen == 0) {
411 *data = (struct locking_tdb_data) { 0 };
412 return true;
414 if (buflen < sizeof(uint32_t)) {
415 return false;
418 share_mode_data_len = PULL_LE_U32(buf, 0);
420 buf += sizeof(uint32_t);
421 buflen -= sizeof(uint32_t);
423 if (buflen < share_mode_data_len) {
424 return false;
427 share_entries_len = buflen - share_mode_data_len;
429 if ((share_entries_len % SHARE_MODE_ENTRY_SIZE) != 0) {
430 return false;
433 *data = (struct locking_tdb_data) {
434 .share_mode_data_buf = buf,
435 .share_mode_data_len = share_mode_data_len,
436 .share_entries = buf + share_mode_data_len,
437 .num_share_entries = share_entries_len / SHARE_MODE_ENTRY_SIZE,
440 return true;
443 struct locking_tdb_data_fetch_state {
444 TALLOC_CTX *mem_ctx;
445 uint8_t *data;
446 size_t datalen;
449 static void locking_tdb_data_fetch_fn(
450 struct server_id exclusive,
451 size_t num_shared,
452 const struct server_id *shared,
453 const uint8_t *data,
454 size_t datalen,
455 void *private_data)
457 struct locking_tdb_data_fetch_state *state = private_data;
458 state->datalen = datalen;
459 state->data = talloc_memdup(state->mem_ctx, data, datalen);
462 static NTSTATUS locking_tdb_data_fetch(
463 TDB_DATA key, TALLOC_CTX *mem_ctx, struct locking_tdb_data **ltdb)
465 struct locking_tdb_data_fetch_state state = { 0 };
466 struct locking_tdb_data *result = NULL;
467 NTSTATUS status;
468 bool ok;
470 result = talloc_zero(mem_ctx, struct locking_tdb_data);
471 if (result == NULL) {
472 return NT_STATUS_NO_MEMORY;
474 state.mem_ctx = result;
476 status = share_mode_g_lock_dump(key, locking_tdb_data_fetch_fn, &state);
477 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
479 * Just return an empty record
481 goto done;
483 if (!NT_STATUS_IS_OK(status)) {
484 DBG_ERR("share_mode_g_lock_dump failed: %s\n",
485 nt_errstr(status));
486 return status;
488 if (state.datalen == 0) {
489 goto done;
492 ok = locking_tdb_data_get(result, state.data, state.datalen);
493 if (!ok) {
494 DBG_ERR("locking_tdb_data_get failed for %zu bytes\n",
495 state.datalen);
496 TALLOC_FREE(result);
497 return NT_STATUS_INTERNAL_DB_CORRUPTION;
500 done:
501 *ltdb = result;
502 return NT_STATUS_OK;
505 static NTSTATUS locking_tdb_data_store(
506 TDB_DATA key,
507 const struct locking_tdb_data *ltdb,
508 const TDB_DATA *share_mode_dbufs,
509 size_t num_share_mode_dbufs)
511 uint8_t share_mode_data_len_buf[4];
512 TDB_DATA dbufs[num_share_mode_dbufs+3];
513 NTSTATUS status;
515 if ((ltdb->share_mode_data_len == 0) &&
516 (ltdb->num_share_entries == 0) &&
517 (num_share_mode_dbufs == 0)) {
519 * Nothing to write
521 status = share_mode_g_lock_writev(key, NULL, 0);
522 if (!NT_STATUS_IS_OK(status)) {
523 DBG_ERR("share_mode_g_lock_writev(NULL) failed: %s\n",
524 nt_errstr(status));
526 return status;
529 PUSH_LE_U32(share_mode_data_len_buf, 0, ltdb->share_mode_data_len);
531 dbufs[0] = (TDB_DATA) {
532 .dptr = share_mode_data_len_buf,
533 .dsize = sizeof(share_mode_data_len_buf),
535 dbufs[1] = (TDB_DATA) {
536 .dptr = discard_const_p(uint8_t, ltdb->share_mode_data_buf),
537 .dsize = ltdb->share_mode_data_len,
540 if (ltdb->num_share_entries > SIZE_MAX/SHARE_MODE_ENTRY_SIZE) {
541 /* overflow */
542 return NT_STATUS_BUFFER_OVERFLOW;
544 dbufs[2] = (TDB_DATA) {
545 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
546 .dsize = ltdb->num_share_entries * SHARE_MODE_ENTRY_SIZE,
549 if (num_share_mode_dbufs != 0) {
550 memcpy(&dbufs[3],
551 share_mode_dbufs,
552 num_share_mode_dbufs * sizeof(TDB_DATA));
555 status = share_mode_g_lock_writev(key, dbufs, ARRAY_SIZE(dbufs));
556 if (!NT_STATUS_IS_OK(status)) {
557 DBG_ERR("share_mode_g_lock_writev() failed: %s\n",
558 nt_errstr(status));
560 return status;
563 /*******************************************************************
564 Get all share mode entries for a dev/inode pair.
565 ********************************************************************/
567 static struct share_mode_data *parse_share_modes(
568 TALLOC_CTX *mem_ctx,
569 struct file_id id,
570 const uint8_t *buf,
571 size_t buflen)
573 struct share_mode_data *d;
574 enum ndr_err_code ndr_err;
575 DATA_BLOB blob;
577 /* See if we already have a cached copy of this key. */
578 d = share_mode_memcache_fetch(mem_ctx, id, buf, buflen);
579 if (d != NULL) {
580 return d;
583 d = talloc(mem_ctx, struct share_mode_data);
584 if (d == NULL) {
585 DEBUG(0, ("talloc failed\n"));
586 goto fail;
589 blob = (DATA_BLOB) {
590 .data = discard_const_p(uint8_t, buf),
591 .length = buflen,
593 ndr_err = ndr_pull_struct_blob_all(
594 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
595 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
596 DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
597 ndr_errstr(ndr_err));
598 goto fail;
601 if (DEBUGLEVEL >= 10) {
602 DEBUG(10, ("parse_share_modes:\n"));
603 NDR_PRINT_DEBUG(share_mode_data, d);
606 return d;
607 fail:
608 TALLOC_FREE(d);
609 return NULL;
612 static NTSTATUS share_mode_data_ltdb_store(struct share_mode_data *d,
613 TDB_DATA key,
614 struct locking_tdb_data *ltdb,
615 const TDB_DATA *share_mode_dbufs,
616 size_t num_share_mode_dbufs)
618 DATA_BLOB blob = { 0 };
619 NTSTATUS status;
621 if (!d->modified) {
622 DBG_DEBUG("share_mode_data not modified\n");
623 goto store;
626 d->unique_content_epoch = generate_unique_u64(d->unique_content_epoch);
628 if (DEBUGLEVEL >= 10) {
629 DBG_DEBUG("\n");
630 NDR_PRINT_DEBUG(share_mode_data, d);
633 if (ltdb->num_share_entries != 0 || num_share_mode_dbufs != 0) {
634 enum ndr_err_code ndr_err;
636 ndr_err = ndr_push_struct_blob(
637 &blob,
638 ltdb,
640 (ndr_push_flags_fn_t)ndr_push_share_mode_data);
641 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
642 DBG_ERR("ndr_push_share_mode_data failed: %s\n",
643 ndr_errstr(ndr_err));
644 return ndr_map_error2ntstatus(ndr_err);
648 ltdb->share_mode_data_buf = blob.data;
649 ltdb->share_mode_data_len = blob.length;
651 store:
652 status = locking_tdb_data_store(key,
653 ltdb,
654 share_mode_dbufs,
655 num_share_mode_dbufs);
656 if (!NT_STATUS_IS_OK(status)) {
657 DBG_ERR("locking_tdb_data_store failed: %s\n",
658 nt_errstr(status));
659 return status;
662 d->modified = false;
663 d->not_stored = (ltdb->share_mode_data_len == 0);
665 return NT_STATUS_OK;
668 /*******************************************************************
669 If modified, store the share_mode_data back into the database.
670 ********************************************************************/
672 static NTSTATUS share_mode_data_store(struct share_mode_data *d)
674 TDB_DATA key = locking_key(&d->id);
675 struct locking_tdb_data *ltdb = NULL;
676 NTSTATUS status;
678 if (!d->modified) {
679 DBG_DEBUG("not modified\n");
680 return NT_STATUS_OK;
683 if (DEBUGLEVEL >= 10) {
684 DBG_DEBUG("\n");
685 NDR_PRINT_DEBUG(share_mode_data, d);
688 status = locking_tdb_data_fetch(key, d, &ltdb);
689 if (!NT_STATUS_IS_OK(status)) {
690 DBG_ERR("locking_tdb_data_fetch failed: %s\n",
691 nt_errstr(status));
692 return status;
695 status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
696 TALLOC_FREE(ltdb);
697 if (!NT_STATUS_IS_OK(status)) {
698 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
699 nt_errstr(status));
700 return status;
703 return NT_STATUS_OK;
706 /*******************************************************************
707 Allocate a new share_mode_data struct, mark it unmodified.
708 fresh is set to note that currently there is no database entry.
709 ********************************************************************/
711 static struct share_mode_data *fresh_share_mode_lock(
712 TALLOC_CTX *mem_ctx, const char *servicepath,
713 const struct smb_filename *smb_fname,
714 const struct timespec *old_write_time)
716 struct share_mode_data *d;
718 if ((servicepath == NULL) || (smb_fname == NULL) ||
719 (old_write_time == NULL)) {
720 return NULL;
723 d = talloc_zero(mem_ctx, struct share_mode_data);
724 if (d == NULL) {
725 goto fail;
727 d->unique_content_epoch = generate_unique_u64(0);
729 d->base_name = talloc_strdup(d, smb_fname->base_name);
730 if (d->base_name == NULL) {
731 goto fail;
733 if (smb_fname->stream_name != NULL) {
734 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
735 if (d->stream_name == NULL) {
736 goto fail;
739 d->servicepath = talloc_strdup(d, servicepath);
740 if (d->servicepath == NULL) {
741 goto fail;
743 d->old_write_time = full_timespec_to_nt_time(old_write_time);
744 d->flags = SHARE_MODE_SHARE_DELETE |
745 SHARE_MODE_SHARE_WRITE |
746 SHARE_MODE_SHARE_READ;
747 d->modified = false;
748 d->not_stored = true;
749 return d;
750 fail:
751 DEBUG(0, ("talloc failed\n"));
752 TALLOC_FREE(d);
753 return NULL;
757 * Key that's locked with g_lock
759 static struct file_id share_mode_lock_key_id = {};
760 static TDB_DATA share_mode_lock_key = {
761 .dptr = (uint8_t *)&share_mode_lock_key_id,
762 .dsize = sizeof(share_mode_lock_key_id),
764 static size_t share_mode_lock_key_refcount = 0;
766 static bool share_mode_g_lock_within_cb(TDB_DATA key)
768 int cmp;
770 if (current_share_mode_glck == NULL) {
771 return false;
774 cmp = tdb_data_cmp(share_mode_lock_key, key);
775 if (cmp != 0) {
776 struct file_id_buf existing;
778 DBG_ERR("Can not lock two share modes "
779 "simultaneously: existing %s requested %s\n",
780 file_id_str_buf(share_mode_lock_key_id, &existing),
781 hex_encode_talloc(talloc_tos(), key.dptr, key.dsize));
782 smb_panic(__location__);
783 return false;
786 return true;
790 * We can only ever have one share mode locked. Use a static
791 * share_mode_data pointer that is shared by multiple nested
792 * share_mode_lock structures, explicitly refcounted.
794 static struct share_mode_data *static_share_mode_data = NULL;
796 /*******************************************************************
797 Either fetch a share mode from the database, or allocate a fresh
798 one if the record doesn't exist.
799 ********************************************************************/
801 struct get_static_share_mode_data_state {
802 TALLOC_CTX *mem_ctx;
803 struct file_id id;
804 const char *servicepath;
805 const struct smb_filename *smb_fname;
806 const struct timespec *old_write_time;
807 NTSTATUS status;
810 static void get_static_share_mode_data_fn(
811 struct server_id exclusive,
812 size_t num_shared,
813 const struct server_id *shared,
814 const uint8_t *data,
815 size_t datalen,
816 void *private_data)
818 struct get_static_share_mode_data_state *state = private_data;
819 struct share_mode_data *d = NULL;
820 struct locking_tdb_data ltdb = { 0 };
822 if (datalen != 0) {
823 bool ok;
825 ok = locking_tdb_data_get(&ltdb, data, datalen);
826 if (!ok) {
827 DBG_ERR("locking_tdb_data_get failed\n");
828 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
829 return;
833 if (ltdb.share_mode_data_len == 0) {
834 if (state->smb_fname == NULL) {
835 state->status = NT_STATUS_NOT_FOUND;
836 return;
838 d = fresh_share_mode_lock(
839 state->mem_ctx,
840 state->servicepath,
841 state->smb_fname,
842 state->old_write_time);
843 if (d == NULL) {
844 state->status = NT_STATUS_NO_MEMORY;
845 return;
847 } else {
848 d = parse_share_modes(
849 lock_ctx,
850 state->id,
851 ltdb.share_mode_data_buf,
852 ltdb.share_mode_data_len);
853 if (d == NULL) {
854 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
855 return;
859 d->id = state->id;
860 static_share_mode_data = d;
863 static NTSTATUS get_static_share_mode_data(
864 struct file_id id,
865 const char *servicepath,
866 const struct smb_filename *smb_fname,
867 const struct timespec *old_write_time)
869 struct get_static_share_mode_data_state state = {
870 .mem_ctx = lock_ctx,
871 .id = id,
872 .servicepath = servicepath,
873 .smb_fname = smb_fname,
874 .old_write_time = old_write_time,
876 NTSTATUS status;
878 SMB_ASSERT(static_share_mode_data == NULL);
880 status = share_mode_g_lock_dump(
881 share_mode_lock_key,
882 get_static_share_mode_data_fn,
883 &state);
884 if (!NT_STATUS_IS_OK(status)) {
885 DBG_GET_SHARE_MODE_LOCK(status,
886 "share_mode_g_lock_dump failed: %s\n",
887 nt_errstr(status));
888 return status;
890 if (!NT_STATUS_IS_OK(state.status)) {
891 DBG_GET_SHARE_MODE_LOCK(status,
892 "get_static_share_mode_data_fn failed: %s\n",
893 nt_errstr(state.status));
894 return state.status;
897 return NT_STATUS_OK;
900 struct file_id share_mode_lock_file_id(const struct share_mode_lock *lck)
902 return lck->id;
905 NTSTATUS share_mode_lock_access_private_data(struct share_mode_lock *lck,
906 struct share_mode_data **data)
909 * For now we always have lck->cached_data,
910 * but we may change that in future.
912 SMB_ASSERT(lck->cached_data != NULL);
913 *data = lck->cached_data;
914 return NT_STATUS_OK;
917 /*******************************************************************
918 Get a share_mode_lock, Reference counted to allow nested calls.
919 ********************************************************************/
921 static int share_mode_lock_destructor(struct share_mode_lock *lck);
923 static bool share_mode_lock_skip_g_lock;
925 static NTSTATUS get_share_mode_lock_internal(
926 struct file_id id,
927 const char *servicepath,
928 const struct smb_filename *smb_fname,
929 const struct timespec *old_write_time,
930 struct share_mode_lock *lck)
932 NTSTATUS status;
934 *lck = (struct share_mode_lock) {
935 .id = id,
938 if (share_mode_lock_key_refcount == 0) {
939 if (!share_mode_lock_skip_g_lock) {
940 TDB_DATA key = locking_key(&id);
942 status = g_lock_lock(
943 lock_ctx,
944 key,
945 G_LOCK_WRITE,
946 (struct timeval) { .tv_sec = 3600 },
947 NULL, NULL);
948 if (!NT_STATUS_IS_OK(status)) {
949 DBG_DEBUG("g_lock_lock failed: %s\n",
950 nt_errstr(status));
951 return status;
954 share_mode_lock_key_id = id;
957 if (!file_id_equal(&share_mode_lock_key_id, &id)) {
958 struct file_id_buf existing;
959 struct file_id_buf requested;
961 DBG_ERR("Can not lock two share modes "
962 "simultaneously: existing %s requested %s\n",
963 file_id_str_buf(share_mode_lock_key_id, &existing),
964 file_id_str_buf(id, &requested));
965 smb_panic(__location__);
966 goto fail;
969 SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
970 share_mode_lock_key_refcount += 1;
972 if (static_share_mode_data != NULL) {
973 goto done;
976 status = get_static_share_mode_data(
978 servicepath,
979 smb_fname,
980 old_write_time);
981 if (!NT_STATUS_IS_OK(status)) {
982 DBG_DEBUG("get_static_share_mode_data failed: %s\n",
983 nt_errstr(status));
984 share_mode_lock_key_refcount -= 1;
985 goto fail;
987 done:
988 lck->cached_data = static_share_mode_data;
990 if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
991 struct file_id_buf returned;
993 DBG_DEBUG("Returning %s (data_cached=%u key_refcount=%zu)\n",
994 file_id_str_buf(id, &returned),
995 static_share_mode_data != NULL,
996 share_mode_lock_key_refcount);
999 return NT_STATUS_OK;
1000 fail:
1001 if (share_mode_lock_key_refcount == 0) {
1002 if (!share_mode_lock_skip_g_lock) {
1003 NTSTATUS ulstatus = g_lock_unlock(lock_ctx, share_mode_lock_key);
1004 if (!NT_STATUS_IS_OK(ulstatus)) {
1005 DBG_ERR("g_lock_unlock failed: %s\n",
1006 nt_errstr(ulstatus));
1010 return status;
1013 static NTSTATUS put_share_mode_lock_internal(struct share_mode_lock *lck)
1015 NTSTATUS status;
1017 SMB_ASSERT(share_mode_lock_key_refcount > 0);
1018 share_mode_lock_key_refcount -= 1;
1020 if (share_mode_lock_key_refcount > 0) {
1021 return NT_STATUS_OK;
1024 status = share_mode_data_store(static_share_mode_data);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 DBG_ERR("share_mode_data_store failed: %s\n",
1027 nt_errstr(status));
1028 return status;
1031 if (!share_mode_lock_skip_g_lock) {
1032 status = g_lock_unlock(lock_ctx, share_mode_lock_key);
1033 if (!NT_STATUS_IS_OK(status)) {
1034 DBG_ERR("g_lock_unlock failed: %s\n",
1035 nt_errstr(status));
1036 return status;
1040 if (!static_share_mode_data->not_stored) {
1042 * This is worth keeping. Without share modes,
1043 * share_mode_data_store above has left nothing in the
1044 * database.
1046 share_mode_memcache_store(static_share_mode_data);
1047 static_share_mode_data = NULL;
1050 TALLOC_FREE(static_share_mode_data);
1051 return NT_STATUS_OK;
1054 static int share_mode_lock_destructor(struct share_mode_lock *lck)
1056 NTSTATUS status;
1058 status = put_share_mode_lock_internal(lck);
1059 if (!NT_STATUS_IS_OK(status)) {
1060 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
1061 nt_errstr(status));
1062 smb_panic("put_share_mode_lock_internal failed\n");
1065 return 0;
1068 /*******************************************************************
1069 Fetch a share mode where we know one MUST exist. This call reference
1070 counts it internally to allow for nested lock fetches.
1071 ********************************************************************/
1073 struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
1074 const struct file_id id)
1076 struct share_mode_lock *lck = NULL;
1077 NTSTATUS status;
1079 lck = talloc(mem_ctx, struct share_mode_lock);
1080 if (lck == NULL) {
1081 return NULL;
1084 status = get_share_mode_lock_internal(id,
1085 NULL, /* servicepath */
1086 NULL, /* smb_fname */
1087 NULL, /* old_write_time */
1088 lck);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 DBG_GET_SHARE_MODE_LOCK(status,
1091 "get_share_mode_lock_internal() failed - %s\n",
1092 nt_errstr(status));
1093 TALLOC_FREE(lck);
1094 return NULL;
1097 talloc_set_destructor(lck, share_mode_lock_destructor);
1098 return lck;
1101 static void share_mode_wakeup_waiters_fn(
1102 struct share_mode_lock *lck,
1103 void *private_data)
1105 if (share_mode_g_lock_within_cb(share_mode_lock_key)) {
1106 g_lock_lock_cb_wake_watchers(current_share_mode_glck);
1107 return;
1110 g_lock_wake_watchers(lock_ctx, share_mode_lock_key);
1113 NTSTATUS share_mode_wakeup_waiters(struct file_id id)
1115 return share_mode_do_locked_vfs_denied(id,
1116 share_mode_wakeup_waiters_fn,
1117 NULL);
1120 struct fsp_update_share_mode_flags_state {
1121 struct files_struct *fsp;
1122 enum ndr_err_code ndr_err;
1123 uint64_t share_mode_epoch;
1124 uint16_t share_mode_flags;
1127 static void fsp_update_share_mode_flags_fn(
1128 struct server_id exclusive,
1129 size_t num_shared,
1130 const struct server_id *shared,
1131 const uint8_t *data,
1132 size_t datalen,
1133 void *private_data)
1135 struct fsp_update_share_mode_flags_state *state = private_data;
1136 struct locking_tdb_data ltdb = { 0 };
1138 if (datalen != 0) {
1139 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1140 if (!ok) {
1141 DBG_DEBUG("locking_tdb_data_get failed\n");
1142 return;
1146 if (ltdb.share_mode_data_len == 0) {
1147 /* Likely a ctdb tombstone record, ignore it */
1148 return;
1151 if (exclusive.pid != 0) {
1152 struct server_id self =
1153 messaging_server_id(state->fsp->conn->sconn->msg_ctx);
1154 bool is_self = server_id_equal(&self, &exclusive);
1156 if (!is_self) {
1158 * If someone else is holding an exclusive
1159 * lock, pretend there's a read lease
1161 state->share_mode_flags = SHARE_MODE_LEASE_READ;
1162 return;
1166 state->ndr_err = get_share_mode_blob_header(ltdb.share_mode_data_buf,
1167 ltdb.share_mode_data_len,
1168 &state->share_mode_epoch,
1169 &state->share_mode_flags);
1172 static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
1174 struct fsp_update_share_mode_flags_state state = { .fsp = fsp, };
1175 int seqnum = g_lock_seqnum(lock_ctx);
1176 TDB_DATA key = {0};
1177 NTSTATUS status;
1179 if (seqnum == fsp->share_mode_flags_seqnum) {
1180 return NT_STATUS_OK;
1183 key = locking_key(&fsp->file_id);
1184 status = share_mode_g_lock_dump(key,
1185 fsp_update_share_mode_flags_fn,
1186 &state);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 /* no DBG_GET_SHARE_MODE_LOCK here! */
1189 DBG_ERR("share_mode_g_lock_dump returned %s\n",
1190 nt_errstr(status));
1191 return status;
1194 if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
1195 DBG_ERR("get_share_mode_blob_header returned %s\n",
1196 ndr_errstr(state.ndr_err));
1197 return ndr_map_error2ntstatus(state.ndr_err);
1200 fsp->share_mode_flags_seqnum = seqnum;
1201 fsp->share_mode_flags = state.share_mode_flags;
1203 return NT_STATUS_OK;
1206 bool file_has_read_lease(struct files_struct *fsp)
1208 NTSTATUS status;
1210 status = fsp_update_share_mode_flags(fsp);
1211 if (!NT_STATUS_IS_OK(status)) {
1212 /* Safe default for leases */
1213 return true;
1216 return (fsp->share_mode_flags & SHARE_MODE_LEASE_READ) != 0;
1219 #define share_mode_lock_assert_private_data(__lck) \
1220 _share_mode_lock_assert_private_data(__lck, __func__, __location__)
1221 static struct share_mode_data *_share_mode_lock_assert_private_data(
1222 struct share_mode_lock *lck,
1223 const char *caller_function,
1224 const char *caller_location)
1226 struct share_mode_data *d = NULL;
1227 NTSTATUS status;
1229 status = share_mode_lock_access_private_data(lck, &d);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 struct file_id id = share_mode_lock_file_id(lck);
1232 struct file_id_buf id_buf;
1233 /* Any error recovery possible here ? */
1234 D_ERR("%s:%s(): share_mode_lock_access_private_data() "
1235 "failed for id=%s - %s\n",
1236 caller_location, caller_function,
1237 file_id_str_buf(id, &id_buf),
1238 nt_errstr(status));
1239 smb_panic(caller_location);
1240 return NULL;
1243 return d;
1246 NTTIME share_mode_changed_write_time(struct share_mode_lock *lck)
1248 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1249 return d->changed_write_time;
1252 void share_mode_set_changed_write_time(struct share_mode_lock *lck, struct timespec write_time)
1254 struct file_id fileid = share_mode_lock_file_id(lck);
1255 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1256 struct file_id_buf ftmp;
1257 struct timeval_buf tbuf;
1258 NTTIME nt = full_timespec_to_nt_time(&write_time);
1260 DBG_INFO("%s id=%s\n",
1261 timespec_string_buf(&write_time, true, &tbuf),
1262 file_id_str_buf(fileid, &ftmp));
1264 if (d->changed_write_time != nt) {
1265 d->modified = true;
1266 d->changed_write_time = nt;
1270 void share_mode_set_old_write_time(struct share_mode_lock *lck, struct timespec write_time)
1272 struct file_id fileid = share_mode_lock_file_id(lck);
1273 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1274 struct file_id_buf ftmp;
1275 struct timeval_buf tbuf;
1276 NTTIME nt = full_timespec_to_nt_time(&write_time);
1278 DBG_INFO("%s id=%s\n",
1279 timespec_string_buf(&write_time, true, &tbuf),
1280 file_id_str_buf(fileid, &ftmp));
1282 if (d->changed_write_time != nt) {
1283 d->modified = true;
1284 d->old_write_time = nt;
1288 const char *share_mode_servicepath(struct share_mode_lock *lck)
1290 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1291 return d->servicepath;
1294 char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1296 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1297 bool has_stream = (d->stream_name != NULL);
1298 char *fname = NULL;
1300 fname = talloc_asprintf(
1301 mem_ctx,
1302 "%s%s%s",
1303 d->base_name,
1304 has_stream ? ":" : "",
1305 has_stream ? d->stream_name : "");
1306 return fname;
1309 char *share_mode_data_dump(
1310 TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1312 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1313 struct ndr_print *p = talloc(mem_ctx, struct ndr_print);
1314 char *ret = NULL;
1316 if (p == NULL) {
1317 return NULL;
1320 *p = (struct ndr_print) {
1321 .print = ndr_print_string_helper,
1322 .depth = 1,
1323 .private_data = talloc_strdup(mem_ctx, ""),
1326 if (p->private_data == NULL) {
1327 TALLOC_FREE(p);
1328 return NULL;
1331 ndr_print_share_mode_data(p, "SHARE_MODE_DATA", d);
1333 ret = p->private_data;
1335 TALLOC_FREE(p);
1337 return ret;
1340 void share_mode_flags_get(
1341 struct share_mode_lock *lck,
1342 uint32_t *access_mask,
1343 uint32_t *share_mode,
1344 uint32_t *lease_type)
1346 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1347 uint16_t flags = d->flags;
1349 if (access_mask != NULL) {
1350 *access_mask =
1351 ((flags & SHARE_MODE_ACCESS_READ) ?
1352 FILE_READ_DATA : 0) |
1353 ((flags & SHARE_MODE_ACCESS_WRITE) ?
1354 FILE_WRITE_DATA : 0) |
1355 ((flags & SHARE_MODE_ACCESS_DELETE) ?
1356 DELETE_ACCESS : 0);
1358 if (share_mode != NULL) {
1359 *share_mode =
1360 ((flags & SHARE_MODE_SHARE_READ) ?
1361 FILE_SHARE_READ : 0) |
1362 ((flags & SHARE_MODE_SHARE_WRITE) ?
1363 FILE_SHARE_WRITE : 0) |
1364 ((flags & SHARE_MODE_SHARE_DELETE) ?
1365 FILE_SHARE_DELETE : 0);
1367 if (lease_type != NULL) {
1368 *lease_type =
1369 ((flags & SHARE_MODE_LEASE_READ) ?
1370 SMB2_LEASE_READ : 0) |
1371 ((flags & SHARE_MODE_LEASE_WRITE) ?
1372 SMB2_LEASE_WRITE : 0) |
1373 ((flags & SHARE_MODE_LEASE_HANDLE) ?
1374 SMB2_LEASE_HANDLE : 0);
1378 void share_mode_flags_set(
1379 struct share_mode_lock *lck,
1380 uint32_t access_mask,
1381 uint32_t share_mode,
1382 uint32_t lease_type,
1383 bool *modified)
1385 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1386 uint16_t flags = 0;
1388 flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
1389 SHARE_MODE_ACCESS_READ : 0;
1390 flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
1391 SHARE_MODE_ACCESS_WRITE : 0;
1392 flags |= (access_mask & (DELETE_ACCESS)) ?
1393 SHARE_MODE_ACCESS_DELETE : 0;
1395 flags |= (share_mode & FILE_SHARE_READ) ?
1396 SHARE_MODE_SHARE_READ : 0;
1397 flags |= (share_mode & FILE_SHARE_WRITE) ?
1398 SHARE_MODE_SHARE_WRITE : 0;
1399 flags |= (share_mode & FILE_SHARE_DELETE) ?
1400 SHARE_MODE_SHARE_DELETE : 0;
1402 flags |= (lease_type & SMB2_LEASE_READ) ?
1403 SHARE_MODE_LEASE_READ : 0;
1404 flags |= (lease_type & SMB2_LEASE_WRITE) ?
1405 SHARE_MODE_LEASE_WRITE : 0;
1406 flags |= (lease_type & SMB2_LEASE_HANDLE) ?
1407 SHARE_MODE_LEASE_HANDLE : 0;
1409 if (d->flags == flags) {
1410 return;
1413 if (modified != NULL) {
1414 *modified = true;
1416 d->flags = flags;
1417 d->modified = true;
1420 struct share_mode_watch_state {
1421 bool blockerdead;
1422 struct server_id blocker;
1423 bool within_cb;
1426 static void share_mode_watch_done(struct tevent_req *subreq);
1428 struct tevent_req *share_mode_watch_send(
1429 TALLOC_CTX *mem_ctx,
1430 struct tevent_context *ev,
1431 struct share_mode_lock *lck,
1432 struct server_id blocker)
1434 struct file_id id = share_mode_lock_file_id(lck);
1435 TDB_DATA key = locking_key(&id);
1436 struct tevent_req *req = NULL, *subreq = NULL;
1437 struct share_mode_watch_state *state = NULL;
1439 req = tevent_req_create(
1440 mem_ctx, &state, struct share_mode_watch_state);
1441 if (req == NULL) {
1442 return NULL;
1445 if (share_mode_g_lock_within_cb(key)) {
1446 state->within_cb = true;
1447 subreq = g_lock_lock_cb_watch_data_send(state, ev,
1448 current_share_mode_glck,
1449 blocker);
1450 if (tevent_req_nomem(subreq, req)) {
1451 return tevent_req_post(req, ev);
1453 } else {
1454 subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker);
1455 if (tevent_req_nomem(subreq, req)) {
1456 return tevent_req_post(req, ev);
1459 tevent_req_set_callback(subreq, share_mode_watch_done, req);
1460 return req;
1463 static void share_mode_watch_done(struct tevent_req *subreq)
1465 struct tevent_req *req = tevent_req_callback_data(
1466 subreq, struct tevent_req);
1467 struct share_mode_watch_state *state = tevent_req_data(
1468 req, struct share_mode_watch_state);
1469 NTSTATUS status;
1471 if (state->within_cb) {
1472 status = g_lock_lock_cb_watch_data_recv(
1473 subreq, &state->blockerdead, &state->blocker);
1474 if (tevent_req_nterror(req, status)) {
1475 return;
1477 } else {
1478 status = g_lock_watch_data_recv(
1479 subreq, &state->blockerdead, &state->blocker);
1480 if (tevent_req_nterror(req, status)) {
1481 return;
1485 tevent_req_done(req);
1488 NTSTATUS share_mode_watch_recv(
1489 struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
1491 struct share_mode_watch_state *state = tevent_req_data(
1492 req, struct share_mode_watch_state);
1493 NTSTATUS status;
1495 if (tevent_req_is_nterror(req, &status)) {
1496 return status;
1498 if (blockerdead != NULL) {
1499 *blockerdead = state->blockerdead;
1501 if (blocker != NULL) {
1502 *blocker = state->blocker;
1504 return NT_STATUS_OK;
1507 struct fetch_share_mode_unlocked_state {
1508 TALLOC_CTX *mem_ctx;
1509 struct file_id id;
1510 struct share_mode_lock *lck;
1513 static void fetch_share_mode_unlocked_parser(
1514 struct server_id exclusive,
1515 size_t num_shared,
1516 const struct server_id *shared,
1517 const uint8_t *data,
1518 size_t datalen,
1519 void *private_data)
1521 struct fetch_share_mode_unlocked_state *state = private_data;
1522 struct locking_tdb_data ltdb = { 0 };
1524 if (datalen != 0) {
1525 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1526 if (!ok) {
1527 DBG_DEBUG("locking_tdb_data_get failed\n");
1528 return;
1532 if (ltdb.share_mode_data_len == 0) {
1533 /* Likely a ctdb tombstone record, ignore it */
1534 return;
1537 state->lck = talloc(state->mem_ctx, struct share_mode_lock);
1538 if (state->lck == NULL) {
1539 DEBUG(0, ("talloc failed\n"));
1540 return;
1542 state->lck->id = state->id;
1544 state->lck->cached_data = parse_share_modes(
1545 state->lck,
1546 state->id,
1547 ltdb.share_mode_data_buf,
1548 ltdb.share_mode_data_len);
1549 if (state->lck->cached_data == NULL) {
1550 DBG_DEBUG("parse_share_modes failed\n");
1551 TALLOC_FREE(state->lck);
1555 /*******************************************************************
1556 Get a share_mode_lock without locking the database or reference
1557 counting. Used by smbstatus to display existing share modes.
1558 ********************************************************************/
1560 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
1561 struct file_id id)
1563 struct fetch_share_mode_unlocked_state state = {
1564 .mem_ctx = mem_ctx,
1565 .id = id,
1567 TDB_DATA key = locking_key(&id);
1568 NTSTATUS status;
1570 status = g_lock_dump(
1571 lock_ctx, key, fetch_share_mode_unlocked_parser, &state);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
1574 return NULL;
1576 return state.lck;
1579 struct fetch_share_mode_state {
1580 struct file_id id;
1581 struct share_mode_lock *lck;
1582 NTSTATUS status;
1585 static void fetch_share_mode_fn(
1586 struct server_id exclusive,
1587 size_t num_shared,
1588 const struct server_id *shared,
1589 const uint8_t *data,
1590 size_t datalen,
1591 void *private_data);
1592 static void fetch_share_mode_done(struct tevent_req *subreq);
1595 * @brief Get a share_mode_lock without locking or refcounting
1597 * This can be used in a clustered Samba environment where the async dbwrap
1598 * request is sent over a socket to the local ctdbd. If the send queue is full
1599 * and the caller was issuing multiple async dbwrap requests in a loop, the
1600 * caller knows it's probably time to stop sending requests for now and try
1601 * again later.
1603 * @param[in] mem_ctx The talloc memory context to use.
1605 * @param[in] ev The event context to work on.
1607 * @param[in] id The file id for the locking.tdb key
1609 * @param[out] queued This boolean out parameter tells the caller whether the
1610 * async request is blocked in a full send queue:
1612 * false := request is dispatched
1614 * true := send queue is full, request waiting to be
1615 * dispatched
1617 * @return The new async request, NULL on error.
1619 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
1620 struct tevent_context *ev,
1621 struct file_id id,
1622 bool *queued)
1624 struct tevent_req *req = NULL, *subreq = NULL;
1625 struct fetch_share_mode_state *state = NULL;
1627 *queued = false;
1629 req = tevent_req_create(mem_ctx, &state,
1630 struct fetch_share_mode_state);
1631 if (req == NULL) {
1632 return NULL;
1634 state->id = id;
1636 subreq = g_lock_dump_send(
1637 state,
1639 lock_ctx,
1640 locking_key(&id),
1641 fetch_share_mode_fn,
1642 state);
1643 if (tevent_req_nomem(subreq, req)) {
1644 return tevent_req_post(req, ev);
1646 tevent_req_set_callback(subreq, fetch_share_mode_done, req);
1647 return req;
1650 static void fetch_share_mode_fn(
1651 struct server_id exclusive,
1652 size_t num_shared,
1653 const struct server_id *shared,
1654 const uint8_t *data,
1655 size_t datalen,
1656 void *private_data)
1658 struct fetch_share_mode_state *state = talloc_get_type_abort(
1659 private_data, struct fetch_share_mode_state);
1660 struct locking_tdb_data ltdb = { 0 };
1662 if (datalen != 0) {
1663 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
1664 if (!ok) {
1665 DBG_DEBUG("locking_tdb_data_get failed\n");
1666 return;
1670 if (ltdb.share_mode_data_len == 0) {
1671 /* Likely a ctdb tombstone record, ignore it */
1672 return;
1675 state->lck = talloc(state, struct share_mode_lock);
1676 if (state->lck == NULL) {
1677 DBG_WARNING("talloc failed\n");
1678 state->status = NT_STATUS_NO_MEMORY;
1679 return;
1681 state->lck->id = state->id,
1683 state->lck->cached_data = parse_share_modes(
1684 state->lck,
1685 state->id,
1686 ltdb.share_mode_data_buf,
1687 ltdb.share_mode_data_len);
1688 if (state->lck->cached_data == NULL) {
1689 DBG_DEBUG("parse_share_modes failed\n");
1690 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1691 TALLOC_FREE(state->lck);
1692 return;
1696 static void fetch_share_mode_done(struct tevent_req *subreq)
1698 struct tevent_req *req = tevent_req_callback_data(
1699 subreq, struct tevent_req);
1700 struct fetch_share_mode_state *state = tevent_req_data(
1701 req, struct fetch_share_mode_state);
1702 NTSTATUS status;
1704 status = g_lock_dump_recv(subreq);
1705 TALLOC_FREE(subreq);
1706 if (tevent_req_nterror(req, status)) {
1707 return;
1709 if (tevent_req_nterror(req, state->status)) {
1710 return;
1712 tevent_req_done(req);
1715 NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
1716 TALLOC_CTX *mem_ctx,
1717 struct share_mode_lock **_lck)
1719 struct fetch_share_mode_state *state = tevent_req_data(
1720 req, struct fetch_share_mode_state);
1721 struct share_mode_lock *lck = NULL;
1723 NTSTATUS status;
1725 if (tevent_req_is_nterror(req, &status)) {
1726 tevent_req_received(req);
1727 return status;
1730 if (state->lck == NULL) {
1731 tevent_req_received(req);
1732 return NT_STATUS_NOT_FOUND;
1735 lck = talloc_move(mem_ctx, &state->lck);
1737 if (DEBUGLEVEL >= 10) {
1738 DBG_DEBUG("share_mode_data:\n");
1739 NDR_PRINT_DEBUG(share_mode_data, lck->cached_data);
1742 *_lck = lck;
1743 tevent_req_received(req);
1744 return NT_STATUS_OK;
1747 struct share_mode_forall_state {
1748 TDB_DATA key;
1749 int (*fn)(struct file_id fid,
1750 const struct share_mode_data *data,
1751 void *private_data);
1752 void *private_data;
1755 static void share_mode_forall_dump_fn(
1756 struct server_id exclusive,
1757 size_t num_shared,
1758 const struct server_id *shared,
1759 const uint8_t *data,
1760 size_t datalen,
1761 void *private_data)
1763 struct share_mode_forall_state *state = private_data;
1764 struct file_id fid;
1765 struct locking_tdb_data ltdb = { 0 };
1766 bool ok;
1767 struct share_mode_data *d;
1769 if (state->key.dsize != sizeof(fid)) {
1770 DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize);
1771 return;
1773 memcpy(&fid, state->key.dptr, sizeof(fid));
1775 ok = locking_tdb_data_get(&ltdb, data, datalen);
1776 if (!ok) {
1777 DBG_DEBUG("locking_tdb_data_get() failed\n");
1778 return;
1781 d = parse_share_modes(
1782 talloc_tos(),
1783 fid,
1784 ltdb.share_mode_data_buf,
1785 ltdb.share_mode_data_len);
1786 if (d == NULL) {
1787 DBG_DEBUG("parse_share_modes() failed\n");
1788 return;
1791 state->fn(fid, d, state->private_data);
1792 TALLOC_FREE(d);
1795 static int share_mode_forall_fn(TDB_DATA key, void *private_data)
1797 struct share_mode_forall_state *state = private_data;
1798 NTSTATUS status;
1800 state->key = key;
1802 status = share_mode_g_lock_dump(
1803 key, share_mode_forall_dump_fn, private_data);
1804 if (!NT_STATUS_IS_OK(status)) {
1805 DBG_GET_SHARE_MODE_LOCK(status,
1806 "g_lock_dump failed: %s\n",
1807 nt_errstr(status));
1809 return 0;
1812 int share_mode_forall(int (*fn)(struct file_id fid,
1813 const struct share_mode_data *data,
1814 void *private_data),
1815 void *private_data)
1817 struct share_mode_forall_state state = {
1818 .fn = fn,
1819 .private_data = private_data
1821 int ret;
1823 if (lock_ctx == NULL) {
1824 return 0;
1827 ret = g_lock_locks(
1828 lock_ctx, share_mode_forall_fn, &state);
1829 if (ret < 0) {
1830 DBG_ERR("g_lock_locks failed\n");
1832 return ret;
1835 struct share_entry_forall_state {
1836 struct file_id fid;
1837 const struct share_mode_data *data;
1838 int (*fn)(struct file_id fid,
1839 const struct share_mode_data *data,
1840 const struct share_mode_entry *entry,
1841 void *private_data);
1842 void *private_data;
1843 int ret;
1846 static bool share_entry_traverse_walker(
1847 struct share_mode_entry *e,
1848 bool *modified,
1849 void *private_data)
1851 struct share_entry_forall_state *state = private_data;
1853 state->ret = state->fn(
1854 state->fid, state->data, e, state->private_data);
1855 return (state->ret != 0);
1858 static int share_entry_traverse_fn(struct file_id fid,
1859 const struct share_mode_data *data,
1860 void *private_data)
1862 struct share_entry_forall_state *state = private_data;
1863 struct share_mode_lock lck = {
1864 .id = fid,
1865 .cached_data = discard_const_p(struct share_mode_data, data)
1867 bool ok;
1869 state->fid = fid;
1870 state->data = data;
1872 ok = share_mode_forall_entries(
1873 &lck, share_entry_traverse_walker, state);
1874 if (!ok) {
1875 DBG_ERR("share_mode_forall_entries failed\n");
1876 return false;
1879 return state->ret;
1882 /*******************************************************************
1883 Call the specified function on each entry under management by the
1884 share mode system.
1885 ********************************************************************/
1887 int share_entry_forall(int (*fn)(struct file_id fid,
1888 const struct share_mode_data *data,
1889 const struct share_mode_entry *entry,
1890 void *private_data),
1891 void *private_data)
1893 struct share_entry_forall_state state = {
1894 .fn = fn, .private_data = private_data };
1896 return share_mode_forall(share_entry_traverse_fn, &state);
1899 static int share_mode_entry_cmp(
1900 struct server_id pid1,
1901 uint64_t share_file_id1,
1902 struct server_id pid2,
1903 uint64_t share_file_id2)
1905 int cmp;
1907 cmp = server_id_cmp(&pid1, &pid2);
1908 if (cmp != 0) {
1909 return cmp;
1911 if (share_file_id1 != share_file_id2) {
1912 return (share_file_id1 < share_file_id2) ? -1 : 1;
1914 return 0;
1917 static size_t share_mode_entry_find(
1918 const uint8_t *data,
1919 size_t num_share_modes,
1920 struct server_id pid,
1921 uint64_t share_file_id,
1922 struct share_mode_entry *e,
1923 bool *match)
1925 ssize_t left, right, middle;
1927 *match = false;
1929 if (num_share_modes == 0) {
1930 return 0;
1933 left = 0;
1934 right = (num_share_modes-1);
1936 while (left <= right) {
1937 const uint8_t *middle_ptr = NULL;
1938 int cmp;
1939 bool ok;
1941 middle = left + ((right - left) / 2);
1942 middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
1944 DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
1945 left,
1946 right,
1947 middle,
1948 middle_ptr);
1950 ok = share_mode_entry_get(middle_ptr, e);
1951 if (!ok) {
1952 DBG_DEBUG("share_mode_entry_get failed\n");
1953 return 0;
1956 cmp = share_mode_entry_cmp(
1957 e->pid, e->share_file_id, pid, share_file_id);
1958 if (cmp == 0) {
1959 *match = true;
1960 return middle;
1963 if (cmp < 0) {
1964 right = middle-1;
1965 } else {
1966 left = middle+1;
1970 return left;
1973 bool set_share_mode(struct share_mode_lock *lck,
1974 struct files_struct *fsp,
1975 uid_t uid,
1976 uint64_t mid,
1977 uint16_t op_type,
1978 const struct smb2_lease_key *lease_key,
1979 uint32_t share_access,
1980 uint32_t access_mask)
1982 struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1983 TDB_DATA key = locking_key(&d->id);
1984 struct server_id my_pid = messaging_server_id(
1985 fsp->conn->sconn->msg_ctx);
1986 struct locking_tdb_data *ltdb = NULL;
1987 size_t idx;
1988 struct share_mode_entry e = { .pid.pid = 0 };
1989 struct share_mode_entry_buf e_buf;
1990 NTSTATUS status;
1991 bool ok, found;
1993 TDB_DATA dbufs[3];
1994 size_t num_dbufs = 0;
1996 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 DBG_ERR("locking_tdb_data_fetch failed: %s\n",
1999 nt_errstr(status));
2000 return false;
2002 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2004 idx = share_mode_entry_find(
2005 ltdb->share_entries,
2006 ltdb->num_share_entries,
2007 my_pid,
2008 fh_get_gen_id(fsp->fh),
2010 &found);
2011 if (found) {
2012 DBG_WARNING("Found duplicate share mode\n");
2013 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2014 goto done;
2017 e = (struct share_mode_entry) {
2018 .pid = my_pid,
2019 .share_access = share_access,
2020 .private_options = fh_get_private_options(fsp->fh),
2021 .access_mask = access_mask,
2022 .op_mid = mid,
2023 .op_type = op_type,
2024 .time.tv_sec = fsp->open_time.tv_sec,
2025 .time.tv_usec = fsp->open_time.tv_usec,
2026 .share_file_id = fh_get_gen_id(fsp->fh),
2027 .uid = (uint32_t)uid,
2028 .flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
2029 SHARE_MODE_FLAG_POSIX_OPEN : 0,
2030 .name_hash = fsp->name_hash,
2033 if (op_type == LEASE_OPLOCK) {
2034 const struct GUID *client_guid = fsp_client_guid(fsp);
2035 e.client_guid = *client_guid;
2036 e.lease_key = *lease_key;
2039 ok = share_mode_entry_put(&e, &e_buf);
2040 if (!ok) {
2041 DBG_DEBUG("share_mode_entry_put failed\n");
2042 status = NT_STATUS_INTERNAL_ERROR;
2043 goto done;
2046 DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
2048 if (idx > 0) {
2049 dbufs[num_dbufs] = (TDB_DATA) {
2050 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
2051 .dsize = idx * SHARE_MODE_ENTRY_SIZE,
2053 num_dbufs += 1;
2056 dbufs[num_dbufs] = (TDB_DATA) {
2057 .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
2059 num_dbufs += 1;
2061 if (idx < ltdb->num_share_entries) {
2062 size_t num_after_idx = (ltdb->num_share_entries-idx);
2063 dbufs[num_dbufs] = (TDB_DATA) {
2064 .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
2065 idx * SHARE_MODE_ENTRY_SIZE,
2066 .dsize = num_after_idx * SHARE_MODE_ENTRY_SIZE,
2068 num_dbufs += 1;
2072 size_t i;
2073 for (i=0; i<num_dbufs; i++) {
2074 DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
2076 dbufs[i].dptr,
2077 dbufs[i].dsize);
2081 if (num_dbufs == 1) {
2083 * Storing a fresh record with just one share entry
2085 d->modified = true;
2089 * If there was any existing data in
2090 * ltdb->share_entries, it's now been
2091 * moved and we've split it into:
2093 * num_dbufs = 3
2094 * dbufs[0] -> old sorted data less than new_entry
2095 * dbufs[1] -> new_share_mode_entry
2096 * dbufs[2] -> old sorted_data greater than new entry.
2098 * So the old data inside ltdb->share_entries is
2099 * no longer valid.
2101 * If we're storing a brand new entry the
2102 * dbufs look like:
2104 * num_dbufs = 1
2105 * dbufs[0] -> new_share_mode_entry
2107 * Either way we must set ltdb->share_entries = NULL
2108 * and ltdb->num_share_entries = 0 so that
2109 * locking_tdb_data_store() doesn't use it to
2110 * store any data. It's no longer there.
2113 ltdb->share_entries = NULL;
2114 ltdb->num_share_entries = 0;
2116 status = share_mode_data_ltdb_store(d, key, ltdb, dbufs, num_dbufs);
2117 if (!NT_STATUS_IS_OK(status)) {
2118 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2119 nt_errstr(status));
2121 done:
2122 TALLOC_FREE(ltdb);
2123 return NT_STATUS_IS_OK(status);
2126 static bool share_mode_for_one_entry(
2127 bool (*fn)(struct share_mode_entry *e,
2128 bool *modified,
2129 void *private_data),
2130 void *private_data,
2131 size_t *i,
2132 uint8_t *data,
2133 size_t *num_share_modes,
2134 bool *writeback)
2136 DATA_BLOB blob = {
2137 .data = data + (*i) * SHARE_MODE_ENTRY_SIZE,
2138 .length = SHARE_MODE_ENTRY_SIZE,
2140 struct share_mode_entry e = {.pid.pid=0};
2141 enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
2142 bool modified = false;
2143 bool stop = false;
2144 struct server_id e_pid;
2145 uint64_t e_share_file_id;
2147 ndr_err = ndr_pull_struct_blob_all_noalloc(
2148 &blob,
2150 (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
2151 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2152 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
2153 *i += 1;
2154 return false;
2156 if (DEBUGLEVEL >= 10) {
2157 DBG_DEBUG("entry[%zu]:\n", *i);
2158 NDR_PRINT_DEBUG(share_mode_entry, &e);
2161 e_pid = e.pid;
2162 e_share_file_id = e.share_file_id;
2164 stop = fn(&e, &modified, private_data);
2166 DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2168 (int)modified,
2169 (int)e.stale);
2171 if (e.stale) {
2172 if (DEBUGLEVEL>=10) {
2173 DBG_DEBUG("share_mode_entry:\n");
2174 NDR_PRINT_DEBUG(share_mode_entry, &e);
2177 if (*i < *num_share_modes) {
2178 memmove(blob.data,
2179 blob.data + SHARE_MODE_ENTRY_SIZE,
2180 (*num_share_modes - *i - 1) *
2181 SHARE_MODE_ENTRY_SIZE);
2183 *num_share_modes -= 1;
2184 *writeback = true;
2185 return stop;
2188 if (modified) {
2189 if (DEBUGLEVEL>=10) {
2190 DBG_DEBUG("share_mode_entry:\n");
2191 NDR_PRINT_DEBUG(share_mode_entry, &e);
2195 * Make sure sorting order is kept intact
2197 SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
2198 SMB_ASSERT(e_share_file_id == e.share_file_id);
2200 ndr_err = ndr_push_struct_into_fixed_blob(
2201 &blob,
2203 (ndr_push_flags_fn_t)
2204 ndr_push_share_mode_entry);
2205 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2206 DBG_WARNING("ndr_push_share_mode_entry "
2207 "failed: %s\n",
2208 ndr_errstr(ndr_err));
2210 * Not much we can do, just ignore it
2213 *i += 1;
2214 *writeback = true;
2215 return stop;
2218 if (stop) {
2219 return true;
2222 *i += 1;
2223 return false;
2226 bool share_mode_forall_entries(
2227 struct share_mode_lock *lck,
2228 bool (*fn)(struct share_mode_entry *e,
2229 bool *modified,
2230 void *private_data),
2231 void *private_data)
2233 struct file_id id = share_mode_lock_file_id(lck);
2234 struct share_mode_data *d = NULL;
2235 TDB_DATA key = locking_key(&id);
2236 struct locking_tdb_data *ltdb = NULL;
2237 uint8_t *share_entries = NULL;
2238 size_t num_share_entries;
2239 bool writeback = false;
2240 NTSTATUS status;
2241 bool stop = false;
2242 size_t i;
2244 status = share_mode_lock_access_private_data(lck, &d);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 struct file_id_buf id_buf;
2247 /* Any error recovery possible here ? */
2248 DBG_ERR("share_mode_lock_access_private_data() failed for "
2249 "%s - %s\n",
2250 file_id_str_buf(id, &id_buf),
2251 nt_errstr(status));
2252 return false;
2255 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2256 if (!NT_STATUS_IS_OK(status)) {
2257 DBG_ERR("locking_tdb_data_fetch failed: %s\n",
2258 nt_errstr(status));
2259 return false;
2261 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2263 num_share_entries = ltdb->num_share_entries;
2264 share_entries = discard_const_p(uint8_t, ltdb->share_entries);
2266 i = 0;
2267 while (i<num_share_entries) {
2268 stop = share_mode_for_one_entry(
2270 private_data,
2272 share_entries,
2273 &num_share_entries,
2274 &writeback);
2275 if (stop) {
2276 break;
2280 DBG_DEBUG("num_share_entries=%zu, writeback=%d\n",
2281 num_share_entries,
2282 (int)writeback);
2284 if (!writeback) {
2285 TALLOC_FREE(ltdb);
2286 return true;
2289 if ((ltdb->num_share_entries != 0 ) && (num_share_entries == 0)) {
2291 * This routine wiped all share entries, let
2292 * share_mode_data_store() delete the record
2294 d->modified = true;
2297 ltdb->num_share_entries = num_share_entries;
2298 ltdb->share_entries = share_entries;
2300 status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
2301 TALLOC_FREE(ltdb);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2304 nt_errstr(status));
2305 return false;
2308 return true;
2311 struct share_mode_count_entries_state {
2312 size_t num_share_modes;
2313 NTSTATUS status;
2316 static void share_mode_count_entries_fn(
2317 struct server_id exclusive,
2318 size_t num_shared,
2319 const struct server_id *shared,
2320 const uint8_t *data,
2321 size_t datalen,
2322 void *private_data)
2324 struct share_mode_count_entries_state *state = private_data;
2325 struct locking_tdb_data ltdb = { 0 };
2326 bool ok;
2328 ok = locking_tdb_data_get(&ltdb, data, datalen);
2329 if (!ok) {
2330 DBG_WARNING("locking_tdb_data_get failed for %zu\n", datalen);
2331 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2332 return;
2334 state->num_share_modes = ltdb.num_share_entries;
2335 state->status = NT_STATUS_OK;
2338 NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
2340 struct share_mode_count_entries_state state = {
2341 .status = NT_STATUS_NOT_FOUND,
2343 NTSTATUS status;
2345 status = g_lock_dump(
2346 lock_ctx,
2347 locking_key(&fid),
2348 share_mode_count_entries_fn,
2349 &state);
2350 if (!NT_STATUS_IS_OK(status)) {
2351 DBG_DEBUG("g_lock_dump failed: %s\n",
2352 nt_errstr(status));
2353 return status;
2355 if (!NT_STATUS_IS_OK(state.status)) {
2356 DBG_DEBUG("share_mode_count_entries_fn failed: %s\n",
2357 nt_errstr(state.status));
2358 return state.status;
2361 *num_share_modes = state.num_share_modes;
2362 return NT_STATUS_OK;
2365 static bool share_mode_entry_do(
2366 struct share_mode_data *d,
2367 struct server_id pid,
2368 uint64_t share_file_id,
2369 void (*fn)(struct share_mode_entry *e,
2370 size_t num_share_modes,
2371 bool *modified,
2372 void *private_data),
2373 void *private_data)
2375 TDB_DATA key = locking_key(&d->id);
2376 struct locking_tdb_data *ltdb = NULL;
2377 size_t idx;
2378 bool found = false;
2379 bool modified = false;
2380 struct share_mode_entry e;
2381 uint8_t *e_ptr = NULL;
2382 NTSTATUS status;
2383 bool ret = false;
2385 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2386 if (!NT_STATUS_IS_OK(status)) {
2387 DBG_ERR("locking_tdb_data_fetch failed: %s\n",
2388 nt_errstr(status));
2389 return false;
2391 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2393 idx = share_mode_entry_find(
2394 ltdb->share_entries,
2395 ltdb->num_share_entries,
2396 pid,
2397 share_file_id,
2399 &found);
2400 if (!found) {
2401 DBG_WARNING("Did not find share mode entry for %"PRIu64"\n",
2402 share_file_id);
2403 goto done;
2406 if (DEBUGLEVEL>=10) {
2407 DBG_DEBUG("entry[%zu]:\n", idx);
2408 NDR_PRINT_DEBUG(share_mode_entry, &e);
2411 fn(&e, ltdb->num_share_entries, &modified, private_data);
2413 DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2414 idx,
2415 (int)modified,
2416 (int)e.stale);
2418 if (!e.stale && !modified) {
2419 ret = true;
2420 goto done;
2423 e_ptr = discard_const_p(uint8_t, ltdb->share_entries) +
2424 idx * SHARE_MODE_ENTRY_SIZE;
2426 if (e.stale) {
2428 * Move the rest down one entry
2430 size_t behind = ltdb->num_share_entries - idx - 1;
2431 if (behind != 0) {
2432 memmove(e_ptr,
2433 e_ptr + SHARE_MODE_ENTRY_SIZE,
2434 behind * SHARE_MODE_ENTRY_SIZE);
2436 ltdb->num_share_entries -= 1;
2438 if (ltdb->num_share_entries == 0) {
2440 * Tell share_mode_lock_destructor() to delete
2441 * the whole record
2443 d->modified = true;
2446 if (DEBUGLEVEL>=10) {
2447 DBG_DEBUG("share_mode_entry:\n");
2448 NDR_PRINT_DEBUG(share_mode_entry, &e);
2450 } else {
2451 struct share_mode_entry_buf buf;
2452 bool ok;
2454 if (ltdb->num_share_entries != 1) {
2456 * Make sure the sorting order stays intact
2458 SMB_ASSERT(server_id_equal(&e.pid, &pid));
2459 SMB_ASSERT(e.share_file_id == share_file_id);
2462 ok = share_mode_entry_put(&e, &buf);
2463 if (!ok) {
2464 DBG_DEBUG("share_mode_entry_put failed\n");
2465 goto done;
2467 memcpy(e_ptr, buf.buf, SHARE_MODE_ENTRY_SIZE);
2470 status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
2471 if (!NT_STATUS_IS_OK(status)) {
2472 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2473 nt_errstr(status));
2474 goto done;
2477 ret = true;
2478 done:
2479 TALLOC_FREE(ltdb);
2480 return ret;
2483 struct del_share_mode_state {
2484 bool ok;
2487 static void del_share_mode_fn(
2488 struct share_mode_entry *e,
2489 size_t num_share_modes,
2490 bool *modified,
2491 void *private_data)
2493 struct del_share_mode_state *state = private_data;
2494 e->stale = true;
2495 state->ok = true;
2498 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
2500 struct del_share_mode_state state = { .ok = false };
2501 struct share_mode_data *d = NULL;
2502 NTSTATUS status;
2503 bool ok;
2505 status = share_mode_lock_access_private_data(lck, &d);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 struct file_id id = share_mode_lock_file_id(lck);
2508 struct file_id_buf id_buf;
2509 /* Any error recovery possible here ? */
2510 DBG_ERR("share_mode_lock_access_private_data() failed for "
2511 "%s %s - %s\n",
2512 file_id_str_buf(id, &id_buf),
2513 fsp_str_dbg(fsp),
2514 nt_errstr(status));
2515 return false;
2518 ok = share_mode_entry_do(
2520 messaging_server_id(fsp->conn->sconn->msg_ctx),
2521 fh_get_gen_id(fsp->fh),
2522 del_share_mode_fn,
2523 &state);
2524 if (!ok) {
2525 DBG_DEBUG("share_mode_entry_do failed\n");
2526 return false;
2528 if (!state.ok) {
2529 DBG_DEBUG("del_share_mode_fn failed\n");
2530 return false;
2532 return true;
2535 struct remove_share_oplock_state {
2536 bool ok;
2539 static void remove_share_oplock_fn(
2540 struct share_mode_entry *e,
2541 size_t num_share_modes,
2542 bool *modified,
2543 void *private_data)
2545 struct remove_share_oplock_state *state = private_data;
2547 e->op_type = NO_OPLOCK;
2548 *modified = true;
2549 state->ok = true;
2552 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2554 struct remove_share_oplock_state state = { .ok = false };
2555 struct share_mode_data *d = NULL;
2556 NTSTATUS status;
2557 bool ok;
2559 status = share_mode_lock_access_private_data(lck, &d);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 struct file_id id = share_mode_lock_file_id(lck);
2562 struct file_id_buf id_buf;
2563 /* Any error recovery possible here ? */
2564 DBG_ERR("share_mode_lock_access_private_data() failed for "
2565 "%s %s - %s\n",
2566 file_id_str_buf(id, &id_buf),
2567 fsp_str_dbg(fsp),
2568 nt_errstr(status));
2569 return false;
2572 ok = share_mode_entry_do(
2574 messaging_server_id(fsp->conn->sconn->msg_ctx),
2575 fh_get_gen_id(fsp->fh),
2576 remove_share_oplock_fn,
2577 &state);
2578 if (!ok) {
2579 DBG_DEBUG("share_mode_entry_do failed\n");
2580 return false;
2582 if (!state.ok) {
2583 DBG_DEBUG("remove_share_oplock_fn failed\n");
2584 return false;
2587 if (fsp->oplock_type == LEASE_OPLOCK) {
2588 remove_lease_if_stale(
2589 lck,
2590 fsp_client_guid(fsp),
2591 &fsp->lease->lease.lease_key);
2594 share_mode_wakeup_waiters(fsp->file_id);
2596 return true;
2599 struct downgrade_share_oplock_state {
2600 bool ok;
2603 static void downgrade_share_oplock_fn(
2604 struct share_mode_entry *e,
2605 size_t num_share_modes,
2606 bool *modified,
2607 void *private_data)
2609 struct downgrade_share_oplock_state *state = private_data;
2611 e->op_type = LEVEL_II_OPLOCK;
2612 *modified = true;
2613 state->ok = true;
2616 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2618 struct downgrade_share_oplock_state state = { .ok = false };
2619 struct share_mode_data *d = NULL;
2620 NTSTATUS status;
2621 bool ok;
2623 status = share_mode_lock_access_private_data(lck, &d);
2624 if (!NT_STATUS_IS_OK(status)) {
2625 struct file_id id = share_mode_lock_file_id(lck);
2626 struct file_id_buf id_buf;
2627 /* Any error recovery possible here ? */
2628 DBG_ERR("share_mode_lock_access_private_data() failed for "
2629 "%s %s - %s\n",
2630 file_id_str_buf(id, &id_buf),
2631 fsp_str_dbg(fsp),
2632 nt_errstr(status));
2633 return false;
2636 ok = share_mode_entry_do(
2638 messaging_server_id(fsp->conn->sconn->msg_ctx),
2639 fh_get_gen_id(fsp->fh),
2640 downgrade_share_oplock_fn,
2641 &state);
2642 if (!ok) {
2643 DBG_DEBUG("share_mode_entry_do failed\n");
2644 return false;
2646 if (!state.ok) {
2647 DBG_DEBUG("downgrade_share_oplock_fn failed\n");
2648 return false;
2651 d->flags |= SHARE_MODE_LEASE_READ;
2652 d->modified = true;
2654 return true;
2657 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
2658 struct files_struct *fsp)
2660 struct server_id disconnected_pid = { .pid = 0 };
2661 bool ok;
2663 if (fsp->op == NULL) {
2664 return false;
2666 if (!fsp->op->global->durable) {
2667 return false;
2670 server_id_set_disconnected(&disconnected_pid);
2672 ok = reset_share_mode_entry(
2673 lck,
2674 messaging_server_id(fsp->conn->sconn->msg_ctx),
2675 fh_get_gen_id(fsp->fh),
2676 disconnected_pid,
2677 UINT64_MAX,
2678 fsp->op->global->open_persistent_id);
2680 return ok;
2683 bool reset_share_mode_entry(
2684 struct share_mode_lock *lck,
2685 struct server_id old_pid,
2686 uint64_t old_share_file_id,
2687 struct server_id new_pid,
2688 uint64_t new_mid,
2689 uint64_t new_share_file_id)
2691 struct file_id id = share_mode_lock_file_id(lck);
2692 struct share_mode_data *d = NULL;
2693 TDB_DATA key = locking_key(&id);
2694 struct locking_tdb_data *ltdb = NULL;
2695 struct share_mode_entry e;
2696 struct share_mode_entry_buf e_buf;
2697 NTSTATUS status;
2698 int cmp;
2699 bool ret = false;
2700 bool ok;
2702 status = share_mode_lock_access_private_data(lck, &d);
2703 if (!NT_STATUS_IS_OK(status)) {
2704 struct file_id_buf id_buf;
2705 /* Any error recovery possible here ? */
2706 DBG_ERR("share_mode_lock_access_private_data() failed for "
2707 "%s - %s\n",
2708 file_id_str_buf(id, &id_buf),
2709 nt_errstr(status));
2710 return false;
2713 status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 DBG_ERR("locking_tdb_data_fetch failed: %s\n",
2716 nt_errstr(status));
2717 return false;
2720 if (ltdb->num_share_entries != 1) {
2721 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2722 goto done;
2725 ok = share_mode_entry_get(ltdb->share_entries, &e);
2726 if (!ok) {
2727 DBG_WARNING("share_mode_entry_get failed\n");
2728 goto done;
2731 cmp = share_mode_entry_cmp(
2732 old_pid, old_share_file_id, e.pid, e.share_file_id);
2733 if (cmp != 0) {
2734 struct server_id_buf tmp1, tmp2;
2735 DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
2736 "got pid=%s, file_id=%"PRIu64"\n",
2737 server_id_str_buf(old_pid, &tmp1),
2738 old_share_file_id,
2739 server_id_str_buf(e.pid, &tmp2),
2740 e.share_file_id);
2741 goto done;
2744 e.pid = new_pid;
2745 if (new_mid != UINT64_MAX) {
2746 e.op_mid = new_mid;
2748 e.share_file_id = new_share_file_id;
2750 ok = share_mode_entry_put(&e, &e_buf);
2751 if (!ok) {
2752 DBG_WARNING("share_mode_entry_put failed\n");
2753 goto done;
2756 ltdb->share_entries = e_buf.buf;
2758 d->modified = true;
2760 status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
2761 if (!NT_STATUS_IS_OK(status)) {
2762 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2763 nt_errstr(status));
2764 goto done;
2767 ret = true;
2768 done:
2769 TALLOC_FREE(ltdb);
2770 return ret;
2773 struct share_mode_do_locked_vfs_denied_state {
2774 struct file_id id;
2775 share_mode_do_locked_vfs_fn_t fn;
2776 void *private_data;
2777 const char *location;
2778 NTSTATUS status;
2781 static void share_mode_do_locked_vfs_denied_fn(struct g_lock_lock_cb_state *glck,
2782 void *cb_private)
2784 struct share_mode_do_locked_vfs_denied_state *state =
2785 (struct share_mode_do_locked_vfs_denied_state *)cb_private;
2786 struct smb_vfs_deny_state vfs_deny = {};
2787 struct share_mode_lock lck;
2789 if (glck != NULL) {
2790 current_share_mode_glck = glck;
2793 state->status = get_share_mode_lock_internal(state->id,
2794 NULL, /* servicepath */
2795 NULL, /* smb_fname */
2796 NULL, /* old_write_time */
2797 &lck);
2798 if (!NT_STATUS_IS_OK(state->status)) {
2799 DBG_GET_SHARE_MODE_LOCK(state->status,
2800 "get_share_mode_lock_internal failed: %s\n",
2801 nt_errstr(state->status));
2802 if (glck != NULL) {
2803 g_lock_lock_cb_unlock(glck);
2804 current_share_mode_glck = NULL;
2806 return;
2809 _smb_vfs_deny_push(&vfs_deny, state->location);
2810 state->fn(&lck, state->private_data);
2811 _smb_vfs_deny_pop(&vfs_deny, state->location);
2813 state->status = put_share_mode_lock_internal(&lck);
2814 if (!NT_STATUS_IS_OK(state->status)) {
2815 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
2816 nt_errstr(state->status));
2817 smb_panic("put_share_mode_lock_internal failed\n");
2818 return;
2821 if (glck != NULL) {
2822 g_lock_lock_cb_unlock(glck);
2823 current_share_mode_glck = NULL;
2825 return;
2829 * @brief Run @fn protected with G_LOCK_WRITE in the given file_id
2831 * @fn is NOT allowed to call SMB_VFS_* or similar functions,
2832 * which may block for some time in the kernel.
2834 * There must be at least one share_mode_entry, otherwise
2835 * NT_STATUS_NOT_FOUND is returned.
2837 * @param[in] id The key for the share_mode record.
2838 * @param[in] fn The function to run under the g_lock.
2839 * @param[in] private_date A private pointer passed to @fn.
2841 NTSTATUS _share_mode_do_locked_vfs_denied(
2842 struct file_id id,
2843 share_mode_do_locked_vfs_fn_t fn,
2844 void *private_data,
2845 const char *location)
2847 struct share_mode_do_locked_vfs_denied_state state = {
2848 .id = id,
2849 .fn = fn,
2850 .private_data = private_data,
2851 .location = location,
2854 if (share_mode_lock_key_refcount == 0) {
2855 TDB_DATA key = locking_key(&id);
2856 NTSTATUS status;
2858 share_mode_lock_skip_g_lock = true;
2859 status = g_lock_lock(
2860 lock_ctx,
2861 key,
2862 G_LOCK_WRITE,
2863 (struct timeval) { .tv_sec = 3600 },
2864 share_mode_do_locked_vfs_denied_fn,
2865 &state);
2866 share_mode_lock_skip_g_lock = false;
2867 if (!NT_STATUS_IS_OK(status)) {
2868 DBG_DEBUG("g_lock_lock failed: %s\n",
2869 nt_errstr(status));
2870 return status;
2872 return state.status;
2875 share_mode_do_locked_vfs_denied_fn(NULL, &state);
2877 return state.status;
2881 * @brief Run @fn protected with G_LOCK_WRITE in the given file_id
2883 * @fn is allowed to call SMB_VFS_* or similar functions,
2884 * which may block for some time in the kernel.
2886 * There must be at least one share_mode_entry, otherwise
2887 * NT_STATUS_NOT_FOUND is returned.
2889 * @param[in] id The key for the share_mode record.
2890 * @param[in] fn The function to run under the g_lock.
2891 * @param[in] private_date A private pointer passed to @fn.
2893 NTSTATUS _share_mode_do_locked_vfs_allowed(
2894 struct file_id id,
2895 share_mode_do_locked_vfs_fn_t fn,
2896 void *private_data,
2897 const char *location)
2899 struct share_mode_lock lck;
2900 NTSTATUS status;
2902 smb_vfs_assert_allowed();
2904 status = get_share_mode_lock_internal(id,
2905 NULL, /* servicepath */
2906 NULL, /* smb_fname */
2907 NULL, /* old_write_time */
2908 &lck);
2909 if (!NT_STATUS_IS_OK(status)) {
2910 DBG_GET_SHARE_MODE_LOCK(status,
2911 "get_share_mode_lock_internal failed: %s\n",
2912 nt_errstr(status));
2913 return status;
2916 fn(&lck, private_data);
2918 status = put_share_mode_lock_internal(&lck);
2919 if (!NT_STATUS_IS_OK(status)) {
2920 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
2921 nt_errstr(status));
2922 smb_panic("put_share_mode_lock_internal failed\n");
2923 return status;
2926 return NT_STATUS_OK;
2929 struct share_mode_entry_prepare_lock_state {
2930 struct file_id id;
2931 const char *servicepath;
2932 const struct smb_filename *smb_fname;
2933 const struct timespec *old_write_time;
2934 share_mode_entry_prepare_lock_fn_t fn;
2935 void *private_data;
2936 const char *location;
2937 bool keep_locked;
2938 struct share_mode_lock *lck;
2939 NTSTATUS status;
2942 static void share_mode_entry_prepare_lock_fn(struct g_lock_lock_cb_state *glck,
2943 void *cb_private)
2945 struct share_mode_entry_prepare_lock_state *state =
2946 (struct share_mode_entry_prepare_lock_state *)cb_private;
2947 struct smb_vfs_deny_state vfs_deny = {};
2949 SMB_ASSERT(glck != NULL);
2950 current_share_mode_glck = glck;
2952 state->status = get_share_mode_lock_internal(state->id,
2953 state->servicepath,
2954 state->smb_fname,
2955 state->old_write_time,
2956 state->lck);
2957 if (!NT_STATUS_IS_OK(state->status)) {
2958 /* no DBG_GET_SHARE_MODE_LOCK here! */
2959 DBG_ERR("get_share_mode_lock_internal failed: %s\n",
2960 nt_errstr(state->status));
2961 g_lock_lock_cb_unlock(glck);
2962 current_share_mode_glck = NULL;
2963 return;
2966 _smb_vfs_deny_push(&vfs_deny, state->location);
2967 state->fn(state->lck, &state->keep_locked, state->private_data);
2968 _smb_vfs_deny_pop(&vfs_deny, state->location);
2970 if (state->keep_locked) {
2971 current_share_mode_glck = NULL;
2972 return;
2975 state->status = put_share_mode_lock_internal(state->lck);
2976 if (!NT_STATUS_IS_OK(state->status)) {
2977 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
2978 nt_errstr(state->status));
2979 smb_panic("put_share_mode_lock_internal failed\n");
2980 return;
2983 g_lock_lock_cb_unlock(glck);
2984 current_share_mode_glck = NULL;
2985 return;
2988 NTSTATUS _share_mode_entry_prepare_lock(
2989 struct share_mode_entry_prepare_state *prepare_state,
2990 struct file_id id,
2991 const char *servicepath,
2992 const struct smb_filename *smb_fname,
2993 const struct timespec *old_write_time,
2994 share_mode_entry_prepare_lock_fn_t fn,
2995 void *private_data,
2996 const char *location)
2998 struct share_mode_entry_prepare_lock_state state = {
2999 .id = id,
3000 .servicepath = servicepath,
3001 .smb_fname = smb_fname,
3002 .old_write_time = old_write_time,
3003 .fn = fn,
3004 .private_data = private_data,
3005 .location = location,
3007 TDB_DATA key = locking_key(&id);
3008 NTSTATUS status;
3010 SMB_ASSERT(share_mode_lock_key_refcount == 0);
3012 SMB_ASSERT(__SHARE_MODE_LOCK_SPACE == sizeof(struct share_mode_lock));
3014 *prepare_state = (struct share_mode_entry_prepare_state) {
3015 .__fid = id,
3016 .__lck_ptr = &prepare_state->__lck_space,
3019 state.lck = prepare_state->__lck_ptr;
3021 share_mode_lock_skip_g_lock = true;
3022 status = g_lock_lock(
3023 lock_ctx,
3024 key,
3025 G_LOCK_WRITE,
3026 (struct timeval) { .tv_sec = 3600 },
3027 share_mode_entry_prepare_lock_fn,
3028 &state);
3029 share_mode_lock_skip_g_lock = false;
3030 if (!state.keep_locked) {
3031 prepare_state->__lck_ptr = NULL;
3033 if (!NT_STATUS_IS_OK(status)) {
3034 DBG_DEBUG("g_lock_lock failed: %s\n",
3035 nt_errstr(status));
3036 return status;
3039 return state.status;
3042 struct share_mode_entry_prepare_unlock_state {
3043 struct file_id id;
3044 share_mode_entry_prepare_unlock_fn_t fn;
3045 void *private_data;
3046 const char *location;
3047 struct share_mode_lock *lck;
3048 NTSTATUS status;
3051 static void share_mode_entry_prepare_unlock_existing_fn(
3052 struct share_mode_entry_prepare_unlock_state *state)
3054 if (state->fn != NULL) {
3055 struct smb_vfs_deny_state vfs_deny = {};
3057 _smb_vfs_deny_push(&vfs_deny, state->location);
3058 state->fn(state->lck, state->private_data);
3059 _smb_vfs_deny_pop(&vfs_deny, state->location);
3062 state->status = put_share_mode_lock_internal(state->lck);
3063 if (!NT_STATUS_IS_OK(state->status)) {
3064 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
3065 nt_errstr(state->status));
3066 smb_panic("put_share_mode_lock_internal failed\n");
3067 return;
3070 return;
3073 static void share_mode_entry_prepare_unlock_relock_fn(struct g_lock_lock_cb_state *glck,
3074 void *cb_private)
3076 struct share_mode_entry_prepare_unlock_state *state =
3077 (struct share_mode_entry_prepare_unlock_state *)cb_private;
3078 struct smb_vfs_deny_state vfs_deny = {};
3080 SMB_ASSERT(glck != NULL);
3081 current_share_mode_glck = glck;
3083 state->status = get_share_mode_lock_internal(state->id,
3084 NULL, /* servicepath */
3085 NULL, /* smb_fname */
3086 NULL, /* old_write_time */
3087 state->lck);
3088 if (!NT_STATUS_IS_OK(state->status)) {
3089 /* no DBG_GET_SHARE_MODE_LOCK here! */
3090 DBG_ERR("get_share_mode_lock_internal failed: %s\n",
3091 nt_errstr(state->status));
3092 g_lock_lock_cb_unlock(glck);
3093 current_share_mode_glck = NULL;
3094 return;
3097 _smb_vfs_deny_push(&vfs_deny, state->location);
3098 state->fn(state->lck, state->private_data);
3099 _smb_vfs_deny_pop(&vfs_deny, state->location);
3101 state->status = put_share_mode_lock_internal(state->lck);
3102 if (!NT_STATUS_IS_OK(state->status)) {
3103 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
3104 nt_errstr(state->status));
3105 smb_panic("put_share_mode_lock_internal failed\n");
3106 return;
3109 g_lock_lock_cb_unlock(glck);
3110 current_share_mode_glck = NULL;
3111 return;
3114 NTSTATUS _share_mode_entry_prepare_unlock(
3115 struct share_mode_entry_prepare_state *prepare_state,
3116 share_mode_entry_prepare_unlock_fn_t fn,
3117 void *private_data,
3118 const char *location)
3120 struct share_mode_entry_prepare_unlock_state state = {
3121 .id = prepare_state->__fid,
3122 .fn = fn,
3123 .private_data = private_data,
3124 .location = location,
3126 TDB_DATA key = locking_key(&prepare_state->__fid);
3127 NTSTATUS status;
3129 if (prepare_state->__lck_ptr != NULL) {
3131 * With an existing lock, we just run the unlock prepare
3132 * function following by the unlock.
3135 SMB_ASSERT(share_mode_lock_key_refcount == 1);
3137 state.lck = prepare_state->__lck_ptr;
3138 prepare_state->__lck_ptr = NULL;
3140 share_mode_entry_prepare_unlock_existing_fn(&state);
3141 return state.status;
3145 * No existing lock, which means
3146 * _share_mode_entry_prepare_lock() didn't steal
3147 * the lock...
3149 SMB_ASSERT(share_mode_lock_key_refcount == 0);
3151 if (fn == NULL) {
3153 * Without an existing lock and without
3154 * a prepare function there's nothing to
3155 * do...
3157 return NT_STATUS_OK;
3161 * In order to run the unlock prepare function
3162 * we need to relock the entry.
3164 state.lck = &prepare_state->__lck_space;
3166 share_mode_lock_skip_g_lock = true;
3167 status = g_lock_lock(
3168 lock_ctx,
3169 key,
3170 G_LOCK_WRITE,
3171 (struct timeval) { .tv_sec = 3600 },
3172 share_mode_entry_prepare_unlock_relock_fn,
3173 &state);
3174 share_mode_lock_skip_g_lock = false;
3175 if (!NT_STATUS_IS_OK(status)) {
3176 DBG_ERR("g_lock_lock failed: %s\n",
3177 nt_errstr(status));
3178 return status;
3181 return state.status;