LCOV - code coverage report
Current view: top level - source3/locking - share_mode_lock.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 744 1225 60.7 %
Date: 2024-02-14 10:14:15 Functions: 65 85 76.5 %

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

Generated by: LCOV version 1.14