smbd: Add share_mode_do_locked()
[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
63 static bool locking_init_internal(bool read_only)
64 {
65         struct db_context *backend;
66         char *db_path;
67
68         brl_init(read_only);
69
70         if (lock_db)
71                 return True;
72
73         db_path = lock_path(talloc_tos(), "locking.tdb");
74         if (db_path == NULL) {
75                 return false;
76         }
77
78         backend = db_open(NULL, db_path,
79                           SMB_OPEN_DATABASE_TDB_HASH_SIZE,
80                           TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
81                           read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
82                           DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
83         TALLOC_FREE(db_path);
84         if (!backend) {
85                 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
86                 return False;
87         }
88
89         lock_db = db_open_watched(NULL, &backend, global_messaging_context());
90         if (lock_db == NULL) {
91                 DBG_ERR("db_open_watched failed\n");
92                 TALLOC_FREE(backend);
93                 return false;
94         }
95
96         if (!posix_locking_init(read_only)) {
97                 TALLOC_FREE(lock_db);
98                 return False;
99         }
100
101         return True;
102 }
103
104 bool locking_init(void)
105 {
106         return locking_init_internal(false);
107 }
108
109 bool locking_init_readonly(void)
110 {
111         return locking_init_internal(true);
112 }
113
114 /*******************************************************************
115  Deinitialize the share_mode management.
116 ******************************************************************/
117
118 bool locking_end(void)
119 {
120         brl_shutdown();
121         TALLOC_FREE(lock_db);
122         return true;
123 }
124
125 /*******************************************************************
126  Form a static locking key for a dev/inode pair.
127 ******************************************************************/
128
129 static TDB_DATA locking_key(const struct file_id *id)
130 {
131         return make_tdb_data((const uint8_t *)id, sizeof(*id));
132 }
133
134 /*******************************************************************
135  Share mode cache utility functions that store/delete/retrieve
136  entries from memcache.
137
138  For now share the statcache (global cache) memory space. If
139  a lock record gets orphaned (which shouldn't happen as we're
140  using the same locking_key data as lookup) it will eventually
141  fall out of the cache via the normal LRU trim mechanism. If
142  necessary we can always make this a separate (smaller) cache.
143 ******************************************************************/
144
145 static DATA_BLOB memcache_key(const struct file_id *id)
146 {
147         return data_blob_const((const void *)id, sizeof(*id));
148 }
149
150 static void share_mode_memcache_store(struct share_mode_data *d)
151 {
152         const DATA_BLOB key = memcache_key(&d->id);
153
154         DBG_DEBUG("stored entry for file %s seq %"PRIx64" key %s\n",
155                   d->base_name,
156                   d->sequence_number,
157                   file_id_string(talloc_tos(), &d->id));
158
159         /* Ensure everything stored in the cache is pristine. */
160         d->modified = false;
161         d->fresh = false;
162
163         /*
164          * Ensure the memory going into the cache
165          * doesn't have a destructor so it can be
166          * cleanly evicted by the memcache LRU
167          * mechanism.
168          */
169         talloc_set_destructor(d, NULL);
170
171         /* Cache will own d after this call. */
172         memcache_add_talloc(NULL,
173                         SHARE_MODE_LOCK_CACHE,
174                         key,
175                         &d);
176 }
177
178 /*
179  * NB. We use ndr_pull_hyper on a stack-created
180  * struct ndr_pull with no talloc allowed, as we
181  * need this to be really fast as an ndr-peek into
182  * the first 8 bytes of the blob.
183  */
184
185 static enum ndr_err_code get_blob_sequence_number(DATA_BLOB *blob,
186                                                 uint64_t *pseq)
187 {
188         struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length};
189         NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq));
190         return NDR_ERR_SUCCESS;
191 }
192
193 static int share_mode_data_nofree_destructor(struct share_mode_data *d)
194 {
195         return -1;
196 }
197
198 static struct share_mode_data *share_mode_memcache_fetch(TALLOC_CTX *mem_ctx,
199                                         const TDB_DATA id_key,
200                                         DATA_BLOB *blob)
201 {
202         enum ndr_err_code ndr_err;
203         struct share_mode_data *d;
204         uint64_t sequence_number;
205         void *ptr;
206         struct file_id id;
207         DATA_BLOB key;
208
209         /* Ensure this is a locking_key record. */
210         if (id_key.dsize != sizeof(id)) {
211                 return NULL;
212         }
213
214         memcpy(&id, id_key.dptr, id_key.dsize);
215         key = memcache_key(&id);
216
217         ptr = memcache_lookup_talloc(NULL,
218                         SHARE_MODE_LOCK_CACHE,
219                         key);
220         if (ptr == NULL) {
221                 DEBUG(10,("failed to find entry for key %s\n",
222                         file_id_string(mem_ctx, &id)));
223                 return NULL;
224         }
225         /* sequence number key is at start of blob. */
226         ndr_err = get_blob_sequence_number(blob, &sequence_number);
227         if (ndr_err != NDR_ERR_SUCCESS) {
228                 /* Bad blob. Remove entry. */
229                 DEBUG(10,("bad blob %u key %s\n",
230                         (unsigned int)ndr_err,
231                         file_id_string(mem_ctx, &id)));
232                 memcache_delete(NULL,
233                         SHARE_MODE_LOCK_CACHE,
234                         key);
235                 return NULL;
236         }
237
238         d = (struct share_mode_data *)ptr;
239         if (d->sequence_number != sequence_number) {
240                 DBG_DEBUG("seq changed (cached %"PRIx64") (new %"PRIx64") "
241                           "for key %s\n",
242                           d->sequence_number,
243                           sequence_number,
244                           file_id_string(mem_ctx, &id));
245                 /* Cache out of date. Remove entry. */
246                 memcache_delete(NULL,
247                         SHARE_MODE_LOCK_CACHE,
248                         key);
249                 return NULL;
250         }
251
252         /* Move onto mem_ctx. */
253         d = talloc_move(mem_ctx, &ptr);
254
255         /*
256          * Now we own d, prevent the cache from freeing it
257          * when we delete the entry.
258          */
259         talloc_set_destructor(d, share_mode_data_nofree_destructor);
260
261         /* Remove from the cache. We own it now. */
262         memcache_delete(NULL,
263                         SHARE_MODE_LOCK_CACHE,
264                         key);
265
266         /* And reset the destructor to none. */
267         talloc_set_destructor(d, NULL);
268
269         DBG_DEBUG("fetched entry for file %s seq %"PRIx64" key %s\n",
270                   d->base_name,
271                   d->sequence_number,
272                   file_id_string(mem_ctx, &id));
273
274         return d;
275 }
276
277 /*******************************************************************
278  Get all share mode entries for a dev/inode pair.
279 ********************************************************************/
280
281 static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
282                                                 const TDB_DATA key,
283                                                 const TDB_DATA dbuf)
284 {
285         struct share_mode_data *d;
286         enum ndr_err_code ndr_err;
287         DATA_BLOB blob;
288
289         blob.data = dbuf.dptr;
290         blob.length = dbuf.dsize;
291
292         /* See if we already have a cached copy of this key. */
293         d = share_mode_memcache_fetch(mem_ctx, key, &blob);
294         if (d != NULL) {
295                 return d;
296         }
297
298         d = talloc(mem_ctx, struct share_mode_data);
299         if (d == NULL) {
300                 DEBUG(0, ("talloc failed\n"));
301                 goto fail;
302         }
303
304         ndr_err = ndr_pull_struct_blob_all(
305                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
306         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
307                 DBG_WARNING("ndr_pull_share_mode_data failed: %s\n",
308                             ndr_errstr(ndr_err));
309                 goto fail;
310         }
311
312         if (DEBUGLEVEL >= 10) {
313                 DEBUG(10, ("parse_share_modes:\n"));
314                 NDR_PRINT_DEBUG(share_mode_data, d);
315         }
316
317         return d;
318 fail:
319         TALLOC_FREE(d);
320         return NULL;
321 }
322
323 /*******************************************************************
324  If modified, store the share_mode_data back into the database.
325 ********************************************************************/
326
327 static NTSTATUS share_mode_data_store(struct share_mode_data *d)
328 {
329         DATA_BLOB blob;
330         enum ndr_err_code ndr_err;
331         NTSTATUS status;
332
333         if (!d->modified) {
334                 DBG_DEBUG("not modified\n");
335                 return NT_STATUS_OK;
336         }
337
338         if (DEBUGLEVEL >= 10) {
339                 DBG_DEBUG("\n");
340                 NDR_PRINT_DEBUG(share_mode_data, d);
341         }
342
343         d->sequence_number += 1;
344         remove_stale_share_mode_entries(d);
345
346         if (d->num_share_modes == 0) {
347                 if (d->fresh) {
348                         DBG_DEBUG("Ignoring fresh emtpy record\n");
349                         return NT_STATUS_OK;
350                 }
351                 status = dbwrap_record_delete(d->record);
352                 return status;
353         }
354
355         ndr_err = ndr_push_struct_blob(
356                 &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data);
357         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
358                 DBG_DEBUG("ndr_push_share_mode_data failed: %s\n",
359                           ndr_errstr(ndr_err));
360                 return ndr_map_error2ntstatus(ndr_err);
361         }
362
363         status = dbwrap_record_store(
364                 d->record,
365                 (TDB_DATA) { .dptr = blob.data, .dsize = blob.length },
366                 TDB_REPLACE);
367         TALLOC_FREE(blob.data);
368
369         if (!NT_STATUS_IS_OK(status)) {
370                 DBG_DEBUG("dbwrap_record_store failed: %s\n",
371                           nt_errstr(status));
372         }
373
374         return status;
375 }
376
377 /*******************************************************************
378  Allocate a new share_mode_data struct, mark it unmodified.
379  fresh is set to note that currently there is no database entry.
380 ********************************************************************/
381
382 static struct share_mode_data *fresh_share_mode_lock(
383         TALLOC_CTX *mem_ctx, const char *servicepath,
384         const struct smb_filename *smb_fname,
385         const struct timespec *old_write_time)
386 {
387         struct share_mode_data *d;
388
389         if ((servicepath == NULL) || (smb_fname == NULL) ||
390             (old_write_time == NULL)) {
391                 return NULL;
392         }
393
394         d = talloc_zero(mem_ctx, struct share_mode_data);
395         if (d == NULL) {
396                 goto fail;
397         }
398         /* New record - new sequence number. */
399         generate_random_buffer((uint8_t *)&d->sequence_number, 8);
400
401         d->base_name = talloc_strdup(d, smb_fname->base_name);
402         if (d->base_name == NULL) {
403                 goto fail;
404         }
405         if (smb_fname->stream_name != NULL) {
406                 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
407                 if (d->stream_name == NULL) {
408                         goto fail;
409                 }
410         }
411         d->servicepath = talloc_strdup(d, servicepath);
412         if (d->servicepath == NULL) {
413                 goto fail;
414         }
415         d->old_write_time = *old_write_time;
416         d->modified = false;
417         d->fresh = true;
418         return d;
419 fail:
420         DEBUG(0, ("talloc failed\n"));
421         TALLOC_FREE(d);
422         return NULL;
423 }
424
425 /*
426  * We can only ever have one share mode locked. Use a static
427  * share_mode_data pointer that is shared by multiple nested
428  * share_mode_lock structures, explicitly refcounted.
429  */
430 static struct share_mode_data *static_share_mode_data = NULL;
431 static size_t static_share_mode_data_refcount = 0;
432
433 /*
434  * db_record for the above. With dbwrap_do_locked we can get a
435  * db_record on the stack, which we can't TALLOC_FREE but which we
436  * need to share with a nested get_share_mode_lock call.
437  */
438 static struct db_record *static_share_mode_record = NULL;
439 static bool static_share_mode_record_talloced = false;
440
441 /*******************************************************************
442  Either fetch a share mode from the database, or allocate a fresh
443  one if the record doesn't exist.
444 ********************************************************************/
445
446 static NTSTATUS get_static_share_mode_data(
447         struct db_record *rec,
448         struct file_id id,
449         const char *servicepath,
450         const struct smb_filename *smb_fname,
451         const struct timespec *old_write_time)
452 {
453         struct share_mode_data *d;
454         TDB_DATA value = dbwrap_record_get_value(rec);
455
456         SMB_ASSERT(static_share_mode_data == NULL);
457
458         if (value.dptr == NULL) {
459                 d = fresh_share_mode_lock(
460                         lock_db, servicepath, smb_fname, old_write_time);
461                 if (d == NULL) {
462                         return NT_STATUS_NO_MEMORY;
463                 }
464         } else {
465                 TDB_DATA key = locking_key(&id);
466                 d = parse_share_modes(lock_db, key, value);
467                 if (d == NULL) {
468                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
469                 }
470         }
471
472         d->id = id;
473         d->record = rec;
474
475         static_share_mode_data = d;
476
477         return NT_STATUS_OK;
478 }
479
480 /*******************************************************************
481  Get a share_mode_lock, Reference counted to allow nested calls.
482 ********************************************************************/
483
484 static int share_mode_lock_destructor(struct share_mode_lock *lck);
485
486 struct share_mode_lock *get_share_mode_lock(
487         TALLOC_CTX *mem_ctx,
488         struct file_id id,
489         const char *servicepath,
490         const struct smb_filename *smb_fname,
491         const struct timespec *old_write_time)
492 {
493         TDB_DATA key = locking_key(&id);
494         struct share_mode_lock *lck = NULL;
495         NTSTATUS status;
496
497         lck = talloc(mem_ctx, struct share_mode_lock);
498         if (lck == NULL) {
499                 DEBUG(1, ("talloc failed\n"));
500                 return NULL;
501         }
502
503         if (static_share_mode_data != NULL) {
504                 if (!file_id_equal(&static_share_mode_data->id, &id)) {
505                         DEBUG(1, ("Can not lock two share modes "
506                                   "simultaneously\n"));
507                         goto fail;
508                 }
509                 goto done;
510         }
511
512         SMB_ASSERT(static_share_mode_data_refcount == 0);
513
514         if (static_share_mode_record == NULL) {
515                 static_share_mode_record = dbwrap_fetch_locked(
516                         lock_db, lock_db, key);
517                 if (static_share_mode_record == NULL) {
518                         DEBUG(3, ("Could not lock share entry\n"));
519                         goto fail;
520                 }
521                 static_share_mode_record_talloced = true;
522
523                 status = get_static_share_mode_data(
524                         static_share_mode_record,
525                         id,
526                         servicepath,
527                         smb_fname,
528                         old_write_time);
529                 if (!NT_STATUS_IS_OK(status)) {
530                         DBG_WARNING("get_static_share_mode_data failed: %s\n",
531                                     nt_errstr(status));
532                         TALLOC_FREE(static_share_mode_record);
533                         goto fail;
534                 }
535         } else {
536                 TDB_DATA static_key;
537                 int cmp;
538
539                 static_key = dbwrap_record_get_key(static_share_mode_record);
540
541                 cmp = tdb_data_cmp(static_key, key);
542                 if (cmp != 0) {
543                         DBG_WARNING("Can not lock two share modes "
544                                     "simultaneously\n");
545                         return NULL;
546                 }
547
548                 status = get_static_share_mode_data(
549                         static_share_mode_record,
550                         id,
551                         servicepath,
552                         smb_fname,
553                         old_write_time);
554                 if (!NT_STATUS_IS_OK(status)) {
555                         DBG_WARNING("get_static_share_mode_data failed: %s\n",
556                                     nt_errstr(status));
557                         goto fail;
558                 }
559         }
560
561 done:
562         static_share_mode_data_refcount += 1;
563         lck->data = static_share_mode_data;
564
565         talloc_set_destructor(lck, share_mode_lock_destructor);
566
567         return lck;
568 fail:
569         TALLOC_FREE(lck);
570         return NULL;
571 }
572
573 static int share_mode_lock_destructor(struct share_mode_lock *lck)
574 {
575         NTSTATUS status;
576
577         SMB_ASSERT(static_share_mode_data_refcount > 0);
578         static_share_mode_data_refcount -= 1;
579
580         if (static_share_mode_data_refcount > 0) {
581                 return 0;
582         }
583
584         status = share_mode_data_store(static_share_mode_data);
585         if (!NT_STATUS_IS_OK(status)) {
586                 DBG_ERR("share_mode_data_store failed: %s\n",
587                         nt_errstr(status));
588                 smb_panic("Could not store share mode data\n");
589         }
590
591         /*
592          * Drop the locking.tdb lock before moving the share_mode_data
593          * to memcache
594          */
595         SMB_ASSERT(static_share_mode_data->record == static_share_mode_record);
596         static_share_mode_data->record = NULL;
597
598         if (static_share_mode_record_talloced) {
599                 TALLOC_FREE(static_share_mode_record);
600         }
601
602         if (static_share_mode_data->num_share_modes != 0) {
603                 /*
604                  * This is worth keeping. Without share modes,
605                  * share_mode_data_store above has left nothing in the
606                  * database.
607                  */
608                 share_mode_memcache_store(static_share_mode_data);
609                 static_share_mode_data = NULL;
610         } else {
611                 /*
612                  * The next opener of this file will find an empty
613                  * locking.tdb record. Don't store the share_mode_data
614                  * in the memcache, fresh_share_mode_lock() will
615                  * generate a fresh seqnum anyway, obsoleting the
616                  * cache entry.
617                  */
618                 TALLOC_FREE(static_share_mode_data);
619         }
620
621         return 0;
622 }
623
624 struct share_mode_do_locked_state {
625         void (*fn)(struct db_record *rec,
626                    bool *modified_dependent,
627                    void *private_data);
628         void *private_data;
629 };
630
631 static void share_mode_do_locked_fn(struct db_record *rec,
632                                     void *private_data)
633 {
634         struct share_mode_do_locked_state *state = private_data;
635         bool modified_dependent = false;
636         bool reset_static_share_mode_record = false;
637
638         if (static_share_mode_record == NULL) {
639                 static_share_mode_record = rec;
640                 static_share_mode_record_talloced = false;
641                 reset_static_share_mode_record = true;
642         } else {
643                 SMB_ASSERT(static_share_mode_record == rec);
644         }
645
646         state->fn(rec, &modified_dependent, state->private_data);
647
648         if (modified_dependent) {
649                 dbwrap_watched_wakeup(rec);
650         }
651
652         if (reset_static_share_mode_record) {
653                 static_share_mode_record = NULL;
654         }
655 }
656
657 NTSTATUS share_mode_do_locked(
658         struct file_id id,
659         void (*fn)(struct db_record *rec,
660                    bool *modified_dependent,
661                    void *private_data),
662         void *private_data)
663 {
664         TDB_DATA key = locking_key(&id);
665         size_t refcount = static_share_mode_data_refcount;
666
667         if (static_share_mode_record != NULL) {
668                 bool modified_dependent = false;
669                 TDB_DATA static_key;
670                 int cmp;
671
672                 static_key = dbwrap_record_get_key(static_share_mode_record);
673
674                 cmp = tdb_data_cmp(static_key, key);
675                 if (cmp != 0) {
676                         DBG_WARNING("Can not lock two share modes "
677                                     "simultaneously\n");
678                         return NT_STATUS_INVALID_LOCK_SEQUENCE;
679                 }
680
681                 fn(static_share_mode_record,
682                    &modified_dependent,
683                    private_data);
684
685                 if (modified_dependent) {
686                         dbwrap_watched_wakeup(static_share_mode_record);
687                 }
688         } else {
689                 struct share_mode_do_locked_state state = {
690                         .fn = fn, .private_data = private_data,
691                 };
692                 NTSTATUS status;
693
694                 status = dbwrap_do_locked(
695                         lock_db, key, share_mode_do_locked_fn, &state);
696                 if (!NT_STATUS_IS_OK(status)) {
697                         DBG_WARNING("dbwrap_do_locked failed: %s\n",
698                                     nt_errstr(status));
699                         return status;
700                 }
701         }
702
703         SMB_ASSERT(refcount == static_share_mode_data_refcount);
704
705         return NT_STATUS_OK;
706 }
707
708 struct fetch_share_mode_unlocked_state {
709         TALLOC_CTX *mem_ctx;
710         struct share_mode_lock *lck;
711 };
712
713 static void fetch_share_mode_unlocked_parser(
714         TDB_DATA key, TDB_DATA data, void *private_data)
715 {
716         struct fetch_share_mode_unlocked_state *state = private_data;
717
718         if (data.dsize == 0) {
719                 /* Likely a ctdb tombstone record, ignore it */
720                 return;
721         }
722
723         state->lck = talloc(state->mem_ctx, struct share_mode_lock);
724         if (state->lck == NULL) {
725                 DEBUG(0, ("talloc failed\n"));
726                 return;
727         }
728
729         state->lck->data = parse_share_modes(state->lck, key, data);
730 }
731
732 /*******************************************************************
733  Get a share_mode_lock without locking the database or reference
734  counting. Used by smbstatus to display existing share modes.
735 ********************************************************************/
736
737 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
738                                                   struct file_id id)
739 {
740         struct fetch_share_mode_unlocked_state state = { .mem_ctx = mem_ctx };
741         TDB_DATA key = locking_key(&id);
742         NTSTATUS status;
743
744         status = dbwrap_parse_record(
745                 lock_db, key, fetch_share_mode_unlocked_parser, &state);
746         if (!NT_STATUS_IS_OK(status)) {
747                 return NULL;
748         }
749         return state.lck;
750 }
751
752 static void fetch_share_mode_done(struct tevent_req *subreq);
753
754 struct fetch_share_mode_state {
755         struct file_id id;
756         TDB_DATA key;
757         struct fetch_share_mode_unlocked_state parser_state;
758         enum dbwrap_req_state req_state;
759 };
760
761 /**
762  * @brief Get a share_mode_lock without locking or refcounting
763  *
764  * This can be used in a clustered Samba environment where the async dbwrap
765  * request is sent over a socket to the local ctdbd. If the send queue is full
766  * and the caller was issuing multiple async dbwrap requests in a loop, the
767  * caller knows it's probably time to stop sending requests for now and try
768  * again later.
769  *
770  * @param[in]  mem_ctx The talloc memory context to use.
771  *
772  * @param[in]  ev      The event context to work on.
773  *
774  * @param[in]  id      The file id for the locking.tdb key
775  *
776  * @param[out] queued  This boolean out parameter tells the caller whether the
777  *                     async request is blocked in a full send queue:
778  *
779  *                     false := request is dispatched
780  *
781  *                     true  := send queue is full, request waiting to be
782  *                              dispatched
783  *
784  * @return             The new async request, NULL on error.
785  **/
786 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
787                                          struct tevent_context *ev,
788                                          struct file_id id,
789                                          bool *queued)
790 {
791         struct tevent_req *req = NULL;
792         struct fetch_share_mode_state *state = NULL;
793         struct tevent_req *subreq = NULL;
794
795         *queued = false;
796
797         req = tevent_req_create(mem_ctx, &state,
798                                 struct fetch_share_mode_state);
799         if (req == NULL) {
800                 return NULL;
801         }
802
803         state->id = id;
804         state->key = locking_key(&state->id);
805         state->parser_state.mem_ctx = state;
806
807         subreq = dbwrap_parse_record_send(state,
808                                           ev,
809                                           lock_db,
810                                           state->key,
811                                           fetch_share_mode_unlocked_parser,
812                                           &state->parser_state,
813                                           &state->req_state);
814         if (tevent_req_nomem(subreq, req)) {
815                 return tevent_req_post(req, ev);
816         }
817         tevent_req_set_callback(subreq, fetch_share_mode_done, req);
818
819         if (state->req_state < DBWRAP_REQ_DISPATCHED) {
820                 *queued = true;
821         }
822         return req;
823 }
824
825 static void fetch_share_mode_done(struct tevent_req *subreq)
826 {
827         struct tevent_req *req = tevent_req_callback_data(
828                 subreq, struct tevent_req);
829         NTSTATUS status;
830
831         status = dbwrap_parse_record_recv(subreq);
832         TALLOC_FREE(subreq);
833         if (tevent_req_nterror(req, status)) {
834                 return;
835         }
836
837         tevent_req_done(req);
838         return;
839 }
840
841 NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
842                                TALLOC_CTX *mem_ctx,
843                                struct share_mode_lock **_lck)
844 {
845         struct fetch_share_mode_state *state = tevent_req_data(
846                 req, struct fetch_share_mode_state);
847         struct share_mode_lock *lck = NULL;
848
849         NTSTATUS status;
850
851         if (tevent_req_is_nterror(req, &status)) {
852                 tevent_req_received(req);
853                 return status;
854         }
855
856         if (state->parser_state.lck->data == NULL) {
857                 tevent_req_received(req);
858                 return NT_STATUS_NOT_FOUND;
859         }
860
861         lck = talloc_move(mem_ctx, &state->parser_state.lck);
862
863         if (DEBUGLEVEL >= 10) {
864                 DBG_DEBUG("share_mode_data:\n");
865                 NDR_PRINT_DEBUG(share_mode_data, lck->data);
866         }
867
868         *_lck = lck;
869         tevent_req_received(req);
870         return NT_STATUS_OK;
871 }
872
873 struct share_mode_forall_state {
874         int (*fn)(struct file_id fid, const struct share_mode_data *data,
875                   void *private_data);
876         void *private_data;
877 };
878
879 static int share_mode_traverse_fn(struct db_record *rec, void *_state)
880 {
881         struct share_mode_forall_state *state =
882                 (struct share_mode_forall_state *)_state;
883         TDB_DATA key;
884         TDB_DATA value;
885         DATA_BLOB blob;
886         enum ndr_err_code ndr_err;
887         struct share_mode_data *d;
888         struct file_id fid;
889         int ret;
890
891         key = dbwrap_record_get_key(rec);
892         value = dbwrap_record_get_value(rec);
893
894         /* Ensure this is a locking_key record. */
895         if (key.dsize != sizeof(fid)) {
896                 return 0;
897         }
898         memcpy(&fid, key.dptr, sizeof(fid));
899
900         d = talloc(talloc_tos(), struct share_mode_data);
901         if (d == NULL) {
902                 return 0;
903         }
904
905         blob.data = value.dptr;
906         blob.length = value.dsize;
907
908         ndr_err = ndr_pull_struct_blob_all(
909                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
910         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
911                 DEBUG(1, ("ndr_pull_share_mode_lock failed\n"));
912                 return 0;
913         }
914
915         if (DEBUGLEVEL > 10) {
916                 DEBUG(11, ("parse_share_modes:\n"));
917                 NDR_PRINT_DEBUG(share_mode_data, d);
918         }
919
920         ret = state->fn(fid, d, state->private_data);
921
922         TALLOC_FREE(d);
923         return ret;
924 }
925
926 int share_mode_forall(int (*fn)(struct file_id fid,
927                                 const struct share_mode_data *data,
928                                 void *private_data),
929                       void *private_data)
930 {
931         struct share_mode_forall_state state = {
932                 .fn = fn,
933                 .private_data = private_data
934         };
935         NTSTATUS status;
936         int count;
937
938         if (lock_db == NULL) {
939                 return 0;
940         }
941
942         status = dbwrap_traverse_read(lock_db, share_mode_traverse_fn,
943                                       &state, &count);
944         if (!NT_STATUS_IS_OK(status)) {
945                 return -1;
946         }
947
948         return count;
949 }
950
951 struct share_entry_forall_state {
952         int (*fn)(struct file_id fid,
953                   const struct share_mode_data *data,
954                   const struct share_mode_entry *entry,
955                   void *private_data);
956         void *private_data;
957 };
958
959 static int share_entry_traverse_fn(struct file_id fid,
960                                    const struct share_mode_data *data,
961                                    void *private_data)
962 {
963         struct share_entry_forall_state *state = private_data;
964         uint32_t i;
965
966         for (i=0; i<data->num_share_modes; i++) {
967                 int ret;
968
969                 ret = state->fn(fid,
970                                 data,
971                                 &data->share_modes[i],
972                                 state->private_data);
973                 if (ret != 0) {
974                         return ret;
975                 }
976         }
977
978         return 0;
979 }
980
981 /*******************************************************************
982  Call the specified function on each entry under management by the
983  share mode system.
984 ********************************************************************/
985
986 int share_entry_forall(int (*fn)(struct file_id fid,
987                                  const struct share_mode_data *data,
988                                  const struct share_mode_entry *entry,
989                                  void *private_data),
990                       void *private_data)
991 {
992         struct share_entry_forall_state state = {
993                 .fn = fn, .private_data = private_data };
994
995         return share_mode_forall(share_entry_traverse_fn, &state);
996 }
997
998 static bool cleanup_disconnected_lease(struct share_mode_lock *lck,
999                                        struct share_mode_entry *e,
1000                                        void *private_data)
1001 {
1002         struct share_mode_data *d = lck->data;
1003         NTSTATUS status;
1004
1005         status = leases_db_del(&e->client_guid, &e->lease_key, &d->id);
1006
1007         if (!NT_STATUS_IS_OK(status)) {
1008                 DBG_DEBUG("leases_db_del failed: %s\n",
1009                           nt_errstr(status));
1010         }
1011
1012         return false;
1013 }
1014
1015 bool share_mode_cleanup_disconnected(struct file_id fid,
1016                                      uint64_t open_persistent_id)
1017 {
1018         bool ret = false;
1019         TALLOC_CTX *frame = talloc_stackframe();
1020         unsigned n;
1021         struct share_mode_data *data;
1022         struct share_mode_lock *lck;
1023         bool ok;
1024
1025         lck = get_existing_share_mode_lock(frame, fid);
1026         if (lck == NULL) {
1027                 DEBUG(5, ("share_mode_cleanup_disconnected: "
1028                           "Could not fetch share mode entry for %s\n",
1029                           file_id_string(frame, &fid)));
1030                 goto done;
1031         }
1032         data = lck->data;
1033
1034         for (n=0; n < data->num_share_modes; n++) {
1035                 struct share_mode_entry *entry = &data->share_modes[n];
1036
1037                 if (!server_id_is_disconnected(&entry->pid)) {
1038                         struct server_id_buf tmp;
1039                         DEBUG(5, ("share_mode_cleanup_disconnected: "
1040                                   "file (file-id='%s', servicepath='%s', "
1041                                   "base_name='%s%s%s') "
1042                                   "is used by server %s ==> do not cleanup\n",
1043                                   file_id_string(frame, &fid),
1044                                   data->servicepath,
1045                                   data->base_name,
1046                                   (data->stream_name == NULL)
1047                                   ? "" : "', stream_name='",
1048                                   (data->stream_name == NULL)
1049                                   ? "" : data->stream_name,
1050                                   server_id_str_buf(entry->pid, &tmp)));
1051                         goto done;
1052                 }
1053                 if (open_persistent_id != entry->share_file_id) {
1054                         DBG_INFO("entry for file "
1055                                  "(file-id='%s', servicepath='%s', "
1056                                  "base_name='%s%s%s') "
1057                                  "has share_file_id %"PRIu64" but expected "
1058                                  "%"PRIu64"==> do not cleanup\n",
1059                                  file_id_string(frame, &fid),
1060                                  data->servicepath,
1061                                  data->base_name,
1062                                  (data->stream_name == NULL)
1063                                  ? "" : "', stream_name='",
1064                                  (data->stream_name == NULL)
1065                                  ? "" : data->stream_name,
1066                                  entry->share_file_id,
1067                                  open_persistent_id);
1068                         goto done;
1069                 }
1070         }
1071
1072         ok = share_mode_forall_leases(lck, cleanup_disconnected_lease, NULL);
1073         if (!ok) {
1074                 DBG_DEBUG("failed to clean up leases associated "
1075                           "with file (file-id='%s', servicepath='%s', "
1076                           "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
1077                           "==> do not cleanup\n",
1078                           file_id_string(frame, &fid),
1079                           data->servicepath,
1080                           data->base_name,
1081                           (data->stream_name == NULL)
1082                           ? "" : "', stream_name='",
1083                           (data->stream_name == NULL)
1084                           ? "" : data->stream_name,
1085                           open_persistent_id);
1086         }
1087
1088         ok = brl_cleanup_disconnected(fid, open_persistent_id);
1089         if (!ok) {
1090                 DBG_DEBUG("failed to clean up byte range locks associated "
1091                           "with file (file-id='%s', servicepath='%s', "
1092                           "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
1093                           "==> do not cleanup\n",
1094                           file_id_string(frame, &fid),
1095                           data->servicepath,
1096                           data->base_name,
1097                           (data->stream_name == NULL)
1098                           ? "" : "', stream_name='",
1099                           (data->stream_name == NULL)
1100                           ? "" : data->stream_name,
1101                           open_persistent_id);
1102                 goto done;
1103         }
1104
1105         DBG_DEBUG("cleaning up %u entries for file "
1106                   "(file-id='%s', servicepath='%s', "
1107                   "base_name='%s%s%s') "
1108                   "from open_persistent_id %"PRIu64"\n",
1109                   data->num_share_modes,
1110                   file_id_string(frame, &fid),
1111                   data->servicepath,
1112                   data->base_name,
1113                   (data->stream_name == NULL)
1114                   ? "" : "', stream_name='",
1115                   (data->stream_name == NULL)
1116                   ? "" : data->stream_name,
1117                   open_persistent_id);
1118
1119         data->num_share_modes = 0;
1120         data->modified = true;
1121
1122         ret = true;
1123 done:
1124         talloc_free(frame);
1125         return ret;
1126 }