1244c21ebba1ca431ddfa9b9250214534ddf6b9f
[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  Either fetch a share mode from the database, or allocate a fresh
435  one if the record doesn't exist.
436 ********************************************************************/
437
438 static NTSTATUS get_static_share_mode_data(
439         struct db_record *rec,
440         struct file_id id,
441         const char *servicepath,
442         const struct smb_filename *smb_fname,
443         const struct timespec *old_write_time)
444 {
445         struct share_mode_data *d;
446         TDB_DATA value = dbwrap_record_get_value(rec);
447
448         SMB_ASSERT(static_share_mode_data == NULL);
449
450         if (value.dptr == NULL) {
451                 d = fresh_share_mode_lock(
452                         lock_db, servicepath, smb_fname, old_write_time);
453                 if (d == NULL) {
454                         return NT_STATUS_NO_MEMORY;
455                 }
456         } else {
457                 TDB_DATA key = locking_key(&id);
458                 d = parse_share_modes(lock_db, key, value);
459                 if (d == NULL) {
460                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
461                 }
462         }
463
464         d->id = id;
465         d->record = rec;
466
467         static_share_mode_data = d;
468
469         return NT_STATUS_OK;
470 }
471
472 /*******************************************************************
473  Get a share_mode_lock, Reference counted to allow nested calls.
474 ********************************************************************/
475
476 static int share_mode_lock_destructor(struct share_mode_lock *lck);
477
478 struct share_mode_lock *get_share_mode_lock(
479         TALLOC_CTX *mem_ctx,
480         struct file_id id,
481         const char *servicepath,
482         const struct smb_filename *smb_fname,
483         const struct timespec *old_write_time)
484 {
485         TDB_DATA key = locking_key(&id);
486         struct db_record *rec = NULL;
487         struct share_mode_lock *lck = NULL;
488         NTSTATUS status;
489
490         lck = talloc(mem_ctx, struct share_mode_lock);
491         if (lck == NULL) {
492                 DEBUG(1, ("talloc failed\n"));
493                 return NULL;
494         }
495
496         if (static_share_mode_data != NULL) {
497                 if (!file_id_equal(&static_share_mode_data->id, &id)) {
498                         DEBUG(1, ("Can not lock two share modes "
499                                   "simultaneously\n"));
500                         goto fail;
501                 }
502                 goto done;
503         }
504
505         SMB_ASSERT(static_share_mode_data_refcount == 0);
506
507         rec = dbwrap_fetch_locked(lock_db, lock_db, key);
508         if (rec == NULL) {
509                 DEBUG(3, ("Could not lock share entry\n"));
510                 goto fail;
511         }
512
513         status = get_static_share_mode_data(
514                 rec, id, servicepath, smb_fname, old_write_time);
515         if (!NT_STATUS_IS_OK(status)) {
516                 DBG_WARNING("get_static_share_mode_data failed: %s\n",
517                             nt_errstr(status));
518                 TALLOC_FREE(rec);
519                 goto fail;
520         }
521
522         /*
523          * This is unnecessary, in share_mode_lock_destructor we
524          * explicitly TALLOC_FREE lck->data->rec. Leave it here as
525          * it's cleaner in the talloc report.
526          */
527         talloc_reparent(lock_db, static_share_mode_data, rec);
528
529 done:
530         static_share_mode_data_refcount += 1;
531         lck->data = static_share_mode_data;
532
533         talloc_set_destructor(lck, share_mode_lock_destructor);
534
535         return lck;
536 fail:
537         TALLOC_FREE(lck);
538         return NULL;
539 }
540
541 static int share_mode_lock_destructor(struct share_mode_lock *lck)
542 {
543         NTSTATUS status;
544
545         SMB_ASSERT(static_share_mode_data_refcount > 0);
546         static_share_mode_data_refcount -= 1;
547
548         if (static_share_mode_data_refcount > 0) {
549                 return 0;
550         }
551
552         status = share_mode_data_store(static_share_mode_data);
553         if (!NT_STATUS_IS_OK(status)) {
554                 DBG_ERR("share_mode_data_store failed: %s\n",
555                         nt_errstr(status));
556                 smb_panic("Could not store share mode data\n");
557         }
558
559         /*
560          * Drop the locking.tdb lock before moving the share_mode_data
561          * to memcache
562          */
563         TALLOC_FREE(static_share_mode_data->record);
564
565         if (static_share_mode_data->num_share_modes != 0) {
566                 /*
567                  * This is worth keeping. Without share modes,
568                  * share_mode_data_store above has left nothing in the
569                  * database.
570                  */
571                 share_mode_memcache_store(static_share_mode_data);
572                 static_share_mode_data = NULL;
573         } else {
574                 /*
575                  * The next opener of this file will find an empty
576                  * locking.tdb record. Don't store the share_mode_data
577                  * in the memcache, fresh_share_mode_lock() will
578                  * generate a fresh seqnum anyway, obsoleting the
579                  * cache entry.
580                  */
581                 TALLOC_FREE(static_share_mode_data);
582         }
583
584         return 0;
585 }
586
587 struct fetch_share_mode_unlocked_state {
588         TALLOC_CTX *mem_ctx;
589         struct share_mode_lock *lck;
590 };
591
592 static void fetch_share_mode_unlocked_parser(
593         TDB_DATA key, TDB_DATA data, void *private_data)
594 {
595         struct fetch_share_mode_unlocked_state *state = private_data;
596
597         if (data.dsize == 0) {
598                 /* Likely a ctdb tombstone record, ignore it */
599                 return;
600         }
601
602         state->lck = talloc(state->mem_ctx, struct share_mode_lock);
603         if (state->lck == NULL) {
604                 DEBUG(0, ("talloc failed\n"));
605                 return;
606         }
607
608         state->lck->data = parse_share_modes(state->lck, key, data);
609 }
610
611 /*******************************************************************
612  Get a share_mode_lock without locking the database or reference
613  counting. Used by smbstatus to display existing share modes.
614 ********************************************************************/
615
616 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
617                                                   struct file_id id)
618 {
619         struct fetch_share_mode_unlocked_state state = { .mem_ctx = mem_ctx };
620         TDB_DATA key = locking_key(&id);
621         NTSTATUS status;
622
623         status = dbwrap_parse_record(
624                 lock_db, key, fetch_share_mode_unlocked_parser, &state);
625         if (!NT_STATUS_IS_OK(status)) {
626                 return NULL;
627         }
628         return state.lck;
629 }
630
631 static void fetch_share_mode_done(struct tevent_req *subreq);
632
633 struct fetch_share_mode_state {
634         struct file_id id;
635         TDB_DATA key;
636         struct fetch_share_mode_unlocked_state parser_state;
637         enum dbwrap_req_state req_state;
638 };
639
640 /**
641  * @brief Get a share_mode_lock without locking or refcounting
642  *
643  * This can be used in a clustered Samba environment where the async dbwrap
644  * request is sent over a socket to the local ctdbd. If the send queue is full
645  * and the caller was issuing multiple async dbwrap requests in a loop, the
646  * caller knows it's probably time to stop sending requests for now and try
647  * again later.
648  *
649  * @param[in]  mem_ctx The talloc memory context to use.
650  *
651  * @param[in]  ev      The event context to work on.
652  *
653  * @param[in]  id      The file id for the locking.tdb key
654  *
655  * @param[out] queued  This boolean out parameter tells the caller whether the
656  *                     async request is blocked in a full send queue:
657  *
658  *                     false := request is dispatched
659  *
660  *                     true  := send queue is full, request waiting to be
661  *                              dispatched
662  *
663  * @return             The new async request, NULL on error.
664  **/
665 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
666                                          struct tevent_context *ev,
667                                          struct file_id id,
668                                          bool *queued)
669 {
670         struct tevent_req *req = NULL;
671         struct fetch_share_mode_state *state = NULL;
672         struct tevent_req *subreq = NULL;
673
674         *queued = false;
675
676         req = tevent_req_create(mem_ctx, &state,
677                                 struct fetch_share_mode_state);
678         if (req == NULL) {
679                 return NULL;
680         }
681
682         state->id = id;
683         state->key = locking_key(&state->id);
684         state->parser_state.mem_ctx = state;
685
686         subreq = dbwrap_parse_record_send(state,
687                                           ev,
688                                           lock_db,
689                                           state->key,
690                                           fetch_share_mode_unlocked_parser,
691                                           &state->parser_state,
692                                           &state->req_state);
693         if (tevent_req_nomem(subreq, req)) {
694                 return tevent_req_post(req, ev);
695         }
696         tevent_req_set_callback(subreq, fetch_share_mode_done, req);
697
698         if (state->req_state < DBWRAP_REQ_DISPATCHED) {
699                 *queued = true;
700         }
701         return req;
702 }
703
704 static void fetch_share_mode_done(struct tevent_req *subreq)
705 {
706         struct tevent_req *req = tevent_req_callback_data(
707                 subreq, struct tevent_req);
708         NTSTATUS status;
709
710         status = dbwrap_parse_record_recv(subreq);
711         TALLOC_FREE(subreq);
712         if (tevent_req_nterror(req, status)) {
713                 return;
714         }
715
716         tevent_req_done(req);
717         return;
718 }
719
720 NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
721                                TALLOC_CTX *mem_ctx,
722                                struct share_mode_lock **_lck)
723 {
724         struct fetch_share_mode_state *state = tevent_req_data(
725                 req, struct fetch_share_mode_state);
726         struct share_mode_lock *lck = NULL;
727
728         NTSTATUS status;
729
730         if (tevent_req_is_nterror(req, &status)) {
731                 tevent_req_received(req);
732                 return status;
733         }
734
735         if (state->parser_state.lck->data == NULL) {
736                 tevent_req_received(req);
737                 return NT_STATUS_NOT_FOUND;
738         }
739
740         lck = talloc_move(mem_ctx, &state->parser_state.lck);
741
742         if (DEBUGLEVEL >= 10) {
743                 DBG_DEBUG("share_mode_data:\n");
744                 NDR_PRINT_DEBUG(share_mode_data, lck->data);
745         }
746
747         *_lck = lck;
748         tevent_req_received(req);
749         return NT_STATUS_OK;
750 }
751
752 struct share_mode_forall_state {
753         int (*fn)(struct file_id fid, const struct share_mode_data *data,
754                   void *private_data);
755         void *private_data;
756 };
757
758 static int share_mode_traverse_fn(struct db_record *rec, void *_state)
759 {
760         struct share_mode_forall_state *state =
761                 (struct share_mode_forall_state *)_state;
762         TDB_DATA key;
763         TDB_DATA value;
764         DATA_BLOB blob;
765         enum ndr_err_code ndr_err;
766         struct share_mode_data *d;
767         struct file_id fid;
768         int ret;
769
770         key = dbwrap_record_get_key(rec);
771         value = dbwrap_record_get_value(rec);
772
773         /* Ensure this is a locking_key record. */
774         if (key.dsize != sizeof(fid)) {
775                 return 0;
776         }
777         memcpy(&fid, key.dptr, sizeof(fid));
778
779         d = talloc(talloc_tos(), struct share_mode_data);
780         if (d == NULL) {
781                 return 0;
782         }
783
784         blob.data = value.dptr;
785         blob.length = value.dsize;
786
787         ndr_err = ndr_pull_struct_blob_all(
788                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
789         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
790                 DEBUG(1, ("ndr_pull_share_mode_lock failed\n"));
791                 return 0;
792         }
793
794         if (DEBUGLEVEL > 10) {
795                 DEBUG(11, ("parse_share_modes:\n"));
796                 NDR_PRINT_DEBUG(share_mode_data, d);
797         }
798
799         ret = state->fn(fid, d, state->private_data);
800
801         TALLOC_FREE(d);
802         return ret;
803 }
804
805 int share_mode_forall(int (*fn)(struct file_id fid,
806                                 const struct share_mode_data *data,
807                                 void *private_data),
808                       void *private_data)
809 {
810         struct share_mode_forall_state state = {
811                 .fn = fn,
812                 .private_data = private_data
813         };
814         NTSTATUS status;
815         int count;
816
817         if (lock_db == NULL) {
818                 return 0;
819         }
820
821         status = dbwrap_traverse_read(lock_db, share_mode_traverse_fn,
822                                       &state, &count);
823         if (!NT_STATUS_IS_OK(status)) {
824                 return -1;
825         }
826
827         return count;
828 }
829
830 struct share_entry_forall_state {
831         int (*fn)(struct file_id fid,
832                   const struct share_mode_data *data,
833                   const struct share_mode_entry *entry,
834                   void *private_data);
835         void *private_data;
836 };
837
838 static int share_entry_traverse_fn(struct file_id fid,
839                                    const struct share_mode_data *data,
840                                    void *private_data)
841 {
842         struct share_entry_forall_state *state = private_data;
843         uint32_t i;
844
845         for (i=0; i<data->num_share_modes; i++) {
846                 int ret;
847
848                 ret = state->fn(fid,
849                                 data,
850                                 &data->share_modes[i],
851                                 state->private_data);
852                 if (ret != 0) {
853                         return ret;
854                 }
855         }
856
857         return 0;
858 }
859
860 /*******************************************************************
861  Call the specified function on each entry under management by the
862  share mode system.
863 ********************************************************************/
864
865 int share_entry_forall(int (*fn)(struct file_id fid,
866                                  const struct share_mode_data *data,
867                                  const struct share_mode_entry *entry,
868                                  void *private_data),
869                       void *private_data)
870 {
871         struct share_entry_forall_state state = {
872                 .fn = fn, .private_data = private_data };
873
874         return share_mode_forall(share_entry_traverse_fn, &state);
875 }
876
877 static bool cleanup_disconnected_lease(struct share_mode_lock *lck,
878                                        struct share_mode_entry *e,
879                                        void *private_data)
880 {
881         struct share_mode_data *d = lck->data;
882         NTSTATUS status;
883
884         status = leases_db_del(&e->client_guid, &e->lease_key, &d->id);
885
886         if (!NT_STATUS_IS_OK(status)) {
887                 DBG_DEBUG("leases_db_del failed: %s\n",
888                           nt_errstr(status));
889         }
890
891         return false;
892 }
893
894 bool share_mode_cleanup_disconnected(struct file_id fid,
895                                      uint64_t open_persistent_id)
896 {
897         bool ret = false;
898         TALLOC_CTX *frame = talloc_stackframe();
899         unsigned n;
900         struct share_mode_data *data;
901         struct share_mode_lock *lck;
902         bool ok;
903
904         lck = get_existing_share_mode_lock(frame, fid);
905         if (lck == NULL) {
906                 DEBUG(5, ("share_mode_cleanup_disconnected: "
907                           "Could not fetch share mode entry for %s\n",
908                           file_id_string(frame, &fid)));
909                 goto done;
910         }
911         data = lck->data;
912
913         for (n=0; n < data->num_share_modes; n++) {
914                 struct share_mode_entry *entry = &data->share_modes[n];
915
916                 if (!server_id_is_disconnected(&entry->pid)) {
917                         struct server_id_buf tmp;
918                         DEBUG(5, ("share_mode_cleanup_disconnected: "
919                                   "file (file-id='%s', servicepath='%s', "
920                                   "base_name='%s%s%s') "
921                                   "is used by server %s ==> do not cleanup\n",
922                                   file_id_string(frame, &fid),
923                                   data->servicepath,
924                                   data->base_name,
925                                   (data->stream_name == NULL)
926                                   ? "" : "', stream_name='",
927                                   (data->stream_name == NULL)
928                                   ? "" : data->stream_name,
929                                   server_id_str_buf(entry->pid, &tmp)));
930                         goto done;
931                 }
932                 if (open_persistent_id != entry->share_file_id) {
933                         DBG_INFO("entry for file "
934                                  "(file-id='%s', servicepath='%s', "
935                                  "base_name='%s%s%s') "
936                                  "has share_file_id %"PRIu64" but expected "
937                                  "%"PRIu64"==> do not cleanup\n",
938                                  file_id_string(frame, &fid),
939                                  data->servicepath,
940                                  data->base_name,
941                                  (data->stream_name == NULL)
942                                  ? "" : "', stream_name='",
943                                  (data->stream_name == NULL)
944                                  ? "" : data->stream_name,
945                                  entry->share_file_id,
946                                  open_persistent_id);
947                         goto done;
948                 }
949         }
950
951         ok = share_mode_forall_leases(lck, cleanup_disconnected_lease, NULL);
952         if (!ok) {
953                 DBG_DEBUG("failed to clean up leases associated "
954                           "with file (file-id='%s', servicepath='%s', "
955                           "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
956                           "==> do not cleanup\n",
957                           file_id_string(frame, &fid),
958                           data->servicepath,
959                           data->base_name,
960                           (data->stream_name == NULL)
961                           ? "" : "', stream_name='",
962                           (data->stream_name == NULL)
963                           ? "" : data->stream_name,
964                           open_persistent_id);
965         }
966
967         ok = brl_cleanup_disconnected(fid, open_persistent_id);
968         if (!ok) {
969                 DBG_DEBUG("failed to clean up byte range locks associated "
970                           "with file (file-id='%s', servicepath='%s', "
971                           "base_name='%s%s%s') and open_persistent_id %"PRIu64" "
972                           "==> do not cleanup\n",
973                           file_id_string(frame, &fid),
974                           data->servicepath,
975                           data->base_name,
976                           (data->stream_name == NULL)
977                           ? "" : "', stream_name='",
978                           (data->stream_name == NULL)
979                           ? "" : data->stream_name,
980                           open_persistent_id);
981                 goto done;
982         }
983
984         DBG_DEBUG("cleaning up %u entries for file "
985                   "(file-id='%s', servicepath='%s', "
986                   "base_name='%s%s%s') "
987                   "from open_persistent_id %"PRIu64"\n",
988                   data->num_share_modes,
989                   file_id_string(frame, &fid),
990                   data->servicepath,
991                   data->base_name,
992                   (data->stream_name == NULL)
993                   ? "" : "', stream_name='",
994                   (data->stream_name == NULL)
995                   ? "" : data->stream_name,
996                   open_persistent_id);
997
998         data->num_share_modes = 0;
999         data->modified = true;
1000
1001         ret = true;
1002 done:
1003         talloc_free(frame);
1004         return ret;
1005 }