Line data Source code
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
7 :
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.
12 :
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.
17 :
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/>.
20 :
21 : Revision History:
22 :
23 : 12 aug 96: Erik.Devriendt@te6.siemens.be
24 : added support for shared memory implementation of share mode locking
25 :
26 : May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
27 : locking to deal with multiple share modes per open file.
28 :
29 : September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
30 : support.
31 :
32 : rewritten completely to use new tdb code. Tridge, Dec '99
33 :
34 : Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
35 : Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
36 : */
37 :
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;
46 : };
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"
66 :
67 : #undef DBGC_CLASS
68 : #define DBGC_CLASS DBGC_LOCKING
69 :
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__))
75 :
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;
79 :
80 : static bool share_mode_g_lock_within_cb(TDB_DATA key);
81 :
82 3470370 : 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)
90 : {
91 3470370 : if (share_mode_g_lock_within_cb(key)) {
92 3254292 : return g_lock_lock_cb_dump(current_share_mode_glck,
93 : fn, private_data);
94 : }
95 :
96 216078 : return g_lock_dump(lock_ctx, key, fn, private_data);
97 : }
98 :
99 928890 : static NTSTATUS share_mode_g_lock_writev(TDB_DATA key,
100 : const TDB_DATA *dbufs,
101 : size_t num_dbufs)
102 : {
103 928890 : if (share_mode_g_lock_within_cb(key)) {
104 756612 : return g_lock_lock_cb_writev(current_share_mode_glck,
105 : dbufs, num_dbufs);
106 : }
107 :
108 172278 : return g_lock_writev_data(lock_ctx, key, dbufs, num_dbufs);
109 : }
110 :
111 200 : static bool locking_init_internal(bool read_only)
112 : {
113 0 : struct db_context *backend;
114 0 : char *db_path;
115 :
116 200 : brl_init(read_only);
117 :
118 200 : if (lock_ctx != NULL) {
119 0 : return True;
120 : }
121 :
122 200 : db_path = lock_path(talloc_tos(), "locking.tdb");
123 200 : if (db_path == NULL) {
124 0 : return false;
125 : }
126 :
127 200 : backend = db_open(NULL, db_path,
128 : SMBD_VOLATILE_TDB_HASH_SIZE,
129 : SMBD_VOLATILE_TDB_FLAGS |
130 : TDB_SEQNUM,
131 : read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
132 : DBWRAP_LOCK_ORDER_NONE,
133 : DBWRAP_FLAG_NONE);
134 200 : TALLOC_FREE(db_path);
135 200 : if (!backend) {
136 0 : DEBUG(0,("ERROR: Failed to initialise locking database\n"));
137 0 : return False;
138 : }
139 :
140 200 : lock_ctx = g_lock_ctx_init_backend(
141 : NULL, global_messaging_context(), &backend);
142 200 : if (lock_ctx == NULL) {
143 0 : TALLOC_FREE(backend);
144 0 : return false;
145 : }
146 200 : g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1);
147 :
148 200 : if (!posix_locking_init(read_only)) {
149 0 : TALLOC_FREE(lock_ctx);
150 0 : return False;
151 : }
152 :
153 200 : return True;
154 : }
155 :
156 174 : bool locking_init(void)
157 : {
158 174 : return locking_init_internal(false);
159 : }
160 :
161 26 : bool locking_init_readonly(void)
162 : {
163 26 : return locking_init_internal(true);
164 : }
165 :
166 : /*******************************************************************
167 : Deinitialize the share_mode management.
168 : ******************************************************************/
169 :
170 31562 : bool locking_end(void)
171 : {
172 31562 : brl_shutdown();
173 31562 : TALLOC_FREE(lock_ctx);
174 31562 : return true;
175 : }
176 :
177 : /*******************************************************************
178 : Form a static locking key for a dev/inode pair.
179 : ******************************************************************/
180 :
181 6115869 : static TDB_DATA locking_key(const struct file_id *id)
182 : {
183 6115869 : return make_tdb_data((const uint8_t *)id, sizeof(*id));
184 : }
185 :
186 : /*******************************************************************
187 : Share mode cache utility functions that store/delete/retrieve
188 : entries from memcache.
189 :
190 : For now share the statcache (global cache) memory space. If
191 : a lock record gets orphaned (which shouldn't happen as we're
192 : using the same locking_key data as lookup) it will eventually
193 : fall out of the cache via the normal LRU trim mechanism. If
194 : necessary we can always make this a separate (smaller) cache.
195 : ******************************************************************/
196 :
197 1131753 : static DATA_BLOB memcache_key(const struct file_id *id)
198 : {
199 1131753 : return data_blob_const((const void *)id, sizeof(*id));
200 : }
201 :
202 533131 : static void share_mode_memcache_store(struct share_mode_data *d)
203 : {
204 533131 : const DATA_BLOB key = memcache_key(&d->id);
205 1360 : struct file_id_buf idbuf;
206 :
207 533131 : DBG_DEBUG("stored entry for file %s epoch %"PRIx64" key %s\n",
208 : d->base_name,
209 : d->unique_content_epoch,
210 : file_id_str_buf(d->id, &idbuf));
211 :
212 : /* Ensure everything stored in the cache is pristine. */
213 533131 : SMB_ASSERT(!d->modified);
214 533131 : SMB_ASSERT(!d->not_stored);
215 :
216 : /*
217 : * Ensure the memory going into the cache
218 : * doesn't have a destructor so it can be
219 : * cleanly evicted by the memcache LRU
220 : * mechanism.
221 : */
222 533131 : talloc_set_destructor(d, NULL);
223 :
224 : /* Cache will own d after this call. */
225 533131 : memcache_add_talloc(NULL,
226 : SHARE_MODE_LOCK_CACHE,
227 : key,
228 : &d);
229 533131 : }
230 :
231 : /*
232 : * NB. We use ndr_pull_hyper on a stack-created
233 : * struct ndr_pull with no talloc allowed, as we
234 : * need this to be really fast as an ndr-peek into
235 : * the first 10 bytes of the blob.
236 : */
237 :
238 479008 : static enum ndr_err_code get_share_mode_blob_header(
239 : const uint8_t *buf, size_t buflen, uint64_t *pepoch, uint16_t *pflags)
240 : {
241 479008 : struct ndr_pull ndr = {
242 : .data = discard_const_p(uint8_t, buf),
243 : .data_size = buflen,
244 : };
245 479008 : NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pepoch));
246 479008 : NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
247 477568 : return NDR_ERR_SUCCESS;
248 : }
249 :
250 457685 : static int share_mode_data_nofree_destructor(struct share_mode_data *d)
251 : {
252 457685 : return -1;
253 : }
254 :
255 598622 : static struct share_mode_data *share_mode_memcache_fetch(
256 : TALLOC_CTX *mem_ctx,
257 : struct file_id id,
258 : const uint8_t *buf,
259 : size_t buflen)
260 : {
261 598622 : const DATA_BLOB key = memcache_key(&id);
262 2209 : enum ndr_err_code ndr_err;
263 2209 : struct share_mode_data *d;
264 2209 : uint64_t unique_content_epoch;
265 2209 : uint16_t flags;
266 2209 : void *ptr;
267 2209 : struct file_id_buf idbuf;
268 :
269 598622 : ptr = memcache_lookup_talloc(NULL,
270 : SHARE_MODE_LOCK_CACHE,
271 : key);
272 598622 : if (ptr == NULL) {
273 130648 : DBG_DEBUG("failed to find entry for key %s\n",
274 : file_id_str_buf(id, &idbuf));
275 130648 : return NULL;
276 : }
277 : /* sequence number key is at start of blob. */
278 467974 : ndr_err = get_share_mode_blob_header(
279 : buf, buflen, &unique_content_epoch, &flags);
280 467974 : if (ndr_err != NDR_ERR_SUCCESS) {
281 : /* Bad blob. Remove entry. */
282 0 : DBG_DEBUG("bad blob %u key %s\n",
283 : (unsigned int)ndr_err,
284 : file_id_str_buf(id, &idbuf));
285 0 : memcache_delete(NULL,
286 : SHARE_MODE_LOCK_CACHE,
287 : key);
288 0 : return NULL;
289 : }
290 :
291 467974 : d = (struct share_mode_data *)ptr;
292 467974 : if (d->unique_content_epoch != unique_content_epoch) {
293 10289 : DBG_DEBUG("epoch changed (cached %"PRIx64") (new %"PRIx64") "
294 : "for key %s\n",
295 : d->unique_content_epoch,
296 : unique_content_epoch,
297 : file_id_str_buf(id, &idbuf));
298 : /* Cache out of date. Remove entry. */
299 10289 : memcache_delete(NULL,
300 : SHARE_MODE_LOCK_CACHE,
301 : key);
302 10289 : return NULL;
303 : }
304 :
305 : /* Move onto mem_ctx. */
306 457685 : d = talloc_move(mem_ctx, &ptr);
307 :
308 : /*
309 : * Now we own d, prevent the cache from freeing it
310 : * when we delete the entry.
311 : */
312 457685 : talloc_set_destructor(d, share_mode_data_nofree_destructor);
313 :
314 : /* Remove from the cache. We own it now. */
315 457685 : memcache_delete(NULL,
316 : SHARE_MODE_LOCK_CACHE,
317 : key);
318 :
319 : /* And reset the destructor to none. */
320 457685 : talloc_set_destructor(d, NULL);
321 :
322 457685 : DBG_DEBUG("fetched entry for file %s epoch %"PRIx64" key %s\n",
323 : d->base_name,
324 : d->unique_content_epoch,
325 : file_id_str_buf(id, &idbuf));
326 :
327 456344 : return d;
328 : }
329 :
330 : /*
331 : * 132 is the sizeof an ndr-encoded struct share_mode_entry_buf.
332 : * Reading/writing entries will immediately error out if this
333 : * size differs (push/pull is done without allocs).
334 : */
335 :
336 : struct share_mode_entry_buf {
337 : uint8_t buf[132];
338 : };
339 : #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))
340 :
341 445369 : static bool share_mode_entry_put(
342 : const struct share_mode_entry *e,
343 : struct share_mode_entry_buf *dst)
344 : {
345 445369 : DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
346 1061 : enum ndr_err_code ndr_err;
347 :
348 445369 : if (DEBUGLEVEL>=10) {
349 0 : DBG_DEBUG("share_mode_entry:\n");
350 0 : NDR_PRINT_DEBUG(share_mode_entry, discard_const_p(void, e));
351 : }
352 :
353 445369 : ndr_err = ndr_push_struct_into_fixed_blob(
354 : &blob,
355 : e,
356 : (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
357 445369 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
358 0 : DBG_WARNING("ndr_push_share_mode_entry failed: %s\n",
359 : ndr_errstr(ndr_err));
360 0 : return false;
361 : }
362 :
363 444308 : return true;
364 : }
365 :
366 499368 : static bool share_mode_entry_get(
367 : const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
368 : {
369 499368 : enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
370 499368 : DATA_BLOB blob = {
371 : .data = discard_const_p(uint8_t, ptr),
372 : .length = SHARE_MODE_ENTRY_SIZE,
373 : };
374 :
375 499368 : ndr_err = ndr_pull_struct_blob_all_noalloc(
376 : &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
377 499368 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
378 0 : DBG_WARNING("ndr_pull_share_mode_entry failed\n");
379 0 : return false;
380 : }
381 498245 : return true;
382 : }
383 :
384 : /*
385 : * locking.tdb records consist of
386 : *
387 : * uint32_t share_mode_data_len
388 : * uint8_t [share_mode_data] This is struct share_mode_data in NDR
389 : *
390 : * 0 [SHARE_MODE_ENTRY_SIZE] Sorted array of share modes,
391 : * 1 [SHARE_MODE_ENTRY_SIZE] filling up the rest of the data in the
392 : * 2 [SHARE_MODE_ENTRY_SIZE] g_lock.c maintained record in locking.tdb
393 : */
394 :
395 : struct locking_tdb_data {
396 : const uint8_t *share_mode_data_buf;
397 : size_t share_mode_data_len;
398 : const uint8_t *share_entries;
399 : size_t num_share_entries;
400 : };
401 :
402 1551377 : static bool locking_tdb_data_get(
403 : struct locking_tdb_data *data, const uint8_t *buf, size_t buflen)
404 : {
405 4705 : uint32_t share_mode_data_len, share_entries_len;
406 :
407 1551377 : if (buflen == 0) {
408 0 : *data = (struct locking_tdb_data) { 0 };
409 0 : return true;
410 : }
411 1551377 : if (buflen < sizeof(uint32_t)) {
412 0 : return false;
413 : }
414 :
415 1551377 : share_mode_data_len = PULL_LE_U32(buf, 0);
416 :
417 1551377 : buf += sizeof(uint32_t);
418 1551377 : buflen -= sizeof(uint32_t);
419 :
420 1551377 : if (buflen < share_mode_data_len) {
421 0 : return false;
422 : }
423 :
424 1551377 : share_entries_len = buflen - share_mode_data_len;
425 :
426 1551377 : if ((share_entries_len % SHARE_MODE_ENTRY_SIZE) != 0) {
427 0 : return false;
428 : }
429 :
430 1551377 : *data = (struct locking_tdb_data) {
431 : .share_mode_data_buf = buf,
432 : .share_mode_data_len = share_mode_data_len,
433 1551377 : .share_entries = buf + share_mode_data_len,
434 1551377 : .num_share_entries = share_entries_len / SHARE_MODE_ENTRY_SIZE,
435 : };
436 :
437 1551377 : return true;
438 : }
439 :
440 : struct locking_tdb_data_fetch_state {
441 : TALLOC_CTX *mem_ctx;
442 : uint8_t *data;
443 : size_t datalen;
444 : };
445 :
446 2492028 : static void locking_tdb_data_fetch_fn(
447 : struct server_id exclusive,
448 : size_t num_shared,
449 : const struct server_id *shared,
450 : const uint8_t *data,
451 : size_t datalen,
452 : void *private_data)
453 : {
454 2492028 : struct locking_tdb_data_fetch_state *state = private_data;
455 2492028 : state->datalen = datalen;
456 2492028 : state->data = talloc_memdup(state->mem_ctx, data, datalen);
457 2492028 : }
458 :
459 2492028 : static NTSTATUS locking_tdb_data_fetch(
460 : TDB_DATA key, TALLOC_CTX *mem_ctx, struct locking_tdb_data **ltdb)
461 : {
462 2492028 : struct locking_tdb_data_fetch_state state = { 0 };
463 2492028 : struct locking_tdb_data *result = NULL;
464 5603 : NTSTATUS status;
465 5603 : bool ok;
466 :
467 2492028 : result = talloc_zero(mem_ctx, struct locking_tdb_data);
468 2492028 : if (result == NULL) {
469 0 : return NT_STATUS_NO_MEMORY;
470 : }
471 2492028 : state.mem_ctx = result;
472 :
473 2492028 : status = share_mode_g_lock_dump(key, locking_tdb_data_fetch_fn, &state);
474 2492028 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
475 : /*
476 : * Just return an empty record
477 : */
478 0 : goto done;
479 : }
480 2492028 : if (!NT_STATUS_IS_OK(status)) {
481 0 : DBG_ERR("share_mode_g_lock_dump failed: %s\n",
482 : nt_errstr(status));
483 0 : return status;
484 : }
485 2492028 : if (state.datalen == 0) {
486 1550317 : goto done;
487 : }
488 :
489 941711 : ok = locking_tdb_data_get(result, state.data, state.datalen);
490 941711 : if (!ok) {
491 0 : DBG_ERR("locking_tdb_data_get failed for %zu bytes\n",
492 : state.datalen);
493 0 : TALLOC_FREE(result);
494 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
495 : }
496 :
497 941711 : done:
498 2492028 : *ltdb = result;
499 2492028 : return NT_STATUS_OK;
500 : }
501 :
502 928890 : static NTSTATUS locking_tdb_data_store(
503 : TDB_DATA key,
504 : const struct locking_tdb_data *ltdb,
505 : const TDB_DATA *share_mode_dbufs,
506 : size_t num_share_mode_dbufs)
507 928890 : {
508 2267 : uint8_t share_mode_data_len_buf[4];
509 928890 : TDB_DATA dbufs[num_share_mode_dbufs+3];
510 2267 : NTSTATUS status;
511 :
512 928890 : if ((ltdb->share_mode_data_len == 0) &&
513 414152 : (ltdb->num_share_entries == 0) &&
514 : (num_share_mode_dbufs == 0)) {
515 : /*
516 : * Nothing to write
517 : */
518 414152 : status = share_mode_g_lock_writev(key, NULL, 0);
519 414152 : if (!NT_STATUS_IS_OK(status)) {
520 0 : DBG_ERR("share_mode_g_lock_writev(NULL) failed: %s\n",
521 : nt_errstr(status));
522 : }
523 414152 : return status;
524 : }
525 :
526 514738 : PUSH_LE_U32(share_mode_data_len_buf, 0, ltdb->share_mode_data_len);
527 :
528 514738 : dbufs[0] = (TDB_DATA) {
529 : .dptr = share_mode_data_len_buf,
530 : .dsize = sizeof(share_mode_data_len_buf),
531 : };
532 514738 : dbufs[1] = (TDB_DATA) {
533 514738 : .dptr = discard_const_p(uint8_t, ltdb->share_mode_data_buf),
534 513369 : .dsize = ltdb->share_mode_data_len,
535 : };
536 :
537 514738 : if (ltdb->num_share_entries > SIZE_MAX/SHARE_MODE_ENTRY_SIZE) {
538 : /* overflow */
539 0 : return NT_STATUS_BUFFER_OVERFLOW;
540 : }
541 514738 : dbufs[2] = (TDB_DATA) {
542 514738 : .dptr = discard_const_p(uint8_t, ltdb->share_entries),
543 514738 : .dsize = ltdb->num_share_entries * SHARE_MODE_ENTRY_SIZE,
544 : };
545 :
546 514738 : if (num_share_mode_dbufs != 0) {
547 442279 : memcpy(&dbufs[3],
548 : share_mode_dbufs,
549 : num_share_mode_dbufs * sizeof(TDB_DATA));
550 : }
551 :
552 514738 : status = share_mode_g_lock_writev(key, dbufs, ARRAY_SIZE(dbufs));
553 514738 : if (!NT_STATUS_IS_OK(status)) {
554 0 : DBG_ERR("share_mode_g_lock_writev() failed: %s\n",
555 : nt_errstr(status));
556 : }
557 514738 : return status;
558 : }
559 :
560 : /*******************************************************************
561 : Get all share mode entries for a dev/inode pair.
562 : ********************************************************************/
563 :
564 598622 : static struct share_mode_data *parse_share_modes(
565 : TALLOC_CTX *mem_ctx,
566 : struct file_id id,
567 : const uint8_t *buf,
568 : size_t buflen)
569 : {
570 2209 : struct share_mode_data *d;
571 2209 : enum ndr_err_code ndr_err;
572 2209 : DATA_BLOB blob;
573 :
574 : /* See if we already have a cached copy of this key. */
575 598622 : d = share_mode_memcache_fetch(mem_ctx, id, buf, buflen);
576 598622 : if (d != NULL) {
577 456344 : return d;
578 : }
579 :
580 140937 : d = talloc(mem_ctx, struct share_mode_data);
581 140937 : if (d == NULL) {
582 0 : DEBUG(0, ("talloc failed\n"));
583 0 : goto fail;
584 : }
585 :
586 140937 : blob = (DATA_BLOB) {
587 : .data = discard_const_p(uint8_t, buf),
588 : .length = buflen,
589 : };
590 140937 : ndr_err = ndr_pull_struct_blob_all(
591 : &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
592 140937 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
593 0 : DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
594 : ndr_errstr(ndr_err));
595 0 : goto fail;
596 : }
597 :
598 140937 : if (DEBUGLEVEL >= 10) {
599 0 : DEBUG(10, ("parse_share_modes:\n"));
600 0 : NDR_PRINT_DEBUG(share_mode_data, d);
601 : }
602 :
603 140069 : return d;
604 0 : fail:
605 0 : TALLOC_FREE(d);
606 0 : return NULL;
607 : }
608 :
609 928890 : static NTSTATUS share_mode_data_ltdb_store(struct share_mode_data *d,
610 : TDB_DATA key,
611 : struct locking_tdb_data *ltdb,
612 : const TDB_DATA *share_mode_dbufs,
613 : size_t num_share_mode_dbufs)
614 : {
615 928890 : DATA_BLOB blob = { 0 };
616 2267 : NTSTATUS status;
617 :
618 928890 : if (!d->modified) {
619 56780 : DBG_DEBUG("share_mode_data not modified\n");
620 56780 : goto store;
621 : }
622 :
623 872110 : d->unique_content_epoch = generate_unique_u64(d->unique_content_epoch);
624 :
625 872110 : if (DEBUGLEVEL >= 10) {
626 0 : DBG_DEBUG("\n");
627 0 : NDR_PRINT_DEBUG(share_mode_data, d);
628 : }
629 :
630 872110 : if (ltdb->num_share_entries != 0 || num_share_mode_dbufs != 0) {
631 1184 : enum ndr_err_code ndr_err;
632 :
633 457958 : ndr_err = ndr_push_struct_blob(
634 : &blob,
635 : ltdb,
636 : d,
637 : (ndr_push_flags_fn_t)ndr_push_share_mode_data);
638 457958 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
639 0 : DBG_ERR("ndr_push_share_mode_data failed: %s\n",
640 : ndr_errstr(ndr_err));
641 0 : return ndr_map_error2ntstatus(ndr_err);
642 : }
643 : }
644 :
645 872110 : ltdb->share_mode_data_buf = blob.data;
646 872110 : ltdb->share_mode_data_len = blob.length;
647 :
648 928890 : store:
649 928890 : status = locking_tdb_data_store(key,
650 : ltdb,
651 : share_mode_dbufs,
652 : num_share_mode_dbufs);
653 928890 : if (!NT_STATUS_IS_OK(status)) {
654 0 : DBG_ERR("locking_tdb_data_store failed: %s\n",
655 : nt_errstr(status));
656 0 : return status;
657 : }
658 :
659 928890 : d->modified = false;
660 928890 : d->not_stored = (ltdb->share_mode_data_len == 0);
661 :
662 928890 : return NT_STATUS_OK;
663 : }
664 :
665 : /*******************************************************************
666 : If modified, store the share_mode_data back into the database.
667 : ********************************************************************/
668 :
669 947257 : static NTSTATUS share_mode_data_store(struct share_mode_data *d)
670 : {
671 947257 : TDB_DATA key = locking_key(&d->id);
672 947257 : struct locking_tdb_data *ltdb = NULL;
673 2258 : NTSTATUS status;
674 :
675 947257 : if (!d->modified) {
676 906958 : DBG_DEBUG("not modified\n");
677 906958 : return NT_STATUS_OK;
678 : }
679 :
680 40299 : if (DEBUGLEVEL >= 10) {
681 0 : DBG_DEBUG("\n");
682 0 : NDR_PRINT_DEBUG(share_mode_data, d);
683 : }
684 :
685 40299 : status = locking_tdb_data_fetch(key, d, <db);
686 40299 : if (!NT_STATUS_IS_OK(status)) {
687 0 : DBG_ERR("locking_tdb_data_fetch failed: %s\n",
688 : nt_errstr(status));
689 0 : return status;
690 : }
691 :
692 40299 : status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
693 40299 : TALLOC_FREE(ltdb);
694 40299 : if (!NT_STATUS_IS_OK(status)) {
695 0 : DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
696 : nt_errstr(status));
697 0 : return status;
698 : }
699 :
700 40299 : return NT_STATUS_OK;
701 : }
702 :
703 : /*******************************************************************
704 : Allocate a new share_mode_data struct, mark it unmodified.
705 : fresh is set to note that currently there is no database entry.
706 : ********************************************************************/
707 :
708 414143 : static struct share_mode_data *fresh_share_mode_lock(
709 : TALLOC_CTX *mem_ctx, const char *servicepath,
710 : const struct smb_filename *smb_fname,
711 : const struct timespec *old_write_time)
712 : {
713 898 : struct share_mode_data *d;
714 :
715 414143 : if ((servicepath == NULL) || (smb_fname == NULL) ||
716 : (old_write_time == NULL)) {
717 0 : return NULL;
718 : }
719 :
720 414143 : d = talloc_zero(mem_ctx, struct share_mode_data);
721 414143 : if (d == NULL) {
722 0 : goto fail;
723 : }
724 414143 : d->unique_content_epoch = generate_unique_u64(0);
725 :
726 414143 : d->base_name = talloc_strdup(d, smb_fname->base_name);
727 414143 : if (d->base_name == NULL) {
728 0 : goto fail;
729 : }
730 414143 : if (smb_fname->stream_name != NULL) {
731 4975 : d->stream_name = talloc_strdup(d, smb_fname->stream_name);
732 4975 : if (d->stream_name == NULL) {
733 0 : goto fail;
734 : }
735 : }
736 414143 : d->servicepath = talloc_strdup(d, servicepath);
737 414143 : if (d->servicepath == NULL) {
738 0 : goto fail;
739 : }
740 414143 : d->old_write_time = full_timespec_to_nt_time(old_write_time);
741 414143 : d->flags = SHARE_MODE_SHARE_DELETE |
742 : SHARE_MODE_SHARE_WRITE |
743 : SHARE_MODE_SHARE_READ;
744 414143 : d->modified = false;
745 414143 : d->not_stored = true;
746 414143 : return d;
747 0 : fail:
748 0 : DEBUG(0, ("talloc failed\n"));
749 0 : TALLOC_FREE(d);
750 0 : return NULL;
751 : }
752 :
753 : /*
754 : * Key that's locked with g_lock
755 : */
756 : static struct file_id share_mode_lock_key_id = {};
757 : static TDB_DATA share_mode_lock_key = {
758 : .dptr = (uint8_t *)&share_mode_lock_key_id,
759 : .dsize = sizeof(share_mode_lock_key_id),
760 : };
761 : static size_t share_mode_lock_key_refcount = 0;
762 :
763 4405281 : static bool share_mode_g_lock_within_cb(TDB_DATA key)
764 : {
765 10385 : int cmp;
766 :
767 4405281 : if (current_share_mode_glck == NULL) {
768 390455 : return false;
769 : }
770 :
771 4013945 : cmp = tdb_data_cmp(share_mode_lock_key, key);
772 4013945 : if (cmp != 0) {
773 0 : struct file_id_buf existing;
774 :
775 0 : DBG_ERR("Can not lock two share modes "
776 : "simultaneously: existing %s requested %s\n",
777 : file_id_str_buf(share_mode_lock_key_id, &existing),
778 : tdb_data_dbg(key));
779 0 : smb_panic(__location__);
780 : return false;
781 : }
782 :
783 4004441 : return true;
784 : }
785 :
786 : /*
787 : * We can only ever have one share mode locked. Use a static
788 : * share_mode_data pointer that is shared by multiple nested
789 : * share_mode_lock structures, explicitly refcounted.
790 : */
791 : static struct share_mode_data *static_share_mode_data = NULL;
792 :
793 : /*******************************************************************
794 : Either fetch a share mode from the database, or allocate a fresh
795 : one if the record doesn't exist.
796 : ********************************************************************/
797 :
798 : struct get_static_share_mode_data_state {
799 : TALLOC_CTX *mem_ctx;
800 : struct file_id id;
801 : const char *servicepath;
802 : const struct smb_filename *smb_fname;
803 : const struct timespec *old_write_time;
804 : NTSTATUS status;
805 : };
806 :
807 948521 : static void get_static_share_mode_data_fn(
808 : struct server_id exclusive,
809 : size_t num_shared,
810 : const struct server_id *shared,
811 : const uint8_t *data,
812 : size_t datalen,
813 : void *private_data)
814 : {
815 948521 : struct get_static_share_mode_data_state *state = private_data;
816 948521 : struct share_mode_data *d = NULL;
817 948521 : struct locking_tdb_data ltdb = { 0 };
818 :
819 948521 : if (datalen != 0) {
820 1360 : bool ok;
821 :
822 533114 : ok = locking_tdb_data_get(<db, data, datalen);
823 533114 : if (!ok) {
824 0 : DBG_ERR("locking_tdb_data_get failed\n");
825 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
826 0 : return;
827 : }
828 : }
829 :
830 948521 : if (ltdb.share_mode_data_len == 0) {
831 415407 : if (state->smb_fname == NULL) {
832 1264 : state->status = NT_STATUS_NOT_FOUND;
833 1264 : return;
834 : }
835 414143 : d = fresh_share_mode_lock(
836 : state->mem_ctx,
837 : state->servicepath,
838 : state->smb_fname,
839 : state->old_write_time);
840 414143 : if (d == NULL) {
841 0 : state->status = NT_STATUS_NO_MEMORY;
842 0 : return;
843 : }
844 : } else {
845 533114 : d = parse_share_modes(
846 : lock_ctx,
847 : state->id,
848 : ltdb.share_mode_data_buf,
849 : ltdb.share_mode_data_len);
850 533114 : if (d == NULL) {
851 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
852 0 : return;
853 : }
854 : }
855 :
856 947257 : d->id = state->id;
857 947257 : static_share_mode_data = d;
858 : }
859 :
860 948521 : static NTSTATUS get_static_share_mode_data(
861 : struct file_id id,
862 : const char *servicepath,
863 : const struct smb_filename *smb_fname,
864 : const struct timespec *old_write_time)
865 : {
866 948521 : struct get_static_share_mode_data_state state = {
867 : .mem_ctx = lock_ctx,
868 : .id = id,
869 : .servicepath = servicepath,
870 : .smb_fname = smb_fname,
871 : .old_write_time = old_write_time,
872 : };
873 2287 : NTSTATUS status;
874 :
875 948521 : SMB_ASSERT(static_share_mode_data == NULL);
876 :
877 948521 : status = share_mode_g_lock_dump(
878 : share_mode_lock_key,
879 : get_static_share_mode_data_fn,
880 : &state);
881 948521 : if (!NT_STATUS_IS_OK(status)) {
882 0 : DBG_GET_SHARE_MODE_LOCK(status,
883 : "share_mode_g_lock_dump failed: %s\n",
884 : nt_errstr(status));
885 0 : return status;
886 : }
887 948521 : if (!NT_STATUS_IS_OK(state.status)) {
888 1264 : DBG_GET_SHARE_MODE_LOCK(state.status,
889 : "get_static_share_mode_data_fn failed: %s\n",
890 : nt_errstr(state.status));
891 1264 : return state.status;
892 : }
893 :
894 947257 : return NT_STATUS_OK;
895 : }
896 :
897 1573278 : struct file_id share_mode_lock_file_id(const struct share_mode_lock *lck)
898 : {
899 1573278 : return lck->id;
900 : }
901 :
902 6865635 : NTSTATUS share_mode_lock_access_private_data(struct share_mode_lock *lck,
903 : struct share_mode_data **data)
904 : {
905 : /*
906 : * For now we always have lck->cached_data,
907 : * but we may change that in future.
908 : */
909 6865635 : SMB_ASSERT(lck->cached_data != NULL);
910 6865635 : *data = lck->cached_data;
911 6865635 : return NT_STATUS_OK;
912 : }
913 :
914 : /*******************************************************************
915 : Get a share_mode_lock, Reference counted to allow nested calls.
916 : ********************************************************************/
917 :
918 : static int share_mode_lock_destructor(struct share_mode_lock *lck);
919 :
920 : static bool share_mode_lock_skip_g_lock;
921 :
922 960738 : static NTSTATUS get_share_mode_lock_internal(
923 : struct file_id id,
924 : const char *servicepath,
925 : const struct smb_filename *smb_fname,
926 : const struct timespec *old_write_time,
927 : struct share_mode_lock *lck)
928 : {
929 2446 : NTSTATUS status;
930 :
931 960738 : *lck = (struct share_mode_lock) {
932 : .id = id,
933 : };
934 :
935 960738 : if (share_mode_lock_key_refcount == 0) {
936 948521 : if (!share_mode_lock_skip_g_lock) {
937 11547 : TDB_DATA key = locking_key(&id);
938 :
939 11603 : status = g_lock_lock(
940 : lock_ctx,
941 : key,
942 : G_LOCK_WRITE,
943 11547 : (struct timeval) { .tv_sec = 3600 },
944 : NULL, NULL);
945 11547 : if (!NT_STATUS_IS_OK(status)) {
946 0 : DBG_DEBUG("g_lock_lock failed: %s\n",
947 : nt_errstr(status));
948 0 : return status;
949 : }
950 : }
951 948521 : share_mode_lock_key_id = id;
952 : }
953 :
954 960738 : if (!file_id_equal(&share_mode_lock_key_id, &id)) {
955 0 : struct file_id_buf existing;
956 0 : struct file_id_buf requested;
957 :
958 0 : DBG_ERR("Can not lock two share modes "
959 : "simultaneously: existing %s requested %s\n",
960 : file_id_str_buf(share_mode_lock_key_id, &existing),
961 : file_id_str_buf(id, &requested));
962 0 : smb_panic(__location__);
963 : goto fail;
964 : }
965 :
966 960738 : SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
967 960738 : share_mode_lock_key_refcount += 1;
968 :
969 960738 : if (static_share_mode_data != NULL) {
970 12217 : goto done;
971 : }
972 :
973 948521 : status = get_static_share_mode_data(
974 : id,
975 : servicepath,
976 : smb_fname,
977 : old_write_time);
978 948521 : if (!NT_STATUS_IS_OK(status)) {
979 1264 : DBG_DEBUG("get_static_share_mode_data failed: %s\n",
980 : nt_errstr(status));
981 1264 : share_mode_lock_key_refcount -= 1;
982 1264 : goto fail;
983 : }
984 947257 : done:
985 959474 : lck->cached_data = static_share_mode_data;
986 :
987 959474 : if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
988 0 : struct file_id_buf returned;
989 :
990 0 : DBG_DEBUG("Returning %s (data_cached=%u key_refcount=%zu)\n",
991 : file_id_str_buf(id, &returned),
992 : static_share_mode_data != NULL,
993 : share_mode_lock_key_refcount);
994 : }
995 :
996 959474 : return NT_STATUS_OK;
997 1264 : fail:
998 1264 : if (share_mode_lock_key_refcount == 0) {
999 1264 : if (!share_mode_lock_skip_g_lock) {
1000 53 : NTSTATUS ulstatus = g_lock_unlock(lock_ctx, share_mode_lock_key);
1001 53 : if (!NT_STATUS_IS_OK(ulstatus)) {
1002 0 : DBG_ERR("g_lock_unlock failed: %s\n",
1003 : nt_errstr(ulstatus));
1004 : }
1005 : }
1006 : }
1007 1264 : return status;
1008 : }
1009 :
1010 959474 : static NTSTATUS put_share_mode_lock_internal(struct share_mode_lock *lck)
1011 : {
1012 2417 : NTSTATUS status;
1013 :
1014 959474 : SMB_ASSERT(share_mode_lock_key_refcount > 0);
1015 959474 : share_mode_lock_key_refcount -= 1;
1016 :
1017 959474 : if (share_mode_lock_key_refcount > 0) {
1018 12217 : return NT_STATUS_OK;
1019 : }
1020 :
1021 947257 : status = share_mode_data_store(static_share_mode_data);
1022 947257 : if (!NT_STATUS_IS_OK(status)) {
1023 0 : DBG_ERR("share_mode_data_store failed: %s\n",
1024 : nt_errstr(status));
1025 0 : return status;
1026 : }
1027 :
1028 947257 : if (!share_mode_lock_skip_g_lock) {
1029 490782 : status = g_lock_unlock(lock_ctx, share_mode_lock_key);
1030 490782 : if (!NT_STATUS_IS_OK(status)) {
1031 0 : DBG_ERR("g_lock_unlock failed: %s\n",
1032 : nt_errstr(status));
1033 0 : return status;
1034 : }
1035 : }
1036 :
1037 947257 : if (!static_share_mode_data->not_stored) {
1038 : /*
1039 : * This is worth keeping. Without share modes,
1040 : * share_mode_data_store above has left nothing in the
1041 : * database.
1042 : */
1043 533131 : share_mode_memcache_store(static_share_mode_data);
1044 533131 : static_share_mode_data = NULL;
1045 : }
1046 :
1047 947257 : TALLOC_FREE(static_share_mode_data);
1048 947257 : return NT_STATUS_OK;
1049 : }
1050 :
1051 8684 : static int share_mode_lock_destructor(struct share_mode_lock *lck)
1052 : {
1053 42 : NTSTATUS status;
1054 :
1055 8684 : status = put_share_mode_lock_internal(lck);
1056 8684 : if (!NT_STATUS_IS_OK(status)) {
1057 0 : DBG_ERR("put_share_mode_lock_internal failed: %s\n",
1058 : nt_errstr(status));
1059 0 : smb_panic("put_share_mode_lock_internal failed\n");
1060 : }
1061 :
1062 8684 : return 0;
1063 : }
1064 :
1065 : /*******************************************************************
1066 : Fetch a share mode where we know one MUST exist. This call reference
1067 : counts it internally to allow for nested lock fetches.
1068 : ********************************************************************/
1069 :
1070 8737 : struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
1071 : const struct file_id id)
1072 : {
1073 8737 : struct share_mode_lock *lck = NULL;
1074 42 : NTSTATUS status;
1075 :
1076 8737 : lck = talloc(mem_ctx, struct share_mode_lock);
1077 8737 : if (lck == NULL) {
1078 0 : return NULL;
1079 : }
1080 :
1081 8737 : status = get_share_mode_lock_internal(id,
1082 : NULL, /* servicepath */
1083 : NULL, /* smb_fname */
1084 : NULL, /* old_write_time */
1085 : lck);
1086 8737 : if (!NT_STATUS_IS_OK(status)) {
1087 53 : DBG_GET_SHARE_MODE_LOCK(status,
1088 : "get_share_mode_lock_internal() failed - %s\n",
1089 : nt_errstr(status));
1090 53 : TALLOC_FREE(lck);
1091 53 : return NULL;
1092 : }
1093 :
1094 8684 : talloc_set_destructor(lck, share_mode_lock_destructor);
1095 8684 : return lck;
1096 : }
1097 :
1098 4870 : static void share_mode_wakeup_waiters_fn(
1099 : struct share_mode_lock *lck,
1100 : void *private_data)
1101 : {
1102 4870 : if (share_mode_g_lock_within_cb(share_mode_lock_key)) {
1103 2542 : g_lock_lock_cb_wake_watchers(current_share_mode_glck);
1104 2542 : return;
1105 : }
1106 :
1107 2328 : g_lock_wake_watchers(lock_ctx, share_mode_lock_key);
1108 : }
1109 :
1110 4870 : NTSTATUS share_mode_wakeup_waiters(struct file_id id)
1111 : {
1112 4870 : return share_mode_do_locked_vfs_denied(id,
1113 : share_mode_wakeup_waiters_fn,
1114 : NULL);
1115 : }
1116 :
1117 : struct fsp_update_share_mode_flags_state {
1118 : struct files_struct *fsp;
1119 : enum ndr_err_code ndr_err;
1120 : uint64_t share_mode_epoch;
1121 : uint16_t share_mode_flags;
1122 : };
1123 :
1124 11034 : static void fsp_update_share_mode_flags_fn(
1125 : struct server_id exclusive,
1126 : size_t num_shared,
1127 : const struct server_id *shared,
1128 : const uint8_t *data,
1129 : size_t datalen,
1130 : void *private_data)
1131 : {
1132 11034 : struct fsp_update_share_mode_flags_state *state = private_data;
1133 11034 : struct locking_tdb_data ltdb = { 0 };
1134 :
1135 11034 : if (datalen != 0) {
1136 11034 : bool ok = locking_tdb_data_get(<db, data, datalen);
1137 11034 : if (!ok) {
1138 0 : DBG_DEBUG("locking_tdb_data_get failed\n");
1139 0 : return;
1140 : }
1141 : }
1142 :
1143 11034 : if (ltdb.share_mode_data_len == 0) {
1144 : /* Likely a ctdb tombstone record, ignore it */
1145 0 : return;
1146 : }
1147 :
1148 11034 : if (exclusive.pid != 0) {
1149 16 : struct server_id self =
1150 3591 : messaging_server_id(state->fsp->conn->sconn->msg_ctx);
1151 3591 : bool is_self = server_id_equal(&self, &exclusive);
1152 :
1153 3591 : if (!is_self) {
1154 : /*
1155 : * If someone else is holding an exclusive
1156 : * lock, pretend there's a read lease
1157 : */
1158 0 : state->share_mode_flags = SHARE_MODE_LEASE_READ;
1159 0 : return;
1160 : }
1161 : }
1162 :
1163 11034 : state->ndr_err = get_share_mode_blob_header(ltdb.share_mode_data_buf,
1164 : ltdb.share_mode_data_len,
1165 : &state->share_mode_epoch,
1166 : &state->share_mode_flags);
1167 : }
1168 :
1169 193204 : static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
1170 : {
1171 193204 : struct fsp_update_share_mode_flags_state state = { .fsp = fsp, };
1172 193204 : int seqnum = g_lock_seqnum(lock_ctx);
1173 193204 : TDB_DATA key = {0};
1174 116 : NTSTATUS status;
1175 :
1176 193204 : if (seqnum == fsp->share_mode_flags_seqnum) {
1177 182160 : return NT_STATUS_OK;
1178 : }
1179 :
1180 11044 : key = locking_key(&fsp->file_id);
1181 11044 : status = share_mode_g_lock_dump(key,
1182 : fsp_update_share_mode_flags_fn,
1183 : &state);
1184 11044 : if (!NT_STATUS_IS_OK(status)) {
1185 : /* no DBG_GET_SHARE_MODE_LOCK here! */
1186 10 : DBG_ERR("share_mode_g_lock_dump returned %s\n",
1187 : nt_errstr(status));
1188 10 : return status;
1189 : }
1190 :
1191 11034 : if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
1192 0 : DBG_ERR("get_share_mode_blob_header returned %s\n",
1193 : ndr_errstr(state.ndr_err));
1194 0 : return ndr_map_error2ntstatus(state.ndr_err);
1195 : }
1196 :
1197 11034 : fsp->share_mode_flags_seqnum = seqnum;
1198 11034 : fsp->share_mode_flags = state.share_mode_flags;
1199 :
1200 11034 : return NT_STATUS_OK;
1201 : }
1202 :
1203 193204 : bool file_has_read_lease(struct files_struct *fsp)
1204 : {
1205 116 : NTSTATUS status;
1206 :
1207 193204 : status = fsp_update_share_mode_flags(fsp);
1208 193204 : if (!NT_STATUS_IS_OK(status)) {
1209 : /* Safe default for leases */
1210 10 : return true;
1211 : }
1212 :
1213 193194 : return (fsp->share_mode_flags & SHARE_MODE_LEASE_READ) != 0;
1214 : }
1215 :
1216 : #define share_mode_lock_assert_private_data(__lck) \
1217 : _share_mode_lock_assert_private_data(__lck, __func__, __location__)
1218 2807800 : static struct share_mode_data *_share_mode_lock_assert_private_data(
1219 : struct share_mode_lock *lck,
1220 : const char *caller_function,
1221 : const char *caller_location)
1222 : {
1223 2807800 : struct share_mode_data *d = NULL;
1224 5683 : NTSTATUS status;
1225 :
1226 2807800 : status = share_mode_lock_access_private_data(lck, &d);
1227 2807800 : if (!NT_STATUS_IS_OK(status)) {
1228 0 : struct file_id id = share_mode_lock_file_id(lck);
1229 0 : struct file_id_buf id_buf;
1230 : /* Any error recovery possible here ? */
1231 0 : D_ERR("%s:%s(): share_mode_lock_access_private_data() "
1232 : "failed for id=%s - %s\n",
1233 : caller_location, caller_function,
1234 : file_id_str_buf(id, &id_buf),
1235 : nt_errstr(status));
1236 0 : smb_panic(caller_location);
1237 : return NULL;
1238 : }
1239 :
1240 2807800 : return d;
1241 : }
1242 :
1243 992 : NTTIME share_mode_changed_write_time(struct share_mode_lock *lck)
1244 : {
1245 992 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1246 992 : return d->changed_write_time;
1247 : }
1248 :
1249 1064 : void share_mode_set_changed_write_time(struct share_mode_lock *lck, struct timespec write_time)
1250 : {
1251 1064 : struct file_id fileid = share_mode_lock_file_id(lck);
1252 1064 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1253 25 : struct file_id_buf ftmp;
1254 25 : struct timeval_buf tbuf;
1255 1064 : NTTIME nt = full_timespec_to_nt_time(&write_time);
1256 :
1257 1064 : DBG_INFO("%s id=%s\n",
1258 : timespec_string_buf(&write_time, true, &tbuf),
1259 : file_id_str_buf(fileid, &ftmp));
1260 :
1261 1064 : if (d->changed_write_time != nt) {
1262 1048 : d->modified = true;
1263 1048 : d->changed_write_time = nt;
1264 : }
1265 1064 : }
1266 :
1267 5684 : void share_mode_set_old_write_time(struct share_mode_lock *lck, struct timespec write_time)
1268 : {
1269 5684 : struct file_id fileid = share_mode_lock_file_id(lck);
1270 5684 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1271 22 : struct file_id_buf ftmp;
1272 22 : struct timeval_buf tbuf;
1273 5684 : NTTIME nt = full_timespec_to_nt_time(&write_time);
1274 :
1275 5684 : DBG_INFO("%s id=%s\n",
1276 : timespec_string_buf(&write_time, true, &tbuf),
1277 : file_id_str_buf(fileid, &ftmp));
1278 :
1279 5684 : if (d->changed_write_time != nt) {
1280 5672 : d->modified = true;
1281 5672 : d->old_write_time = nt;
1282 : }
1283 5684 : }
1284 :
1285 10 : const char *share_mode_servicepath(struct share_mode_lock *lck)
1286 : {
1287 10 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1288 10 : return d->servicepath;
1289 : }
1290 :
1291 21 : char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1292 : {
1293 21 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1294 21 : bool has_stream = (d->stream_name != NULL);
1295 21 : char *fname = NULL;
1296 :
1297 21 : fname = talloc_asprintf(
1298 : mem_ctx,
1299 : "%s%s%s",
1300 : d->base_name,
1301 : has_stream ? ":" : "",
1302 : has_stream ? d->stream_name : "");
1303 21 : return fname;
1304 : }
1305 :
1306 6 : char *share_mode_data_dump(
1307 : TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
1308 : {
1309 6 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1310 6 : struct ndr_print *p = talloc(mem_ctx, struct ndr_print);
1311 6 : char *ret = NULL;
1312 :
1313 6 : if (p == NULL) {
1314 0 : return NULL;
1315 : }
1316 :
1317 6 : *p = (struct ndr_print) {
1318 : .print = ndr_print_string_helper,
1319 : .depth = 1,
1320 6 : .private_data = talloc_strdup(mem_ctx, ""),
1321 : };
1322 :
1323 6 : if (p->private_data == NULL) {
1324 0 : TALLOC_FREE(p);
1325 0 : return NULL;
1326 : }
1327 :
1328 6 : ndr_print_share_mode_data(p, "SHARE_MODE_DATA", d);
1329 :
1330 6 : ret = p->private_data;
1331 :
1332 6 : TALLOC_FREE(p);
1333 :
1334 6 : return ret;
1335 : }
1336 :
1337 1554865 : void share_mode_flags_get(
1338 : struct share_mode_lock *lck,
1339 : uint32_t *access_mask,
1340 : uint32_t *share_mode,
1341 : uint32_t *lease_type)
1342 : {
1343 1554865 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1344 1554865 : uint16_t flags = d->flags;
1345 :
1346 1554865 : if (access_mask != NULL) {
1347 1194505 : *access_mask =
1348 : ((flags & SHARE_MODE_ACCESS_READ) ?
1349 1194505 : FILE_READ_DATA : 0) |
1350 : ((flags & SHARE_MODE_ACCESS_WRITE) ?
1351 1194505 : FILE_WRITE_DATA : 0) |
1352 : ((flags & SHARE_MODE_ACCESS_DELETE) ?
1353 1194505 : DELETE_ACCESS : 0);
1354 : }
1355 1554865 : if (share_mode != NULL) {
1356 1194505 : *share_mode =
1357 : ((flags & SHARE_MODE_SHARE_READ) ?
1358 1194505 : FILE_SHARE_READ : 0) |
1359 : ((flags & SHARE_MODE_SHARE_WRITE) ?
1360 1194505 : FILE_SHARE_WRITE : 0) |
1361 : ((flags & SHARE_MODE_SHARE_DELETE) ?
1362 : FILE_SHARE_DELETE : 0);
1363 : }
1364 1554865 : if (lease_type != NULL) {
1365 1152641 : *lease_type =
1366 : ((flags & SHARE_MODE_LEASE_READ) ?
1367 1152641 : SMB2_LEASE_READ : 0) |
1368 : ((flags & SHARE_MODE_LEASE_WRITE) ?
1369 1152641 : SMB2_LEASE_WRITE : 0) |
1370 : ((flags & SHARE_MODE_LEASE_HANDLE) ?
1371 1152641 : SMB2_LEASE_HANDLE : 0);
1372 : }
1373 1554865 : }
1374 :
1375 802879 : void share_mode_flags_set(
1376 : struct share_mode_lock *lck,
1377 : uint32_t access_mask,
1378 : uint32_t share_mode,
1379 : uint32_t lease_type,
1380 : bool *modified)
1381 : {
1382 802879 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1383 802879 : uint16_t flags = 0;
1384 :
1385 802879 : flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
1386 : SHARE_MODE_ACCESS_READ : 0;
1387 802879 : flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
1388 : SHARE_MODE_ACCESS_WRITE : 0;
1389 802879 : flags |= (access_mask & (DELETE_ACCESS)) ?
1390 802879 : SHARE_MODE_ACCESS_DELETE : 0;
1391 :
1392 802879 : flags |= (share_mode & FILE_SHARE_READ) ?
1393 802879 : SHARE_MODE_SHARE_READ : 0;
1394 802879 : flags |= (share_mode & FILE_SHARE_WRITE) ?
1395 802879 : SHARE_MODE_SHARE_WRITE : 0;
1396 802879 : flags |= (share_mode & FILE_SHARE_DELETE) ?
1397 802879 : SHARE_MODE_SHARE_DELETE : 0;
1398 :
1399 802879 : flags |= (lease_type & SMB2_LEASE_READ) ?
1400 802879 : SHARE_MODE_LEASE_READ : 0;
1401 802879 : flags |= (lease_type & SMB2_LEASE_WRITE) ?
1402 802879 : SHARE_MODE_LEASE_WRITE : 0;
1403 802879 : flags |= (lease_type & SMB2_LEASE_HANDLE) ?
1404 802879 : SHARE_MODE_LEASE_HANDLE : 0;
1405 :
1406 802879 : if (d->flags == flags) {
1407 426588 : return;
1408 : }
1409 :
1410 375692 : if (modified != NULL) {
1411 322 : *modified = true;
1412 : }
1413 375692 : d->flags = flags;
1414 375692 : d->modified = true;
1415 : }
1416 :
1417 : struct share_mode_watch_state {
1418 : bool blockerdead;
1419 : struct server_id blocker;
1420 : bool within_cb;
1421 : };
1422 :
1423 : static void share_mode_watch_done(struct tevent_req *subreq);
1424 :
1425 1151 : struct tevent_req *share_mode_watch_send(
1426 : TALLOC_CTX *mem_ctx,
1427 : struct tevent_context *ev,
1428 : struct share_mode_lock *lck,
1429 : struct server_id blocker)
1430 : {
1431 1151 : struct file_id id = share_mode_lock_file_id(lck);
1432 1151 : TDB_DATA key = locking_key(&id);
1433 1151 : struct tevent_req *req = NULL, *subreq = NULL;
1434 1151 : struct share_mode_watch_state *state = NULL;
1435 :
1436 1151 : req = tevent_req_create(
1437 : mem_ctx, &state, struct share_mode_watch_state);
1438 1151 : if (req == NULL) {
1439 0 : return NULL;
1440 : }
1441 :
1442 1151 : if (share_mode_g_lock_within_cb(key)) {
1443 499 : state->within_cb = true;
1444 499 : subreq = g_lock_lock_cb_watch_data_send(state, ev,
1445 : current_share_mode_glck,
1446 : blocker);
1447 499 : if (tevent_req_nomem(subreq, req)) {
1448 0 : return tevent_req_post(req, ev);
1449 : }
1450 : } else {
1451 652 : subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker);
1452 652 : if (tevent_req_nomem(subreq, req)) {
1453 0 : return tevent_req_post(req, ev);
1454 : }
1455 : }
1456 1151 : tevent_req_set_callback(subreq, share_mode_watch_done, req);
1457 1151 : return req;
1458 : }
1459 :
1460 533 : static void share_mode_watch_done(struct tevent_req *subreq)
1461 : {
1462 533 : struct tevent_req *req = tevent_req_callback_data(
1463 : subreq, struct tevent_req);
1464 533 : struct share_mode_watch_state *state = tevent_req_data(
1465 : req, struct share_mode_watch_state);
1466 0 : NTSTATUS status;
1467 :
1468 533 : if (state->within_cb) {
1469 447 : status = g_lock_lock_cb_watch_data_recv(
1470 : subreq, &state->blockerdead, &state->blocker);
1471 447 : if (tevent_req_nterror(req, status)) {
1472 0 : return;
1473 : }
1474 : } else {
1475 86 : status = g_lock_watch_data_recv(
1476 : subreq, &state->blockerdead, &state->blocker);
1477 86 : if (tevent_req_nterror(req, status)) {
1478 0 : return;
1479 : }
1480 : }
1481 :
1482 533 : tevent_req_done(req);
1483 : }
1484 :
1485 1015 : NTSTATUS share_mode_watch_recv(
1486 : struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
1487 : {
1488 1015 : struct share_mode_watch_state *state = tevent_req_data(
1489 : req, struct share_mode_watch_state);
1490 2 : NTSTATUS status;
1491 :
1492 1015 : if (tevent_req_is_nterror(req, &status)) {
1493 482 : return status;
1494 : }
1495 533 : if (blockerdead != NULL) {
1496 0 : *blockerdead = state->blockerdead;
1497 : }
1498 533 : if (blocker != NULL) {
1499 0 : *blocker = state->blocker;
1500 : }
1501 533 : return NT_STATUS_OK;
1502 : }
1503 :
1504 : struct fetch_share_mode_unlocked_state {
1505 : TALLOC_CTX *mem_ctx;
1506 : struct file_id id;
1507 : struct share_mode_lock *lck;
1508 : };
1509 :
1510 46731 : static void fetch_share_mode_unlocked_parser(
1511 : struct server_id exclusive,
1512 : size_t num_shared,
1513 : const struct server_id *shared,
1514 : const uint8_t *data,
1515 : size_t datalen,
1516 : void *private_data)
1517 : {
1518 46731 : struct fetch_share_mode_unlocked_state *state = private_data;
1519 46731 : struct locking_tdb_data ltdb = { 0 };
1520 :
1521 46731 : if (datalen != 0) {
1522 46731 : bool ok = locking_tdb_data_get(<db, data, datalen);
1523 46731 : if (!ok) {
1524 0 : DBG_DEBUG("locking_tdb_data_get failed\n");
1525 0 : return;
1526 : }
1527 : }
1528 :
1529 46731 : if (ltdb.share_mode_data_len == 0) {
1530 : /* Likely a ctdb tombstone record, ignore it */
1531 0 : return;
1532 : }
1533 :
1534 46731 : state->lck = talloc(state->mem_ctx, struct share_mode_lock);
1535 46731 : if (state->lck == NULL) {
1536 0 : DEBUG(0, ("talloc failed\n"));
1537 0 : return;
1538 : }
1539 46731 : state->lck->id = state->id;
1540 :
1541 92613 : state->lck->cached_data = parse_share_modes(
1542 45882 : state->lck,
1543 : state->id,
1544 : ltdb.share_mode_data_buf,
1545 : ltdb.share_mode_data_len);
1546 46731 : if (state->lck->cached_data == NULL) {
1547 0 : DBG_DEBUG("parse_share_modes failed\n");
1548 849 : TALLOC_FREE(state->lck);
1549 : }
1550 : }
1551 :
1552 : /*******************************************************************
1553 : Get a share_mode_lock without locking the database or reference
1554 : counting. Used by smbstatus to display existing share modes.
1555 : ********************************************************************/
1556 :
1557 871671 : struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
1558 : struct file_id id)
1559 : {
1560 871671 : struct fetch_share_mode_unlocked_state state = {
1561 : .mem_ctx = mem_ctx,
1562 : .id = id,
1563 : };
1564 871671 : TDB_DATA key = locking_key(&id);
1565 1284 : NTSTATUS status;
1566 :
1567 871671 : status = g_lock_dump(
1568 : lock_ctx, key, fetch_share_mode_unlocked_parser, &state);
1569 871671 : if (!NT_STATUS_IS_OK(status)) {
1570 824940 : DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
1571 824940 : return NULL;
1572 : }
1573 46731 : return state.lck;
1574 : }
1575 :
1576 : struct fetch_share_mode_state {
1577 : struct file_id id;
1578 : struct share_mode_lock *lck;
1579 : NTSTATUS status;
1580 : };
1581 :
1582 : static void fetch_share_mode_fn(
1583 : struct server_id exclusive,
1584 : size_t num_shared,
1585 : const struct server_id *shared,
1586 : const uint8_t *data,
1587 : size_t datalen,
1588 : void *private_data);
1589 : static void fetch_share_mode_done(struct tevent_req *subreq);
1590 :
1591 : /**
1592 : * @brief Get a share_mode_lock without locking or refcounting
1593 : *
1594 : * This can be used in a clustered Samba environment where the async dbwrap
1595 : * request is sent over a socket to the local ctdbd. If the send queue is full
1596 : * and the caller was issuing multiple async dbwrap requests in a loop, the
1597 : * caller knows it's probably time to stop sending requests for now and try
1598 : * again later.
1599 : *
1600 : * @param[in] mem_ctx The talloc memory context to use.
1601 : *
1602 : * @param[in] ev The event context to work on.
1603 : *
1604 : * @param[in] id The file id for the locking.tdb key
1605 : *
1606 : * @param[out] queued This boolean out parameter tells the caller whether the
1607 : * async request is blocked in a full send queue:
1608 : *
1609 : * false := request is dispatched
1610 : *
1611 : * true := send queue is full, request waiting to be
1612 : * dispatched
1613 : *
1614 : * @return The new async request, NULL on error.
1615 : **/
1616 0 : struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
1617 : struct tevent_context *ev,
1618 : struct file_id id,
1619 : bool *queued)
1620 : {
1621 0 : struct tevent_req *req = NULL, *subreq = NULL;
1622 0 : struct fetch_share_mode_state *state = NULL;
1623 :
1624 0 : *queued = false;
1625 :
1626 0 : req = tevent_req_create(mem_ctx, &state,
1627 : struct fetch_share_mode_state);
1628 0 : if (req == NULL) {
1629 0 : return NULL;
1630 : }
1631 0 : state->id = id;
1632 :
1633 0 : subreq = g_lock_dump_send(
1634 : state,
1635 : ev,
1636 : lock_ctx,
1637 : locking_key(&id),
1638 : fetch_share_mode_fn,
1639 : state);
1640 0 : if (tevent_req_nomem(subreq, req)) {
1641 0 : return tevent_req_post(req, ev);
1642 : }
1643 0 : tevent_req_set_callback(subreq, fetch_share_mode_done, req);
1644 0 : return req;
1645 : }
1646 :
1647 0 : static void fetch_share_mode_fn(
1648 : struct server_id exclusive,
1649 : size_t num_shared,
1650 : const struct server_id *shared,
1651 : const uint8_t *data,
1652 : size_t datalen,
1653 : void *private_data)
1654 : {
1655 0 : struct fetch_share_mode_state *state = talloc_get_type_abort(
1656 : private_data, struct fetch_share_mode_state);
1657 0 : struct locking_tdb_data ltdb = { 0 };
1658 :
1659 0 : if (datalen != 0) {
1660 0 : bool ok = locking_tdb_data_get(<db, data, datalen);
1661 0 : if (!ok) {
1662 0 : DBG_DEBUG("locking_tdb_data_get failed\n");
1663 0 : return;
1664 : }
1665 : }
1666 :
1667 0 : if (ltdb.share_mode_data_len == 0) {
1668 : /* Likely a ctdb tombstone record, ignore it */
1669 0 : return;
1670 : }
1671 :
1672 0 : state->lck = talloc(state, struct share_mode_lock);
1673 0 : if (state->lck == NULL) {
1674 0 : DBG_WARNING("talloc failed\n");
1675 0 : state->status = NT_STATUS_NO_MEMORY;
1676 0 : return;
1677 : }
1678 0 : state->lck->id = state->id,
1679 :
1680 0 : state->lck->cached_data = parse_share_modes(
1681 0 : state->lck,
1682 : state->id,
1683 : ltdb.share_mode_data_buf,
1684 : ltdb.share_mode_data_len);
1685 0 : if (state->lck->cached_data == NULL) {
1686 0 : DBG_DEBUG("parse_share_modes failed\n");
1687 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1688 0 : TALLOC_FREE(state->lck);
1689 0 : return;
1690 : }
1691 : }
1692 :
1693 0 : static void fetch_share_mode_done(struct tevent_req *subreq)
1694 : {
1695 0 : struct tevent_req *req = tevent_req_callback_data(
1696 : subreq, struct tevent_req);
1697 0 : struct fetch_share_mode_state *state = tevent_req_data(
1698 : req, struct fetch_share_mode_state);
1699 0 : NTSTATUS status;
1700 :
1701 0 : status = g_lock_dump_recv(subreq);
1702 0 : TALLOC_FREE(subreq);
1703 0 : if (tevent_req_nterror(req, status)) {
1704 0 : return;
1705 : }
1706 0 : if (tevent_req_nterror(req, state->status)) {
1707 0 : return;
1708 : }
1709 0 : tevent_req_done(req);
1710 : }
1711 :
1712 0 : NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
1713 : TALLOC_CTX *mem_ctx,
1714 : struct share_mode_lock **_lck)
1715 : {
1716 0 : struct fetch_share_mode_state *state = tevent_req_data(
1717 : req, struct fetch_share_mode_state);
1718 0 : struct share_mode_lock *lck = NULL;
1719 :
1720 0 : NTSTATUS status;
1721 :
1722 0 : if (tevent_req_is_nterror(req, &status)) {
1723 0 : tevent_req_received(req);
1724 0 : return status;
1725 : }
1726 :
1727 0 : if (state->lck == NULL) {
1728 0 : tevent_req_received(req);
1729 0 : return NT_STATUS_NOT_FOUND;
1730 : }
1731 :
1732 0 : lck = talloc_move(mem_ctx, &state->lck);
1733 :
1734 0 : if (DEBUGLEVEL >= 10) {
1735 0 : DBG_DEBUG("share_mode_data:\n");
1736 0 : NDR_PRINT_DEBUG(share_mode_data, lck->cached_data);
1737 : }
1738 :
1739 0 : *_lck = lck;
1740 0 : tevent_req_received(req);
1741 0 : return NT_STATUS_OK;
1742 : }
1743 :
1744 : struct share_mode_forall_state {
1745 : TDB_DATA key;
1746 : int (*fn)(struct file_id fid,
1747 : const struct share_mode_data *data,
1748 : void *private_data);
1749 : void *private_data;
1750 : };
1751 :
1752 18777 : static void share_mode_forall_dump_fn(
1753 : struct server_id exclusive,
1754 : size_t num_shared,
1755 : const struct server_id *shared,
1756 : const uint8_t *data,
1757 : size_t datalen,
1758 : void *private_data)
1759 : {
1760 18777 : struct share_mode_forall_state *state = private_data;
1761 0 : struct file_id fid;
1762 18777 : struct locking_tdb_data ltdb = { 0 };
1763 0 : bool ok;
1764 0 : struct share_mode_data *d;
1765 :
1766 18777 : if (state->key.dsize != sizeof(fid)) {
1767 0 : DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize);
1768 0 : return;
1769 : }
1770 18777 : memcpy(&fid, state->key.dptr, sizeof(fid));
1771 :
1772 18777 : ok = locking_tdb_data_get(<db, data, datalen);
1773 18777 : if (!ok) {
1774 0 : DBG_DEBUG("locking_tdb_data_get() failed\n");
1775 0 : return;
1776 : }
1777 :
1778 18777 : d = parse_share_modes(
1779 : talloc_tos(),
1780 : fid,
1781 : ltdb.share_mode_data_buf,
1782 : ltdb.share_mode_data_len);
1783 18777 : if (d == NULL) {
1784 0 : DBG_DEBUG("parse_share_modes() failed\n");
1785 0 : return;
1786 : }
1787 :
1788 18777 : state->fn(fid, d, state->private_data);
1789 18777 : TALLOC_FREE(d);
1790 : }
1791 :
1792 18777 : static int share_mode_forall_fn(TDB_DATA key, void *private_data)
1793 : {
1794 18777 : struct share_mode_forall_state *state = private_data;
1795 0 : NTSTATUS status;
1796 :
1797 18777 : state->key = key;
1798 :
1799 18777 : status = share_mode_g_lock_dump(
1800 : key, share_mode_forall_dump_fn, private_data);
1801 18777 : if (!NT_STATUS_IS_OK(status)) {
1802 0 : DBG_GET_SHARE_MODE_LOCK(status,
1803 : "g_lock_dump failed: %s\n",
1804 : nt_errstr(status));
1805 : }
1806 18777 : return 0;
1807 : }
1808 :
1809 6333 : int share_mode_forall(int (*fn)(struct file_id fid,
1810 : const struct share_mode_data *data,
1811 : void *private_data),
1812 : void *private_data)
1813 : {
1814 6333 : struct share_mode_forall_state state = {
1815 : .fn = fn,
1816 : .private_data = private_data
1817 : };
1818 0 : int ret;
1819 :
1820 6333 : if (lock_ctx == NULL) {
1821 0 : return 0;
1822 : }
1823 :
1824 6333 : ret = g_lock_locks(
1825 : lock_ctx, share_mode_forall_fn, &state);
1826 6333 : if (ret < 0) {
1827 0 : DBG_ERR("g_lock_locks failed\n");
1828 : }
1829 6333 : return ret;
1830 : }
1831 :
1832 : struct share_entry_forall_state {
1833 : struct file_id fid;
1834 : const struct share_mode_data *data;
1835 : int (*fn)(struct file_id fid,
1836 : const struct share_mode_data *data,
1837 : const struct share_mode_entry *entry,
1838 : void *private_data);
1839 : void *private_data;
1840 : int ret;
1841 : };
1842 :
1843 18 : static bool share_entry_traverse_walker(
1844 : struct share_mode_entry *e,
1845 : bool *modified,
1846 : void *private_data)
1847 : {
1848 18 : struct share_entry_forall_state *state = private_data;
1849 :
1850 18 : state->ret = state->fn(
1851 : state->fid, state->data, e, state->private_data);
1852 18 : return (state->ret != 0);
1853 : }
1854 :
1855 18 : static int share_entry_traverse_fn(struct file_id fid,
1856 : const struct share_mode_data *data,
1857 : void *private_data)
1858 : {
1859 18 : struct share_entry_forall_state *state = private_data;
1860 18 : struct share_mode_lock lck = {
1861 : .id = fid,
1862 : .cached_data = discard_const_p(struct share_mode_data, data)
1863 : };
1864 0 : bool ok;
1865 :
1866 18 : state->fid = fid;
1867 18 : state->data = data;
1868 :
1869 18 : ok = share_mode_forall_entries(
1870 : &lck, share_entry_traverse_walker, state);
1871 18 : if (!ok) {
1872 0 : DBG_ERR("share_mode_forall_entries failed\n");
1873 0 : return false;
1874 : }
1875 :
1876 18 : return state->ret;
1877 : }
1878 :
1879 : /*******************************************************************
1880 : Call the specified function on each entry under management by the
1881 : share mode system.
1882 : ********************************************************************/
1883 :
1884 34 : int share_entry_forall(int (*fn)(struct file_id fid,
1885 : const struct share_mode_data *data,
1886 : const struct share_mode_entry *entry,
1887 : void *private_data),
1888 : void *private_data)
1889 : {
1890 34 : struct share_entry_forall_state state = {
1891 : .fn = fn, .private_data = private_data };
1892 :
1893 34 : return share_mode_forall(share_entry_traverse_fn, &state);
1894 : }
1895 :
1896 499368 : static int share_mode_entry_cmp(
1897 : struct server_id pid1,
1898 : uint64_t share_file_id1,
1899 : struct server_id pid2,
1900 : uint64_t share_file_id2)
1901 : {
1902 1123 : int cmp;
1903 :
1904 500491 : cmp = server_id_cmp(&pid1, &pid2);
1905 499368 : if (cmp != 0) {
1906 45172 : return cmp;
1907 : }
1908 454171 : if (share_file_id1 != share_file_id2) {
1909 8848 : return (share_file_id1 < share_file_id2) ? -1 : 1;
1910 : }
1911 444262 : return 0;
1912 : }
1913 :
1914 887312 : static size_t share_mode_entry_find(
1915 : const uint8_t *data,
1916 : size_t num_share_modes,
1917 : struct server_id pid,
1918 : uint64_t share_file_id,
1919 : struct share_mode_entry *e,
1920 : bool *match)
1921 : {
1922 1999 : ssize_t left, right, middle;
1923 :
1924 887312 : *match = false;
1925 :
1926 887312 : if (num_share_modes == 0) {
1927 413271 : return 0;
1928 : }
1929 :
1930 473143 : left = 0;
1931 473143 : right = (num_share_modes-1);
1932 :
1933 527188 : while (left <= right) {
1934 499078 : const uint8_t *middle_ptr = NULL;
1935 1123 : int cmp;
1936 1123 : bool ok;
1937 :
1938 499078 : middle = left + ((right - left) / 2);
1939 499078 : middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
1940 :
1941 499078 : DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
1942 : left,
1943 : right,
1944 : middle,
1945 : middle_ptr);
1946 :
1947 499078 : ok = share_mode_entry_get(middle_ptr, e);
1948 499078 : if (!ok) {
1949 0 : DBG_DEBUG("share_mode_entry_get failed\n");
1950 0 : return 0;
1951 : }
1952 :
1953 499078 : cmp = share_mode_entry_cmp(
1954 : e->pid, e->share_file_id, pid, share_file_id);
1955 498017 : if (cmp == 0) {
1956 445033 : *match = true;
1957 445033 : return middle;
1958 : }
1959 :
1960 54045 : if (cmp < 0) {
1961 25459 : right = middle-1;
1962 : } else {
1963 28586 : left = middle+1;
1964 : }
1965 : }
1966 :
1967 28110 : return left;
1968 : }
1969 :
1970 442279 : bool set_share_mode(struct share_mode_lock *lck,
1971 : struct files_struct *fsp,
1972 : uid_t uid,
1973 : uint64_t mid,
1974 : uint16_t op_type,
1975 : const struct smb2_lease_key *lease_key,
1976 : uint32_t share_access,
1977 : uint32_t access_mask)
1978 : {
1979 442279 : struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
1980 442279 : TDB_DATA key = locking_key(&d->id);
1981 442279 : struct server_id my_pid = messaging_server_id(
1982 442279 : fsp->conn->sconn->msg_ctx);
1983 442279 : struct locking_tdb_data *ltdb = NULL;
1984 938 : size_t idx;
1985 442279 : struct share_mode_entry e = { .pid.pid = 0 };
1986 938 : struct share_mode_entry_buf e_buf;
1987 938 : NTSTATUS status;
1988 938 : bool ok, found;
1989 :
1990 938 : TDB_DATA dbufs[3];
1991 442279 : size_t num_dbufs = 0;
1992 :
1993 442279 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
1994 442279 : if (!NT_STATUS_IS_OK(status)) {
1995 0 : DBG_ERR("locking_tdb_data_fetch failed: %s\n",
1996 : nt_errstr(status));
1997 0 : return false;
1998 : }
1999 442279 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2000 :
2001 442279 : idx = share_mode_entry_find(
2002 441341 : ltdb->share_entries,
2003 442279 : ltdb->num_share_entries,
2004 : my_pid,
2005 : fh_get_gen_id(fsp->fh),
2006 : &e,
2007 : &found);
2008 442279 : if (found) {
2009 0 : DBG_WARNING("Found duplicate share mode\n");
2010 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2011 0 : goto done;
2012 : }
2013 :
2014 884558 : e = (struct share_mode_entry) {
2015 : .pid = my_pid,
2016 : .share_access = share_access,
2017 442279 : .private_options = fh_get_private_options(fsp->fh),
2018 : .access_mask = access_mask,
2019 : .op_mid = mid,
2020 : .op_type = op_type,
2021 442279 : .time.tv_sec = fsp->open_time.tv_sec,
2022 442279 : .time.tv_usec = fsp->open_time.tv_usec,
2023 442279 : .share_file_id = fh_get_gen_id(fsp->fh),
2024 : .uid = (uint32_t)uid,
2025 : .flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
2026 442279 : SHARE_MODE_FLAG_POSIX_OPEN : 0,
2027 442279 : .name_hash = fsp->name_hash,
2028 : };
2029 :
2030 442279 : if (op_type == LEASE_OPLOCK) {
2031 972 : const struct GUID *client_guid = fsp_client_guid(fsp);
2032 972 : e.client_guid = *client_guid;
2033 972 : e.lease_key = *lease_key;
2034 : }
2035 :
2036 442279 : ok = share_mode_entry_put(&e, &e_buf);
2037 442279 : if (!ok) {
2038 0 : DBG_DEBUG("share_mode_entry_put failed\n");
2039 0 : status = NT_STATUS_INTERNAL_ERROR;
2040 0 : goto done;
2041 : }
2042 :
2043 442279 : DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
2044 :
2045 442279 : if (idx > 0) {
2046 12195 : dbufs[num_dbufs] = (TDB_DATA) {
2047 12195 : .dptr = discard_const_p(uint8_t, ltdb->share_entries),
2048 12195 : .dsize = idx * SHARE_MODE_ENTRY_SIZE,
2049 : };
2050 12195 : num_dbufs += 1;
2051 : }
2052 :
2053 442279 : dbufs[num_dbufs] = (TDB_DATA) {
2054 : .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
2055 : };
2056 442279 : num_dbufs += 1;
2057 :
2058 442279 : if (idx < ltdb->num_share_entries) {
2059 19943 : size_t num_after_idx = (ltdb->num_share_entries-idx);
2060 19943 : dbufs[num_dbufs] = (TDB_DATA) {
2061 19943 : .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
2062 19943 : idx * SHARE_MODE_ENTRY_SIZE,
2063 19943 : .dsize = num_after_idx * SHARE_MODE_ENTRY_SIZE,
2064 : };
2065 19943 : num_dbufs += 1;
2066 : }
2067 :
2068 : {
2069 938 : size_t i;
2070 916696 : for (i=0; i<num_dbufs; i++) {
2071 474417 : DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
2072 : i,
2073 : dbufs[i].dptr,
2074 : dbufs[i].dsize);
2075 : }
2076 : }
2077 :
2078 442279 : if (num_dbufs == 1) {
2079 : /*
2080 : * Storing a fresh record with just one share entry
2081 : */
2082 414169 : d->modified = true;
2083 : }
2084 :
2085 : /*
2086 : * If there was any existing data in
2087 : * ltdb->share_entries, it's now been
2088 : * moved and we've split it into:
2089 : *
2090 : * num_dbufs = 3
2091 : * dbufs[0] -> old sorted data less than new_entry
2092 : * dbufs[1] -> new_share_mode_entry
2093 : * dbufs[2] -> old sorted_data greater than new entry.
2094 : *
2095 : * So the old data inside ltdb->share_entries is
2096 : * no longer valid.
2097 : *
2098 : * If we're storing a brand new entry the
2099 : * dbufs look like:
2100 : *
2101 : * num_dbufs = 1
2102 : * dbufs[0] -> new_share_mode_entry
2103 : *
2104 : * Either way we must set ltdb->share_entries = NULL
2105 : * and ltdb->num_share_entries = 0 so that
2106 : * locking_tdb_data_store() doesn't use it to
2107 : * store any data. It's no longer there.
2108 : */
2109 :
2110 442279 : ltdb->share_entries = NULL;
2111 442279 : ltdb->num_share_entries = 0;
2112 :
2113 442279 : status = share_mode_data_ltdb_store(d, key, ltdb, dbufs, num_dbufs);
2114 442279 : if (!NT_STATUS_IS_OK(status)) {
2115 0 : DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2116 : nt_errstr(status));
2117 : }
2118 442279 : done:
2119 442279 : TALLOC_FREE(ltdb);
2120 442279 : return NT_STATUS_IS_OK(status);
2121 : }
2122 :
2123 459654 : static bool share_mode_for_one_entry(
2124 : bool (*fn)(struct share_mode_entry *e,
2125 : bool *modified,
2126 : void *private_data),
2127 : void *private_data,
2128 : size_t *i,
2129 : uint8_t *data,
2130 : size_t *num_share_modes,
2131 : bool *writeback)
2132 : {
2133 459654 : DATA_BLOB blob = {
2134 459654 : .data = data + (*i) * SHARE_MODE_ENTRY_SIZE,
2135 : .length = SHARE_MODE_ENTRY_SIZE,
2136 : };
2137 459654 : struct share_mode_entry e = {.pid.pid=0};
2138 459654 : enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
2139 459654 : bool modified = false;
2140 459654 : bool stop = false;
2141 1096 : struct server_id e_pid;
2142 1096 : uint64_t e_share_file_id;
2143 :
2144 459654 : ndr_err = ndr_pull_struct_blob_all_noalloc(
2145 : &blob,
2146 : &e,
2147 : (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
2148 459654 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2149 0 : DBG_WARNING("ndr_pull_share_mode_entry failed\n");
2150 0 : *i += 1;
2151 0 : return false;
2152 : }
2153 459654 : if (DEBUGLEVEL >= 10) {
2154 0 : DBG_DEBUG("entry[%zu]:\n", *i);
2155 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2156 : }
2157 :
2158 459654 : e_pid = e.pid;
2159 459654 : e_share_file_id = e.share_file_id;
2160 :
2161 459654 : stop = fn(&e, &modified, private_data);
2162 :
2163 459654 : DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2164 : *i,
2165 : (int)modified,
2166 : (int)e.stale);
2167 :
2168 459654 : if (e.stale) {
2169 29 : if (DEBUGLEVEL>=10) {
2170 0 : DBG_DEBUG("share_mode_entry:\n");
2171 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2172 : }
2173 :
2174 29 : if (*i < *num_share_modes) {
2175 29 : memmove(blob.data,
2176 29 : blob.data + SHARE_MODE_ENTRY_SIZE,
2177 29 : (*num_share_modes - *i - 1) *
2178 : SHARE_MODE_ENTRY_SIZE);
2179 : }
2180 29 : *num_share_modes -= 1;
2181 29 : *writeback = true;
2182 29 : return stop;
2183 : }
2184 :
2185 459625 : if (modified) {
2186 1043 : if (DEBUGLEVEL>=10) {
2187 0 : DBG_DEBUG("share_mode_entry:\n");
2188 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2189 : }
2190 :
2191 : /*
2192 : * Make sure sorting order is kept intact
2193 : */
2194 1043 : SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
2195 1043 : SMB_ASSERT(e_share_file_id == e.share_file_id);
2196 :
2197 1043 : ndr_err = ndr_push_struct_into_fixed_blob(
2198 : &blob,
2199 : &e,
2200 : (ndr_push_flags_fn_t)
2201 : ndr_push_share_mode_entry);
2202 1043 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2203 0 : DBG_WARNING("ndr_push_share_mode_entry "
2204 : "failed: %s\n",
2205 : ndr_errstr(ndr_err));
2206 : /*
2207 : * Not much we can do, just ignore it
2208 : */
2209 : }
2210 1043 : *i += 1;
2211 1043 : *writeback = true;
2212 1043 : return stop;
2213 : }
2214 :
2215 458582 : if (stop) {
2216 627 : return true;
2217 : }
2218 :
2219 457935 : *i += 1;
2220 457935 : return false;
2221 : }
2222 :
2223 1564127 : bool share_mode_forall_entries(
2224 : struct share_mode_lock *lck,
2225 : bool (*fn)(struct share_mode_entry *e,
2226 : bool *modified,
2227 : void *private_data),
2228 : void *private_data)
2229 : {
2230 1564127 : struct file_id id = share_mode_lock_file_id(lck);
2231 1564127 : struct share_mode_data *d = NULL;
2232 1564127 : TDB_DATA key = locking_key(&id);
2233 1564127 : struct locking_tdb_data *ltdb = NULL;
2234 1564127 : uint8_t *share_entries = NULL;
2235 3352 : size_t num_share_entries;
2236 1564127 : bool writeback = false;
2237 3352 : NTSTATUS status;
2238 1564127 : bool stop = false;
2239 3352 : size_t i;
2240 :
2241 1564127 : status = share_mode_lock_access_private_data(lck, &d);
2242 1564127 : if (!NT_STATUS_IS_OK(status)) {
2243 0 : struct file_id_buf id_buf;
2244 : /* Any error recovery possible here ? */
2245 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
2246 : "%s - %s\n",
2247 : file_id_str_buf(id, &id_buf),
2248 : nt_errstr(status));
2249 0 : return false;
2250 : }
2251 :
2252 1564127 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
2253 1564127 : if (!NT_STATUS_IS_OK(status)) {
2254 0 : DBG_ERR("locking_tdb_data_fetch failed: %s\n",
2255 : nt_errstr(status));
2256 0 : return false;
2257 : }
2258 1564127 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2259 :
2260 1564127 : num_share_entries = ltdb->num_share_entries;
2261 1564127 : share_entries = discard_const_p(uint8_t, ltdb->share_entries);
2262 :
2263 1564127 : i = 0;
2264 2023134 : while (i<num_share_entries) {
2265 459654 : stop = share_mode_for_one_entry(
2266 : fn,
2267 : private_data,
2268 : &i,
2269 : share_entries,
2270 : &num_share_entries,
2271 : &writeback);
2272 459654 : if (stop) {
2273 627 : break;
2274 : }
2275 : }
2276 :
2277 1564127 : DBG_DEBUG("num_share_entries=%zu, writeback=%d\n",
2278 : num_share_entries,
2279 : (int)writeback);
2280 :
2281 1564127 : if (!writeback) {
2282 1563138 : TALLOC_FREE(ltdb);
2283 1563138 : return true;
2284 : }
2285 :
2286 989 : if ((ltdb->num_share_entries != 0 ) && (num_share_entries == 0)) {
2287 : /*
2288 : * This routine wiped all share entries, let
2289 : * share_mode_data_store() delete the record
2290 : */
2291 29 : d->modified = true;
2292 : }
2293 :
2294 989 : ltdb->num_share_entries = num_share_entries;
2295 989 : ltdb->share_entries = share_entries;
2296 :
2297 989 : status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
2298 989 : TALLOC_FREE(ltdb);
2299 989 : if (!NT_STATUS_IS_OK(status)) {
2300 0 : DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2301 : nt_errstr(status));
2302 0 : return false;
2303 : }
2304 :
2305 973 : return true;
2306 : }
2307 :
2308 : struct share_mode_count_entries_state {
2309 : size_t num_share_modes;
2310 : NTSTATUS status;
2311 : };
2312 :
2313 10 : static void share_mode_count_entries_fn(
2314 : struct server_id exclusive,
2315 : size_t num_shared,
2316 : const struct server_id *shared,
2317 : const uint8_t *data,
2318 : size_t datalen,
2319 : void *private_data)
2320 : {
2321 10 : struct share_mode_count_entries_state *state = private_data;
2322 10 : struct locking_tdb_data ltdb = { 0 };
2323 0 : bool ok;
2324 :
2325 10 : ok = locking_tdb_data_get(<db, data, datalen);
2326 10 : if (!ok) {
2327 0 : DBG_WARNING("locking_tdb_data_get failed for %zu\n", datalen);
2328 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2329 0 : return;
2330 : }
2331 10 : state->num_share_modes = ltdb.num_share_entries;
2332 10 : state->status = NT_STATUS_OK;
2333 : }
2334 :
2335 10 : NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
2336 : {
2337 10 : struct share_mode_count_entries_state state = {
2338 : .status = NT_STATUS_NOT_FOUND,
2339 : };
2340 0 : NTSTATUS status;
2341 :
2342 10 : status = g_lock_dump(
2343 : lock_ctx,
2344 : locking_key(&fid),
2345 : share_mode_count_entries_fn,
2346 : &state);
2347 10 : if (!NT_STATUS_IS_OK(status)) {
2348 0 : DBG_DEBUG("g_lock_dump failed: %s\n",
2349 : nt_errstr(status));
2350 0 : return status;
2351 : }
2352 10 : if (!NT_STATUS_IS_OK(state.status)) {
2353 0 : DBG_DEBUG("share_mode_count_entries_fn failed: %s\n",
2354 : nt_errstr(state.status));
2355 0 : return state.status;
2356 : }
2357 :
2358 10 : *num_share_modes = state.num_share_modes;
2359 10 : return NT_STATUS_OK;
2360 : }
2361 :
2362 445033 : static bool share_mode_entry_do(
2363 : struct share_mode_data *d,
2364 : struct server_id pid,
2365 : uint64_t share_file_id,
2366 : void (*fn)(struct share_mode_entry *e,
2367 : size_t num_share_modes,
2368 : bool *modified,
2369 : void *private_data),
2370 : void *private_data)
2371 : {
2372 445033 : TDB_DATA key = locking_key(&d->id);
2373 445033 : struct locking_tdb_data *ltdb = NULL;
2374 1061 : size_t idx;
2375 445033 : bool found = false;
2376 445033 : bool modified = false;
2377 1061 : struct share_mode_entry e;
2378 445033 : uint8_t *e_ptr = NULL;
2379 1061 : NTSTATUS status;
2380 445033 : bool ret = false;
2381 :
2382 445033 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
2383 445033 : if (!NT_STATUS_IS_OK(status)) {
2384 0 : DBG_ERR("locking_tdb_data_fetch failed: %s\n",
2385 : nt_errstr(status));
2386 0 : return false;
2387 : }
2388 445033 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2389 :
2390 446094 : idx = share_mode_entry_find(
2391 443972 : ltdb->share_entries,
2392 445033 : ltdb->num_share_entries,
2393 : pid,
2394 : share_file_id,
2395 : &e,
2396 : &found);
2397 445033 : if (!found) {
2398 0 : DBG_WARNING("Did not find share mode entry for %"PRIu64"\n",
2399 : share_file_id);
2400 0 : goto done;
2401 : }
2402 :
2403 445033 : if (DEBUGLEVEL>=10) {
2404 0 : DBG_DEBUG("entry[%zu]:\n", idx);
2405 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2406 : }
2407 :
2408 445033 : fn(&e, ltdb->num_share_entries, &modified, private_data);
2409 :
2410 445033 : DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
2411 : idx,
2412 : (int)modified,
2413 : (int)e.stale);
2414 :
2415 445033 : if (!e.stale && !modified) {
2416 0 : ret = true;
2417 0 : goto done;
2418 : }
2419 :
2420 445033 : e_ptr = discard_const_p(uint8_t, ltdb->share_entries) +
2421 445033 : idx * SHARE_MODE_ENTRY_SIZE;
2422 :
2423 445033 : if (e.stale) {
2424 : /*
2425 : * Move the rest down one entry
2426 : */
2427 442233 : size_t behind = ltdb->num_share_entries - idx - 1;
2428 442233 : if (behind != 0) {
2429 18125 : memmove(e_ptr,
2430 17187 : e_ptr + SHARE_MODE_ENTRY_SIZE,
2431 : behind * SHARE_MODE_ENTRY_SIZE);
2432 : }
2433 442233 : ltdb->num_share_entries -= 1;
2434 :
2435 442233 : if (ltdb->num_share_entries == 0) {
2436 : /*
2437 : * Tell share_mode_lock_destructor() to delete
2438 : * the whole record
2439 : */
2440 414123 : d->modified = true;
2441 : }
2442 :
2443 442233 : if (DEBUGLEVEL>=10) {
2444 0 : DBG_DEBUG("share_mode_entry:\n");
2445 0 : NDR_PRINT_DEBUG(share_mode_entry, &e);
2446 : }
2447 : } else {
2448 123 : struct share_mode_entry_buf buf;
2449 123 : bool ok;
2450 :
2451 2800 : if (ltdb->num_share_entries != 1) {
2452 : /*
2453 : * Make sure the sorting order stays intact
2454 : */
2455 550 : SMB_ASSERT(server_id_equal(&e.pid, &pid));
2456 550 : SMB_ASSERT(e.share_file_id == share_file_id);
2457 : }
2458 :
2459 2800 : ok = share_mode_entry_put(&e, &buf);
2460 2800 : if (!ok) {
2461 0 : DBG_DEBUG("share_mode_entry_put failed\n");
2462 0 : goto done;
2463 : }
2464 2800 : memcpy(e_ptr, buf.buf, SHARE_MODE_ENTRY_SIZE);
2465 : }
2466 :
2467 445033 : status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
2468 445033 : if (!NT_STATUS_IS_OK(status)) {
2469 0 : DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2470 : nt_errstr(status));
2471 0 : goto done;
2472 : }
2473 :
2474 443972 : ret = true;
2475 445033 : done:
2476 445033 : TALLOC_FREE(ltdb);
2477 443972 : return ret;
2478 : }
2479 :
2480 : struct del_share_mode_state {
2481 : bool ok;
2482 : };
2483 :
2484 442233 : static void del_share_mode_fn(
2485 : struct share_mode_entry *e,
2486 : size_t num_share_modes,
2487 : bool *modified,
2488 : void *private_data)
2489 : {
2490 442233 : struct del_share_mode_state *state = private_data;
2491 442233 : e->stale = true;
2492 442233 : state->ok = true;
2493 442233 : }
2494 :
2495 442233 : bool del_share_mode_open_id(struct share_mode_lock *lck,
2496 : struct server_id open_pid,
2497 : uint64_t open_file_id)
2498 : {
2499 442233 : struct del_share_mode_state state = { .ok = false };
2500 442233 : struct share_mode_data *d = NULL;
2501 938 : NTSTATUS status;
2502 938 : bool ok;
2503 :
2504 442233 : status = share_mode_lock_access_private_data(lck, &d);
2505 442233 : if (!NT_STATUS_IS_OK(status)) {
2506 : /* Any error recovery possible here ? */
2507 0 : return false;
2508 : }
2509 :
2510 442233 : ok = share_mode_entry_do(
2511 : d,
2512 : open_pid,
2513 : open_file_id,
2514 : del_share_mode_fn,
2515 : &state);
2516 442233 : if (!ok) {
2517 0 : DBG_DEBUG("share_mode_entry_do failed\n");
2518 0 : return false;
2519 : }
2520 442233 : if (!state.ok) {
2521 0 : DBG_DEBUG("del_share_mode_fn failed\n");
2522 0 : return false;
2523 : }
2524 441295 : return true;
2525 : }
2526 :
2527 442233 : bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
2528 : {
2529 938 : struct server_id pid =
2530 442233 : messaging_server_id(fsp->conn->sconn->msg_ctx);
2531 938 : bool ok;
2532 :
2533 442233 : ok = del_share_mode_open_id(lck, pid, fh_get_gen_id(fsp->fh));
2534 442233 : if (!ok) {
2535 0 : struct file_id id = share_mode_lock_file_id(lck);
2536 0 : struct file_id_buf id_buf;
2537 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
2538 : "%s %s\n",
2539 : file_id_str_buf(id, &id_buf),
2540 : fsp_str_dbg(fsp));
2541 0 : return false;
2542 : }
2543 441295 : return true;
2544 : }
2545 :
2546 : struct remove_share_oplock_state {
2547 : bool ok;
2548 : };
2549 :
2550 2646 : static void remove_share_oplock_fn(
2551 : struct share_mode_entry *e,
2552 : size_t num_share_modes,
2553 : bool *modified,
2554 : void *private_data)
2555 : {
2556 2646 : struct remove_share_oplock_state *state = private_data;
2557 :
2558 2646 : e->op_type = NO_OPLOCK;
2559 2646 : *modified = true;
2560 2646 : state->ok = true;
2561 2646 : }
2562 :
2563 2646 : bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2564 : {
2565 2646 : struct remove_share_oplock_state state = { .ok = false };
2566 2646 : struct share_mode_data *d = NULL;
2567 123 : NTSTATUS status;
2568 123 : bool ok;
2569 :
2570 2646 : status = share_mode_lock_access_private_data(lck, &d);
2571 2646 : if (!NT_STATUS_IS_OK(status)) {
2572 0 : struct file_id id = share_mode_lock_file_id(lck);
2573 0 : struct file_id_buf id_buf;
2574 : /* Any error recovery possible here ? */
2575 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
2576 : "%s %s - %s\n",
2577 : file_id_str_buf(id, &id_buf),
2578 : fsp_str_dbg(fsp),
2579 : nt_errstr(status));
2580 0 : return false;
2581 : }
2582 :
2583 5292 : ok = share_mode_entry_do(
2584 : d,
2585 2646 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2586 : fh_get_gen_id(fsp->fh),
2587 : remove_share_oplock_fn,
2588 : &state);
2589 2646 : if (!ok) {
2590 0 : DBG_DEBUG("share_mode_entry_do failed\n");
2591 0 : return false;
2592 : }
2593 2646 : if (!state.ok) {
2594 0 : DBG_DEBUG("remove_share_oplock_fn failed\n");
2595 0 : return false;
2596 : }
2597 :
2598 2646 : if (fsp->oplock_type == LEASE_OPLOCK) {
2599 962 : remove_lease_if_stale(
2600 : lck,
2601 : fsp_client_guid(fsp),
2602 962 : &fsp->lease->lease.lease_key);
2603 : }
2604 :
2605 2646 : share_mode_wakeup_waiters(fsp->file_id);
2606 :
2607 2646 : return true;
2608 : }
2609 :
2610 : struct downgrade_share_oplock_state {
2611 : bool ok;
2612 : };
2613 :
2614 154 : static void downgrade_share_oplock_fn(
2615 : struct share_mode_entry *e,
2616 : size_t num_share_modes,
2617 : bool *modified,
2618 : void *private_data)
2619 : {
2620 154 : struct downgrade_share_oplock_state *state = private_data;
2621 :
2622 154 : e->op_type = LEVEL_II_OPLOCK;
2623 154 : *modified = true;
2624 154 : state->ok = true;
2625 154 : }
2626 :
2627 154 : bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2628 : {
2629 154 : struct downgrade_share_oplock_state state = { .ok = false };
2630 154 : struct share_mode_data *d = NULL;
2631 0 : NTSTATUS status;
2632 0 : bool ok;
2633 :
2634 154 : status = share_mode_lock_access_private_data(lck, &d);
2635 154 : if (!NT_STATUS_IS_OK(status)) {
2636 0 : struct file_id id = share_mode_lock_file_id(lck);
2637 0 : struct file_id_buf id_buf;
2638 : /* Any error recovery possible here ? */
2639 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
2640 : "%s %s - %s\n",
2641 : file_id_str_buf(id, &id_buf),
2642 : fsp_str_dbg(fsp),
2643 : nt_errstr(status));
2644 0 : return false;
2645 : }
2646 :
2647 308 : ok = share_mode_entry_do(
2648 : d,
2649 154 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2650 : fh_get_gen_id(fsp->fh),
2651 : downgrade_share_oplock_fn,
2652 : &state);
2653 154 : if (!ok) {
2654 0 : DBG_DEBUG("share_mode_entry_do failed\n");
2655 0 : return false;
2656 : }
2657 154 : if (!state.ok) {
2658 0 : DBG_DEBUG("downgrade_share_oplock_fn failed\n");
2659 0 : return false;
2660 : }
2661 :
2662 154 : d->flags |= SHARE_MODE_LEASE_READ;
2663 154 : d->modified = true;
2664 :
2665 154 : return true;
2666 : }
2667 :
2668 160 : bool mark_share_mode_disconnected(struct share_mode_lock *lck,
2669 : struct files_struct *fsp)
2670 : {
2671 160 : struct server_id disconnected_pid = { .pid = 0 };
2672 0 : bool ok;
2673 :
2674 160 : if (fsp->op == NULL) {
2675 0 : return false;
2676 : }
2677 160 : if (!fsp->op->global->durable) {
2678 0 : return false;
2679 : }
2680 :
2681 160 : server_id_set_disconnected(&disconnected_pid);
2682 :
2683 160 : ok = reset_share_mode_entry(
2684 : lck,
2685 160 : messaging_server_id(fsp->conn->sconn->msg_ctx),
2686 : fh_get_gen_id(fsp->fh),
2687 : disconnected_pid,
2688 : UINT64_MAX,
2689 160 : fsp->op->global->open_persistent_id);
2690 :
2691 160 : return ok;
2692 : }
2693 :
2694 290 : bool reset_share_mode_entry(
2695 : struct share_mode_lock *lck,
2696 : struct server_id old_pid,
2697 : uint64_t old_share_file_id,
2698 : struct server_id new_pid,
2699 : uint64_t new_mid,
2700 : uint64_t new_share_file_id)
2701 : {
2702 290 : struct file_id id = share_mode_lock_file_id(lck);
2703 290 : struct share_mode_data *d = NULL;
2704 290 : TDB_DATA key = locking_key(&id);
2705 290 : struct locking_tdb_data *ltdb = NULL;
2706 0 : struct share_mode_entry e;
2707 0 : struct share_mode_entry_buf e_buf;
2708 0 : NTSTATUS status;
2709 0 : int cmp;
2710 290 : bool ret = false;
2711 0 : bool ok;
2712 :
2713 290 : status = share_mode_lock_access_private_data(lck, &d);
2714 290 : if (!NT_STATUS_IS_OK(status)) {
2715 0 : struct file_id_buf id_buf;
2716 : /* Any error recovery possible here ? */
2717 0 : DBG_ERR("share_mode_lock_access_private_data() failed for "
2718 : "%s - %s\n",
2719 : file_id_str_buf(id, &id_buf),
2720 : nt_errstr(status));
2721 0 : return false;
2722 : }
2723 :
2724 290 : status = locking_tdb_data_fetch(key, talloc_tos(), <db);
2725 290 : if (!NT_STATUS_IS_OK(status)) {
2726 0 : DBG_ERR("locking_tdb_data_fetch failed: %s\n",
2727 : nt_errstr(status));
2728 0 : return false;
2729 : }
2730 :
2731 290 : if (ltdb->num_share_entries != 1) {
2732 0 : DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
2733 0 : goto done;
2734 : }
2735 :
2736 290 : ok = share_mode_entry_get(ltdb->share_entries, &e);
2737 290 : if (!ok) {
2738 0 : DBG_WARNING("share_mode_entry_get failed\n");
2739 0 : goto done;
2740 : }
2741 :
2742 290 : cmp = share_mode_entry_cmp(
2743 : old_pid, old_share_file_id, e.pid, e.share_file_id);
2744 290 : if (cmp != 0) {
2745 0 : struct server_id_buf tmp1, tmp2;
2746 0 : DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
2747 : "got pid=%s, file_id=%"PRIu64"\n",
2748 : server_id_str_buf(old_pid, &tmp1),
2749 : old_share_file_id,
2750 : server_id_str_buf(e.pid, &tmp2),
2751 : e.share_file_id);
2752 0 : goto done;
2753 : }
2754 :
2755 290 : e.pid = new_pid;
2756 290 : if (new_mid != UINT64_MAX) {
2757 130 : e.op_mid = new_mid;
2758 : }
2759 290 : e.share_file_id = new_share_file_id;
2760 :
2761 290 : ok = share_mode_entry_put(&e, &e_buf);
2762 290 : if (!ok) {
2763 0 : DBG_WARNING("share_mode_entry_put failed\n");
2764 0 : goto done;
2765 : }
2766 :
2767 290 : ltdb->share_entries = e_buf.buf;
2768 :
2769 290 : d->modified = true;
2770 :
2771 290 : status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
2772 290 : if (!NT_STATUS_IS_OK(status)) {
2773 0 : DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
2774 : nt_errstr(status));
2775 0 : goto done;
2776 : }
2777 :
2778 290 : ret = true;
2779 290 : done:
2780 290 : TALLOC_FREE(ltdb);
2781 290 : return ret;
2782 : }
2783 :
2784 : struct share_mode_do_locked_vfs_denied_state {
2785 : struct file_id id;
2786 : share_mode_do_locked_vfs_fn_t fn;
2787 : void *private_data;
2788 : const char *location;
2789 : NTSTATUS status;
2790 : };
2791 :
2792 47316 : static void share_mode_do_locked_vfs_denied_fn(struct g_lock_lock_cb_state *glck,
2793 : void *cb_private)
2794 : {
2795 47316 : struct share_mode_do_locked_vfs_denied_state *state =
2796 : (struct share_mode_do_locked_vfs_denied_state *)cb_private;
2797 47316 : struct smb_vfs_deny_state vfs_deny = {};
2798 435 : struct share_mode_lock lck;
2799 :
2800 47316 : if (glck != NULL) {
2801 41586 : current_share_mode_glck = glck;
2802 : }
2803 :
2804 47316 : state->status = get_share_mode_lock_internal(state->id,
2805 : NULL, /* servicepath */
2806 : NULL, /* smb_fname */
2807 : NULL, /* old_write_time */
2808 : &lck);
2809 47316 : if (!NT_STATUS_IS_OK(state->status)) {
2810 1211 : DBG_GET_SHARE_MODE_LOCK(state->status,
2811 : "get_share_mode_lock_internal failed: %s\n",
2812 : nt_errstr(state->status));
2813 1211 : if (glck != NULL) {
2814 1211 : g_lock_lock_cb_unlock(glck);
2815 1211 : current_share_mode_glck = NULL;
2816 : }
2817 1211 : return;
2818 : }
2819 :
2820 46105 : _smb_vfs_deny_push(&vfs_deny, state->location);
2821 46105 : state->fn(&lck, state->private_data);
2822 46105 : _smb_vfs_deny_pop(&vfs_deny, state->location);
2823 :
2824 46105 : state->status = put_share_mode_lock_internal(&lck);
2825 46105 : if (!NT_STATUS_IS_OK(state->status)) {
2826 0 : DBG_ERR("put_share_mode_lock_internal failed: %s\n",
2827 : nt_errstr(state->status));
2828 0 : smb_panic("put_share_mode_lock_internal failed\n");
2829 : return;
2830 : }
2831 :
2832 46105 : if (glck != NULL) {
2833 40375 : g_lock_lock_cb_unlock(glck);
2834 40375 : current_share_mode_glck = NULL;
2835 : }
2836 45699 : return;
2837 : }
2838 :
2839 : /**
2840 : * @brief Run @fn protected with G_LOCK_WRITE in the given file_id
2841 : *
2842 : * @fn is NOT allowed to call SMB_VFS_* or similar functions,
2843 : * which may block for some time in the kernel.
2844 : *
2845 : * There must be at least one share_mode_entry, otherwise
2846 : * NT_STATUS_NOT_FOUND is returned.
2847 : *
2848 : * @param[in] id The key for the share_mode record.
2849 : * @param[in] fn The function to run under the g_lock.
2850 : * @param[in] private_date A private pointer passed to @fn.
2851 : */
2852 47316 : NTSTATUS _share_mode_do_locked_vfs_denied(
2853 : struct file_id id,
2854 : share_mode_do_locked_vfs_fn_t fn,
2855 : void *private_data,
2856 : const char *location)
2857 : {
2858 47316 : struct share_mode_do_locked_vfs_denied_state state = {
2859 : .id = id,
2860 : .fn = fn,
2861 : .private_data = private_data,
2862 : .location = location,
2863 : };
2864 :
2865 47316 : if (share_mode_lock_key_refcount == 0) {
2866 41586 : TDB_DATA key = locking_key(&id);
2867 302 : NTSTATUS status;
2868 :
2869 41586 : share_mode_lock_skip_g_lock = true;
2870 41586 : status = g_lock_lock(
2871 : lock_ctx,
2872 : key,
2873 : G_LOCK_WRITE,
2874 41586 : (struct timeval) { .tv_sec = 3600 },
2875 : share_mode_do_locked_vfs_denied_fn,
2876 : &state);
2877 41586 : share_mode_lock_skip_g_lock = false;
2878 41586 : if (!NT_STATUS_IS_OK(status)) {
2879 0 : DBG_DEBUG("g_lock_lock failed: %s\n",
2880 : nt_errstr(status));
2881 0 : return status;
2882 : }
2883 41586 : return state.status;
2884 : }
2885 :
2886 5730 : share_mode_do_locked_vfs_denied_fn(NULL, &state);
2887 :
2888 5730 : return state.status;
2889 : }
2890 :
2891 : /**
2892 : * @brief Run @fn protected with G_LOCK_WRITE in the given file_id
2893 : *
2894 : * @fn is allowed to call SMB_VFS_* or similar functions,
2895 : * which may block for some time in the kernel.
2896 : *
2897 : * There must be at least one share_mode_entry, otherwise
2898 : * NT_STATUS_NOT_FOUND is returned.
2899 : *
2900 : * @param[in] id The key for the share_mode record.
2901 : * @param[in] fn The function to run under the g_lock.
2902 : * @param[in] private_date A private pointer passed to @fn.
2903 : */
2904 9297 : NTSTATUS _share_mode_do_locked_vfs_allowed(
2905 : struct file_id id,
2906 : share_mode_do_locked_vfs_fn_t fn,
2907 : void *private_data,
2908 : const char *location)
2909 : {
2910 40 : struct share_mode_lock lck;
2911 40 : NTSTATUS status;
2912 :
2913 9297 : smb_vfs_assert_allowed();
2914 :
2915 9297 : status = get_share_mode_lock_internal(id,
2916 : NULL, /* servicepath */
2917 : NULL, /* smb_fname */
2918 : NULL, /* old_write_time */
2919 : &lck);
2920 9297 : if (!NT_STATUS_IS_OK(status)) {
2921 0 : DBG_GET_SHARE_MODE_LOCK(status,
2922 : "get_share_mode_lock_internal failed: %s\n",
2923 : nt_errstr(status));
2924 0 : return status;
2925 : }
2926 :
2927 9297 : fn(&lck, private_data);
2928 :
2929 9297 : status = put_share_mode_lock_internal(&lck);
2930 9297 : if (!NT_STATUS_IS_OK(status)) {
2931 0 : DBG_ERR("put_share_mode_lock_internal failed: %s\n",
2932 : nt_errstr(status));
2933 0 : smb_panic("put_share_mode_lock_internal failed\n");
2934 : return status;
2935 : }
2936 :
2937 9297 : return NT_STATUS_OK;
2938 : }
2939 :
2940 : struct share_mode_entry_prepare_lock_state {
2941 : struct file_id id;
2942 : const char *servicepath;
2943 : const struct smb_filename *smb_fname;
2944 : const struct timespec *old_write_time;
2945 : share_mode_entry_prepare_lock_fn_t fn;
2946 : void *private_data;
2947 : const char *location;
2948 : bool keep_locked;
2949 : struct share_mode_lock *lck;
2950 : NTSTATUS status;
2951 : };
2952 :
2953 895386 : static void share_mode_entry_prepare_lock_fn(struct g_lock_lock_cb_state *glck,
2954 : void *cb_private)
2955 : {
2956 895386 : struct share_mode_entry_prepare_lock_state *state =
2957 : (struct share_mode_entry_prepare_lock_state *)cb_private;
2958 895386 : struct smb_vfs_deny_state vfs_deny = {};
2959 :
2960 895386 : SMB_ASSERT(glck != NULL);
2961 895386 : current_share_mode_glck = glck;
2962 :
2963 895386 : state->status = get_share_mode_lock_internal(state->id,
2964 : state->servicepath,
2965 : state->smb_fname,
2966 : state->old_write_time,
2967 : state->lck);
2968 895386 : if (!NT_STATUS_IS_OK(state->status)) {
2969 : /* no DBG_GET_SHARE_MODE_LOCK here! */
2970 0 : DBG_ERR("get_share_mode_lock_internal failed: %s\n",
2971 : nt_errstr(state->status));
2972 0 : g_lock_lock_cb_unlock(glck);
2973 0 : current_share_mode_glck = NULL;
2974 0 : return;
2975 : }
2976 :
2977 895386 : _smb_vfs_deny_push(&vfs_deny, state->location);
2978 895386 : state->fn(state->lck, &state->keep_locked, state->private_data);
2979 895386 : _smb_vfs_deny_pop(&vfs_deny, state->location);
2980 :
2981 895386 : if (state->keep_locked) {
2982 479288 : current_share_mode_glck = NULL;
2983 479288 : return;
2984 : }
2985 :
2986 416098 : state->status = put_share_mode_lock_internal(state->lck);
2987 416098 : if (!NT_STATUS_IS_OK(state->status)) {
2988 0 : DBG_ERR("put_share_mode_lock_internal failed: %s\n",
2989 : nt_errstr(state->status));
2990 0 : smb_panic("put_share_mode_lock_internal failed\n");
2991 : return;
2992 : }
2993 :
2994 416098 : g_lock_lock_cb_unlock(glck);
2995 416098 : current_share_mode_glck = NULL;
2996 416098 : return;
2997 : }
2998 :
2999 895386 : NTSTATUS _share_mode_entry_prepare_lock(
3000 : struct share_mode_entry_prepare_state *prepare_state,
3001 : struct file_id id,
3002 : const char *servicepath,
3003 : const struct smb_filename *smb_fname,
3004 : const struct timespec *old_write_time,
3005 : share_mode_entry_prepare_lock_fn_t fn,
3006 : void *private_data,
3007 : const char *location)
3008 : {
3009 895386 : struct share_mode_entry_prepare_lock_state state = {
3010 : .id = id,
3011 : .servicepath = servicepath,
3012 : .smb_fname = smb_fname,
3013 : .old_write_time = old_write_time,
3014 : .fn = fn,
3015 : .private_data = private_data,
3016 : .location = location,
3017 : };
3018 895386 : TDB_DATA key = locking_key(&id);
3019 1929 : NTSTATUS status;
3020 :
3021 895386 : SMB_ASSERT(share_mode_lock_key_refcount == 0);
3022 :
3023 1929 : SMB_ASSERT(__SHARE_MODE_LOCK_SPACE >= sizeof(struct share_mode_lock));
3024 :
3025 895386 : *prepare_state = (struct share_mode_entry_prepare_state) {
3026 : .__fid = id,
3027 895386 : .__lck_ptr = &prepare_state->__lck_space,
3028 : };
3029 :
3030 895386 : state.lck = prepare_state->__lck_ptr;
3031 :
3032 895386 : share_mode_lock_skip_g_lock = true;
3033 895386 : status = g_lock_lock(
3034 : lock_ctx,
3035 : key,
3036 : G_LOCK_WRITE,
3037 895386 : (struct timeval) { .tv_sec = 3600 },
3038 : share_mode_entry_prepare_lock_fn,
3039 : &state);
3040 895386 : share_mode_lock_skip_g_lock = false;
3041 895386 : if (!state.keep_locked) {
3042 416098 : prepare_state->__lck_ptr = NULL;
3043 : }
3044 895386 : if (!NT_STATUS_IS_OK(status)) {
3045 0 : DBG_DEBUG("g_lock_lock failed: %s\n",
3046 : nt_errstr(status));
3047 0 : return status;
3048 : }
3049 :
3050 895386 : return state.status;
3051 : }
3052 :
3053 : struct share_mode_entry_prepare_unlock_state {
3054 : struct file_id id;
3055 : share_mode_entry_prepare_unlock_fn_t fn;
3056 : void *private_data;
3057 : const char *location;
3058 : struct share_mode_lock *lck;
3059 : NTSTATUS status;
3060 : };
3061 :
3062 479288 : static void share_mode_entry_prepare_unlock_existing_fn(
3063 : struct share_mode_entry_prepare_unlock_state *state)
3064 : {
3065 479288 : if (state->fn != NULL) {
3066 170351 : struct smb_vfs_deny_state vfs_deny = {};
3067 :
3068 170351 : _smb_vfs_deny_push(&vfs_deny, state->location);
3069 170351 : state->fn(state->lck, state->private_data);
3070 170351 : _smb_vfs_deny_pop(&vfs_deny, state->location);
3071 : }
3072 :
3073 479288 : state->status = put_share_mode_lock_internal(state->lck);
3074 479288 : if (!NT_STATUS_IS_OK(state->status)) {
3075 0 : DBG_ERR("put_share_mode_lock_internal failed: %s\n",
3076 : nt_errstr(state->status));
3077 0 : smb_panic("put_share_mode_lock_internal failed\n");
3078 : return;
3079 : }
3080 :
3081 479288 : return;
3082 : }
3083 :
3084 2 : static void share_mode_entry_prepare_unlock_relock_fn(struct g_lock_lock_cb_state *glck,
3085 : void *cb_private)
3086 : {
3087 2 : struct share_mode_entry_prepare_unlock_state *state =
3088 : (struct share_mode_entry_prepare_unlock_state *)cb_private;
3089 2 : struct smb_vfs_deny_state vfs_deny = {};
3090 :
3091 2 : SMB_ASSERT(glck != NULL);
3092 2 : current_share_mode_glck = glck;
3093 :
3094 2 : state->status = get_share_mode_lock_internal(state->id,
3095 : NULL, /* servicepath */
3096 : NULL, /* smb_fname */
3097 : NULL, /* old_write_time */
3098 : state->lck);
3099 2 : if (!NT_STATUS_IS_OK(state->status)) {
3100 : /* no DBG_GET_SHARE_MODE_LOCK here! */
3101 0 : DBG_ERR("get_share_mode_lock_internal failed: %s\n",
3102 : nt_errstr(state->status));
3103 0 : g_lock_lock_cb_unlock(glck);
3104 0 : current_share_mode_glck = NULL;
3105 0 : return;
3106 : }
3107 :
3108 2 : _smb_vfs_deny_push(&vfs_deny, state->location);
3109 2 : state->fn(state->lck, state->private_data);
3110 2 : _smb_vfs_deny_pop(&vfs_deny, state->location);
3111 :
3112 2 : state->status = put_share_mode_lock_internal(state->lck);
3113 2 : if (!NT_STATUS_IS_OK(state->status)) {
3114 0 : DBG_ERR("put_share_mode_lock_internal failed: %s\n",
3115 : nt_errstr(state->status));
3116 0 : smb_panic("put_share_mode_lock_internal failed\n");
3117 : return;
3118 : }
3119 :
3120 2 : g_lock_lock_cb_unlock(glck);
3121 2 : current_share_mode_glck = NULL;
3122 2 : return;
3123 : }
3124 :
3125 884488 : NTSTATUS _share_mode_entry_prepare_unlock(
3126 : struct share_mode_entry_prepare_state *prepare_state,
3127 : share_mode_entry_prepare_unlock_fn_t fn,
3128 : void *private_data,
3129 : const char *location)
3130 : {
3131 884488 : struct share_mode_entry_prepare_unlock_state state = {
3132 : .id = prepare_state->__fid,
3133 : .fn = fn,
3134 : .private_data = private_data,
3135 : .location = location,
3136 : };
3137 884488 : TDB_DATA key = locking_key(&prepare_state->__fid);
3138 1876 : NTSTATUS status;
3139 :
3140 884488 : if (prepare_state->__lck_ptr != NULL) {
3141 : /*
3142 : * With an existing lock, we just run the unlock prepare
3143 : * function following by the unlock.
3144 : */
3145 :
3146 479288 : SMB_ASSERT(share_mode_lock_key_refcount == 1);
3147 :
3148 479288 : state.lck = prepare_state->__lck_ptr;
3149 479288 : prepare_state->__lck_ptr = NULL;
3150 :
3151 479288 : share_mode_entry_prepare_unlock_existing_fn(&state);
3152 479288 : return state.status;
3153 : }
3154 :
3155 : /*
3156 : * No existing lock, which means
3157 : * _share_mode_entry_prepare_lock() didn't steal
3158 : * the lock...
3159 : */
3160 405200 : SMB_ASSERT(share_mode_lock_key_refcount == 0);
3161 :
3162 405200 : if (fn == NULL) {
3163 : /*
3164 : * Without an existing lock and without
3165 : * a prepare function there's nothing to
3166 : * do...
3167 : */
3168 405198 : return NT_STATUS_OK;
3169 : }
3170 :
3171 : /*
3172 : * In order to run the unlock prepare function
3173 : * we need to relock the entry.
3174 : */
3175 2 : state.lck = &prepare_state->__lck_space;
3176 :
3177 2 : share_mode_lock_skip_g_lock = true;
3178 2 : status = g_lock_lock(
3179 : lock_ctx,
3180 : key,
3181 : G_LOCK_WRITE,
3182 2 : (struct timeval) { .tv_sec = 3600 },
3183 : share_mode_entry_prepare_unlock_relock_fn,
3184 : &state);
3185 2 : share_mode_lock_skip_g_lock = false;
3186 2 : if (!NT_STATUS_IS_OK(status)) {
3187 0 : DBG_ERR("g_lock_lock failed: %s\n",
3188 : nt_errstr(status));
3189 0 : return status;
3190 : }
3191 :
3192 2 : return state.status;
3193 : }
|