87468bd7f3f4d9257f82f47482969838679a3606
[amitay/samba.git] / source3 / locking / share_mode_lock.c
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 "system/filesys.h"
40 #include "lib/util/server_id.h"
41 #include "locking/proto.h"
42 #include "smbd/globals.h"
43 #include "dbwrap/dbwrap.h"
44 #include "dbwrap/dbwrap_open.h"
45 #include "../libcli/security/security.h"
46 #include "serverid.h"
47 #include "messages.h"
48 #include "util_tdb.h"
49 #include "../librpc/gen_ndr/ndr_open_files.h"
50 #include "source3/lib/dbwrap/dbwrap_watch.h"
51 #include "locking/leases_db.h"
52 #include "../lib/util/memcache.h"
53 #include "lib/util/tevent_ntstatus.h"
54
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_LOCKING
57
58 #define NO_LOCKING_COUNT (-1)
59
60 /* the locking database handle */
61 static struct db_context *lock_db;
62 static struct db_context *share_entries_db;
63
64 static bool locking_init_internal(bool read_only)
65 {
66         struct db_context *backend;
67         char *db_path;
68
69         brl_init(read_only);
70
71         if (lock_db)
72                 return True;
73
74         db_path = lock_path(talloc_tos(), "locking.tdb");
75         if (db_path == NULL) {
76                 return false;
77         }
78
79         backend = db_open(NULL, db_path,
80                           SMB_OPEN_DATABASE_TDB_HASH_SIZE,
81                           TDB_DEFAULT|
82                           TDB_VOLATILE|
83                           TDB_CLEAR_IF_FIRST|
84                           TDB_INCOMPATIBLE_HASH|
85                           TDB_SEQNUM,
86                           read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
87                           DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
88         TALLOC_FREE(db_path);
89         if (!backend) {
90                 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
91                 return False;
92         }
93
94         lock_db = db_open_watched(NULL, &backend, global_messaging_context());
95         if (lock_db == NULL) {
96                 DBG_ERR("db_open_watched failed\n");
97                 TALLOC_FREE(backend);
98                 return false;
99         }
100
101         db_path = lock_path(talloc_tos(), "share_entries.tdb");
102         if (db_path == NULL) {
103                 return false;
104         }
105
106         share_entries_db = db_open(
107                 NULL, db_path,
108                 SMB_OPEN_DATABASE_TDB_HASH_SIZE,
109                 TDB_DEFAULT|
110                 TDB_VOLATILE|
111                 TDB_CLEAR_IF_FIRST|
112                 TDB_INCOMPATIBLE_HASH,
113                 read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
114                 DBWRAP_LOCK_ORDER_3, DBWRAP_FLAG_NONE);
115         TALLOC_FREE(db_path);
116
117         if (share_entries_db == NULL) {
118                 TALLOC_FREE(lock_db);
119                 return false;
120         }
121
122         if (!posix_locking_init(read_only)) {
123                 TALLOC_FREE(share_entries_db);
124                 TALLOC_FREE(lock_db);
125                 return False;
126         }
127
128         return True;
129 }
130
131 bool locking_init(void)
132 {
133         return locking_init_internal(false);
134 }
135
136 bool locking_init_readonly(void)
137 {
138         return locking_init_internal(true);
139 }
140
141 /*******************************************************************
142  Deinitialize the share_mode management.
143 ******************************************************************/
144
145 bool locking_end(void)
146 {
147         brl_shutdown();
148         TALLOC_FREE(lock_db);
149         return true;
150 }
151
152 /*******************************************************************
153  Form a static locking key for a dev/inode pair.
154 ******************************************************************/
155
156 static TDB_DATA locking_key(const struct file_id *id)
157 {
158         return make_tdb_data((const uint8_t *)id, sizeof(*id));
159 }
160
161 /*******************************************************************
162  Share mode cache utility functions that store/delete/retrieve
163  entries from memcache.
164
165  For now share the statcache (global cache) memory space. If
166  a lock record gets orphaned (which shouldn't happen as we're
167  using the same locking_key data as lookup) it will eventually
168  fall out of the cache via the normal LRU trim mechanism. If
169  necessary we can always make this a separate (smaller) cache.
170 ******************************************************************/
171
172 static DATA_BLOB memcache_key(const struct file_id *id)
173 {
174         return data_blob_const((const void *)id, sizeof(*id));
175 }
176
177 static void share_mode_memcache_store(struct share_mode_data *d)
178 {
179         const DATA_BLOB key = memcache_key(&d->id);
180         struct file_id_buf idbuf;
181
182         DBG_DEBUG("stored entry for file %s seq %"PRIx64" key %s\n",
183                   d->base_name,
184                   d->sequence_number,
185                   file_id_str_buf(d->id, &idbuf));
186
187         /* Ensure everything stored in the cache is pristine. */
188         d->modified = false;
189         d->fresh = false;
190
191         /*
192          * Ensure the memory going into the cache
193          * doesn't have a destructor so it can be
194          * cleanly evicted by the memcache LRU
195          * mechanism.
196          */
197         talloc_set_destructor(d, NULL);
198
199         /* Cache will own d after this call. */
200         memcache_add_talloc(NULL,
201                         SHARE_MODE_LOCK_CACHE,
202                         key,
203                         &d);
204 }
205
206 /*
207  * NB. We use ndr_pull_hyper on a stack-created
208  * struct ndr_pull with no talloc allowed, as we
209  * need this to be really fast as an ndr-peek into
210  * the first 10 bytes of the blob.
211  */
212
213 static enum ndr_err_code get_share_mode_blob_header(
214         DATA_BLOB *blob, uint64_t *pseq, uint16_t *pflags)
215 {
216         struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length};
217         NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq));
218         NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
219         return NDR_ERR_SUCCESS;
220 }
221
222 struct fsp_update_share_mode_flags_state {
223         enum ndr_err_code ndr_err;
224         uint16_t share_mode_flags;
225 };
226
227 static void fsp_update_share_mode_flags_fn(
228         TDB_DATA value, bool *modified_dependent, void *private_data)
229 {
230         struct fsp_update_share_mode_flags_state *state = private_data;
231         DATA_BLOB blob = { .data = value.dptr, .length = value.dsize };
232         uint64_t seq;
233
234         state->ndr_err = get_share_mode_blob_header(
235                 &blob, &seq, &state->share_mode_flags);
236 }
237
238 static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
239 {
240         struct fsp_update_share_mode_flags_state state = {0};
241         int seqnum = dbwrap_get_seqnum(lock_db);
242         NTSTATUS status;
243
244         if (seqnum == fsp->share_mode_flags_seqnum) {
245                 return NT_STATUS_OK;
246         }
247
248         status = share_mode_do_locked(
249                 fsp->file_id, fsp_update_share_mode_flags_fn, &state);
250         if (!NT_STATUS_IS_OK(status)) {
251                 DBG_DEBUG("share_mode_do_locked returned %s\n",
252                           nt_errstr(status));
253                 return status;
254         }
255
256         if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
257                 DBG_DEBUG("get_share_mode_blob_header returned %s\n",
258                           ndr_errstr(state.ndr_err));
259                 return ndr_map_error2ntstatus(state.ndr_err);
260         }
261
262         fsp->share_mode_flags_seqnum = seqnum;
263         fsp->share_mode_flags = state.share_mode_flags;
264
265         return NT_STATUS_OK;
266 }
267
268 bool file_has_read_lease(struct files_struct *fsp)
269 {
270         NTSTATUS status;
271
272         status = fsp_update_share_mode_flags(fsp);
273         if (!NT_STATUS_IS_OK(status)) {
274                 /* Safe default for leases */
275                 return true;
276         }
277
278         return (fsp->share_mode_flags & SHARE_MODE_LEASE_READ) != 0;
279 }
280
281 static int share_mode_data_nofree_destructor(struct share_mode_data *d)
282 {
283         return -1;
284 }
285
286 static struct share_mode_data *share_mode_memcache_fetch(TALLOC_CTX *mem_ctx,
287                                         const TDB_DATA id_key,
288                                         DATA_BLOB *blob)
289 {
290         enum ndr_err_code ndr_err;
291         struct share_mode_data *d;
292         uint64_t sequence_number;
293         uint16_t flags;
294         void *ptr;
295         struct file_id id;
296         struct file_id_buf idbuf;
297         DATA_BLOB key;
298
299         /* Ensure this is a locking_key record. */
300         if (id_key.dsize != sizeof(id)) {
301                 return NULL;
302         }
303
304         memcpy(&id, id_key.dptr, id_key.dsize);
305         key = memcache_key(&id);
306
307         ptr = memcache_lookup_talloc(NULL,
308                         SHARE_MODE_LOCK_CACHE,
309                         key);
310         if (ptr == NULL) {
311                 DBG_DEBUG("failed to find entry for key %s\n",
312                           file_id_str_buf(id, &idbuf));
313                 return NULL;
314         }
315         /* sequence number key is at start of blob. */
316         ndr_err = get_share_mode_blob_header(blob, &sequence_number, &flags);
317         if (ndr_err != NDR_ERR_SUCCESS) {
318                 /* Bad blob. Remove entry. */
319                 DBG_DEBUG("bad blob %u key %s\n",
320                           (unsigned int)ndr_err,
321                           file_id_str_buf(id, &idbuf));
322                 memcache_delete(NULL,
323                         SHARE_MODE_LOCK_CACHE,
324                         key);
325                 return NULL;
326         }
327
328         d = (struct share_mode_data *)ptr;
329         if (d->sequence_number != sequence_number) {
330                 DBG_DEBUG("seq changed (cached %"PRIx64") (new %"PRIx64") "
331                           "for key %s\n",
332                           d->sequence_number,
333                           sequence_number,
334                           file_id_str_buf(id, &idbuf));
335                 /* Cache out of date. Remove entry. */
336                 memcache_delete(NULL,
337                         SHARE_MODE_LOCK_CACHE,
338                         key);
339                 return NULL;
340         }
341
342         /* Move onto mem_ctx. */
343         d = talloc_move(mem_ctx, &ptr);
344
345         /*
346          * Now we own d, prevent the cache from freeing it
347          * when we delete the entry.
348          */
349         talloc_set_destructor(d, share_mode_data_nofree_destructor);
350
351         /* Remove from the cache. We own it now. */
352         memcache_delete(NULL,
353                         SHARE_MODE_LOCK_CACHE,
354                         key);
355
356         /* And reset the destructor to none. */
357         talloc_set_destructor(d, NULL);
358
359         DBG_DEBUG("fetched entry for file %s seq %"PRIx64" key %s\n",
360                   d->base_name,
361                   d->sequence_number,
362                   file_id_str_buf(id, &idbuf));
363
364         return d;
365 }
366
367 /*******************************************************************
368  Get all share mode entries for a dev/inode pair.
369 ********************************************************************/
370
371 static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
372                                                 const TDB_DATA key,
373                                                 const TDB_DATA dbuf)
374 {
375         struct share_mode_data *d;
376         enum ndr_err_code ndr_err;
377         DATA_BLOB blob;
378
379         blob.data = dbuf.dptr;
380         blob.length = dbuf.dsize;
381
382         /* See if we already have a cached copy of this key. */
383         d = share_mode_memcache_fetch(mem_ctx, key, &blob);
384         if (d != NULL) {
385                 return d;
386         }
387
388         d = talloc(mem_ctx, struct share_mode_data);
389         if (d == NULL) {
390                 DEBUG(0, ("talloc failed\n"));
391                 goto fail;
392         }
393
394         ndr_err = ndr_pull_struct_blob_all(
395                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
396         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
397                 DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
398                             ndr_errstr(ndr_err));
399                 goto fail;
400         }
401
402         if (DEBUGLEVEL >= 10) {
403                 DEBUG(10, ("parse_share_modes:\n"));
404                 NDR_PRINT_DEBUG(share_mode_data, d);
405         }
406
407         /*
408          * We have a non-zero locking.tdb record that was correctly
409          * parsed. This means a share_entries.tdb entry exists,
410          * otherwise we'd have paniced before in
411          * share_mode_data_store()
412          */
413         d->have_share_modes = true;
414
415         return d;
416 fail:
417         TALLOC_FREE(d);
418         return NULL;
419 }
420
421 /*******************************************************************
422  If modified, store the share_mode_data back into the database.
423 ********************************************************************/
424
425 static NTSTATUS share_mode_data_store(
426         struct share_mode_data *d, struct db_record *rec)
427 {
428         DATA_BLOB blob;
429         enum ndr_err_code ndr_err;
430         NTSTATUS status;
431
432         if (!d->modified) {
433                 DBG_DEBUG("not modified\n");
434                 return NT_STATUS_OK;
435         }
436
437         if (DEBUGLEVEL >= 10) {
438                 DBG_DEBUG("\n");
439                 NDR_PRINT_DEBUG(share_mode_data, d);
440         }
441
442         d->sequence_number += 1;
443
444         if (!d->have_share_modes) {
445                 TDB_DATA key = dbwrap_record_get_key(rec);
446                 bool share_entries_exist;
447                 share_entries_exist = dbwrap_exists(share_entries_db, key);
448                 SMB_ASSERT(!share_entries_exist);
449
450                 TALLOC_FREE(d->delete_tokens);
451                 d->num_delete_tokens = 0;
452
453                 if (d->fresh) {
454                         DBG_DEBUG("Ignoring fresh empty record\n");
455                         return NT_STATUS_OK;
456                 }
457                 status = dbwrap_record_delete(rec);
458                 return status;
459         }
460
461         ndr_err = ndr_push_struct_blob(
462                 &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data);
463         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
464                 DBG_DEBUG("ndr_push_share_mode_data failed: %s\n",
465                           ndr_errstr(ndr_err));
466                 return ndr_map_error2ntstatus(ndr_err);
467         }
468
469         status = dbwrap_record_store(
470                 rec,
471                 (TDB_DATA) { .dptr = blob.data, .dsize = blob.length },
472                 TDB_REPLACE);
473         TALLOC_FREE(blob.data);
474
475         if (!NT_STATUS_IS_OK(status)) {
476                 DBG_DEBUG("dbwrap_record_store failed: %s\n",
477                           nt_errstr(status));
478         }
479
480         return status;
481 }
482
483 /*******************************************************************
484  Allocate a new share_mode_data struct, mark it unmodified.
485  fresh is set to note that currently there is no database entry.
486 ********************************************************************/
487
488 static struct share_mode_data *fresh_share_mode_lock(
489         TALLOC_CTX *mem_ctx, const char *servicepath,
490         const struct smb_filename *smb_fname,
491         const struct timespec *old_write_time)
492 {
493         struct share_mode_data *d;
494
495         if ((servicepath == NULL) || (smb_fname == NULL) ||
496             (old_write_time == NULL)) {
497                 return NULL;
498         }
499
500         d = talloc_zero(mem_ctx, struct share_mode_data);
501         if (d == NULL) {
502                 goto fail;
503         }
504         /* New record - new sequence number. */
505         generate_random_buffer((uint8_t *)&d->sequence_number, 8);
506
507         d->base_name = talloc_strdup(d, smb_fname->base_name);
508         if (d->base_name == NULL) {
509                 goto fail;
510         }
511         if (smb_fname->stream_name != NULL) {
512                 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
513                 if (d->stream_name == NULL) {
514                         goto fail;
515                 }
516         }
517         d->servicepath = talloc_strdup(d, servicepath);
518         if (d->servicepath == NULL) {
519                 goto fail;
520         }
521         d->old_write_time = full_timespec_to_nt_time(old_write_time);
522         d->modified = false;
523         d->fresh = true;
524         return d;
525 fail:
526         DEBUG(0, ("talloc failed\n"));
527         TALLOC_FREE(d);
528         return NULL;
529 }
530
531 /*
532  * We can only ever have one share mode locked. Use a static
533  * share_mode_data pointer that is shared by multiple nested
534  * share_mode_lock structures, explicitly refcounted.
535  */
536 static struct share_mode_data *static_share_mode_data = NULL;
537 static size_t static_share_mode_data_refcount = 0;
538
539 /*
540  * db_record for the above. With dbwrap_do_locked we can get a
541  * db_record on the stack, which we can't TALLOC_FREE but which we
542  * need to share with a nested get_share_mode_lock call.
543  */
544 static struct db_record *static_share_mode_record = NULL;
545 static TDB_DATA static_share_mode_record_value = {0};
546 static bool static_share_mode_record_talloced = false;
547
548 /*******************************************************************
549  Either fetch a share mode from the database, or allocate a fresh
550  one if the record doesn't exist.
551 ********************************************************************/
552
553 static NTSTATUS get_static_share_mode_data(
554         struct db_record *rec,
555         struct file_id id,
556         const char *servicepath,
557         const struct smb_filename *smb_fname,
558         const struct timespec *old_write_time)
559 {
560         struct share_mode_data *d;
561         TDB_DATA value = dbwrap_record_get_value(rec);
562
563         SMB_ASSERT(static_share_mode_data == NULL);
564
565         if (value.dptr == NULL) {
566                 d = fresh_share_mode_lock(
567                         lock_db, servicepath, smb_fname, old_write_time);
568                 if (d == NULL) {
569                         if (smb_fname == NULL) {
570                                 return NT_STATUS_NOT_FOUND;
571                         }
572                         return NT_STATUS_NO_MEMORY;
573                 }
574         } else {
575                 TDB_DATA key = locking_key(&id);
576                 d = parse_share_modes(lock_db, key, value);
577                 if (d == NULL) {
578                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
579                 }
580         }
581
582         d->id = id;
583
584         static_share_mode_data = d;
585
586         return NT_STATUS_OK;
587 }
588
589 /*******************************************************************
590  Get a share_mode_lock, Reference counted to allow nested calls.
591 ********************************************************************/
592
593 static int share_mode_lock_destructor(struct share_mode_lock *lck);
594
595 struct share_mode_lock *get_share_mode_lock(
596         TALLOC_CTX *mem_ctx,
597         struct file_id id,
598         const char *servicepath,
599         const struct smb_filename *smb_fname,
600         const struct timespec *old_write_time)
601 {
602         TDB_DATA key = locking_key(&id);
603         struct share_mode_lock *lck = NULL;
604         NTSTATUS status;
605
606         lck = talloc(mem_ctx, struct share_mode_lock);
607         if (lck == NULL) {
608                 DEBUG(1, ("talloc failed\n"));
609                 return NULL;
610         }
611
612         if (static_share_mode_data != NULL) {
613                 if (!file_id_equal(&static_share_mode_data->id, &id)) {
614                         DEBUG(1, ("Can not lock two share modes "
615                                   "simultaneously\n"));
616                         goto fail;
617                 }
618                 goto done;
619         }
620
621         SMB_ASSERT(static_share_mode_data_refcount == 0);
622
623         if (static_share_mode_record == NULL) {
624                 static_share_mode_record = dbwrap_fetch_locked(
625                         lock_db, lock_db, key);
626                 if (static_share_mode_record == NULL) {
627                         DEBUG(3, ("Could not lock share entry\n"));
628                         goto fail;
629                 }
630                 static_share_mode_record_talloced = true;
631                 static_share_mode_record_value = dbwrap_record_get_value(
632                         static_share_mode_record);
633
634         } else {
635                 TDB_DATA static_key;
636                 int cmp;
637
638                 static_key = dbwrap_record_get_key(static_share_mode_record);
639
640                 cmp = tdb_data_cmp(static_key, key);
641                 if (cmp != 0) {
642                         DBG_WARNING("Can not lock two share modes "
643                                     "simultaneously\n");
644                         return NULL;
645                 }
646         }
647
648         status = get_static_share_mode_data(static_share_mode_record,
649                                             id,
650                                             servicepath,
651                                             smb_fname,
652                                             old_write_time);
653         if (!NT_STATUS_IS_OK(status)) {
654                 DBG_DEBUG("get_static_share_mode_data failed: %s\n",
655                           nt_errstr(status));
656                 TALLOC_FREE(static_share_mode_record);
657                 goto fail;
658         }
659
660 done:
661         static_share_mode_data_refcount += 1;
662         lck->data = static_share_mode_data;
663
664         talloc_set_destructor(lck, share_mode_lock_destructor);
665
666         return lck;
667 fail:
668         TALLOC_FREE(lck);
669         return NULL;
670 }
671
672 static int share_mode_lock_destructor(struct share_mode_lock *lck)
673 {
674         NTSTATUS status;
675
676         SMB_ASSERT(static_share_mode_data_refcount > 0);
677         static_share_mode_data_refcount -= 1;
678
679         if (static_share_mode_data_refcount > 0) {
680                 return 0;
681         }
682
683         status = share_mode_data_store(
684                 static_share_mode_data, static_share_mode_record);
685         if (!NT_STATUS_IS_OK(status)) {
686                 DBG_ERR("share_mode_data_store failed: %s\n",
687                         nt_errstr(status));
688                 smb_panic("Could not store share mode data\n");
689         }
690
691         if (static_share_mode_record_talloced) {
692                 TALLOC_FREE(static_share_mode_record);
693         }
694
695         if (static_share_mode_data->have_share_modes) {
696                 /*
697                  * This is worth keeping. Without share modes,
698                  * share_mode_data_store above has left nothing in the
699                  * database.
700                  */
701                 share_mode_memcache_store(static_share_mode_data);
702                 static_share_mode_data = NULL;
703         } else {
704                 /*
705                  * The next opener of this file will find an empty
706                  * locking.tdb record. Don't store the share_mode_data
707                  * in the memcache, fresh_share_mode_lock() will
708                  * generate a fresh seqnum anyway, obsoleting the
709                  * cache entry.
710                  */
711                 TALLOC_FREE(static_share_mode_data);
712         }
713
714         return 0;
715 }
716
717 struct share_mode_do_locked_state {
718         void (*fn)(TDB_DATA value,
719                    bool *modified_dependent,
720                    void *private_data);
721         void *private_data;
722 };
723
724 static void share_mode_do_locked_fn(
725         struct db_record *rec,
726         TDB_DATA value,
727         void *private_data)
728 {
729         struct share_mode_do_locked_state *state = private_data;
730         bool modified_dependent = false;
731         bool reset_static_share_mode_record = false;
732
733         if (static_share_mode_record == NULL) {
734                 static_share_mode_record = rec;
735                 static_share_mode_record_value = value;
736                 static_share_mode_record_talloced = false;
737                 reset_static_share_mode_record = true;
738         } else {
739                 SMB_ASSERT(static_share_mode_record == rec);
740         }
741
742         state->fn(value, &modified_dependent, state->private_data);
743
744         if (modified_dependent) {
745                 dbwrap_watched_wakeup(rec);
746         }
747
748         if (reset_static_share_mode_record) {
749                 static_share_mode_record = NULL;
750         }
751 }
752
753 NTSTATUS share_mode_do_locked(
754         struct file_id id,
755         void (*fn)(TDB_DATA value,
756                    bool *modified_dependent,
757                    void *private_data),
758         void *private_data)
759 {
760         TDB_DATA key = locking_key(&id);
761         size_t refcount = static_share_mode_data_refcount;
762
763         if (static_share_mode_record != NULL) {
764                 bool modified_dependent = false;
765                 TDB_DATA static_key;
766                 int cmp;
767
768                 static_key = dbwrap_record_get_key(static_share_mode_record);
769
770                 cmp = tdb_data_cmp(static_key, key);
771                 if (cmp != 0) {
772                         DBG_WARNING("Can not lock two share modes "
773                                     "simultaneously\n");
774                         return NT_STATUS_INVALID_LOCK_SEQUENCE;
775                 }
776
777                 fn(static_share_mode_record_value,
778                    &modified_dependent,
779                    private_data);
780
781                 if (modified_dependent) {
782                         dbwrap_watched_wakeup(static_share_mode_record);
783                 }
784         } else {
785                 struct share_mode_do_locked_state state = {
786                         .fn = fn, .private_data = private_data,
787                 };
788                 NTSTATUS status;
789
790                 status = dbwrap_do_locked(
791                         lock_db, key, share_mode_do_locked_fn, &state);
792                 if (!NT_STATUS_IS_OK(status)) {
793                         DBG_WARNING("dbwrap_do_locked failed: %s\n",
794                                     nt_errstr(status));
795                         return status;
796                 }
797         }
798
799         SMB_ASSERT(refcount == static_share_mode_data_refcount);
800
801         return NT_STATUS_OK;
802 }
803
804 static void share_mode_wakeup_waiters_fn(TDB_DATA value,
805                                          bool *modified_dependent,
806                                          void *private_data)
807 {
808         *modified_dependent = true;
809 }
810
811 NTSTATUS share_mode_wakeup_waiters(struct file_id id)
812 {
813         return share_mode_do_locked(id, share_mode_wakeup_waiters_fn, NULL);
814 }
815
816 bool share_mode_have_entries(struct share_mode_lock *lck)
817 {
818         return lck->data->have_share_modes;
819 }
820
821 struct share_mode_watch_state {
822         struct tevent_context *ev;
823         bool blockerdead;
824         struct server_id blocker;
825         struct tevent_req *subreq;
826 };
827
828 static void share_mode_watch_fn(
829         TDB_DATA value, bool *modified_dependent, void *private_data)
830 {
831         struct share_mode_watch_state *state = talloc_get_type_abort(
832                 private_data, struct share_mode_watch_state);
833
834         state->subreq = dbwrap_watched_watch_send(
835                 state, state->ev, static_share_mode_record, state->blocker);
836 }
837
838 static void share_mode_watch_done(struct tevent_req *subreq);
839
840 struct tevent_req *share_mode_watch_send(
841         TALLOC_CTX *mem_ctx,
842         struct tevent_context *ev,
843         struct file_id id,
844         struct server_id blocker)
845 {
846         struct tevent_req *req = NULL;
847         struct share_mode_watch_state *state = NULL;
848         NTSTATUS status;
849
850         req = tevent_req_create(
851                 mem_ctx, &state, struct share_mode_watch_state);
852         if (req == NULL) {
853                 return NULL;
854         }
855         state->ev = ev;
856         state->blocker = blocker;
857
858         status = share_mode_do_locked(id, share_mode_watch_fn, state);
859         if (tevent_req_nterror(req, status)) {
860                 return tevent_req_post(req, ev);
861         }
862         if (tevent_req_nomem(state->subreq, req)) {
863                 return tevent_req_post(req, ev);
864         }
865         tevent_req_set_callback(state->subreq, share_mode_watch_done, req);
866         return req;
867 }
868
869 static void share_mode_watch_done(struct tevent_req *subreq)
870 {
871         struct tevent_req *req = tevent_req_callback_data(
872                 subreq, struct tevent_req);
873         struct share_mode_watch_state *state = tevent_req_data(
874                 req, struct share_mode_watch_state);
875         NTSTATUS status;
876
877         status = dbwrap_watched_watch_recv(
878                 subreq, &state->blockerdead, &state->blocker);
879         if (tevent_req_nterror(req, status)) {
880                 return;
881         }
882         tevent_req_done(req);
883 }
884
885 NTSTATUS share_mode_watch_recv(
886         struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
887 {
888         struct share_mode_watch_state *state = tevent_req_data(
889                 req, struct share_mode_watch_state);
890         NTSTATUS status;
891
892         if (tevent_req_is_nterror(req, &status)) {
893                 return status;
894         }
895         if (blockerdead != NULL) {
896                 *blockerdead = state->blockerdead;
897         }
898         if (blocker != NULL) {
899                 *blocker = state->blocker;
900         }
901         return NT_STATUS_OK;
902 }
903
904 struct fetch_share_mode_unlocked_state {
905         TALLOC_CTX *mem_ctx;
906         struct share_mode_lock *lck;
907 };
908
909 static void fetch_share_mode_unlocked_parser(
910         TDB_DATA key, TDB_DATA data, void *private_data)
911 {
912         struct fetch_share_mode_unlocked_state *state = private_data;
913
914         if (data.dsize == 0) {
915                 /* Likely a ctdb tombstone record, ignore it */
916                 return;
917         }
918
919         state->lck = talloc(state->mem_ctx, struct share_mode_lock);
920         if (state->lck == NULL) {
921                 DEBUG(0, ("talloc failed\n"));
922                 return;
923         }
924
925         state->lck->data = parse_share_modes(state->lck, key, data);
926 }
927
928 /*******************************************************************
929  Get a share_mode_lock without locking the database or reference
930  counting. Used by smbstatus to display existing share modes.
931 ********************************************************************/
932
933 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
934                                                   struct file_id id)
935 {
936         struct fetch_share_mode_unlocked_state state = { .mem_ctx = mem_ctx };
937         TDB_DATA key = locking_key(&id);
938         NTSTATUS status;
939
940         status = dbwrap_parse_record(
941                 lock_db, key, fetch_share_mode_unlocked_parser, &state);
942         if (!NT_STATUS_IS_OK(status)) {
943                 return NULL;
944         }
945         return state.lck;
946 }
947
948 static void fetch_share_mode_done(struct tevent_req *subreq);
949
950 struct fetch_share_mode_state {
951         struct file_id id;
952         TDB_DATA key;
953         struct fetch_share_mode_unlocked_state parser_state;
954         enum dbwrap_req_state req_state;
955 };
956
957 /**
958  * @brief Get a share_mode_lock without locking or refcounting
959  *
960  * This can be used in a clustered Samba environment where the async dbwrap
961  * request is sent over a socket to the local ctdbd. If the send queue is full
962  * and the caller was issuing multiple async dbwrap requests in a loop, the
963  * caller knows it's probably time to stop sending requests for now and try
964  * again later.
965  *
966  * @param[in]  mem_ctx The talloc memory context to use.
967  *
968  * @param[in]  ev      The event context to work on.
969  *
970  * @param[in]  id      The file id for the locking.tdb key
971  *
972  * @param[out] queued  This boolean out parameter tells the caller whether the
973  *                     async request is blocked in a full send queue:
974  *
975  *                     false := request is dispatched
976  *
977  *                     true  := send queue is full, request waiting to be
978  *                              dispatched
979  *
980  * @return             The new async request, NULL on error.
981  **/
982 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
983                                          struct tevent_context *ev,
984                                          struct file_id id,
985                                          bool *queued)
986 {
987         struct tevent_req *req = NULL;
988         struct fetch_share_mode_state *state = NULL;
989         struct tevent_req *subreq = NULL;
990
991         *queued = false;
992
993         req = tevent_req_create(mem_ctx, &state,
994                                 struct fetch_share_mode_state);
995         if (req == NULL) {
996                 return NULL;
997         }
998
999         state->id = id;
1000         state->key = locking_key(&state->id);
1001         state->parser_state.mem_ctx = state;
1002
1003         subreq = dbwrap_parse_record_send(state,
1004                                           ev,
1005                                           lock_db,
1006                                           state->key,
1007                                           fetch_share_mode_unlocked_parser,
1008                                           &state->parser_state,
1009                                           &state->req_state);
1010         if (tevent_req_nomem(subreq, req)) {
1011                 return tevent_req_post(req, ev);
1012         }
1013         tevent_req_set_callback(subreq, fetch_share_mode_done, req);
1014
1015         if (state->req_state < DBWRAP_REQ_DISPATCHED) {
1016                 *queued = true;
1017         }
1018         return req;
1019 }
1020
1021 static void fetch_share_mode_done(struct tevent_req *subreq)
1022 {
1023         struct tevent_req *req = tevent_req_callback_data(
1024                 subreq, struct tevent_req);
1025         NTSTATUS status;
1026
1027         status = dbwrap_parse_record_recv(subreq);
1028         TALLOC_FREE(subreq);
1029         if (tevent_req_nterror(req, status)) {
1030                 return;
1031         }
1032
1033         tevent_req_done(req);
1034         return;
1035 }
1036
1037 NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
1038                                TALLOC_CTX *mem_ctx,
1039                                struct share_mode_lock **_lck)
1040 {
1041         struct fetch_share_mode_state *state = tevent_req_data(
1042                 req, struct fetch_share_mode_state);
1043         struct share_mode_lock *lck = NULL;
1044
1045         NTSTATUS status;
1046
1047         if (tevent_req_is_nterror(req, &status)) {
1048                 tevent_req_received(req);
1049                 return status;
1050         }
1051
1052         if (state->parser_state.lck->data == NULL) {
1053                 tevent_req_received(req);
1054                 return NT_STATUS_NOT_FOUND;
1055         }
1056
1057         lck = talloc_move(mem_ctx, &state->parser_state.lck);
1058
1059         if (DEBUGLEVEL >= 10) {
1060                 DBG_DEBUG("share_mode_data:\n");
1061                 NDR_PRINT_DEBUG(share_mode_data, lck->data);
1062         }
1063
1064         *_lck = lck;
1065         tevent_req_received(req);
1066         return NT_STATUS_OK;
1067 }
1068
1069 struct share_mode_forall_state {
1070         int (*fn)(struct file_id fid, const struct share_mode_data *data,
1071                   void *private_data);
1072         void *private_data;
1073 };
1074
1075 static int share_mode_traverse_fn(struct db_record *rec, void *_state)
1076 {
1077         struct share_mode_forall_state *state =
1078                 (struct share_mode_forall_state *)_state;
1079         TDB_DATA key;
1080         TDB_DATA value;
1081         DATA_BLOB blob;
1082         enum ndr_err_code ndr_err;
1083         struct share_mode_data *d;
1084         struct file_id fid;
1085         int ret;
1086
1087         key = dbwrap_record_get_key(rec);
1088         value = dbwrap_record_get_value(rec);
1089
1090         /* Ensure this is a locking_key record. */
1091         if (key.dsize != sizeof(fid)) {
1092                 return 0;
1093         }
1094         memcpy(&fid, key.dptr, sizeof(fid));
1095
1096         d = talloc(talloc_tos(), struct share_mode_data);
1097         if (d == NULL) {
1098                 return 0;
1099         }
1100
1101         blob.data = value.dptr;
1102         blob.length = value.dsize;
1103
1104         ndr_err = ndr_pull_struct_blob_all(
1105                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
1106         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1107                 DEBUG(1, ("ndr_pull_share_mode_lock failed\n"));
1108                 return 0;
1109         }
1110
1111         if (DEBUGLEVEL > 10) {
1112                 DEBUG(11, ("parse_share_modes:\n"));
1113                 NDR_PRINT_DEBUG(share_mode_data, d);
1114         }
1115
1116         ret = state->fn(fid, d, state->private_data);
1117
1118         TALLOC_FREE(d);
1119         return ret;
1120 }
1121
1122 int share_mode_forall(int (*fn)(struct file_id fid,
1123                                 const struct share_mode_data *data,
1124                                 void *private_data),
1125                       void *private_data)
1126 {
1127         struct share_mode_forall_state state = {
1128                 .fn = fn,
1129                 .private_data = private_data
1130         };
1131         NTSTATUS status;
1132         int count;
1133
1134         if (lock_db == NULL) {
1135                 return 0;
1136         }
1137
1138         status = dbwrap_traverse_read(lock_db, share_mode_traverse_fn,
1139                                       &state, &count);
1140         if (!NT_STATUS_IS_OK(status)) {
1141                 return -1;
1142         }
1143
1144         return count;
1145 }
1146
1147 struct share_entry_forall_state {
1148         struct file_id fid;
1149         const struct share_mode_data *data;
1150         int (*fn)(struct file_id fid,
1151                   const struct share_mode_data *data,
1152                   const struct share_mode_entry *entry,
1153                   void *private_data);
1154         void *private_data;
1155         int ret;
1156 };
1157
1158 static bool share_entry_traverse_walker(
1159         struct share_mode_entry *e,
1160         bool *modified,
1161         void *private_data)
1162 {
1163         struct share_entry_forall_state *state = private_data;
1164
1165         state->ret = state->fn(
1166                 state->fid, state->data, e, state->private_data);
1167         return (state->ret != 0);
1168 }
1169
1170 static int share_entry_traverse_fn(struct file_id fid,
1171                                    const struct share_mode_data *data,
1172                                    void *private_data)
1173 {
1174         struct share_entry_forall_state *state = private_data;
1175         struct share_mode_lock lck = {
1176                 .data = discard_const_p(struct share_mode_data, data)
1177         };
1178         bool ok;
1179
1180         state->fid = fid;
1181         state->data = data;
1182
1183         ok = share_mode_forall_entries(
1184                 &lck, share_entry_traverse_walker, state);
1185         if (!ok) {
1186                 DBG_DEBUG("share_mode_forall_entries failed\n");
1187                 return false;
1188         }
1189
1190         return state->ret;
1191 }
1192
1193 /*******************************************************************
1194  Call the specified function on each entry under management by the
1195  share mode system.
1196 ********************************************************************/
1197
1198 int share_entry_forall(int (*fn)(struct file_id fid,
1199                                  const struct share_mode_data *data,
1200                                  const struct share_mode_entry *entry,
1201                                  void *private_data),
1202                       void *private_data)
1203 {
1204         struct share_entry_forall_state state = {
1205                 .fn = fn, .private_data = private_data };
1206
1207         return share_mode_forall(share_entry_traverse_fn, &state);
1208 }
1209
1210 struct cleanup_disconnected_state {
1211         struct share_mode_lock *lck;
1212         uint64_t open_persistent_id;
1213         size_t num_disconnected;
1214         bool found_connected;
1215 };
1216
1217 static bool cleanup_disconnected_lease(struct share_mode_entry *e,
1218                                        void *private_data)
1219 {
1220         struct cleanup_disconnected_state *state = private_data;
1221         NTSTATUS status;
1222
1223         status = leases_db_del(
1224                 &e->client_guid, &e->lease_key, &state->lck->data->id);
1225
1226         if (!NT_STATUS_IS_OK(status)) {
1227                 DBG_DEBUG("leases_db_del failed: %s\n",
1228                           nt_errstr(status));
1229         }
1230
1231         return false;
1232 }
1233
1234 static bool share_mode_find_connected_fn(
1235         struct share_mode_entry *e,
1236         bool *modified,
1237         void *private_data)
1238 {
1239         struct cleanup_disconnected_state *state = private_data;
1240         struct share_mode_data *d = state->lck->data;
1241         bool disconnected;
1242
1243         disconnected = server_id_is_disconnected(&e->pid);
1244         if (!disconnected) {
1245                 struct file_id_buf tmp1;
1246                 struct server_id_buf tmp2;
1247                 DBG_INFO("file (file-id='%s', servicepath='%s', "
1248                          "base_name='%s%s%s') "
1249                          "is used by server %s ==> do not cleanup\n",
1250                          file_id_str_buf(d->id, &tmp1),
1251                          d->servicepath,
1252                          d->base_name,
1253                          (d->stream_name == NULL)
1254                          ? "" : "', stream_name='",
1255                          (d->stream_name == NULL)
1256                          ? "" : d->stream_name,
1257                          server_id_str_buf(e->pid, &tmp2));
1258                 state->found_connected = true;
1259                 return true;
1260         }
1261
1262         if (state->open_persistent_id != e->share_file_id) {
1263                 struct file_id_buf tmp;
1264                 DBG_INFO("entry for file "
1265                          "(file-id='%s', servicepath='%s', "
1266                          "base_name='%s%s%s') "
1267                          "has share_file_id %"PRIu64" but expected "
1268                          "%"PRIu64"==> do not cleanup\n",
1269                          file_id_str_buf(d->id, &tmp),
1270                          d->servicepath,
1271                          d->base_name,
1272                          (d->stream_name == NULL)
1273                          ? "" : "', stream_name='",
1274                          (d->stream_name == NULL)
1275                          ? "" : d->stream_name,
1276                          e->share_file_id,
1277                          state->open_persistent_id);
1278                 state->found_connected = true;
1279                 return true;
1280         }
1281
1282         state->num_disconnected += 1;
1283
1284         return false;
1285 }
1286
1287 bool share_mode_cleanup_disconnected(struct file_id fid,
1288                                      uint64_t open_persistent_id)
1289 {
1290         struct cleanup_disconnected_state state = {
1291                 .open_persistent_id = open_persistent_id
1292         };
1293         struct share_mode_data *data;
1294         bool ret = false;
1295         TALLOC_CTX *frame = talloc_stackframe();
1296         struct file_id_buf idbuf;
1297         NTSTATUS status;
1298         bool ok;
1299
1300         state.lck = get_existing_share_mode_lock(frame, fid);
1301         if (state.lck == NULL) {
1302                 DBG_INFO("Could not fetch share mode entry for %s\n",
1303                          file_id_str_buf(fid, &idbuf));
1304                 goto done;
1305         }
1306         data = state.lck->data;
1307
1308         ok = share_mode_forall_entries(
1309                 state.lck, share_mode_find_connected_fn, &state);
1310         if (!ok) {
1311                 DBG_DEBUG("share_mode_forall_entries failed\n");
1312                 goto done;
1313         }
1314         if (state.found_connected) {
1315                 DBG_DEBUG("Found connected entry\n");
1316                 goto done;
1317         }
1318
1319         ok = share_mode_forall_leases(
1320                 state.lck, cleanup_disconnected_lease, &state);
1321         if (!ok) {
1322                 DBG_DEBUG("failed to clean up leases associated "
1323                           "with file (file-id='%s', servicepath='%s', "
1324                           "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
1325                           "==> do not cleanup\n",
1326                           file_id_str_buf(fid, &idbuf),
1327                           data->servicepath,
1328                           data->base_name,
1329                           (data->stream_name == NULL)
1330                           ? "" : "', stream_name='",
1331                           (data->stream_name == NULL)
1332                           ? "" : data->stream_name,
1333                           open_persistent_id);
1334         }
1335
1336         ok = brl_cleanup_disconnected(fid, open_persistent_id);
1337         if (!ok) {
1338                 DBG_DEBUG("failed to clean up byte range locks associated "
1339                           "with file (file-id='%s', servicepath='%s', "
1340                           "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
1341                           "==> do not cleanup\n",
1342                           file_id_str_buf(fid, &idbuf),
1343                           data->servicepath,
1344                           data->base_name,
1345                           (data->stream_name == NULL)
1346                           ? "" : "', stream_name='",
1347                           (data->stream_name == NULL)
1348                           ? "" : data->stream_name,
1349                           open_persistent_id);
1350                 goto done;
1351         }
1352
1353         DBG_DEBUG("cleaning up %zu entries for file "
1354                   "(file-id='%s', servicepath='%s', "
1355                   "base_name='%s%s%s') "
1356                   "from open_persistent_id %"PRIu64"\n",
1357                   state.num_disconnected,
1358                   file_id_str_buf(fid, &idbuf),
1359                   data->servicepath,
1360                   data->base_name,
1361                   (data->stream_name == NULL)
1362                   ? "" : "', stream_name='",
1363                   (data->stream_name == NULL)
1364                   ? "" : data->stream_name,
1365                   open_persistent_id);
1366
1367         /*
1368          * No connected share entries left, wipe them all
1369          */
1370         status = dbwrap_delete(share_entries_db, locking_key(&fid));
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 DBG_DEBUG("dbwrap_delete failed: %s\n",
1373                           nt_errstr(status));
1374                 goto done;
1375         }
1376
1377         data->have_share_modes = false;
1378         data->modified = true;
1379
1380         ret = true;
1381 done:
1382         talloc_free(frame);
1383         return ret;
1384 }
1385
1386 static int share_mode_entry_cmp(
1387         struct server_id pid1,
1388         uint64_t share_file_id1,
1389         struct server_id pid2,
1390         uint64_t share_file_id2)
1391 {
1392         int cmp;
1393
1394         cmp = server_id_cmp(&pid1, &pid2);
1395         if (cmp != 0) {
1396                 return cmp;
1397         }
1398         if (share_file_id1 != share_file_id2) {
1399                 return (share_file_id1 < share_file_id2) ? -1 : 1;
1400         }
1401         return 0;
1402 }
1403
1404 /*
1405  * 132 is the sizeof an ndr-encoded struct share_mode_entry_buf.
1406  * Reading/writing entries will immediately error out if this
1407  * size differs (push/pull is done without allocs).
1408  */
1409
1410 struct share_mode_entry_buf {
1411         uint8_t buf[132];
1412 };
1413 #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))
1414
1415 static bool share_mode_entry_put(
1416         const struct share_mode_entry *e,
1417         struct share_mode_entry_buf *dst)
1418 {
1419         DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
1420         enum ndr_err_code ndr_err;
1421
1422         if (DEBUGLEVEL>=10) {
1423                 DBG_DEBUG("share_mode_entry:\n");
1424                 NDR_PRINT_DEBUG(share_mode_entry, discard_const_p(void, e));
1425         }
1426
1427         ndr_err = ndr_push_struct_into_fixed_blob(
1428                 &blob,
1429                 e,
1430                 (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
1431         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1432                 DBG_WARNING("ndr_push_share_mode_entry failed: %s\n",
1433                             ndr_errstr(ndr_err));
1434                 return false;
1435         }
1436
1437         return true;
1438 }
1439
1440 static bool share_mode_entry_get(
1441         const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
1442 {
1443         enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
1444         DATA_BLOB blob = {
1445                 .data = discard_const_p(uint8_t, ptr),
1446                 .length = SHARE_MODE_ENTRY_SIZE,
1447         };
1448
1449         ndr_err = ndr_pull_struct_blob_all_noalloc(
1450                 &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
1451         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1452                 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
1453                 return false;
1454         }
1455         return true;
1456 }
1457
1458 static size_t share_mode_entry_find(
1459         uint8_t *data,
1460         size_t num_share_modes,
1461         struct server_id pid,
1462         uint64_t share_file_id,
1463         struct share_mode_entry *e,
1464         bool *match)
1465 {
1466         ssize_t left, right, middle;
1467
1468         if (num_share_modes == 0) {
1469                 *match = false;
1470                 return 0;
1471         }
1472
1473         left = 0;
1474         right = (num_share_modes-1);
1475
1476         while (left <= right) {
1477                 const uint8_t *middle_ptr = NULL;
1478                 int cmp;
1479                 bool ok;
1480
1481                 middle = left + ((right - left) / 2);
1482                 middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
1483
1484                 DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
1485                           left,
1486                           right,
1487                           middle,
1488                           middle_ptr);
1489
1490                 ok = share_mode_entry_get(middle_ptr, e);
1491                 if (!ok) {
1492                         DBG_DEBUG("share_mode_entry_get failed\n");
1493                         return false;
1494                 }
1495
1496                 cmp = share_mode_entry_cmp(
1497                         e->pid, e->share_file_id, pid, share_file_id);
1498                 if (cmp == 0) {
1499                         *match = true;
1500                         return middle;
1501                 }
1502
1503                 if (cmp < 0) {
1504                         right = middle-1;
1505                 } else {
1506                         left = middle+1;
1507                 }
1508         }
1509
1510         *match = false;
1511         return left;
1512 }
1513
1514 struct set_share_mode_state {
1515         struct share_mode_entry e;
1516         bool created_share_mode_record;
1517         NTSTATUS status;
1518 };
1519
1520 static void set_share_mode_fn(
1521         struct db_record *rec,
1522         TDB_DATA data,
1523         void *private_data)
1524 {
1525         struct set_share_mode_state *state = private_data;
1526         size_t idx, num_share_modes;
1527         struct share_mode_entry tmp;
1528         struct share_mode_entry_buf buf;
1529         bool ok, found;
1530
1531         TDB_DATA dbufs[3];
1532         size_t num_dbufs = 0;
1533
1534         if ((data.dsize % SHARE_MODE_ENTRY_SIZE) != 0) {
1535                 DBG_WARNING("Got invalid record size %zu\n", data.dsize);
1536                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1537                 return;
1538         }
1539         num_share_modes = data.dsize / SHARE_MODE_ENTRY_SIZE;
1540
1541         ok = share_mode_entry_put(&state->e, &buf);
1542         if (!ok) {
1543                 DBG_DEBUG("share_mode_entry_put failed\n");
1544                 state->status = NT_STATUS_INTERNAL_ERROR;
1545                 return;
1546         }
1547
1548         DBG_DEBUG("num_share_modes=%zu\n", num_share_modes);
1549
1550         idx = share_mode_entry_find(
1551                 data.dptr,
1552                 num_share_modes,
1553                 state->e.pid,
1554                 state->e.share_file_id,
1555                 &tmp,
1556                 &found);
1557         if (found) {
1558                 DBG_WARNING("Found duplicate share mode\n");
1559                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1560                 return;
1561         }
1562
1563         DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
1564
1565         if (idx > 0) {
1566                 dbufs[num_dbufs] = (TDB_DATA) {
1567                         .dptr = data.dptr,
1568                         .dsize = idx * SHARE_MODE_ENTRY_SIZE,
1569                 };
1570                 num_dbufs += 1;
1571         }
1572
1573         dbufs[num_dbufs] = (TDB_DATA) {
1574                 .dptr = buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
1575         };
1576         num_dbufs += 1;
1577
1578         if (idx < num_share_modes) {
1579                 dbufs[num_dbufs] = (TDB_DATA) {
1580                         .dptr = data.dptr + idx * SHARE_MODE_ENTRY_SIZE,
1581                         .dsize = (num_share_modes-idx) * SHARE_MODE_ENTRY_SIZE,
1582                 };
1583                 num_dbufs += 1;
1584         }
1585
1586         {
1587                 size_t i;
1588                 for (i=0; i<num_dbufs; i++) {
1589                         DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
1590                                   i,
1591                                   dbufs[i].dptr,
1592                                   dbufs[i].dsize);
1593                 }
1594         }
1595
1596         state->created_share_mode_record = (num_share_modes == 0);
1597         state->status = dbwrap_record_storev(rec, dbufs, num_dbufs, 0);
1598 }
1599
1600 bool set_share_mode(struct share_mode_lock *lck,
1601                     struct files_struct *fsp,
1602                     uid_t uid,
1603                     uint64_t mid,
1604                     uint16_t op_type,
1605                     uint32_t share_access,
1606                     uint32_t access_mask)
1607 {
1608         struct share_mode_data *d = lck->data;
1609         struct set_share_mode_state state = {
1610                 .status = NT_STATUS_OK,
1611                 .e.pid = messaging_server_id(fsp->conn->sconn->msg_ctx),
1612                 .e.share_access = share_access,
1613                 .e.private_options = fsp->fh->private_options,
1614                 .e.access_mask = access_mask,
1615                 .e.op_mid = mid,
1616                 .e.op_type = op_type,
1617                 .e.time.tv_sec = fsp->open_time.tv_sec,
1618                 .e.time.tv_usec = fsp->open_time.tv_usec,
1619                 .e.share_file_id = fsp->fh->gen_id,
1620                 .e.uid = (uint32_t)uid,
1621                 .e.flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
1622                 SHARE_MODE_FLAG_POSIX_OPEN : 0,
1623                 .e.name_hash = fsp->name_hash,
1624         };
1625         NTSTATUS status;
1626
1627         if (op_type == LEASE_OPLOCK) {
1628                 const struct GUID *client_guid = fsp_client_guid(fsp);
1629                 state.e.client_guid = *client_guid;
1630                 state.e.lease_key = fsp->lease->lease.lease_key;
1631         }
1632
1633         status = dbwrap_do_locked(
1634                 share_entries_db,
1635                 locking_key(&d->id),
1636                 set_share_mode_fn,
1637                 &state);
1638         if (!NT_STATUS_IS_OK(status)) {
1639                 DBG_WARNING("dbwrap_do_locked failed: %s\n",
1640                             nt_errstr(status));
1641                 return false;
1642         }
1643         if (!NT_STATUS_IS_OK(state.status)) {
1644                 DBG_WARNING("set_share_mode_fn failed: %s\n",
1645                             nt_errstr(state.status));
1646                 return false;
1647         }
1648
1649         if (state.created_share_mode_record) {
1650                 d->have_share_modes = true;
1651                 d->modified = true;
1652         }
1653
1654         return true;
1655 }
1656
1657 struct share_mode_forall_entries_state {
1658         struct share_mode_lock *lck;
1659         bool (*fn)(struct share_mode_entry *e,
1660                    bool *modified,
1661                    void *private_data);
1662         void *private_data;
1663         bool ok;
1664 };
1665
1666 static bool share_mode_for_one_entry(
1667         struct share_mode_forall_entries_state *state,
1668         size_t *i,
1669         size_t *num_share_modes,
1670         TDB_DATA data,
1671         bool *writeback)
1672 {
1673         DATA_BLOB blob = {
1674                 .data = data.dptr + (*i) * SHARE_MODE_ENTRY_SIZE,
1675                 .length = SHARE_MODE_ENTRY_SIZE,
1676         };
1677         struct share_mode_entry e = {.pid.pid=0};
1678         enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
1679         bool modified = false;
1680         bool stop = false;
1681         struct server_id e_pid;
1682         uint64_t e_share_file_id;
1683
1684         ndr_err = ndr_pull_struct_blob_all_noalloc(
1685                 &blob,
1686                 &e,
1687                 (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
1688         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1689                 DBG_WARNING("ndr_pull_share_mode_entry failed\n");
1690                 *i += 1;
1691                 return false;
1692         }
1693         if (DEBUGLEVEL >= 10) {
1694                 DBG_DEBUG("entry[%zu]:\n", *i);
1695                 NDR_PRINT_DEBUG(share_mode_entry, &e);
1696         }
1697
1698         e_pid = e.pid;
1699         e_share_file_id = e.share_file_id;
1700
1701         stop = state->fn(&e, &modified, state->private_data);
1702
1703         DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
1704                   *i,
1705                   (int)modified,
1706                   (int)e.stale);
1707
1708         if (modified) {
1709                 if (DEBUGLEVEL>=10) {
1710                         DBG_DEBUG("share_mode_entry:\n");
1711                         NDR_PRINT_DEBUG(share_mode_entry, &e);
1712                 }
1713
1714                 /*
1715                  * Make sure sorting order is kept intact
1716                  */
1717                 SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
1718                 SMB_ASSERT(e_share_file_id == e.share_file_id);
1719
1720                 ndr_err = ndr_push_struct_into_fixed_blob(
1721                         &blob,
1722                         &e,
1723                         (ndr_push_flags_fn_t)
1724                         ndr_push_share_mode_entry);
1725                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1726                         DBG_WARNING("ndr_push_share_mode_entry "
1727                                     "failed: %s\n",
1728                                     ndr_errstr(ndr_err));
1729                         /*
1730                          * Not much we can do, just ignore it
1731                          */
1732                 }
1733                 *i += 1;
1734                 *writeback = true;
1735                 return stop;
1736         }
1737
1738         if (e.stale) {
1739                 if (*i < *num_share_modes) {
1740                         memmove(blob.data,
1741                                 blob.data + SHARE_MODE_ENTRY_SIZE,
1742                                 (*num_share_modes - *i - 1) *
1743                                 SHARE_MODE_ENTRY_SIZE);
1744                 }
1745                 *num_share_modes -= 1;
1746                 *writeback = true;
1747                 return stop;
1748         }
1749
1750         if (stop) {
1751                 return true;
1752         }
1753
1754         *i += 1;
1755         return false;
1756 }
1757
1758 static void share_mode_forall_entries_fn(
1759         struct db_record *rec,
1760         TDB_DATA data,
1761         void *private_data)
1762 {
1763         struct share_mode_forall_entries_state *state = private_data;
1764         struct share_mode_data *d = state->lck->data;
1765         size_t num_share_modes;
1766         bool writeback = false;
1767         NTSTATUS status;
1768         bool stop = false;
1769         size_t i;
1770
1771         if ((data.dsize % SHARE_MODE_ENTRY_SIZE) != 0) {
1772                 DBG_WARNING("Invalid data size %zu\n", data.dsize);
1773                 return;
1774         }
1775         num_share_modes = data.dsize / SHARE_MODE_ENTRY_SIZE;
1776
1777         DBG_DEBUG("num_share_modes=%zu\n", num_share_modes);
1778
1779         i = 0;
1780         while (i<num_share_modes) {
1781                 stop = share_mode_for_one_entry(
1782                         state, &i, &num_share_modes, data, &writeback);
1783                 if (stop) {
1784                         break;
1785                 }
1786         }
1787
1788         DBG_DEBUG("num_share_modes=%zu, writeback=%d\n",
1789                   num_share_modes,
1790                   (int)writeback);
1791
1792         if (!writeback) {
1793                 state->ok = true;
1794                 return;
1795         }
1796
1797         if (num_share_modes == 0) {
1798                 if (data.dsize != 0) {
1799                         d->have_share_modes = false;
1800                         d->modified = true;
1801                 }
1802                 status = dbwrap_record_delete(rec);
1803         } else {
1804                 TDB_DATA value = {
1805                         .dptr = data.dptr,
1806                         .dsize = num_share_modes * SHARE_MODE_ENTRY_SIZE,
1807                 };
1808                 status = dbwrap_record_store(rec, value, 0);
1809         }
1810
1811         if (!NT_STATUS_IS_OK(status)) {
1812                 DBG_DEBUG("Storing record with %zu entries failed: %s\n",
1813                           num_share_modes,
1814                           nt_errstr(status));
1815                 return;
1816         }
1817
1818
1819         state->ok = true;
1820 }
1821
1822 bool share_mode_forall_entries(
1823         struct share_mode_lock *lck,
1824         bool (*fn)(struct share_mode_entry *e,
1825                    bool *modified,
1826                    void *private_data),
1827         void *private_data)
1828 {
1829         struct share_mode_forall_entries_state state = {
1830                 .lck = lck,
1831                 .fn = fn,
1832                 .private_data = private_data,
1833         };
1834         NTSTATUS status;
1835
1836         status = dbwrap_do_locked(
1837                 share_entries_db,
1838                 locking_key(&lck->data->id),
1839                 share_mode_forall_entries_fn,
1840                 &state);
1841         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
1842                 status = NT_STATUS_OK;
1843                 state.ok = true;
1844         }
1845         if (!NT_STATUS_IS_OK(status)) {
1846                 DBG_DEBUG("dbwrap_do_locked failed: %s\n",
1847                           nt_errstr(status));
1848                 return false;
1849         }
1850
1851         return state.ok;
1852 }
1853
1854 struct share_mode_count_entries_state {
1855         size_t num_share_modes;
1856         NTSTATUS status;
1857 };
1858
1859 static void share_mode_count_entries_fn(
1860         TDB_DATA key, TDB_DATA data, void *private_data)
1861 {
1862         struct share_mode_count_entries_state *state = private_data;
1863
1864         if ((data.dsize % SHARE_MODE_ENTRY_SIZE) != 0) {
1865                 DBG_WARNING("Invalid data size %zu\n", data.dsize);
1866                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1867                 return;
1868         }
1869         state->num_share_modes = data.dsize / SHARE_MODE_ENTRY_SIZE;
1870         state->status = NT_STATUS_OK;
1871 }
1872
1873 NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
1874 {
1875         struct share_mode_count_entries_state state = {
1876                 .status = NT_STATUS_NOT_FOUND,
1877         };
1878         NTSTATUS status;
1879
1880         status = dbwrap_parse_record(
1881                 share_entries_db,
1882                 locking_key(&fid),
1883                 share_mode_count_entries_fn,
1884                 &state);
1885         if (!NT_STATUS_IS_OK(status)) {
1886                 DBG_DEBUG("dbwrap_parse_record failed: %s\n",
1887                           nt_errstr(status));
1888                 return status;
1889         }
1890         if (!NT_STATUS_IS_OK(state.status)) {
1891                 DBG_DEBUG("share_mode_forall_entries_fn failed: %s\n",
1892                           nt_errstr(state.status));
1893                 return state.status;
1894         }
1895
1896         *num_share_modes = state.num_share_modes;
1897         return NT_STATUS_OK;
1898 }
1899
1900 struct share_mode_entry_do_state {
1901         struct server_id pid;
1902         uint64_t share_file_id;
1903         void (*fn)(struct share_mode_entry *e,
1904                    size_t num_share_modes,
1905                    bool *modified,
1906                    void *private_data);
1907         void *private_data;
1908         size_t num_share_modes;
1909         NTSTATUS status;
1910 };
1911
1912 static void share_mode_entry_do_fn(
1913         struct db_record *rec,
1914         TDB_DATA data,
1915         void *private_data)
1916 {
1917         struct share_mode_entry_do_state *state = private_data;
1918         size_t idx;
1919         bool found = false;
1920         bool modified;
1921         struct share_mode_entry e;
1922         struct share_mode_entry_buf buf;
1923         TDB_DATA dbufs[3];
1924         size_t num_dbufs = 0;
1925
1926         if ((data.dsize % SHARE_MODE_ENTRY_SIZE) != 0) {
1927                 DBG_WARNING("Invalid data size %zu\n", data.dsize);
1928                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1929                 return;
1930         }
1931         state->num_share_modes = data.dsize / SHARE_MODE_ENTRY_SIZE;
1932
1933         DBG_DEBUG("state->num_share_modes=%zu\n", state->num_share_modes);
1934
1935         idx = share_mode_entry_find(
1936                 data.dptr,
1937                 state->num_share_modes,
1938                 state->pid,
1939                 state->share_file_id,
1940                 &e,
1941                 &found);
1942         if (!found) {
1943                 DBG_WARNING("Did not find share mode entry for %"PRIu64"\n",
1944                             state->share_file_id);
1945                 state->status = NT_STATUS_NOT_FOUND;
1946                 return;
1947         }
1948
1949         state->fn(&e, state->num_share_modes, &modified, state->private_data);
1950
1951         if (!e.stale && !modified) {
1952                 state->status = NT_STATUS_OK;
1953                 return;
1954         }
1955
1956         if (idx > 0) {
1957                 dbufs[num_dbufs] = (TDB_DATA) {
1958                         .dptr = data.dptr,
1959                         .dsize = idx * SHARE_MODE_ENTRY_SIZE,
1960                 };
1961                 num_dbufs += 1;
1962         }
1963
1964         if (!e.stale) {
1965                 bool ok = share_mode_entry_put(&e, &buf);
1966                 if (!ok) {
1967                         DBG_DEBUG("share_mode_entry_put failed\n");
1968                         state->status = NT_STATUS_INTERNAL_ERROR;
1969                         return;
1970                 }
1971
1972                 dbufs[num_dbufs] = (TDB_DATA) {
1973                         .dptr = buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
1974                 };
1975                 num_dbufs += 1;
1976         }
1977
1978         idx += 1;
1979
1980         if (idx < state->num_share_modes) {
1981                 size_t behind = state->num_share_modes - idx;
1982                 dbufs[num_dbufs] = (TDB_DATA) {
1983                         .dptr = data.dptr + idx * SHARE_MODE_ENTRY_SIZE,
1984                         .dsize = behind * SHARE_MODE_ENTRY_SIZE,
1985                 };
1986                 num_dbufs += 1;
1987         }
1988
1989         if (e.stale) {
1990                 state->num_share_modes -= 1;
1991         }
1992
1993         if (state->num_share_modes == 0) {
1994                 state->status = dbwrap_record_delete(rec);
1995                 if (!NT_STATUS_IS_OK(state->status)) {
1996                         DBG_DEBUG("dbwrap_record_delete failed: %s\n",
1997                                   nt_errstr(state->status));
1998                 }
1999                 return;
2000         }
2001
2002         state->status = dbwrap_record_storev(rec, dbufs, num_dbufs, 0);
2003         if (!NT_STATUS_IS_OK(state->status)) {
2004                 DBG_DEBUG("dbwrap_record_storev failed: %s\n",
2005                           nt_errstr(state->status));
2006                 return;
2007         }
2008 }
2009
2010 static bool share_mode_entry_do(
2011         struct share_mode_lock *lck,
2012         struct server_id pid,
2013         uint64_t share_file_id,
2014         void (*fn)(struct share_mode_entry *e,
2015                    size_t num_share_modes,
2016                    bool *modified,
2017                    void *private_data),
2018         void *private_data)
2019 {
2020         struct share_mode_data *d = lck->data;
2021         struct share_mode_entry_do_state state = {
2022                 .pid = pid,
2023                 .share_file_id = share_file_id,
2024                 .fn = fn,
2025                 .private_data = private_data,
2026         };
2027         NTSTATUS status;
2028         bool have_share_modes;
2029
2030         status = dbwrap_do_locked(
2031                 share_entries_db,
2032                 locking_key(&d->id),
2033                 share_mode_entry_do_fn,
2034                 &state);
2035         if (!NT_STATUS_IS_OK(status)) {
2036                 DBG_DEBUG("share_mode_forall_entries failed: %s\n",
2037                           nt_errstr(status));
2038                 return false;
2039         }
2040         if (!NT_STATUS_IS_OK(state.status)) {
2041                 DBG_DEBUG("share_mode_entry_do_fn failed: %s\n",
2042                           nt_errstr(status));
2043                 return false;
2044         }
2045
2046         have_share_modes = (state.num_share_modes != 0);
2047         if (d->have_share_modes != have_share_modes) {
2048                 d->have_share_modes = have_share_modes;
2049                 d->modified = true;
2050         }
2051
2052         return true;
2053 }
2054
2055 struct del_share_mode_state {
2056         bool ok;
2057 };
2058
2059 static void del_share_mode_fn(
2060         struct share_mode_entry *e,
2061         size_t num_share_modes,
2062         bool *modified,
2063         void *private_data)
2064 {
2065         struct del_share_mode_state *state = private_data;
2066         e->stale = true;
2067         state->ok = true;
2068 }
2069
2070 bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
2071 {
2072         struct del_share_mode_state state = { .ok = false };
2073         bool ok;
2074
2075         ok = share_mode_entry_do(
2076                 lck,
2077                 messaging_server_id(fsp->conn->sconn->msg_ctx),
2078                 fsp->fh->gen_id,
2079                 del_share_mode_fn,
2080                 &state);
2081         if (!ok) {
2082                 DBG_DEBUG("share_mode_entry_do failed\n");
2083                 return false;
2084         }
2085         if (!state.ok) {
2086                 DBG_DEBUG("del_share_mode_fn failed\n");
2087                 return false;
2088         }
2089         return true;
2090 }
2091
2092 struct remove_share_oplock_state {
2093         bool ok;
2094 };
2095
2096 static void remove_share_oplock_fn(
2097         struct share_mode_entry *e,
2098         size_t num_share_modes,
2099         bool *modified,
2100         void *private_data)
2101 {
2102         struct remove_share_oplock_state *state = private_data;
2103
2104         e->op_type = NO_OPLOCK;
2105         *modified = true;
2106         state->ok = true;
2107 }
2108
2109 bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2110 {
2111         struct remove_share_oplock_state state = { .ok = false };
2112         bool ok;
2113
2114         ok = share_mode_entry_do(
2115                 lck,
2116                 messaging_server_id(fsp->conn->sconn->msg_ctx),
2117                 fsp->fh->gen_id,
2118                 remove_share_oplock_fn,
2119                 &state);
2120         if (!ok) {
2121                 DBG_DEBUG("share_mode_entry_do failed\n");
2122                 return false;
2123         }
2124         if (!state.ok) {
2125                 DBG_DEBUG("remove_share_oplock_fn failed\n");
2126                 return false;
2127         }
2128
2129         if (fsp->oplock_type == LEASE_OPLOCK) {
2130                 remove_lease_if_stale(
2131                         lck,
2132                         fsp_client_guid(fsp),
2133                         &fsp->lease->lease.lease_key);
2134         }
2135
2136         share_mode_wakeup_waiters(fsp->file_id);
2137
2138         return true;
2139 }
2140
2141 struct downgrade_share_oplock_state {
2142         bool ok;
2143 };
2144
2145 static void downgrade_share_oplock_fn(
2146         struct share_mode_entry *e,
2147         size_t num_share_modes,
2148         bool *modified,
2149         void *private_data)
2150 {
2151         struct downgrade_share_oplock_state *state = private_data;
2152
2153         e->op_type = LEVEL_II_OPLOCK;
2154         *modified = true;
2155         state->ok = true;
2156 }
2157
2158 bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
2159 {
2160         struct downgrade_share_oplock_state state = { .ok = false };
2161         bool ok;
2162
2163         ok = share_mode_entry_do(
2164                 lck,
2165                 messaging_server_id(fsp->conn->sconn->msg_ctx),
2166                 fsp->fh->gen_id,
2167                 downgrade_share_oplock_fn,
2168                 &state);
2169         if (!ok) {
2170                 DBG_DEBUG("share_mode_entry_do failed\n");
2171                 return false;
2172         }
2173         if (!state.ok) {
2174                 DBG_DEBUG("downgrade_share_oplock_fn failed\n");
2175                 return false;
2176         }
2177
2178         lck->data->flags |= SHARE_MODE_LEASE_READ;
2179         lck->data->modified = true;
2180
2181         return true;
2182 }
2183
2184 struct mark_share_mode_disconnected_state {
2185         uint64_t open_persistent_id;
2186         bool ok;
2187 };
2188
2189 static void mark_share_mode_disconnected_fn(
2190         struct share_mode_entry *e,
2191         size_t num_share_modes,
2192         bool *modified,
2193         void *private_data)
2194 {
2195         struct mark_share_mode_disconnected_state *state = private_data;
2196
2197         if (num_share_modes != 1) {
2198                 state->ok = false;
2199                 return;
2200         }
2201
2202         server_id_set_disconnected(&e->pid);
2203         e->share_file_id = state->open_persistent_id;
2204         *modified = true;
2205         state->ok = true;
2206 }
2207
2208 bool mark_share_mode_disconnected(struct share_mode_lock *lck,
2209                                   struct files_struct *fsp)
2210 {
2211         struct mark_share_mode_disconnected_state state;
2212         bool ok;
2213
2214         if (fsp->op == NULL) {
2215                 return false;
2216         }
2217         if (!fsp->op->global->durable) {
2218                 return false;
2219         }
2220
2221         state = (struct mark_share_mode_disconnected_state) {
2222                 .open_persistent_id = fsp->op->global->open_persistent_id,
2223         };
2224
2225         ok = share_mode_entry_do(
2226                 lck,
2227                 messaging_server_id(fsp->conn->sconn->msg_ctx),
2228                 fsp->fh->gen_id,
2229                 mark_share_mode_disconnected_fn,
2230                 &state);
2231         if (!ok) {
2232                 DBG_DEBUG("share_mode_entry_do failed\n");
2233                 return false;
2234         }
2235         if (!state.ok) {
2236                 DBG_DEBUG("mark_share_mode_disconnected_fn failed\n");
2237                 return false;
2238         }
2239
2240         lck->data->modified = true;
2241         return true;
2242 }
2243
2244 static void reset_share_mode_entry_del_fn(
2245         struct share_mode_entry *e,
2246         size_t num_share_modes,
2247         bool *modified,
2248         void *private_data)
2249 {
2250         struct set_share_mode_state *state = private_data;
2251
2252         state->e = *e;
2253         e->stale = true;
2254         state->status = NT_STATUS_OK;
2255 }
2256
2257 bool reset_share_mode_entry(
2258         struct share_mode_lock *lck,
2259         struct server_id old_pid,
2260         uint64_t old_share_file_id,
2261         struct server_id new_pid,
2262         uint64_t new_mid,
2263         uint64_t new_share_file_id)
2264 {
2265         struct share_mode_data *d = lck->data;
2266         struct set_share_mode_state state = {
2267                 .status = NT_STATUS_INTERNAL_ERROR,
2268         };
2269         NTSTATUS status;
2270         bool ok;
2271
2272         ok = share_mode_entry_do(
2273                 lck,
2274                 old_pid,
2275                 old_share_file_id,
2276                 reset_share_mode_entry_del_fn,
2277                 &state);
2278         if (!ok) {
2279                 DBG_DEBUG("share_mode_entry_do failed\n");
2280                 return false;
2281         }
2282         if (!NT_STATUS_IS_OK(state.status)) {
2283                 DBG_DEBUG("reset_share_mode_entry_del_fn failed: %s\n",
2284                           nt_errstr(state.status));
2285                 return false;
2286         }
2287
2288         state.status = NT_STATUS_INTERNAL_ERROR;
2289         state.e.pid = new_pid;
2290         state.e.op_mid = new_mid;
2291         state.e.share_file_id = new_share_file_id;
2292
2293         status = dbwrap_do_locked(
2294                 share_entries_db,
2295                 locking_key(&d->id),
2296                 set_share_mode_fn,
2297                 &state);
2298         if (!NT_STATUS_IS_OK(status)) {
2299                 DBG_WARNING("dbwrap_do_locked failed: %s\n",
2300                             nt_errstr(status));
2301                 return false;
2302         }
2303         if (!NT_STATUS_IS_OK(state.status)) {
2304                 DBG_WARNING("set_share_mode_fn failed: %s\n",
2305                             nt_errstr(state.status));
2306                 return false;
2307         }
2308         d->have_share_modes = true;
2309
2310         return true;
2311 }