LCOV - code coverage report
Current view: top level - source3/locking - share_mode_lock.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 998 1327 75.2 %
Date: 2024-02-28 12:06:22 Functions: 81 85 95.3 %

          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     3699576 : 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     3699576 :         if (share_mode_g_lock_within_cb(key)) {
      92     3471793 :                 return g_lock_lock_cb_dump(current_share_mode_glck,
      93             :                                            fn, private_data);
      94             :         }
      95             : 
      96      227783 :         return g_lock_dump(lock_ctx, key, fn, private_data);
      97             : }
      98             : 
      99      991459 : static NTSTATUS share_mode_g_lock_writev(TDB_DATA key,
     100             :                                          const TDB_DATA *dbufs,
     101             :                                          size_t num_dbufs)
     102             : {
     103      991459 :         if (share_mode_g_lock_within_cb(key)) {
     104      808295 :                 return g_lock_lock_cb_writev(current_share_mode_glck,
     105             :                                              dbufs, num_dbufs);
     106             :         }
     107             : 
     108      183164 :         return g_lock_writev_data(lock_ctx, key, dbufs, num_dbufs);
     109             : }
     110             : 
     111         209 : static bool locking_init_internal(bool read_only)
     112             : {
     113           0 :         struct db_context *backend;
     114           0 :         char *db_path;
     115             : 
     116         209 :         brl_init(read_only);
     117             : 
     118         209 :         if (lock_ctx != NULL) {
     119           0 :                 return True;
     120             :         }
     121             : 
     122         209 :         db_path = lock_path(talloc_tos(), "locking.tdb");
     123         209 :         if (db_path == NULL) {
     124           0 :                 return false;
     125             :         }
     126             : 
     127         209 :         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         209 :         TALLOC_FREE(db_path);
     135         209 :         if (!backend) {
     136           0 :                 DEBUG(0,("ERROR: Failed to initialise locking database\n"));
     137           0 :                 return False;
     138             :         }
     139             : 
     140         209 :         lock_ctx = g_lock_ctx_init_backend(
     141             :                 NULL, global_messaging_context(), &backend);
     142         209 :         if (lock_ctx == NULL) {
     143           0 :                 TALLOC_FREE(backend);
     144           0 :                 return false;
     145             :         }
     146         209 :         g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1);
     147             : 
     148         209 :         if (!posix_locking_init(read_only)) {
     149           0 :                 TALLOC_FREE(lock_ctx);
     150           0 :                 return False;
     151             :         }
     152             : 
     153         209 :         return True;
     154             : }
     155             : 
     156         178 : bool locking_init(void)
     157             : {
     158         178 :         return locking_init_internal(false);
     159             : }
     160             : 
     161          31 : bool locking_init_readonly(void)
     162             : {
     163          31 :         return locking_init_internal(true);
     164             : }
     165             : 
     166             : /*******************************************************************
     167             :  Deinitialize the share_mode management.
     168             : ******************************************************************/
     169             : 
     170       35399 : bool locking_end(void)
     171             : {
     172       35399 :         brl_shutdown();
     173       35399 :         TALLOC_FREE(lock_ctx);
     174       35399 :         return true;
     175             : }
     176             : 
     177             : /*******************************************************************
     178             :  Form a static locking key for a dev/inode pair.
     179             : ******************************************************************/
     180             : 
     181     6482513 : static TDB_DATA locking_key(const struct file_id *id)
     182             : {
     183     6482513 :         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     1198234 : static DATA_BLOB memcache_key(const struct file_id *id)
     198             : {
     199     1198234 :         return data_blob_const((const void *)id, sizeof(*id));
     200             : }
     201             : 
     202      565103 : static void share_mode_memcache_store(struct share_mode_data *d)
     203             : {
     204      565103 :         const DATA_BLOB key = memcache_key(&d->id);
     205        1360 :         struct file_id_buf idbuf;
     206             : 
     207      565103 :         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      565103 :         SMB_ASSERT(!d->modified);
     214      565103 :         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      565103 :         talloc_set_destructor(d, NULL);
     223             : 
     224             :         /* Cache will own d after this call. */
     225      565103 :         memcache_add_talloc(NULL,
     226             :                         SHARE_MODE_LOCK_CACHE,
     227             :                         key,
     228             :                         &d);
     229      565103 : }
     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      511117 : 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      511117 :         struct ndr_pull ndr = {
     242             :                 .data = discard_const_p(uint8_t, buf),
     243             :                 .data_size = buflen,
     244             :         };
     245      511117 :         NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pepoch));
     246      511117 :         NDR_CHECK(ndr_pull_uint16(&ndr, NDR_SCALARS, pflags));
     247      509677 :         return NDR_ERR_SUCCESS;
     248             : }
     249             : 
     250      489813 : static int share_mode_data_nofree_destructor(struct share_mode_data *d)
     251             : {
     252      489813 :         return -1;
     253             : }
     254             : 
     255      633131 : 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      633131 :         const DATA_BLOB key = memcache_key(&id);
     262        2209 :         enum ndr_err_code ndr_err;
     263        2209 :         struct share_mode_data *d;
     264        2209 :         uint64_t unique_content_epoch;
     265        2209 :         uint16_t flags;
     266        2209 :         void *ptr;
     267        2209 :         struct file_id_buf idbuf;
     268             : 
     269      633131 :         ptr = memcache_lookup_talloc(NULL,
     270             :                         SHARE_MODE_LOCK_CACHE,
     271             :                         key);
     272      633131 :         if (ptr == NULL) {
     273      133197 :                 DBG_DEBUG("failed to find entry for key %s\n",
     274             :                           file_id_str_buf(id, &idbuf));
     275      133197 :                 return NULL;
     276             :         }
     277             :         /* sequence number key is at start of blob. */
     278      499934 :         ndr_err = get_share_mode_blob_header(
     279             :                 buf, buflen, &unique_content_epoch, &flags);
     280      499934 :         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      499934 :         d = (struct share_mode_data *)ptr;
     292      499934 :         if (d->unique_content_epoch != unique_content_epoch) {
     293       10121 :                 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       10121 :                 memcache_delete(NULL,
     300             :                         SHARE_MODE_LOCK_CACHE,
     301             :                         key);
     302       10121 :                 return NULL;
     303             :         }
     304             : 
     305             :         /* Move onto mem_ctx. */
     306      489813 :         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      489813 :         talloc_set_destructor(d, share_mode_data_nofree_destructor);
     313             : 
     314             :         /* Remove from the cache. We own it now. */
     315      489813 :         memcache_delete(NULL,
     316             :                         SHARE_MODE_LOCK_CACHE,
     317             :                         key);
     318             : 
     319             :         /* And reset the destructor to none. */
     320      489813 :         talloc_set_destructor(d, NULL);
     321             : 
     322      489813 :         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      488472 :         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      476405 : static bool share_mode_entry_put(
     342             :         const struct share_mode_entry *e,
     343             :         struct share_mode_entry_buf *dst)
     344             : {
     345      476405 :         DATA_BLOB blob = { .data = dst->buf, .length = sizeof(dst->buf) };
     346        1061 :         enum ndr_err_code ndr_err;
     347             : 
     348      476405 :         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      476405 :         ndr_err = ndr_push_struct_into_fixed_blob(
     354             :                 &blob,
     355             :                 e,
     356             :                 (ndr_push_flags_fn_t)ndr_push_share_mode_entry);
     357      476405 :         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      475344 :         return true;
     364             : }
     365             : 
     366      530724 : static bool share_mode_entry_get(
     367             :         const uint8_t ptr[SHARE_MODE_ENTRY_SIZE], struct share_mode_entry *e)
     368             : {
     369      530724 :         enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
     370      530724 :         DATA_BLOB blob = {
     371             :                 .data = discard_const_p(uint8_t, ptr),
     372             :                 .length = SHARE_MODE_ENTRY_SIZE,
     373             :         };
     374             : 
     375      530724 :         ndr_err = ndr_pull_struct_blob_all_noalloc(
     376             :                 &blob, e, (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
     377      530724 :         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      529601 :         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     1640685 : static bool locking_tdb_data_get(
     403             :         struct locking_tdb_data *data, const uint8_t *buf, size_t buflen)
     404             : {
     405        4705 :         uint32_t share_mode_data_len, share_entries_len;
     406             : 
     407     1640685 :         if (buflen == 0) {
     408           0 :                 *data = (struct locking_tdb_data) { 0 };
     409           0 :                 return true;
     410             :         }
     411     1640685 :         if (buflen < sizeof(uint32_t)) {
     412           0 :                 return false;
     413             :         }
     414             : 
     415     1640685 :         share_mode_data_len = PULL_LE_U32(buf, 0);
     416             : 
     417     1640685 :         buf += sizeof(uint32_t);
     418     1640685 :         buflen -= sizeof(uint32_t);
     419             : 
     420     1640685 :         if (buflen < share_mode_data_len) {
     421           0 :                 return false;
     422             :         }
     423             : 
     424     1640685 :         share_entries_len = buflen - share_mode_data_len;
     425             : 
     426     1640685 :         if ((share_entries_len % SHARE_MODE_ENTRY_SIZE) != 0) {
     427           0 :                 return false;
     428             :         }
     429             : 
     430     1640685 :         *data = (struct locking_tdb_data) {
     431             :                 .share_mode_data_buf = buf,
     432             :                 .share_mode_data_len = share_mode_data_len,
     433     1640685 :                 .share_entries = buf + share_mode_data_len,
     434     1640685 :                 .num_share_entries = share_entries_len / SHARE_MODE_ENTRY_SIZE,
     435             :         };
     436             : 
     437     1640685 :         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     2657660 : 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     2657660 :         struct locking_tdb_data_fetch_state *state = private_data;
     455     2657660 :         state->datalen = datalen;
     456     2657660 :         state->data = talloc_memdup(state->mem_ctx, data, datalen);
     457     2657660 : }
     458             : 
     459     2657660 : static NTSTATUS locking_tdb_data_fetch(
     460             :         TDB_DATA key, TALLOC_CTX *mem_ctx, struct locking_tdb_data **ltdb)
     461             : {
     462     2657660 :         struct locking_tdb_data_fetch_state state = { 0 };
     463     2657660 :         struct locking_tdb_data *result = NULL;
     464        5603 :         NTSTATUS status;
     465        5603 :         bool ok;
     466             : 
     467     2657660 :         result = talloc_zero(mem_ctx, struct locking_tdb_data);
     468     2657660 :         if (result == NULL) {
     469           0 :                 return NT_STATUS_NO_MEMORY;
     470             :         }
     471     2657660 :         state.mem_ctx = result;
     472             : 
     473     2657660 :         status = share_mode_g_lock_dump(key, locking_tdb_data_fetch_fn, &state);
     474     2657660 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     475             :                 /*
     476             :                  * Just return an empty record
     477             :                  */
     478           0 :                 goto done;
     479             :         }
     480     2657660 :         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     2657660 :         if (state.datalen == 0) {
     486     1661299 :                 goto done;
     487             :         }
     488             : 
     489      996361 :         ok = locking_tdb_data_get(result, state.data, state.datalen);
     490      996361 :         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      996361 : done:
     498     2657660 :         *ltdb = result;
     499     2657660 :         return NT_STATUS_OK;
     500             : }
     501             : 
     502      991459 : 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      991459 : {
     508        2267 :         uint8_t share_mode_data_len_buf[4];
     509      991459 :         TDB_DATA dbufs[num_share_mode_dbufs+3];
     510        2267 :         NTSTATUS status;
     511             : 
     512      991459 :         if ((ltdb->share_mode_data_len == 0) &&
     513      445143 :             (ltdb->num_share_entries == 0) &&
     514             :             (num_share_mode_dbufs == 0)) {
     515             :                 /*
     516             :                  * Nothing to write
     517             :                  */
     518      445143 :                 status = share_mode_g_lock_writev(key, NULL, 0);
     519      445143 :                 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      445143 :                 return status;
     524             :         }
     525             : 
     526      546316 :         PUSH_LE_U32(share_mode_data_len_buf, 0, ltdb->share_mode_data_len);
     527             : 
     528      546316 :         dbufs[0] = (TDB_DATA) {
     529             :                 .dptr = share_mode_data_len_buf,
     530             :                 .dsize = sizeof(share_mode_data_len_buf),
     531             :         };
     532      546316 :         dbufs[1] = (TDB_DATA) {
     533      546316 :                 .dptr = discard_const_p(uint8_t, ltdb->share_mode_data_buf),
     534      544947 :                 .dsize = ltdb->share_mode_data_len,
     535             :         };
     536             : 
     537      546316 :         if (ltdb->num_share_entries > SIZE_MAX/SHARE_MODE_ENTRY_SIZE) {
     538             :                 /* overflow */
     539           0 :                 return NT_STATUS_BUFFER_OVERFLOW;
     540             :         }
     541      546316 :         dbufs[2] = (TDB_DATA) {
     542      546316 :                 .dptr = discard_const_p(uint8_t, ltdb->share_entries),
     543      546316 :                 .dsize = ltdb->num_share_entries * SHARE_MODE_ENTRY_SIZE,
     544             :         };
     545             : 
     546      546316 :         if (num_share_mode_dbufs != 0) {
     547      473315 :                 memcpy(&dbufs[3],
     548             :                        share_mode_dbufs,
     549             :                        num_share_mode_dbufs * sizeof(TDB_DATA));
     550             :         }
     551             : 
     552      546316 :         status = share_mode_g_lock_writev(key, dbufs, ARRAY_SIZE(dbufs));
     553      546316 :         if (!NT_STATUS_IS_OK(status)) {
     554           0 :                 DBG_ERR("share_mode_g_lock_writev() failed: %s\n",
     555             :                         nt_errstr(status));
     556             :         }
     557      546316 :         return status;
     558             : }
     559             : 
     560             : /*******************************************************************
     561             :  Get all share mode entries for a dev/inode pair.
     562             : ********************************************************************/
     563             : 
     564      633131 : static struct share_mode_data *parse_share_modes(
     565             :         TALLOC_CTX *mem_ctx,
     566             :         struct file_id id,
     567             :         const uint8_t *buf,
     568             :         size_t buflen)
     569             : {
     570        2209 :         struct share_mode_data *d;
     571        2209 :         enum ndr_err_code ndr_err;
     572        2209 :         DATA_BLOB blob;
     573             : 
     574             :         /* See if we already have a cached copy of this key. */
     575      633131 :         d = share_mode_memcache_fetch(mem_ctx, id, buf, buflen);
     576      633131 :         if (d != NULL) {
     577      488472 :                 return d;
     578             :         }
     579             : 
     580      143318 :         d = talloc(mem_ctx, struct share_mode_data);
     581      143318 :         if (d == NULL) {
     582           0 :                 DEBUG(0, ("talloc failed\n"));
     583           0 :                 goto fail;
     584             :         }
     585             : 
     586      143318 :         blob = (DATA_BLOB) {
     587             :                 .data = discard_const_p(uint8_t, buf),
     588             :                 .length = buflen,
     589             :         };
     590      143318 :         ndr_err = ndr_pull_struct_blob_all(
     591             :                 &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
     592      143318 :         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      143318 :         if (DEBUGLEVEL >= 10) {
     599           0 :                 DEBUG(10, ("parse_share_modes:\n"));
     600           0 :                 NDR_PRINT_DEBUG(share_mode_data, d);
     601             :         }
     602             : 
     603      142450 :         return d;
     604           0 : fail:
     605           0 :         TALLOC_FREE(d);
     606           0 :         return NULL;
     607             : }
     608             : 
     609      991459 : 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      991459 :         DATA_BLOB blob = { 0 };
     616        2267 :         NTSTATUS status;
     617             : 
     618      991459 :         if (!d->modified) {
     619       56863 :                 DBG_DEBUG("share_mode_data not modified\n");
     620       56863 :                 goto store;
     621             :         }
     622             : 
     623      934596 :         d->unique_content_epoch = generate_unique_u64(d->unique_content_epoch);
     624             : 
     625      934596 :         if (DEBUGLEVEL >= 10) {
     626           0 :                 DBG_DEBUG("\n");
     627           0 :                 NDR_PRINT_DEBUG(share_mode_data, d);
     628             :         }
     629             : 
     630      934596 :         if (ltdb->num_share_entries != 0 || num_share_mode_dbufs != 0) {
     631        1184 :                 enum ndr_err_code ndr_err;
     632             : 
     633      489453 :                 ndr_err = ndr_push_struct_blob(
     634             :                         &blob,
     635             :                         ltdb,
     636             :                         d,
     637             :                         (ndr_push_flags_fn_t)ndr_push_share_mode_data);
     638      489453 :                 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      934596 :         ltdb->share_mode_data_buf = blob.data;
     646      934596 :         ltdb->share_mode_data_len = blob.length;
     647             : 
     648      991459 : store:
     649      991459 :         status = locking_tdb_data_store(key,
     650             :                                         ltdb,
     651             :                                         share_mode_dbufs,
     652             :                                         num_share_mode_dbufs);
     653      991459 :         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      991459 :         d->modified = false;
     660      991459 :         d->not_stored = (ltdb->share_mode_data_len == 0);
     661             : 
     662      991459 :         return NT_STATUS_OK;
     663             : }
     664             : 
     665             : /*******************************************************************
     666             :  If modified, store the share_mode_data back into the database.
     667             : ********************************************************************/
     668             : 
     669     1010220 : static NTSTATUS share_mode_data_store(struct share_mode_data *d)
     670             : {
     671     1010220 :         TDB_DATA key = locking_key(&d->id);
     672     1010220 :         struct locking_tdb_data *ltdb = NULL;
     673        2258 :         NTSTATUS status;
     674             : 
     675     1010220 :         if (!d->modified) {
     676      969468 :                 DBG_DEBUG("not modified\n");
     677      969468 :                 return NT_STATUS_OK;
     678             :         }
     679             : 
     680       40752 :         if (DEBUGLEVEL >= 10) {
     681           0 :                 DBG_DEBUG("\n");
     682           0 :                 NDR_PRINT_DEBUG(share_mode_data, d);
     683             :         }
     684             : 
     685       40752 :         status = locking_tdb_data_fetch(key, d, &ltdb);
     686       40752 :         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       40752 :         status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
     693       40752 :         TALLOC_FREE(ltdb);
     694       40752 :         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       40752 :         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      445132 : static struct share_mode_data *fresh_share_mode_lock(
     709             :         TALLOC_CTX *mem_ctx, const char *servicepath,
     710             :         const struct smb_filename *smb_fname,
     711             :         const struct timespec *old_write_time)
     712             : {
     713         898 :         struct share_mode_data *d;
     714             : 
     715      445132 :         if ((servicepath == NULL) || (smb_fname == NULL) ||
     716             :             (old_write_time == NULL)) {
     717           0 :                 return NULL;
     718             :         }
     719             : 
     720      445132 :         d = talloc_zero(mem_ctx, struct share_mode_data);
     721      445132 :         if (d == NULL) {
     722           0 :                 goto fail;
     723             :         }
     724      445132 :         d->unique_content_epoch = generate_unique_u64(0);
     725             : 
     726      445132 :         d->base_name = talloc_strdup(d, smb_fname->base_name);
     727      445132 :         if (d->base_name == NULL) {
     728           0 :                 goto fail;
     729             :         }
     730      445132 :         if (smb_fname->stream_name != NULL) {
     731        4996 :                 d->stream_name = talloc_strdup(d, smb_fname->stream_name);
     732        4996 :                 if (d->stream_name == NULL) {
     733           0 :                         goto fail;
     734             :                 }
     735             :         }
     736      445132 :         d->servicepath = talloc_strdup(d, servicepath);
     737      445132 :         if (d->servicepath == NULL) {
     738           0 :                 goto fail;
     739             :         }
     740      445132 :         d->old_write_time = full_timespec_to_nt_time(old_write_time);
     741      445132 :         d->flags = SHARE_MODE_SHARE_DELETE |
     742             :                 SHARE_MODE_SHARE_WRITE |
     743             :                 SHARE_MODE_SHARE_READ;
     744      445132 :         d->modified = false;
     745      445132 :         d->not_stored = true;
     746      445132 :         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     4697059 : static bool share_mode_g_lock_within_cb(TDB_DATA key)
     764             : {
     765       10385 :         int cmp;
     766             : 
     767     4697059 :         if (current_share_mode_glck == NULL) {
     768      413048 :                 return false;
     769             :         }
     770             : 
     771     4283130 :         cmp = tdb_data_cmp(share_mode_lock_key, key);
     772     4283130 :         if (cmp != 0) {
     773           0 :                 struct file_id_buf existing;
     774             : 
     775           0 :                 DBG_ERR("Can not lock two share modes "
     776             :                         "simultaneously: existing %s requested %s\n",
     777             :                         file_id_str_buf(share_mode_lock_key_id, &existing),
     778             :                         tdb_data_dbg(key));
     779           0 :                 smb_panic(__location__);
     780             :                 return false;
     781             :         }
     782             : 
     783     4273626 :         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     1011562 : 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     1011562 :         struct get_static_share_mode_data_state *state = private_data;
     816     1011562 :         struct share_mode_data *d = NULL;
     817     1011562 :         struct locking_tdb_data ltdb = { 0 };
     818             : 
     819     1011562 :         if (datalen != 0) {
     820        1360 :                 bool ok;
     821             : 
     822      565088 :                 ok = locking_tdb_data_get(&ltdb, data, datalen);
     823      565088 :                 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     1011562 :         if (ltdb.share_mode_data_len == 0) {
     831      446474 :                 if (state->smb_fname == NULL) {
     832        1342 :                         state->status = NT_STATUS_NOT_FOUND;
     833        1342 :                         return;
     834             :                 }
     835      445132 :                 d = fresh_share_mode_lock(
     836             :                         state->mem_ctx,
     837             :                         state->servicepath,
     838             :                         state->smb_fname,
     839             :                         state->old_write_time);
     840      445132 :                 if (d == NULL) {
     841           0 :                         state->status = NT_STATUS_NO_MEMORY;
     842           0 :                         return;
     843             :                 }
     844             :         } else {
     845      565088 :                 d = parse_share_modes(
     846             :                         lock_ctx,
     847             :                         state->id,
     848             :                         ltdb.share_mode_data_buf,
     849             :                         ltdb.share_mode_data_len);
     850      565088 :                 if (d == NULL) {
     851           0 :                         state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     852           0 :                         return;
     853             :                 }
     854             :         }
     855             : 
     856     1010220 :         d->id = state->id;
     857     1010220 :         static_share_mode_data = d;
     858             : }
     859             : 
     860     1011562 : 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     1011562 :         struct get_static_share_mode_data_state state = {
     867             :                 .mem_ctx = lock_ctx,
     868             :                 .id = id,
     869             :                 .servicepath = servicepath,
     870             :                 .smb_fname = smb_fname,
     871             :                 .old_write_time = old_write_time,
     872             :         };
     873        2287 :         NTSTATUS status;
     874             : 
     875     1011562 :         SMB_ASSERT(static_share_mode_data == NULL);
     876             : 
     877     1011562 :         status = share_mode_g_lock_dump(
     878             :                 share_mode_lock_key,
     879             :                 get_static_share_mode_data_fn,
     880             :                 &state);
     881     1011562 :         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     1011562 :         if (!NT_STATUS_IS_OK(state.status)) {
     888        1342 :                 DBG_GET_SHARE_MODE_LOCK(state.status,
     889             :                         "get_static_share_mode_data_fn failed: %s\n",
     890             :                         nt_errstr(state.status));
     891        1342 :                 return state.status;
     892             :         }
     893             : 
     894     1010220 :         return NT_STATUS_OK;
     895             : }
     896             : 
     897     1676575 : struct file_id share_mode_lock_file_id(const struct share_mode_lock *lck)
     898             : {
     899     1676575 :         return lck->id;
     900             : }
     901             : 
     902     7338546 : 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     7338546 :         SMB_ASSERT(lck->cached_data != NULL);
     910     7338546 :         *data = lck->cached_data;
     911     7338546 :         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     1023872 : static NTSTATUS get_share_mode_lock_internal(
     923             :         struct file_id id,
     924             :         const char *servicepath,
     925             :         const struct smb_filename *smb_fname,
     926             :         const struct timespec *old_write_time,
     927             :         struct share_mode_lock *lck)
     928             : {
     929        2446 :         NTSTATUS status;
     930             : 
     931     1023872 :         *lck = (struct share_mode_lock) {
     932             :                 .id = id,
     933             :         };
     934             : 
     935     1023872 :         if (share_mode_lock_key_refcount == 0) {
     936     1011562 :                 if (!share_mode_lock_skip_g_lock) {
     937       11716 :                         TDB_DATA key = locking_key(&id);
     938             : 
     939       11772 :                         status = g_lock_lock(
     940             :                                 lock_ctx,
     941             :                                 key,
     942             :                                 G_LOCK_WRITE,
     943       11716 :                                 (struct timeval) { .tv_sec = 3600 },
     944             :                                 NULL, NULL);
     945       11716 :                         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     1011562 :                 share_mode_lock_key_id = id;
     952             :         }
     953             : 
     954     1023872 :         if (!file_id_equal(&share_mode_lock_key_id, &id)) {
     955           0 :                 struct file_id_buf existing;
     956           0 :                 struct file_id_buf requested;
     957             : 
     958           0 :                 DBG_ERR("Can not lock two share modes "
     959             :                         "simultaneously: existing %s requested %s\n",
     960             :                         file_id_str_buf(share_mode_lock_key_id, &existing),
     961             :                         file_id_str_buf(id, &requested));
     962           0 :                 smb_panic(__location__);
     963             :                 goto fail;
     964             :         }
     965             : 
     966     1023872 :         SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX);
     967     1023872 :         share_mode_lock_key_refcount += 1;
     968             : 
     969     1023872 :         if (static_share_mode_data != NULL) {
     970       12310 :                 goto done;
     971             :         }
     972             : 
     973     1011562 :         status = get_static_share_mode_data(
     974             :                 id,
     975             :                 servicepath,
     976             :                 smb_fname,
     977             :                 old_write_time);
     978     1011562 :         if (!NT_STATUS_IS_OK(status)) {
     979        1342 :                 DBG_DEBUG("get_static_share_mode_data failed: %s\n",
     980             :                           nt_errstr(status));
     981        1342 :                 share_mode_lock_key_refcount -= 1;
     982        1342 :                 goto fail;
     983             :         }
     984     1010220 : done:
     985     1022530 :         lck->cached_data = static_share_mode_data;
     986             : 
     987     1022530 :         if (CHECK_DEBUGLVL(DBGLVL_DEBUG)) {
     988           0 :                 struct file_id_buf returned;
     989             : 
     990           0 :                 DBG_DEBUG("Returning %s (data_cached=%u key_refcount=%zu)\n",
     991             :                           file_id_str_buf(id, &returned),
     992             :                           static_share_mode_data != NULL,
     993             :                           share_mode_lock_key_refcount);
     994             :         }
     995             : 
     996     1022530 :         return NT_STATUS_OK;
     997        1342 : fail:
     998        1342 :         if (share_mode_lock_key_refcount == 0) {
     999        1342 :                 if (!share_mode_lock_skip_g_lock) {
    1000          82 :                         NTSTATUS ulstatus = g_lock_unlock(lock_ctx, share_mode_lock_key);
    1001          82 :                         if (!NT_STATUS_IS_OK(ulstatus)) {
    1002           0 :                                 DBG_ERR("g_lock_unlock failed: %s\n",
    1003             :                                         nt_errstr(ulstatus));
    1004             :                         }
    1005             :                 }
    1006             :         }
    1007        1342 :         return status;
    1008             : }
    1009             : 
    1010     1022530 : static NTSTATUS put_share_mode_lock_internal(struct share_mode_lock *lck)
    1011             : {
    1012        2417 :         NTSTATUS status;
    1013             : 
    1014     1022530 :         SMB_ASSERT(share_mode_lock_key_refcount > 0);
    1015     1022530 :         share_mode_lock_key_refcount -= 1;
    1016             : 
    1017     1022530 :         if (share_mode_lock_key_refcount > 0) {
    1018       12310 :                 return NT_STATUS_OK;
    1019             :         }
    1020             : 
    1021     1010220 :         status = share_mode_data_store(static_share_mode_data);
    1022     1010220 :         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     1010220 :         if (!share_mode_lock_skip_g_lock) {
    1029      523126 :                 status = g_lock_unlock(lock_ctx, share_mode_lock_key);
    1030      523126 :                 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     1010220 :         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      565103 :                 share_mode_memcache_store(static_share_mode_data);
    1044      565103 :                 static_share_mode_data = NULL;
    1045             :         }
    1046             : 
    1047     1010220 :         TALLOC_FREE(static_share_mode_data);
    1048     1010220 :         return NT_STATUS_OK;
    1049             : }
    1050             : 
    1051        8863 : static int share_mode_lock_destructor(struct share_mode_lock *lck)
    1052             : {
    1053          42 :         NTSTATUS status;
    1054             : 
    1055        8863 :         status = put_share_mode_lock_internal(lck);
    1056        8863 :         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        8863 :         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        8945 : struct share_mode_lock *get_existing_share_mode_lock(TALLOC_CTX *mem_ctx,
    1071             :                                                      const struct file_id id)
    1072             : {
    1073        8945 :         struct share_mode_lock *lck = NULL;
    1074          42 :         NTSTATUS status;
    1075             : 
    1076        8945 :         lck = talloc(mem_ctx, struct share_mode_lock);
    1077        8945 :         if (lck == NULL) {
    1078           0 :                 return NULL;
    1079             :         }
    1080             : 
    1081        8945 :         status = get_share_mode_lock_internal(id,
    1082             :                                               NULL, /* servicepath */
    1083             :                                               NULL, /* smb_fname */
    1084             :                                               NULL, /* old_write_time */
    1085             :                                               lck);
    1086        8945 :         if (!NT_STATUS_IS_OK(status)) {
    1087          82 :                 DBG_GET_SHARE_MODE_LOCK(status,
    1088             :                         "get_share_mode_lock_internal() failed - %s\n",
    1089             :                         nt_errstr(status));
    1090          82 :                 TALLOC_FREE(lck);
    1091          82 :                 return NULL;
    1092             :         }
    1093             : 
    1094        8863 :         talloc_set_destructor(lck, share_mode_lock_destructor);
    1095        8863 :         return lck;
    1096             : }
    1097             : 
    1098        4873 : static void share_mode_wakeup_waiters_fn(
    1099             :         struct share_mode_lock *lck,
    1100             :         void *private_data)
    1101             : {
    1102        4873 :         if (share_mode_g_lock_within_cb(share_mode_lock_key)) {
    1103        2543 :                 g_lock_lock_cb_wake_watchers(current_share_mode_glck);
    1104        2543 :                 return;
    1105             :         }
    1106             : 
    1107        2330 :         g_lock_wake_watchers(lock_ctx, share_mode_lock_key);
    1108             : }
    1109             : 
    1110        4873 : NTSTATUS share_mode_wakeup_waiters(struct file_id id)
    1111             : {
    1112        4873 :         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       11183 : 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       11183 :         struct fsp_update_share_mode_flags_state *state = private_data;
    1133       11183 :         struct locking_tdb_data ltdb = { 0 };
    1134             : 
    1135       11183 :         if (datalen != 0) {
    1136       11183 :                 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
    1137       11183 :                 if (!ok) {
    1138           0 :                         DBG_DEBUG("locking_tdb_data_get failed\n");
    1139           0 :                         return;
    1140             :                 }
    1141             :         }
    1142             : 
    1143       11183 :         if (ltdb.share_mode_data_len == 0) {
    1144             :                 /* Likely a ctdb tombstone record, ignore it */
    1145           0 :                 return;
    1146             :         }
    1147             : 
    1148       11183 :         if (exclusive.pid != 0) {
    1149          16 :                 struct server_id self =
    1150        3594 :                         messaging_server_id(state->fsp->conn->sconn->msg_ctx);
    1151        3594 :                 bool is_self = server_id_equal(&self, &exclusive);
    1152             : 
    1153        3594 :                 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       11183 :         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      201670 : static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
    1170             : {
    1171      201670 :         struct fsp_update_share_mode_flags_state state = { .fsp = fsp, };
    1172      201670 :         int seqnum = g_lock_seqnum(lock_ctx);
    1173      201670 :         TDB_DATA key = {0};
    1174         116 :         NTSTATUS status;
    1175             : 
    1176      201670 :         if (seqnum == fsp->share_mode_flags_seqnum) {
    1177      190477 :                 return NT_STATUS_OK;
    1178             :         }
    1179             : 
    1180       11193 :         key = locking_key(&fsp->file_id);
    1181       11193 :         status = share_mode_g_lock_dump(key,
    1182             :                              fsp_update_share_mode_flags_fn,
    1183             :                              &state);
    1184       11193 :         if (!NT_STATUS_IS_OK(status)) {
    1185             :                 /* no DBG_GET_SHARE_MODE_LOCK here! */
    1186          10 :                 DBG_ERR("share_mode_g_lock_dump returned %s\n",
    1187             :                         nt_errstr(status));
    1188          10 :                 return status;
    1189             :         }
    1190             : 
    1191       11183 :         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       11183 :         fsp->share_mode_flags_seqnum = seqnum;
    1198       11183 :         fsp->share_mode_flags = state.share_mode_flags;
    1199             : 
    1200       11183 :         return NT_STATUS_OK;
    1201             : }
    1202             : 
    1203      201670 : bool file_has_read_lease(struct files_struct *fsp)
    1204             : {
    1205         116 :         NTSTATUS status;
    1206             : 
    1207      201670 :         status = fsp_update_share_mode_flags(fsp);
    1208      201670 :         if (!NT_STATUS_IS_OK(status)) {
    1209             :                 /* Safe default for leases */
    1210          10 :                 return true;
    1211             :         }
    1212             : 
    1213      201660 :         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     3005796 : 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     3005796 :         struct share_mode_data *d = NULL;
    1224        5683 :         NTSTATUS status;
    1225             : 
    1226     3005796 :         status = share_mode_lock_access_private_data(lck, &d);
    1227     3005796 :         if (!NT_STATUS_IS_OK(status)) {
    1228           0 :                 struct file_id id = share_mode_lock_file_id(lck);
    1229           0 :                 struct file_id_buf id_buf;
    1230             :                 /* Any error recovery possible here ? */
    1231           0 :                 D_ERR("%s:%s(): share_mode_lock_access_private_data() "
    1232             :                       "failed for id=%s - %s\n",
    1233             :                       caller_location, caller_function,
    1234             :                       file_id_str_buf(id, &id_buf),
    1235             :                       nt_errstr(status));
    1236           0 :                 smb_panic(caller_location);
    1237             :                 return NULL;
    1238             :         }
    1239             : 
    1240     3005796 :         return d;
    1241             : }
    1242             : 
    1243        1038 : NTTIME share_mode_changed_write_time(struct share_mode_lock *lck)
    1244             : {
    1245        1038 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1246        1038 :         return d->changed_write_time;
    1247             : }
    1248             : 
    1249        1110 : void share_mode_set_changed_write_time(struct share_mode_lock *lck, struct timespec write_time)
    1250             : {
    1251        1110 :         struct file_id fileid = share_mode_lock_file_id(lck);
    1252        1110 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1253          25 :         struct file_id_buf ftmp;
    1254          25 :         struct timeval_buf tbuf;
    1255        1110 :         NTTIME nt = full_timespec_to_nt_time(&write_time);
    1256             : 
    1257        1110 :         DBG_INFO("%s id=%s\n",
    1258             :                  timespec_string_buf(&write_time, true, &tbuf),
    1259             :                  file_id_str_buf(fileid, &ftmp));
    1260             : 
    1261        1110 :         if (d->changed_write_time != nt) {
    1262        1094 :                 d->modified = true;
    1263        1094 :                 d->changed_write_time = nt;
    1264             :         }
    1265        1110 : }
    1266             : 
    1267        5828 : void share_mode_set_old_write_time(struct share_mode_lock *lck, struct timespec write_time)
    1268             : {
    1269        5828 :         struct file_id fileid = share_mode_lock_file_id(lck);
    1270        5828 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1271          22 :         struct file_id_buf ftmp;
    1272          22 :         struct timeval_buf tbuf;
    1273        5828 :         NTTIME nt = full_timespec_to_nt_time(&write_time);
    1274             : 
    1275        5828 :         DBG_INFO("%s id=%s\n",
    1276             :                  timespec_string_buf(&write_time, true, &tbuf),
    1277             :                  file_id_str_buf(fileid, &ftmp));
    1278             : 
    1279        5828 :         if (d->changed_write_time != nt) {
    1280        5816 :                 d->modified = true;
    1281        5816 :                 d->old_write_time = nt;
    1282             :         }
    1283        5828 : }
    1284             : 
    1285          10 : const char *share_mode_servicepath(struct share_mode_lock *lck)
    1286             : {
    1287          10 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1288          10 :         return d->servicepath;
    1289             : }
    1290             : 
    1291          65 : char *share_mode_filename(TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
    1292             : {
    1293          65 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1294          65 :         bool has_stream = (d->stream_name != NULL);
    1295          65 :         char *fname = NULL;
    1296             : 
    1297          65 :         fname = talloc_asprintf(
    1298             :                 mem_ctx,
    1299             :                 "%s%s%s",
    1300             :                 d->base_name,
    1301             :                 has_stream ? ":" : "",
    1302             :                 has_stream ? d->stream_name : "");
    1303          65 :         return fname;
    1304             : }
    1305             : 
    1306           6 : char *share_mode_data_dump(
    1307             :         TALLOC_CTX *mem_ctx, struct share_mode_lock *lck)
    1308             : {
    1309           6 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1310           6 :         struct ndr_print *p = talloc(mem_ctx, struct ndr_print);
    1311           6 :         char *ret = NULL;
    1312             : 
    1313           6 :         if (p == NULL) {
    1314           0 :                 return NULL;
    1315             :         }
    1316             : 
    1317           6 :         *p = (struct ndr_print) {
    1318             :                 .print = ndr_print_string_helper,
    1319             :                 .depth = 1,
    1320           6 :                 .private_data = talloc_strdup(mem_ctx, ""),
    1321             :         };
    1322             : 
    1323           6 :         if (p->private_data == NULL) {
    1324           0 :                 TALLOC_FREE(p);
    1325           0 :                 return NULL;
    1326             :         }
    1327             : 
    1328           6 :         ndr_print_share_mode_data(p, "SHARE_MODE_DATA", d);
    1329             : 
    1330           6 :         ret = p->private_data;
    1331             : 
    1332           6 :         TALLOC_FREE(p);
    1333             : 
    1334           6 :         return ret;
    1335             : }
    1336             : 
    1337     1664328 : 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     1664328 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1344     1664328 :         uint16_t flags = d->flags;
    1345             : 
    1346     1664328 :         if (access_mask != NULL) {
    1347     1277787 :                 *access_mask =
    1348             :                         ((flags & SHARE_MODE_ACCESS_READ) ?
    1349     1277787 :                          FILE_READ_DATA : 0) |
    1350             :                         ((flags & SHARE_MODE_ACCESS_WRITE) ?
    1351     1277787 :                          FILE_WRITE_DATA : 0) |
    1352             :                         ((flags & SHARE_MODE_ACCESS_DELETE) ?
    1353     1277787 :                          DELETE_ACCESS : 0);
    1354             :         }
    1355     1664328 :         if (share_mode != NULL) {
    1356     1277787 :                 *share_mode =
    1357             :                         ((flags & SHARE_MODE_SHARE_READ) ?
    1358     1277787 :                          FILE_SHARE_READ : 0) |
    1359             :                         ((flags & SHARE_MODE_SHARE_WRITE) ?
    1360     1277787 :                          FILE_SHARE_WRITE : 0) |
    1361             :                         ((flags & SHARE_MODE_SHARE_DELETE) ?
    1362             :                          FILE_SHARE_DELETE : 0);
    1363             :         }
    1364     1664328 :         if (lease_type != NULL) {
    1365     1235742 :                 *lease_type =
    1366             :                         ((flags & SHARE_MODE_LEASE_READ) ?
    1367     1235742 :                          SMB2_LEASE_READ : 0) |
    1368             :                         ((flags & SHARE_MODE_LEASE_WRITE) ?
    1369     1235742 :                          SMB2_LEASE_WRITE : 0) |
    1370             :                         ((flags & SHARE_MODE_LEASE_HANDLE) ?
    1371     1235742 :                          SMB2_LEASE_HANDLE : 0);
    1372             :         }
    1373     1664328 : }
    1374             : 
    1375      860096 : 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      860096 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1383      860096 :         uint16_t flags = 0;
    1384             : 
    1385      860096 :         flags |= (access_mask & (FILE_READ_DATA | FILE_EXECUTE)) ?
    1386             :                 SHARE_MODE_ACCESS_READ : 0;
    1387      860096 :         flags |= (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
    1388             :                 SHARE_MODE_ACCESS_WRITE : 0;
    1389      860096 :         flags |= (access_mask & (DELETE_ACCESS)) ?
    1390      860096 :                 SHARE_MODE_ACCESS_DELETE : 0;
    1391             : 
    1392      860096 :         flags |= (share_mode & FILE_SHARE_READ) ?
    1393      860096 :                 SHARE_MODE_SHARE_READ : 0;
    1394      860096 :         flags |= (share_mode & FILE_SHARE_WRITE) ?
    1395      860096 :                 SHARE_MODE_SHARE_WRITE : 0;
    1396      860096 :         flags |= (share_mode & FILE_SHARE_DELETE) ?
    1397      860096 :                 SHARE_MODE_SHARE_DELETE : 0;
    1398             : 
    1399      860096 :         flags |= (lease_type & SMB2_LEASE_READ) ?
    1400      860096 :                 SHARE_MODE_LEASE_READ : 0;
    1401      860096 :         flags |= (lease_type & SMB2_LEASE_WRITE) ?
    1402      860096 :                 SHARE_MODE_LEASE_WRITE : 0;
    1403      860096 :         flags |= (lease_type & SMB2_LEASE_HANDLE) ?
    1404      860096 :                 SHARE_MODE_LEASE_HANDLE : 0;
    1405             : 
    1406      860096 :         if (d->flags == flags) {
    1407      460541 :                 return;
    1408             :         }
    1409             : 
    1410      398956 :         if (modified != NULL) {
    1411         322 :                 *modified = true;
    1412             :         }
    1413      398956 :         d->flags = flags;
    1414      398956 :         d->modified = true;
    1415             : }
    1416             : 
    1417             : struct share_mode_watch_state {
    1418             :         bool blockerdead;
    1419             :         struct server_id blocker;
    1420             :         bool within_cb;
    1421             : };
    1422             : 
    1423             : static void share_mode_watch_done(struct tevent_req *subreq);
    1424             : 
    1425        1151 : struct tevent_req *share_mode_watch_send(
    1426             :         TALLOC_CTX *mem_ctx,
    1427             :         struct tevent_context *ev,
    1428             :         struct share_mode_lock *lck,
    1429             :         struct server_id blocker)
    1430             : {
    1431        1151 :         struct file_id id = share_mode_lock_file_id(lck);
    1432        1151 :         TDB_DATA key = locking_key(&id);
    1433        1151 :         struct tevent_req *req = NULL, *subreq = NULL;
    1434        1151 :         struct share_mode_watch_state *state = NULL;
    1435             : 
    1436        1151 :         req = tevent_req_create(
    1437             :                 mem_ctx, &state, struct share_mode_watch_state);
    1438        1151 :         if (req == NULL) {
    1439           0 :                 return NULL;
    1440             :         }
    1441             : 
    1442        1151 :         if (share_mode_g_lock_within_cb(key)) {
    1443         499 :                 state->within_cb = true;
    1444         499 :                 subreq = g_lock_lock_cb_watch_data_send(state, ev,
    1445             :                                                         current_share_mode_glck,
    1446             :                                                         blocker);
    1447         499 :                 if (tevent_req_nomem(subreq, req)) {
    1448           0 :                         return tevent_req_post(req, ev);
    1449             :                 }
    1450             :         } else {
    1451         652 :                 subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker);
    1452         652 :                 if (tevent_req_nomem(subreq, req)) {
    1453           0 :                         return tevent_req_post(req, ev);
    1454             :                 }
    1455             :         }
    1456        1151 :         tevent_req_set_callback(subreq, share_mode_watch_done, req);
    1457        1151 :         return req;
    1458             : }
    1459             : 
    1460         533 : static void share_mode_watch_done(struct tevent_req *subreq)
    1461             : {
    1462         533 :         struct tevent_req *req = tevent_req_callback_data(
    1463             :                 subreq, struct tevent_req);
    1464         533 :         struct share_mode_watch_state *state = tevent_req_data(
    1465             :                 req, struct share_mode_watch_state);
    1466           0 :         NTSTATUS status;
    1467             : 
    1468         533 :         if (state->within_cb) {
    1469         447 :                 status = g_lock_lock_cb_watch_data_recv(
    1470             :                         subreq, &state->blockerdead, &state->blocker);
    1471         447 :                 if (tevent_req_nterror(req, status)) {
    1472           0 :                         return;
    1473             :                 }
    1474             :         } else {
    1475          86 :                 status = g_lock_watch_data_recv(
    1476             :                         subreq, &state->blockerdead, &state->blocker);
    1477          86 :                 if (tevent_req_nterror(req, status)) {
    1478           0 :                         return;
    1479             :                 }
    1480             :         }
    1481             : 
    1482         533 :         tevent_req_done(req);
    1483             : }
    1484             : 
    1485        1015 : NTSTATUS share_mode_watch_recv(
    1486             :         struct tevent_req *req, bool *blockerdead, struct server_id *blocker)
    1487             : {
    1488        1015 :         struct share_mode_watch_state *state = tevent_req_data(
    1489             :                 req, struct share_mode_watch_state);
    1490           2 :         NTSTATUS status;
    1491             : 
    1492        1015 :         if (tevent_req_is_nterror(req, &status)) {
    1493         482 :                 return status;
    1494             :         }
    1495         533 :         if (blockerdead != NULL) {
    1496           0 :                 *blockerdead = state->blockerdead;
    1497             :         }
    1498         533 :         if (blocker != NULL) {
    1499           0 :                 *blocker = state->blocker;
    1500             :         }
    1501         533 :         return NT_STATUS_OK;
    1502             : }
    1503             : 
    1504             : struct fetch_share_mode_unlocked_state {
    1505             :         TALLOC_CTX *mem_ctx;
    1506             :         struct file_id id;
    1507             :         struct share_mode_lock *lck;
    1508             : };
    1509             : 
    1510       48882 : 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       48882 :         struct fetch_share_mode_unlocked_state *state = private_data;
    1519       48882 :         struct locking_tdb_data ltdb = { 0 };
    1520             : 
    1521       48882 :         if (datalen != 0) {
    1522       48882 :                 bool ok = locking_tdb_data_get(&ltdb, data, datalen);
    1523       48882 :                 if (!ok) {
    1524           0 :                         DBG_DEBUG("locking_tdb_data_get failed\n");
    1525           0 :                         return;
    1526             :                 }
    1527             :         }
    1528             : 
    1529       48882 :         if (ltdb.share_mode_data_len == 0) {
    1530             :                 /* Likely a ctdb tombstone record, ignore it */
    1531           0 :                 return;
    1532             :         }
    1533             : 
    1534       48882 :         state->lck = talloc(state->mem_ctx, struct share_mode_lock);
    1535       48882 :         if (state->lck == NULL) {
    1536           0 :                 DEBUG(0, ("talloc failed\n"));
    1537           0 :                 return;
    1538             :         }
    1539       48882 :         state->lck->id = state->id;
    1540             : 
    1541       96915 :         state->lck->cached_data = parse_share_modes(
    1542       48033 :                 state->lck,
    1543             :                 state->id,
    1544             :                 ltdb.share_mode_data_buf,
    1545             :                 ltdb.share_mode_data_len);
    1546       48882 :         if (state->lck->cached_data == NULL) {
    1547           0 :                 DBG_DEBUG("parse_share_modes failed\n");
    1548         849 :                 TALLOC_FREE(state->lck);
    1549             :         }
    1550             : }
    1551             : 
    1552             : /*******************************************************************
    1553             :  Get a share_mode_lock without locking the database or reference
    1554             :  counting. Used by smbstatus to display existing share modes.
    1555             : ********************************************************************/
    1556             : 
    1557      884911 : struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
    1558             :                                                   struct file_id id)
    1559             : {
    1560      884911 :         struct fetch_share_mode_unlocked_state state = {
    1561             :                 .mem_ctx = mem_ctx,
    1562             :                 .id = id,
    1563             :         };
    1564      884911 :         TDB_DATA key = locking_key(&id);
    1565        1284 :         NTSTATUS status;
    1566             : 
    1567      884911 :         status = g_lock_dump(
    1568             :                 lock_ctx, key, fetch_share_mode_unlocked_parser, &state);
    1569      884911 :         if (!NT_STATUS_IS_OK(status)) {
    1570      836029 :                 DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status));
    1571      836029 :                 return NULL;
    1572             :         }
    1573       48882 :         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           0 :         NTSTATUS status;
    1700             : 
    1701           0 :         status = g_lock_dump_recv(subreq);
    1702           0 :         TALLOC_FREE(subreq);
    1703           0 :         if (tevent_req_nterror(req, status)) {
    1704           0 :                 return;
    1705             :         }
    1706           0 :         if (tevent_req_nterror(req, state->status)) {
    1707           0 :                 return;
    1708             :         }
    1709           0 :         tevent_req_done(req);
    1710             : }
    1711             : 
    1712           0 : NTSTATUS fetch_share_mode_recv(struct tevent_req *req,
    1713             :                                TALLOC_CTX *mem_ctx,
    1714             :                                struct share_mode_lock **_lck)
    1715             : {
    1716           0 :         struct fetch_share_mode_state *state = tevent_req_data(
    1717             :                 req, struct fetch_share_mode_state);
    1718           0 :         struct share_mode_lock *lck = NULL;
    1719             : 
    1720           0 :         NTSTATUS status;
    1721             : 
    1722           0 :         if (tevent_req_is_nterror(req, &status)) {
    1723           0 :                 tevent_req_received(req);
    1724           0 :                 return status;
    1725             :         }
    1726             : 
    1727           0 :         if (state->lck == NULL) {
    1728           0 :                 tevent_req_received(req);
    1729           0 :                 return NT_STATUS_NOT_FOUND;
    1730             :         }
    1731             : 
    1732           0 :         lck = talloc_move(mem_ctx, &state->lck);
    1733             : 
    1734           0 :         if (DEBUGLEVEL >= 10) {
    1735           0 :                 DBG_DEBUG("share_mode_data:\n");
    1736           0 :                 NDR_PRINT_DEBUG(share_mode_data, lck->cached_data);
    1737             :         }
    1738             : 
    1739           0 :         *_lck = lck;
    1740           0 :         tevent_req_received(req);
    1741           0 :         return NT_STATUS_OK;
    1742             : }
    1743             : 
    1744             : struct share_mode_forall_state {
    1745             :         TDB_DATA key;
    1746             :         int (*fn)(struct file_id fid,
    1747             :                   const struct share_mode_data *data,
    1748             :                   void *private_data);
    1749             :         void *private_data;
    1750             : };
    1751             : 
    1752       19161 : 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       19161 :         struct share_mode_forall_state *state = private_data;
    1761           0 :         struct file_id fid;
    1762       19161 :         struct locking_tdb_data ltdb = { 0 };
    1763           0 :         bool ok;
    1764           0 :         struct share_mode_data *d;
    1765             : 
    1766       19161 :         if (state->key.dsize != sizeof(fid)) {
    1767           0 :                 DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize);
    1768           0 :                 return;
    1769             :         }
    1770       19161 :         memcpy(&fid, state->key.dptr, sizeof(fid));
    1771             : 
    1772       19161 :         ok = locking_tdb_data_get(&ltdb, data, datalen);
    1773       19161 :         if (!ok) {
    1774           0 :                 DBG_DEBUG("locking_tdb_data_get() failed\n");
    1775           0 :                 return;
    1776             :         }
    1777             : 
    1778       19161 :         d = parse_share_modes(
    1779             :                 talloc_tos(),
    1780             :                 fid,
    1781             :                 ltdb.share_mode_data_buf,
    1782             :                 ltdb.share_mode_data_len);
    1783       19161 :         if (d == NULL) {
    1784           0 :                 DBG_DEBUG("parse_share_modes() failed\n");
    1785           0 :                 return;
    1786             :         }
    1787             : 
    1788       19161 :         state->fn(fid, d, state->private_data);
    1789       19161 :         TALLOC_FREE(d);
    1790             : }
    1791             : 
    1792       19161 : static int share_mode_forall_fn(TDB_DATA key, void *private_data)
    1793             : {
    1794       19161 :         struct share_mode_forall_state *state = private_data;
    1795           0 :         NTSTATUS status;
    1796             : 
    1797       19161 :         state->key = key;
    1798             : 
    1799       19161 :         status = share_mode_g_lock_dump(
    1800             :                 key, share_mode_forall_dump_fn, private_data);
    1801       19161 :         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       19161 :         return 0;
    1807             : }
    1808             : 
    1809        6648 : 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        6648 :         struct share_mode_forall_state state = {
    1815             :                 .fn = fn,
    1816             :                 .private_data = private_data
    1817             :         };
    1818           0 :         int ret;
    1819             : 
    1820        6648 :         if (lock_ctx == NULL) {
    1821           0 :                 return 0;
    1822             :         }
    1823             : 
    1824        6648 :         ret = g_lock_locks(
    1825             :                 lock_ctx, share_mode_forall_fn, &state);
    1826        6648 :         if (ret < 0) {
    1827           0 :                 DBG_ERR("g_lock_locks failed\n");
    1828             :         }
    1829        6648 :         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          23 : static bool share_entry_traverse_walker(
    1844             :         struct share_mode_entry *e,
    1845             :         bool *modified,
    1846             :         void *private_data)
    1847             : {
    1848          23 :         struct share_entry_forall_state *state = private_data;
    1849             : 
    1850          23 :         state->ret = state->fn(
    1851             :                 state->fid, state->data, e, state->private_data);
    1852          23 :         return (state->ret != 0);
    1853             : }
    1854             : 
    1855          23 : static int share_entry_traverse_fn(struct file_id fid,
    1856             :                                    const struct share_mode_data *data,
    1857             :                                    void *private_data)
    1858             : {
    1859          23 :         struct share_entry_forall_state *state = private_data;
    1860          23 :         struct share_mode_lock lck = {
    1861             :                 .id = fid,
    1862             :                 .cached_data = discard_const_p(struct share_mode_data, data)
    1863             :         };
    1864           0 :         bool ok;
    1865             : 
    1866          23 :         state->fid = fid;
    1867          23 :         state->data = data;
    1868             : 
    1869          23 :         ok = share_mode_forall_entries(
    1870             :                 &lck, share_entry_traverse_walker, state);
    1871          23 :         if (!ok) {
    1872           0 :                 DBG_ERR("share_mode_forall_entries failed\n");
    1873           0 :                 return false;
    1874             :         }
    1875             : 
    1876          23 :         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          39 : 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          39 :         struct share_entry_forall_state state = {
    1891             :                 .fn = fn, .private_data = private_data };
    1892             : 
    1893          39 :         return share_mode_forall(share_entry_traverse_fn, &state);
    1894             : }
    1895             : 
    1896      530724 : static int share_mode_entry_cmp(
    1897             :         struct server_id pid1,
    1898             :         uint64_t share_file_id1,
    1899             :         struct server_id pid2,
    1900             :         uint64_t share_file_id2)
    1901             : {
    1902        1123 :         int cmp;
    1903             : 
    1904      531847 :         cmp = server_id_cmp(&pid1, &pid2);
    1905      530724 :         if (cmp != 0) {
    1906       45455 :                 return cmp;
    1907             :         }
    1908      485244 :         if (share_file_id1 != share_file_id2) {
    1909        8885 :                 return (share_file_id1 < share_file_id2) ? -1 : 1;
    1910             :         }
    1911      475298 :         return 0;
    1912             : }
    1913             : 
    1914      949384 : static size_t share_mode_entry_find(
    1915             :         const uint8_t *data,
    1916             :         size_t num_share_modes,
    1917             :         struct server_id pid,
    1918             :         uint64_t share_file_id,
    1919             :         struct share_mode_entry *e,
    1920             :         bool *match)
    1921             : {
    1922        1999 :         ssize_t left, right, middle;
    1923             : 
    1924      949384 :         *match = false;
    1925             : 
    1926      949384 :         if (num_share_modes == 0) {
    1927      444260 :                 return 0;
    1928             :         }
    1929             : 
    1930      504226 :         left = 0;
    1931      504226 :         right = (num_share_modes-1);
    1932             : 
    1933      558591 :         while (left <= right) {
    1934      530434 :                 const uint8_t *middle_ptr = NULL;
    1935        1123 :                 int cmp;
    1936        1123 :                 bool ok;
    1937             : 
    1938      530434 :                 middle = left + ((right - left) / 2);
    1939      530434 :                 middle_ptr = data + middle * SHARE_MODE_ENTRY_SIZE;
    1940             : 
    1941      530434 :                 DBG_DEBUG("left=%zu, right=%zu, middle=%zu, middle_ptr=%p\n",
    1942             :                           left,
    1943             :                           right,
    1944             :                           middle,
    1945             :                           middle_ptr);
    1946             : 
    1947      530434 :                 ok = share_mode_entry_get(middle_ptr, e);
    1948      530434 :                 if (!ok) {
    1949           0 :                         DBG_DEBUG("share_mode_entry_get failed\n");
    1950           0 :                         return 0;
    1951             :                 }
    1952             : 
    1953      530434 :                 cmp = share_mode_entry_cmp(
    1954             :                         e->pid, e->share_file_id, pid, share_file_id);
    1955      529373 :                 if (cmp == 0) {
    1956      476069 :                         *match = true;
    1957      476069 :                         return middle;
    1958             :                 }
    1959             : 
    1960       54365 :                 if (cmp < 0) {
    1961       25700 :                         right = middle-1;
    1962             :                 } else {
    1963       28665 :                         left = middle+1;
    1964             :                 }
    1965             :         }
    1966             : 
    1967       28157 :         return left;
    1968             : }
    1969             : 
    1970      473315 : 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      473315 :         struct share_mode_data *d = share_mode_lock_assert_private_data(lck);
    1980      473315 :         TDB_DATA key = locking_key(&d->id);
    1981      473315 :         struct server_id my_pid = messaging_server_id(
    1982      473315 :                 fsp->conn->sconn->msg_ctx);
    1983      473315 :         struct locking_tdb_data *ltdb = NULL;
    1984         938 :         size_t idx;
    1985      473315 :         struct share_mode_entry e = { .pid.pid = 0 };
    1986         938 :         struct share_mode_entry_buf e_buf;
    1987         938 :         NTSTATUS status;
    1988         938 :         bool ok, found;
    1989             : 
    1990         938 :         TDB_DATA dbufs[3];
    1991      473315 :         size_t num_dbufs = 0;
    1992             : 
    1993      473315 :         status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
    1994      473315 :         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      473315 :         DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
    2000             : 
    2001      473315 :         idx = share_mode_entry_find(
    2002      472377 :                 ltdb->share_entries,
    2003      473315 :                 ltdb->num_share_entries,
    2004             :                 my_pid,
    2005             :                 fh_get_gen_id(fsp->fh),
    2006             :                 &e,
    2007             :                 &found);
    2008      473315 :         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      946630 :         e = (struct share_mode_entry) {
    2015             :                 .pid = my_pid,
    2016             :                 .share_access = share_access,
    2017      473315 :                 .private_options = fh_get_private_options(fsp->fh),
    2018             :                 .access_mask = access_mask,
    2019             :                 .op_mid = mid,
    2020             :                 .op_type = op_type,
    2021      473315 :                 .time.tv_sec = fsp->open_time.tv_sec,
    2022      473315 :                 .time.tv_usec = fsp->open_time.tv_usec,
    2023      473315 :                 .share_file_id = fh_get_gen_id(fsp->fh),
    2024             :                 .uid = (uint32_t)uid,
    2025             :                 .flags = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
    2026      473315 :                         SHARE_MODE_FLAG_POSIX_OPEN : 0,
    2027      473315 :                 .name_hash = fsp->name_hash,
    2028             :         };
    2029             : 
    2030      473315 :         if (op_type == LEASE_OPLOCK) {
    2031         972 :                 const struct GUID *client_guid = fsp_client_guid(fsp);
    2032         972 :                 e.client_guid = *client_guid;
    2033         972 :                 e.lease_key = *lease_key;
    2034             :         }
    2035             : 
    2036      473315 :         ok = share_mode_entry_put(&e, &e_buf);
    2037      473315 :         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      473315 :         DBG_DEBUG("idx=%zu, found=%d\n", idx, (int)found);
    2044             : 
    2045      473315 :         if (idx > 0) {
    2046       12211 :                 dbufs[num_dbufs] = (TDB_DATA) {
    2047       12211 :                         .dptr = discard_const_p(uint8_t, ltdb->share_entries),
    2048       12211 :                         .dsize = idx * SHARE_MODE_ENTRY_SIZE,
    2049             :                 };
    2050       12211 :                 num_dbufs += 1;
    2051             :         }
    2052             : 
    2053      473315 :         dbufs[num_dbufs] = (TDB_DATA) {
    2054             :                 .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
    2055             :         };
    2056      473315 :         num_dbufs += 1;
    2057             : 
    2058      473315 :         if (idx < ltdb->num_share_entries) {
    2059       20095 :                 size_t num_after_idx = (ltdb->num_share_entries-idx);
    2060       20095 :                 dbufs[num_dbufs] = (TDB_DATA) {
    2061       20095 :                         .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
    2062       20095 :                                 idx * SHARE_MODE_ENTRY_SIZE,
    2063       20095 :                         .dsize = num_after_idx * SHARE_MODE_ENTRY_SIZE,
    2064             :                 };
    2065       20095 :                 num_dbufs += 1;
    2066             :         }
    2067             : 
    2068             :         {
    2069         938 :                 size_t i;
    2070      978936 :                 for (i=0; i<num_dbufs; i++) {
    2071      505621 :                         DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
    2072             :                                   i,
    2073             :                                   dbufs[i].dptr,
    2074             :                                   dbufs[i].dsize);
    2075             :                 }
    2076             :         }
    2077             : 
    2078      473315 :         if (num_dbufs == 1) {
    2079             :                 /*
    2080             :                  * Storing a fresh record with just one share entry
    2081             :                  */
    2082      445158 :                 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      473315 :         ltdb->share_entries = NULL;
    2111      473315 :         ltdb->num_share_entries = 0;
    2112             : 
    2113      473315 :         status = share_mode_data_ltdb_store(d, key, ltdb, dbufs, num_dbufs);
    2114      473315 :         if (!NT_STATUS_IS_OK(status)) {
    2115           0 :                 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
    2116             :                         nt_errstr(status));
    2117             :         }
    2118      473315 : done:
    2119      473315 :         TALLOC_FREE(ltdb);
    2120      473315 :         return NT_STATUS_IS_OK(status);
    2121             : }
    2122             : 
    2123      482817 : 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      482817 :         DATA_BLOB blob = {
    2134      482817 :                 .data = data + (*i) * SHARE_MODE_ENTRY_SIZE,
    2135             :                 .length = SHARE_MODE_ENTRY_SIZE,
    2136             :         };
    2137      482817 :         struct share_mode_entry e = {.pid.pid=0};
    2138      482817 :         enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
    2139      482817 :         bool modified = false;
    2140      482817 :         bool stop = false;
    2141        1096 :         struct server_id e_pid;
    2142        1096 :         uint64_t e_share_file_id;
    2143             : 
    2144      482817 :         ndr_err = ndr_pull_struct_blob_all_noalloc(
    2145             :                 &blob,
    2146             :                 &e,
    2147             :                 (ndr_pull_flags_fn_t)ndr_pull_share_mode_entry);
    2148      482817 :         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      482817 :         if (DEBUGLEVEL >= 10) {
    2154           0 :                 DBG_DEBUG("entry[%zu]:\n", *i);
    2155           0 :                 NDR_PRINT_DEBUG(share_mode_entry, &e);
    2156             :         }
    2157             : 
    2158      482817 :         e_pid = e.pid;
    2159      482817 :         e_share_file_id = e.share_file_id;
    2160             : 
    2161      482817 :         stop = fn(&e, &modified, private_data);
    2162             : 
    2163      482817 :         DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
    2164             :                   *i,
    2165             :                   (int)modified,
    2166             :                   (int)e.stale);
    2167             : 
    2168      482817 :         if (e.stale) {
    2169          31 :                 if (DEBUGLEVEL>=10) {
    2170           0 :                         DBG_DEBUG("share_mode_entry:\n");
    2171           0 :                         NDR_PRINT_DEBUG(share_mode_entry, &e);
    2172             :                 }
    2173             : 
    2174          31 :                 if (*i < *num_share_modes) {
    2175          31 :                         memmove(blob.data,
    2176          31 :                                 blob.data + SHARE_MODE_ENTRY_SIZE,
    2177          31 :                                 (*num_share_modes - *i - 1) *
    2178             :                                 SHARE_MODE_ENTRY_SIZE);
    2179             :                 }
    2180          31 :                 *num_share_modes -= 1;
    2181          31 :                 *writeback = true;
    2182          31 :                 return stop;
    2183             :         }
    2184             : 
    2185      482786 :         if (modified) {
    2186        1087 :                 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        1087 :                 SMB_ASSERT(server_id_equal(&e_pid, &e.pid));
    2195        1087 :                 SMB_ASSERT(e_share_file_id == e.share_file_id);
    2196             : 
    2197        1087 :                 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        1087 :                 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        1087 :                 *i += 1;
    2211        1087 :                 *writeback = true;
    2212        1087 :                 return stop;
    2213             :         }
    2214             : 
    2215      481699 :         if (stop) {
    2216         649 :                 return true;
    2217             :         }
    2218             : 
    2219      481030 :         *i += 1;
    2220      481030 :         return false;
    2221             : }
    2222             : 
    2223     1667234 : 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     1667234 :         struct file_id id = share_mode_lock_file_id(lck);
    2231     1667234 :         struct share_mode_data *d = NULL;
    2232     1667234 :         TDB_DATA key = locking_key(&id);
    2233     1667234 :         struct locking_tdb_data *ltdb = NULL;
    2234     1667234 :         uint8_t *share_entries = NULL;
    2235        3352 :         size_t num_share_entries;
    2236     1667234 :         bool writeback = false;
    2237        3352 :         NTSTATUS status;
    2238     1667234 :         bool stop = false;
    2239        3352 :         size_t i;
    2240             : 
    2241     1667234 :         status = share_mode_lock_access_private_data(lck, &d);
    2242     1667234 :         if (!NT_STATUS_IS_OK(status)) {
    2243           0 :                 struct file_id_buf id_buf;
    2244             :                 /* Any error recovery possible here ? */
    2245           0 :                 DBG_ERR("share_mode_lock_access_private_data() failed for "
    2246             :                         "%s - %s\n",
    2247             :                         file_id_str_buf(id, &id_buf),
    2248             :                         nt_errstr(status));
    2249           0 :                 return false;
    2250             :         }
    2251             : 
    2252     1667234 :         status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
    2253     1667234 :         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     1667234 :         DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
    2259             : 
    2260     1667234 :         num_share_entries = ltdb->num_share_entries;
    2261     1667234 :         share_entries = discard_const_p(uint8_t, ltdb->share_entries);
    2262             : 
    2263     1667234 :         i = 0;
    2264     2149382 :         while (i<num_share_entries) {
    2265      482817 :                 stop = share_mode_for_one_entry(
    2266             :                         fn,
    2267             :                         private_data,
    2268             :                         &i,
    2269             :                         share_entries,
    2270             :                         &num_share_entries,
    2271             :                         &writeback);
    2272      482817 :                 if (stop) {
    2273         649 :                         break;
    2274             :                 }
    2275             :         }
    2276             : 
    2277     1667234 :         DBG_DEBUG("num_share_entries=%zu, writeback=%d\n",
    2278             :                   num_share_entries,
    2279             :                   (int)writeback);
    2280             : 
    2281     1667234 :         if (!writeback) {
    2282     1666201 :                 TALLOC_FREE(ltdb);
    2283     1666201 :                 return true;
    2284             :         }
    2285             : 
    2286        1033 :         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          31 :                 d->modified = true;
    2292             :         }
    2293             : 
    2294        1033 :         ltdb->num_share_entries = num_share_entries;
    2295        1033 :         ltdb->share_entries = share_entries;
    2296             : 
    2297        1033 :         status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
    2298        1033 :         TALLOC_FREE(ltdb);
    2299        1033 :         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        1017 :         return true;
    2306             : }
    2307             : 
    2308             : struct share_mode_count_entries_state {
    2309             :         size_t num_share_modes;
    2310             :         NTSTATUS status;
    2311             : };
    2312             : 
    2313          10 : static void share_mode_count_entries_fn(
    2314             :         struct server_id exclusive,
    2315             :         size_t num_shared,
    2316             :         const struct server_id *shared,
    2317             :         const uint8_t *data,
    2318             :         size_t datalen,
    2319             :         void *private_data)
    2320             : {
    2321          10 :         struct share_mode_count_entries_state *state = private_data;
    2322          10 :         struct locking_tdb_data ltdb = { 0 };
    2323           0 :         bool ok;
    2324             : 
    2325          10 :         ok = locking_tdb_data_get(&ltdb, data, datalen);
    2326          10 :         if (!ok) {
    2327           0 :                 DBG_WARNING("locking_tdb_data_get failed for %zu\n", datalen);
    2328           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
    2329           0 :                 return;
    2330             :         }
    2331          10 :         state->num_share_modes = ltdb.num_share_entries;
    2332          10 :         state->status = NT_STATUS_OK;
    2333             : }
    2334             : 
    2335          10 : NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes)
    2336             : {
    2337          10 :         struct share_mode_count_entries_state state = {
    2338             :                 .status = NT_STATUS_NOT_FOUND,
    2339             :         };
    2340           0 :         NTSTATUS status;
    2341             : 
    2342          10 :         status = g_lock_dump(
    2343             :                 lock_ctx,
    2344             :                 locking_key(&fid),
    2345             :                 share_mode_count_entries_fn,
    2346             :                 &state);
    2347          10 :         if (!NT_STATUS_IS_OK(status)) {
    2348           0 :                 DBG_DEBUG("g_lock_dump failed: %s\n",
    2349             :                           nt_errstr(status));
    2350           0 :                 return status;
    2351             :         }
    2352          10 :         if (!NT_STATUS_IS_OK(state.status)) {
    2353           0 :                 DBG_DEBUG("share_mode_count_entries_fn failed: %s\n",
    2354             :                           nt_errstr(state.status));
    2355           0 :                 return state.status;
    2356             :         }
    2357             : 
    2358          10 :         *num_share_modes = state.num_share_modes;
    2359          10 :         return NT_STATUS_OK;
    2360             : }
    2361             : 
    2362      476069 : 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      476069 :         TDB_DATA key = locking_key(&d->id);
    2373      476069 :         struct locking_tdb_data *ltdb = NULL;
    2374        1061 :         size_t idx;
    2375      476069 :         bool found = false;
    2376      476069 :         bool modified = false;
    2377        1061 :         struct share_mode_entry e;
    2378      476069 :         uint8_t *e_ptr = NULL;
    2379        1061 :         NTSTATUS status;
    2380      476069 :         bool ret = false;
    2381             : 
    2382      476069 :         status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
    2383      476069 :         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      476069 :         DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
    2389             : 
    2390      477130 :         idx = share_mode_entry_find(
    2391      475008 :                 ltdb->share_entries,
    2392      476069 :                 ltdb->num_share_entries,
    2393             :                 pid,
    2394             :                 share_file_id,
    2395             :                 &e,
    2396             :                 &found);
    2397      476069 :         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      476069 :         if (DEBUGLEVEL>=10) {
    2404           0 :                 DBG_DEBUG("entry[%zu]:\n", idx);
    2405           0 :                 NDR_PRINT_DEBUG(share_mode_entry, &e);
    2406             :         }
    2407             : 
    2408      476069 :         fn(&e, ltdb->num_share_entries, &modified, private_data);
    2409             : 
    2410      476069 :         DBG_DEBUG("entry[%zu]: modified=%d, e.stale=%d\n",
    2411             :                   idx,
    2412             :                   (int)modified,
    2413             :                   (int)e.stale);
    2414             : 
    2415      476069 :         if (!e.stale && !modified) {
    2416           0 :                 ret = true;
    2417           0 :                 goto done;
    2418             :         }
    2419             : 
    2420      476069 :         e_ptr = discard_const_p(uint8_t, ltdb->share_entries) +
    2421      476069 :                 idx * SHARE_MODE_ENTRY_SIZE;
    2422             : 
    2423      476069 :         if (e.stale) {
    2424             :                 /*
    2425             :                  * Move the rest down one entry
    2426             :                  */
    2427      473269 :                 size_t behind = ltdb->num_share_entries - idx - 1;
    2428      473269 :                 if (behind != 0) {
    2429       18011 :                         memmove(e_ptr,
    2430       17073 :                                 e_ptr + SHARE_MODE_ENTRY_SIZE,
    2431             :                                 behind * SHARE_MODE_ENTRY_SIZE);
    2432             :                 }
    2433      473269 :                 ltdb->num_share_entries -= 1;
    2434             : 
    2435      473269 :                 if (ltdb->num_share_entries == 0) {
    2436             :                         /*
    2437             :                          * Tell share_mode_lock_destructor() to delete
    2438             :                          * the whole record
    2439             :                          */
    2440      445112 :                         d->modified = true;
    2441             :                 }
    2442             : 
    2443      473269 :                 if (DEBUGLEVEL>=10) {
    2444           0 :                         DBG_DEBUG("share_mode_entry:\n");
    2445           0 :                         NDR_PRINT_DEBUG(share_mode_entry, &e);
    2446             :                 }
    2447             :         } else {
    2448         123 :                 struct share_mode_entry_buf buf;
    2449         123 :                 bool ok;
    2450             : 
    2451        2800 :                 if (ltdb->num_share_entries != 1) {
    2452             :                         /*
    2453             :                          * Make sure the sorting order stays intact
    2454             :                          */
    2455         553 :                         SMB_ASSERT(server_id_equal(&e.pid, &pid));
    2456         553 :                         SMB_ASSERT(e.share_file_id == share_file_id);
    2457             :                 }
    2458             : 
    2459        2800 :                 ok = share_mode_entry_put(&e, &buf);
    2460        2800 :                 if (!ok) {
    2461           0 :                         DBG_DEBUG("share_mode_entry_put failed\n");
    2462           0 :                         goto done;
    2463             :                 }
    2464        2800 :                 memcpy(e_ptr, buf.buf, SHARE_MODE_ENTRY_SIZE);
    2465             :         }
    2466             : 
    2467      476069 :         status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
    2468      476069 :         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      475008 :         ret = true;
    2475      476069 : done:
    2476      476069 :         TALLOC_FREE(ltdb);
    2477      475008 :         return ret;
    2478             : }
    2479             : 
    2480             : struct del_share_mode_state {
    2481             :         bool ok;
    2482             : };
    2483             : 
    2484      473269 : 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      473269 :         struct del_share_mode_state *state = private_data;
    2491      473269 :         e->stale = true;
    2492      473269 :         state->ok = true;
    2493      473269 : }
    2494             : 
    2495      473269 : 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      473269 :         struct del_share_mode_state state = { .ok = false };
    2500      473269 :         struct share_mode_data *d = NULL;
    2501         938 :         NTSTATUS status;
    2502         938 :         bool ok;
    2503             : 
    2504      473269 :         status = share_mode_lock_access_private_data(lck, &d);
    2505      473269 :         if (!NT_STATUS_IS_OK(status)) {
    2506             :                 /* Any error recovery possible here ? */
    2507           0 :                 return false;
    2508             :         }
    2509             : 
    2510      473269 :         ok = share_mode_entry_do(
    2511             :                 d,
    2512             :                 open_pid,
    2513             :                 open_file_id,
    2514             :                 del_share_mode_fn,
    2515             :                 &state);
    2516      473269 :         if (!ok) {
    2517           0 :                 DBG_DEBUG("share_mode_entry_do failed\n");
    2518           0 :                 return false;
    2519             :         }
    2520      473269 :         if (!state.ok) {
    2521           0 :                 DBG_DEBUG("del_share_mode_fn failed\n");
    2522           0 :                 return false;
    2523             :         }
    2524      472331 :         return true;
    2525             : }
    2526             : 
    2527      473269 : bool del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
    2528             : {
    2529         938 :         struct server_id pid =
    2530      473269 :                 messaging_server_id(fsp->conn->sconn->msg_ctx);
    2531         938 :         bool ok;
    2532             : 
    2533      473269 :         ok = del_share_mode_open_id(lck, pid, fh_get_gen_id(fsp->fh));
    2534      473269 :         if (!ok) {
    2535           0 :                 struct file_id id = share_mode_lock_file_id(lck);
    2536           0 :                 struct file_id_buf id_buf;
    2537           0 :                 DBG_ERR("share_mode_lock_access_private_data() failed for "
    2538             :                         "%s %s\n",
    2539             :                         file_id_str_buf(id, &id_buf),
    2540             :                         fsp_str_dbg(fsp));
    2541           0 :                 return false;
    2542             :         }
    2543      472331 :         return true;
    2544             : }
    2545             : 
    2546             : struct remove_share_oplock_state {
    2547             :         bool ok;
    2548             : };
    2549             : 
    2550        2646 : static void remove_share_oplock_fn(
    2551             :         struct share_mode_entry *e,
    2552             :         size_t num_share_modes,
    2553             :         bool *modified,
    2554             :         void *private_data)
    2555             : {
    2556        2646 :         struct remove_share_oplock_state *state = private_data;
    2557             : 
    2558        2646 :         e->op_type = NO_OPLOCK;
    2559        2646 :         *modified = true;
    2560        2646 :         state->ok = true;
    2561        2646 : }
    2562             : 
    2563        2646 : bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
    2564             : {
    2565        2646 :         struct remove_share_oplock_state state = { .ok = false };
    2566        2646 :         struct share_mode_data *d = NULL;
    2567         123 :         NTSTATUS status;
    2568         123 :         bool ok;
    2569             : 
    2570        2646 :         status = share_mode_lock_access_private_data(lck, &d);
    2571        2646 :         if (!NT_STATUS_IS_OK(status)) {
    2572           0 :                 struct file_id id = share_mode_lock_file_id(lck);
    2573           0 :                 struct file_id_buf id_buf;
    2574             :                 /* Any error recovery possible here ? */
    2575           0 :                 DBG_ERR("share_mode_lock_access_private_data() failed for "
    2576             :                         "%s %s - %s\n",
    2577             :                         file_id_str_buf(id, &id_buf),
    2578             :                         fsp_str_dbg(fsp),
    2579             :                         nt_errstr(status));
    2580           0 :                 return false;
    2581             :         }
    2582             : 
    2583        5292 :         ok = share_mode_entry_do(
    2584             :                 d,
    2585        2646 :                 messaging_server_id(fsp->conn->sconn->msg_ctx),
    2586             :                 fh_get_gen_id(fsp->fh),
    2587             :                 remove_share_oplock_fn,
    2588             :                 &state);
    2589        2646 :         if (!ok) {
    2590           0 :                 DBG_DEBUG("share_mode_entry_do failed\n");
    2591           0 :                 return false;
    2592             :         }
    2593        2646 :         if (!state.ok) {
    2594           0 :                 DBG_DEBUG("remove_share_oplock_fn failed\n");
    2595           0 :                 return false;
    2596             :         }
    2597             : 
    2598        2646 :         if (fsp->oplock_type == LEASE_OPLOCK) {
    2599         962 :                 remove_lease_if_stale(
    2600             :                         lck,
    2601             :                         fsp_client_guid(fsp),
    2602         962 :                         &fsp->lease->lease.lease_key);
    2603             :         }
    2604             : 
    2605        2646 :         share_mode_wakeup_waiters(fsp->file_id);
    2606             : 
    2607        2646 :         return true;
    2608             : }
    2609             : 
    2610             : struct downgrade_share_oplock_state {
    2611             :         bool ok;
    2612             : };
    2613             : 
    2614         154 : static void downgrade_share_oplock_fn(
    2615             :         struct share_mode_entry *e,
    2616             :         size_t num_share_modes,
    2617             :         bool *modified,
    2618             :         void *private_data)
    2619             : {
    2620         154 :         struct downgrade_share_oplock_state *state = private_data;
    2621             : 
    2622         154 :         e->op_type = LEVEL_II_OPLOCK;
    2623         154 :         *modified = true;
    2624         154 :         state->ok = true;
    2625         154 : }
    2626             : 
    2627         154 : bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
    2628             : {
    2629         154 :         struct downgrade_share_oplock_state state = { .ok = false };
    2630         154 :         struct share_mode_data *d = NULL;
    2631           0 :         NTSTATUS status;
    2632           0 :         bool ok;
    2633             : 
    2634         154 :         status = share_mode_lock_access_private_data(lck, &d);
    2635         154 :         if (!NT_STATUS_IS_OK(status)) {
    2636           0 :                 struct file_id id = share_mode_lock_file_id(lck);
    2637           0 :                 struct file_id_buf id_buf;
    2638             :                 /* Any error recovery possible here ? */
    2639           0 :                 DBG_ERR("share_mode_lock_access_private_data() failed for "
    2640             :                         "%s %s - %s\n",
    2641             :                         file_id_str_buf(id, &id_buf),
    2642             :                         fsp_str_dbg(fsp),
    2643             :                         nt_errstr(status));
    2644           0 :                 return false;
    2645             :         }
    2646             : 
    2647         308 :         ok = share_mode_entry_do(
    2648             :                 d,
    2649         154 :                 messaging_server_id(fsp->conn->sconn->msg_ctx),
    2650             :                 fh_get_gen_id(fsp->fh),
    2651             :                 downgrade_share_oplock_fn,
    2652             :                 &state);
    2653         154 :         if (!ok) {
    2654           0 :                 DBG_DEBUG("share_mode_entry_do failed\n");
    2655           0 :                 return false;
    2656             :         }
    2657         154 :         if (!state.ok) {
    2658           0 :                 DBG_DEBUG("downgrade_share_oplock_fn failed\n");
    2659           0 :                 return false;
    2660             :         }
    2661             : 
    2662         154 :         d->flags |= SHARE_MODE_LEASE_READ;
    2663         154 :         d->modified = true;
    2664             : 
    2665         154 :         return true;
    2666             : }
    2667             : 
    2668         160 : bool mark_share_mode_disconnected(struct share_mode_lock *lck,
    2669             :                                   struct files_struct *fsp)
    2670             : {
    2671         160 :         struct server_id disconnected_pid = { .pid = 0 };
    2672           0 :         bool ok;
    2673             : 
    2674         160 :         if (fsp->op == NULL) {
    2675           0 :                 return false;
    2676             :         }
    2677         160 :         if (!fsp->op->global->durable) {
    2678           0 :                 return false;
    2679             :         }
    2680             : 
    2681         160 :         server_id_set_disconnected(&disconnected_pid);
    2682             : 
    2683         160 :         ok = reset_share_mode_entry(
    2684             :                 lck,
    2685         160 :                 messaging_server_id(fsp->conn->sconn->msg_ctx),
    2686             :                 fh_get_gen_id(fsp->fh),
    2687             :                 disconnected_pid,
    2688             :                 UINT64_MAX,
    2689         160 :                 fsp->op->global->open_persistent_id);
    2690             : 
    2691         160 :         return ok;
    2692             : }
    2693             : 
    2694         290 : bool reset_share_mode_entry(
    2695             :         struct share_mode_lock *lck,
    2696             :         struct server_id old_pid,
    2697             :         uint64_t old_share_file_id,
    2698             :         struct server_id new_pid,
    2699             :         uint64_t new_mid,
    2700             :         uint64_t new_share_file_id)
    2701             : {
    2702         290 :         struct file_id id = share_mode_lock_file_id(lck);
    2703         290 :         struct share_mode_data *d = NULL;
    2704         290 :         TDB_DATA key = locking_key(&id);
    2705         290 :         struct locking_tdb_data *ltdb = NULL;
    2706           0 :         struct share_mode_entry e;
    2707           0 :         struct share_mode_entry_buf e_buf;
    2708           0 :         NTSTATUS status;
    2709           0 :         int cmp;
    2710         290 :         bool ret = false;
    2711           0 :         bool ok;
    2712             : 
    2713         290 :         status = share_mode_lock_access_private_data(lck, &d);
    2714         290 :         if (!NT_STATUS_IS_OK(status)) {
    2715           0 :                 struct file_id_buf id_buf;
    2716             :                 /* Any error recovery possible here ? */
    2717           0 :                 DBG_ERR("share_mode_lock_access_private_data() failed for "
    2718             :                         "%s - %s\n",
    2719             :                         file_id_str_buf(id, &id_buf),
    2720             :                         nt_errstr(status));
    2721           0 :                 return false;
    2722             :         }
    2723             : 
    2724         290 :         status = locking_tdb_data_fetch(key, talloc_tos(), &ltdb);
    2725         290 :         if (!NT_STATUS_IS_OK(status)) {
    2726           0 :                 DBG_ERR("locking_tdb_data_fetch failed: %s\n",
    2727             :                         nt_errstr(status));
    2728           0 :                 return false;
    2729             :         }
    2730             : 
    2731         290 :         if (ltdb->num_share_entries != 1) {
    2732           0 :                 DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
    2733           0 :                 goto done;
    2734             :         }
    2735             : 
    2736         290 :         ok = share_mode_entry_get(ltdb->share_entries, &e);
    2737         290 :         if (!ok) {
    2738           0 :                 DBG_WARNING("share_mode_entry_get failed\n");
    2739           0 :                 goto done;
    2740             :         }
    2741             : 
    2742         290 :         cmp = share_mode_entry_cmp(
    2743             :                 old_pid, old_share_file_id, e.pid, e.share_file_id);
    2744         290 :         if (cmp != 0) {
    2745           0 :                 struct server_id_buf tmp1, tmp2;
    2746           0 :                 DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
    2747             :                             "got pid=%s, file_id=%"PRIu64"\n",
    2748             :                             server_id_str_buf(old_pid, &tmp1),
    2749             :                             old_share_file_id,
    2750             :                             server_id_str_buf(e.pid, &tmp2),
    2751             :                             e.share_file_id);
    2752           0 :                 goto done;
    2753             :         }
    2754             : 
    2755         290 :         e.pid = new_pid;
    2756         290 :         if (new_mid != UINT64_MAX) {
    2757         130 :                 e.op_mid = new_mid;
    2758             :         }
    2759         290 :         e.share_file_id = new_share_file_id;
    2760             : 
    2761         290 :         ok = share_mode_entry_put(&e, &e_buf);
    2762         290 :         if (!ok) {
    2763           0 :                 DBG_WARNING("share_mode_entry_put failed\n");
    2764           0 :                 goto done;
    2765             :         }
    2766             : 
    2767         290 :         ltdb->share_entries = e_buf.buf;
    2768             : 
    2769         290 :         d->modified = true;
    2770             : 
    2771         290 :         status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
    2772         290 :         if (!NT_STATUS_IS_OK(status)) {
    2773           0 :                 DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
    2774             :                         nt_errstr(status));
    2775           0 :                 goto done;
    2776             :         }
    2777             : 
    2778         290 :         ret = true;
    2779         290 : done:
    2780         290 :         TALLOC_FREE(ltdb);
    2781         290 :         return ret;
    2782             : }
    2783             : 
    2784             : struct share_mode_do_locked_vfs_denied_state {
    2785             :         struct file_id id;
    2786             :         share_mode_do_locked_vfs_fn_t fn;
    2787             :         void *private_data;
    2788             :         const char *location;
    2789             :         NTSTATUS status;
    2790             : };
    2791             : 
    2792       47867 : static void share_mode_do_locked_vfs_denied_fn(struct g_lock_lock_cb_state *glck,
    2793             :                                                void *cb_private)
    2794             : {
    2795       47867 :         struct share_mode_do_locked_vfs_denied_state *state =
    2796             :                 (struct share_mode_do_locked_vfs_denied_state *)cb_private;
    2797       47867 :         struct smb_vfs_deny_state vfs_deny = {};
    2798         435 :         struct share_mode_lock lck;
    2799             : 
    2800       47867 :         if (glck != NULL) {
    2801       42089 :                 current_share_mode_glck = glck;
    2802             :         }
    2803             : 
    2804       47867 :         state->status = get_share_mode_lock_internal(state->id,
    2805             :                                                      NULL,  /* servicepath */
    2806             :                                                      NULL,  /* smb_fname */
    2807             :                                                      NULL,  /* old_write_time */
    2808             :                                                      &lck);
    2809       47867 :         if (!NT_STATUS_IS_OK(state->status)) {
    2810        1260 :                 DBG_GET_SHARE_MODE_LOCK(state->status,
    2811             :                         "get_share_mode_lock_internal failed: %s\n",
    2812             :                         nt_errstr(state->status));
    2813        1260 :                 if (glck != NULL) {
    2814        1260 :                         g_lock_lock_cb_unlock(glck);
    2815        1260 :                         current_share_mode_glck = NULL;
    2816             :                 }
    2817        1260 :                 return;
    2818             :         }
    2819             : 
    2820       46607 :         _smb_vfs_deny_push(&vfs_deny, state->location);
    2821       46607 :         state->fn(&lck, state->private_data);
    2822       46607 :         _smb_vfs_deny_pop(&vfs_deny, state->location);
    2823             : 
    2824       46607 :         state->status = put_share_mode_lock_internal(&lck);
    2825       46607 :         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       46607 :         if (glck != NULL) {
    2833       40829 :                 g_lock_lock_cb_unlock(glck);
    2834       40829 :                 current_share_mode_glck = NULL;
    2835             :         }
    2836       46201 :         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       47867 : 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       47867 :         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       47867 :         if (share_mode_lock_key_refcount == 0) {
    2866       42089 :                 TDB_DATA key = locking_key(&id);
    2867         302 :                 NTSTATUS status;
    2868             : 
    2869       42089 :                 share_mode_lock_skip_g_lock = true;
    2870       42089 :                 status = g_lock_lock(
    2871             :                         lock_ctx,
    2872             :                         key,
    2873             :                         G_LOCK_WRITE,
    2874       42089 :                         (struct timeval) { .tv_sec = 3600 },
    2875             :                         share_mode_do_locked_vfs_denied_fn,
    2876             :                         &state);
    2877       42089 :                 share_mode_lock_skip_g_lock = false;
    2878       42089 :                 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       42089 :                 return state.status;
    2884             :         }
    2885             : 
    2886        5778 :         share_mode_do_locked_vfs_denied_fn(NULL, &state);
    2887             : 
    2888        5778 :         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        9303 : NTSTATUS _share_mode_do_locked_vfs_allowed(
    2905             :         struct file_id id,
    2906             :         share_mode_do_locked_vfs_fn_t fn,
    2907             :         void *private_data,
    2908             :         const char *location)
    2909             : {
    2910          40 :         struct share_mode_lock lck;
    2911          40 :         NTSTATUS status;
    2912             : 
    2913        9303 :         smb_vfs_assert_allowed();
    2914             : 
    2915        9303 :         status = get_share_mode_lock_internal(id,
    2916             :                                               NULL,  /* servicepath */
    2917             :                                               NULL,  /* smb_fname */
    2918             :                                               NULL,  /* old_write_time */
    2919             :                                               &lck);
    2920        9303 :         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        9303 :         fn(&lck, private_data);
    2928             : 
    2929        9303 :         status = put_share_mode_lock_internal(&lck);
    2930        9303 :         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        9303 :         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      957755 : static void share_mode_entry_prepare_lock_fn(struct g_lock_lock_cb_state *glck,
    2954             :                                              void *cb_private)
    2955             : {
    2956      957755 :         struct share_mode_entry_prepare_lock_state *state =
    2957             :                 (struct share_mode_entry_prepare_lock_state *)cb_private;
    2958      957755 :         struct smb_vfs_deny_state vfs_deny = {};
    2959             : 
    2960      957755 :         SMB_ASSERT(glck != NULL);
    2961      957755 :         current_share_mode_glck = glck;
    2962             : 
    2963      957755 :         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      957755 :         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      957755 :         _smb_vfs_deny_push(&vfs_deny, state->location);
    2978      957755 :         state->fn(state->lck, &state->keep_locked, state->private_data);
    2979      957755 :         _smb_vfs_deny_pop(&vfs_deny, state->location);
    2980             : 
    2981      957755 :         if (state->keep_locked) {
    2982      511492 :                 current_share_mode_glck = NULL;
    2983      511492 :                 return;
    2984             :         }
    2985             : 
    2986      446263 :         state->status = put_share_mode_lock_internal(state->lck);
    2987      446263 :         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      446263 :         g_lock_lock_cb_unlock(glck);
    2995      446263 :         current_share_mode_glck = NULL;
    2996      446263 :         return;
    2997             : }
    2998             : 
    2999      957755 : 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      957755 :         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      957755 :         TDB_DATA key = locking_key(&id);
    3019        1929 :         NTSTATUS status;
    3020             : 
    3021      957755 :         SMB_ASSERT(share_mode_lock_key_refcount == 0);
    3022             : 
    3023        1929 :         SMB_ASSERT(__SHARE_MODE_LOCK_SPACE >= sizeof(struct share_mode_lock));
    3024             : 
    3025      957755 :         *prepare_state = (struct share_mode_entry_prepare_state) {
    3026             :                 .__fid = id,
    3027      957755 :                 .__lck_ptr = &prepare_state->__lck_space,
    3028             :         };
    3029             : 
    3030      957755 :         state.lck = prepare_state->__lck_ptr;
    3031             : 
    3032      957755 :         share_mode_lock_skip_g_lock = true;
    3033      957755 :         status = g_lock_lock(
    3034             :                 lock_ctx,
    3035             :                 key,
    3036             :                 G_LOCK_WRITE,
    3037      957755 :                 (struct timeval) { .tv_sec = 3600 },
    3038             :                 share_mode_entry_prepare_lock_fn,
    3039             :                 &state);
    3040      957755 :         share_mode_lock_skip_g_lock = false;
    3041      957755 :         if (!state.keep_locked) {
    3042      446263 :                 prepare_state->__lck_ptr = NULL;
    3043             :         }
    3044      957755 :         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      957755 :         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      511492 : static void share_mode_entry_prepare_unlock_existing_fn(
    3063             :         struct share_mode_entry_prepare_unlock_state *state)
    3064             : {
    3065      511492 :         if (state->fn != NULL) {
    3066      181194 :                 struct smb_vfs_deny_state vfs_deny = {};
    3067             : 
    3068      181194 :                 _smb_vfs_deny_push(&vfs_deny, state->location);
    3069      181194 :                 state->fn(state->lck, state->private_data);
    3070      181194 :                 _smb_vfs_deny_pop(&vfs_deny, state->location);
    3071             :         }
    3072             : 
    3073      511492 :         state->status = put_share_mode_lock_internal(state->lck);
    3074      511492 :         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      511492 :         return;
    3082             : }
    3083             : 
    3084           2 : static void share_mode_entry_prepare_unlock_relock_fn(struct g_lock_lock_cb_state *glck,
    3085             :                                                       void *cb_private)
    3086             : {
    3087           2 :         struct share_mode_entry_prepare_unlock_state *state =
    3088             :                 (struct share_mode_entry_prepare_unlock_state *)cb_private;
    3089           2 :         struct smb_vfs_deny_state vfs_deny = {};
    3090             : 
    3091           2 :         SMB_ASSERT(glck != NULL);
    3092           2 :         current_share_mode_glck = glck;
    3093             : 
    3094           2 :         state->status = get_share_mode_lock_internal(state->id,
    3095             :                                                      NULL,  /* servicepath */
    3096             :                                                      NULL,  /* smb_fname */
    3097             :                                                      NULL,  /* old_write_time */
    3098             :                                                      state->lck);
    3099           2 :         if (!NT_STATUS_IS_OK(state->status)) {
    3100             :                 /* no DBG_GET_SHARE_MODE_LOCK here! */
    3101           0 :                 DBG_ERR("get_share_mode_lock_internal failed: %s\n",
    3102             :                         nt_errstr(state->status));
    3103           0 :                 g_lock_lock_cb_unlock(glck);
    3104           0 :                 current_share_mode_glck = NULL;
    3105           0 :                 return;
    3106             :         }
    3107             : 
    3108           2 :         _smb_vfs_deny_push(&vfs_deny, state->location);
    3109           2 :         state->fn(state->lck, state->private_data);
    3110           2 :         _smb_vfs_deny_pop(&vfs_deny, state->location);
    3111             : 
    3112           2 :         state->status = put_share_mode_lock_internal(state->lck);
    3113           2 :         if (!NT_STATUS_IS_OK(state->status)) {
    3114           0 :                 DBG_ERR("put_share_mode_lock_internal failed: %s\n",
    3115             :                         nt_errstr(state->status));
    3116           0 :                 smb_panic("put_share_mode_lock_internal failed\n");
    3117             :                 return;
    3118             :         }
    3119             : 
    3120           2 :         g_lock_lock_cb_unlock(glck);
    3121           2 :         current_share_mode_glck = NULL;
    3122           2 :         return;
    3123             : }
    3124             : 
    3125      946560 : 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      946560 :         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      946560 :         TDB_DATA key = locking_key(&prepare_state->__fid);
    3138        1876 :         NTSTATUS status;
    3139             : 
    3140      946560 :         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      511492 :                 SMB_ASSERT(share_mode_lock_key_refcount == 1);
    3147             : 
    3148      511492 :                 state.lck = prepare_state->__lck_ptr;
    3149      511492 :                 prepare_state->__lck_ptr = NULL;
    3150             : 
    3151      511492 :                 share_mode_entry_prepare_unlock_existing_fn(&state);
    3152      511492 :                 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      435068 :         SMB_ASSERT(share_mode_lock_key_refcount == 0);
    3161             : 
    3162      435068 :         if (fn == NULL) {
    3163             :                 /*
    3164             :                  * Without an existing lock and without
    3165             :                  * a prepare function there's nothing to
    3166             :                  * do...
    3167             :                  */
    3168      435066 :                 return NT_STATUS_OK;
    3169             :         }
    3170             : 
    3171             :         /*
    3172             :          * In order to run the unlock prepare function
    3173             :          * we need to relock the entry.
    3174             :          */
    3175           2 :         state.lck = &prepare_state->__lck_space;
    3176             : 
    3177           2 :         share_mode_lock_skip_g_lock = true;
    3178           2 :         status = g_lock_lock(
    3179             :                 lock_ctx,
    3180             :                 key,
    3181             :                 G_LOCK_WRITE,
    3182           2 :                 (struct timeval) { .tv_sec = 3600 },
    3183             :                 share_mode_entry_prepare_unlock_relock_fn,
    3184             :                 &state);
    3185           2 :         share_mode_lock_skip_g_lock = false;
    3186           2 :         if (!NT_STATUS_IS_OK(status)) {
    3187           0 :                 DBG_ERR("g_lock_lock failed: %s\n",
    3188             :                         nt_errstr(status));
    3189           0 :                 return status;
    3190             :         }
    3191             : 
    3192           2 :         return state.status;
    3193             : }

Generated by: LCOV version 1.14