LCOV - code coverage report
Current view: top level - source3/locking - share_mode_lock.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 605 983 61.5 %
Date: 2024-06-13 04:01:37 Functions: 49 68 72.1 %

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

Generated by: LCOV version 1.13