LCOV - code coverage report
Current view: top level - source3/locking - brlock.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 506 756 66.9 %
Date: 2024-05-31 13:13:24 Functions: 33 36 91.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    byte range locking code
       4             :    Updated to handle range splits/merges.
       5             : 
       6             :    Copyright (C) Andrew Tridgell 1992-2000
       7             :    Copyright (C) Jeremy Allison 1992-2000
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : /* This module implements a tdb based byte range locking service,
      24             :    replacing the fcntl() based byte range locking previously
      25             :    used. This allows us to provide the same semantics as NT */
      26             : 
      27             : #include "includes.h"
      28             : #include "system/filesys.h"
      29             : #include "lib/util/server_id.h"
      30             : #include "locking/proto.h"
      31             : #include "smbd/globals.h"
      32             : #include "dbwrap/dbwrap.h"
      33             : #include "dbwrap/dbwrap_open.h"
      34             : #include "serverid.h"
      35             : #include "messages.h"
      36             : #include "util_tdb.h"
      37             : 
      38             : #undef DBGC_CLASS
      39             : #define DBGC_CLASS DBGC_LOCKING
      40             : 
      41             : /* The open brlock.tdb database. */
      42             : 
      43             : static struct db_context *brlock_db;
      44             : 
      45             : struct byte_range_lock {
      46             :         struct files_struct *fsp;
      47             :         TALLOC_CTX *req_mem_ctx;
      48             :         const struct GUID *req_guid;
      49             :         unsigned int num_locks;
      50             :         bool modified;
      51             :         struct lock_struct *lock_data;
      52             :         struct db_record *record;
      53             : };
      54             : 
      55             : /****************************************************************************
      56             :  Debug info at level 10 for lock struct.
      57             : ****************************************************************************/
      58             : 
      59           0 : static void print_lock_struct(unsigned int i, const struct lock_struct *pls)
      60             : {
      61           0 :         struct server_id_buf tmp;
      62             : 
      63           0 :         DBG_DEBUG("[%u]: smblctx = %"PRIu64", tid = %"PRIu32", pid = %s, "
      64             :                   "start = %"PRIu64", size = %"PRIu64", fnum = %"PRIu64", "
      65             :                   "%s %s\n",
      66             :                   i,
      67             :                   pls->context.smblctx,
      68             :                   pls->context.tid,
      69             :                   server_id_str_buf(pls->context.pid, &tmp),
      70             :                   pls->start,
      71             :                   pls->size,
      72             :                   pls->fnum,
      73             :                   lock_type_name(pls->lock_type),
      74             :                   lock_flav_name(pls->lock_flav));
      75           0 : }
      76             : 
      77      350299 : unsigned int brl_num_locks(const struct byte_range_lock *brl)
      78             : {
      79      350299 :         return brl->num_locks;
      80             : }
      81             : 
      82        8462 : struct files_struct *brl_fsp(struct byte_range_lock *brl)
      83             : {
      84        8462 :         return brl->fsp;
      85             : }
      86             : 
      87          60 : TALLOC_CTX *brl_req_mem_ctx(const struct byte_range_lock *brl)
      88             : {
      89          60 :         if (brl->req_mem_ctx == NULL) {
      90           0 :                 return talloc_get_type_abort(brl, struct byte_range_lock);
      91             :         }
      92             : 
      93          60 :         return brl->req_mem_ctx;
      94             : }
      95             : 
      96          60 : const struct GUID *brl_req_guid(const struct byte_range_lock *brl)
      97             : {
      98          60 :         if (brl->req_guid == NULL) {
      99           0 :                 static const struct GUID brl_zero_req_guid;
     100           0 :                 return &brl_zero_req_guid;
     101             :         }
     102             : 
     103          60 :         return brl->req_guid;
     104             : }
     105             : 
     106             : /****************************************************************************
     107             :  See if two locking contexts are equal.
     108             : ****************************************************************************/
     109             : 
     110        6844 : static bool brl_same_context(const struct lock_context *ctx1,
     111             :                              const struct lock_context *ctx2)
     112             : {
     113        6844 :         return (server_id_equal(&ctx1->pid, &ctx2->pid) &&
     114       12075 :                 (ctx1->smblctx == ctx2->smblctx) &&
     115        5256 :                 (ctx1->tid == ctx2->tid));
     116             : }
     117             : 
     118      547409 : bool byte_range_valid(uint64_t ofs, uint64_t len)
     119             : {
     120      547409 :         uint64_t max_len = UINT64_MAX - ofs;
     121          98 :         uint64_t effective_len;
     122             : 
     123             :         /*
     124             :          * [MS-FSA] specifies this:
     125             :          *
     126             :          * If (((FileOffset + Length - 1) < FileOffset) && Length != 0) {
     127             :          *   return STATUS_INVALID_LOCK_RANGE
     128             :          * }
     129             :          *
     130             :          * We avoid integer wrapping and calculate
     131             :          * max and effective len instead.
     132             :          */
     133             : 
     134      547409 :         if (len == 0) {
     135         790 :                 return true;
     136             :         }
     137             : 
     138      546615 :         effective_len = len - 1;
     139      546615 :         if (effective_len <= max_len) {
     140      546601 :                 return true;
     141             :         }
     142             : 
     143          14 :         return false;
     144             : }
     145             : 
     146      270826 : bool byte_range_overlap(uint64_t ofs1,
     147             :                         uint64_t len1,
     148             :                         uint64_t ofs2,
     149             :                         uint64_t len2)
     150             : {
     151          36 :         uint64_t last1;
     152          36 :         uint64_t last2;
     153          36 :         bool valid;
     154             : 
     155             :         /*
     156             :          * This is based on [MS-FSA] 2.1.4.10
     157             :          * Algorithm for Determining If a Range Access
     158             :          * Conflicts with Byte-Range Locks
     159             :          */
     160             : 
     161             :         /*
     162             :          * The {0, 0} range doesn't conflict with any byte-range lock
     163             :          */
     164      270826 :         if (ofs1 == 0 && len1 == 0) {
     165          98 :                 return false;
     166             :         }
     167      270728 :         if (ofs2 == 0 && len2 == 0) {
     168           0 :                 return false;
     169             :         }
     170             : 
     171             :         /*
     172             :          * The caller should have checked that the ranges are
     173             :          * valid. But currently we gracefully handle
     174             :          * the overflow of a read/write check.
     175             :          */
     176      270728 :         valid = byte_range_valid(ofs1, len1);
     177      270728 :         if (valid) {
     178      270728 :                 last1 = ofs1 + len1 - 1;
     179             :         } else {
     180           0 :                 last1 = UINT64_MAX;
     181             :         }
     182      270728 :         valid = byte_range_valid(ofs2, len2);
     183      270728 :         if (valid) {
     184      270728 :                 last2 = ofs2 + len2 - 1;
     185             :         } else {
     186           0 :                 last2 = UINT64_MAX;
     187             :         }
     188             : 
     189             :         /*
     190             :          * If one range starts after the last
     191             :          * byte of the other range there's
     192             :          * no conflict.
     193             :          */
     194      270728 :         if (ofs1 > last2) {
     195        1872 :                 return false;
     196             :         }
     197      268848 :         if (ofs2 > last1) {
     198      265446 :                 return false;
     199             :         }
     200             : 
     201        3382 :         return true;
     202             : }
     203             : 
     204             : /****************************************************************************
     205             :  See if lck1 and lck2 overlap.
     206             : ****************************************************************************/
     207             : 
     208      270652 : static bool brl_overlap(const struct lock_struct *lck1,
     209             :                         const struct lock_struct *lck2)
     210             : {
     211      541268 :         return byte_range_overlap(lck1->start,
     212      270652 :                                   lck1->size,
     213      270652 :                                   lck2->start,
     214      270652 :                                   lck2->size);
     215             : }
     216             : 
     217             : /****************************************************************************
     218             :  See if lock2 can be added when lock1 is in place.
     219             : ****************************************************************************/
     220             : 
     221      270407 : static bool brl_conflict(const struct lock_struct *lck1,
     222             :                          const struct lock_struct *lck2)
     223             : {
     224             :         /* Read locks never conflict. */
     225      270407 :         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
     226        1138 :                 return False;
     227             :         }
     228             : 
     229             :         /* A READ lock can stack on top of a WRITE lock if they have the same
     230             :          * context & fnum. */
     231      270009 :         if (lck1->lock_type == WRITE_LOCK && lck2->lock_type == READ_LOCK &&
     232         740 :             brl_same_context(&lck1->context, &lck2->context) &&
     233         322 :             lck1->fnum == lck2->fnum) {
     234         298 :                 return False;
     235             :         }
     236             : 
     237      268971 :         return brl_overlap(lck1, lck2);
     238             : }
     239             : 
     240             : /****************************************************************************
     241             :  See if lock2 can be added when lock1 is in place - when both locks are POSIX
     242             :  flavour. POSIX locks ignore fnum - they only care about dev/ino which we
     243             :  know already match.
     244             : ****************************************************************************/
     245             : 
     246         480 : static bool brl_conflict_posix(const struct lock_struct *lck1,
     247             :                                 const struct lock_struct *lck2)
     248             : {
     249             : #if defined(DEVELOPER)
     250         480 :         SMB_ASSERT(lck1->lock_flav == POSIX_LOCK);
     251         480 :         SMB_ASSERT(lck2->lock_flav == POSIX_LOCK);
     252             : #endif
     253             : 
     254             :         /* Read locks never conflict. */
     255         480 :         if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
     256         464 :                 return False;
     257             :         }
     258             : 
     259             :         /* Locks on the same context don't conflict. Ignore fnum. */
     260          16 :         if (brl_same_context(&lck1->context, &lck2->context)) {
     261           4 :                 return False;
     262             :         }
     263             : 
     264             :         /* One is read, the other write, or the context is different,
     265             :            do they overlap ? */
     266          12 :         return brl_overlap(lck1, lck2);
     267             : }
     268             : 
     269             : /****************************************************************************
     270             :  Check to see if this lock conflicts, but ignore our own locks on the
     271             :  same fnum only. This is the read/write lock check code path.
     272             :  This is never used in the POSIX lock case.
     273             : ****************************************************************************/
     274             : 
     275        2175 : static bool brl_conflict_other(const struct lock_struct *lock,
     276             :                                const struct lock_struct *rw_probe)
     277             : {
     278        2175 :         if (lock->lock_type == READ_LOCK && rw_probe->lock_type == READ_LOCK) {
     279         506 :                 return False;
     280             :         }
     281             : 
     282        1669 :         if (lock->lock_flav == POSIX_LOCK &&
     283           8 :             rw_probe->lock_flav == POSIX_LOCK) {
     284             :                 /*
     285             :                  * POSIX flavour locks never conflict here - this is only called
     286             :                  * in the read/write path.
     287             :                  */
     288           0 :                 return False;
     289             :         }
     290             : 
     291        1669 :         if (!brl_overlap(lock, rw_probe)) {
     292             :                 /*
     293             :                  * I/O can only conflict when overlapping a lock, thus let it
     294             :                  * pass
     295             :                  */
     296        1342 :                 return false;
     297             :         }
     298             : 
     299         318 :         if (!brl_same_context(&lock->context, &rw_probe->context)) {
     300             :                 /*
     301             :                  * Different process, conflict
     302             :                  */
     303         224 :                 return true;
     304             :         }
     305             : 
     306          88 :         if (lock->fnum != rw_probe->fnum) {
     307             :                 /*
     308             :                  * Different file handle, conflict
     309             :                  */
     310           0 :                 return true;
     311             :         }
     312             : 
     313          88 :         if ((lock->lock_type == READ_LOCK) &&
     314          28 :             (rw_probe->lock_type == WRITE_LOCK)) {
     315             :                 /*
     316             :                  * Incoming WRITE locks conflict with existing READ locks even
     317             :                  * if the context is the same. JRA. See LOCKTEST7 in
     318             :                  * smbtorture.
     319             :                  */
     320          28 :                 return true;
     321             :         }
     322             : 
     323             :         /*
     324             :          * I/O request compatible with existing lock, let it pass without
     325             :          * conflict
     326             :          */
     327             : 
     328          54 :         return false;
     329             : }
     330             : 
     331             : /****************************************************************************
     332             :  Open up the brlock.tdb database.
     333             : ****************************************************************************/
     334             : 
     335         198 : void brl_init(bool read_only)
     336             : {
     337           0 :         int tdb_flags;
     338           0 :         char *db_path;
     339             : 
     340         198 :         if (brlock_db) {
     341           0 :                 return;
     342             :         }
     343             : 
     344         198 :         tdb_flags = SMBD_VOLATILE_TDB_FLAGS | TDB_SEQNUM;
     345             : 
     346         198 :         db_path = lock_path(talloc_tos(), "brlock.tdb");
     347         198 :         if (db_path == NULL) {
     348           0 :                 DEBUG(0, ("out of memory!\n"));
     349           0 :                 return;
     350             :         }
     351             : 
     352         198 :         brlock_db = db_open(NULL, db_path,
     353             :                             SMBD_VOLATILE_TDB_HASH_SIZE, tdb_flags,
     354             :                             read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644,
     355             :                             DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
     356         198 :         if (!brlock_db) {
     357           0 :                 DEBUG(0,("Failed to open byte range locking database %s\n",
     358             :                          db_path));
     359           0 :                 TALLOC_FREE(db_path);
     360           0 :                 return;
     361             :         }
     362         198 :         TALLOC_FREE(db_path);
     363             : }
     364             : 
     365             : /****************************************************************************
     366             :  Close down the brlock.tdb database.
     367             : ****************************************************************************/
     368             : 
     369       31929 : void brl_shutdown(void)
     370             : {
     371       31929 :         TALLOC_FREE(brlock_db);
     372       31929 : }
     373             : 
     374             : /****************************************************************************
     375             :  Lock a range of bytes - Windows lock semantics.
     376             : ****************************************************************************/
     377             : 
     378        5807 : NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
     379             :                                   struct lock_struct *plock)
     380             : {
     381          26 :         unsigned int i;
     382        5807 :         files_struct *fsp = br_lck->fsp;
     383        5807 :         struct lock_struct *locks = br_lck->lock_data;
     384          26 :         NTSTATUS status;
     385          26 :         bool valid;
     386             : 
     387        5807 :         SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
     388             : 
     389        5807 :         valid = byte_range_valid(plock->start, plock->size);
     390        5807 :         if (!valid) {
     391          14 :                 return NT_STATUS_INVALID_LOCK_RANGE;
     392             :         }
     393             : 
     394      273206 :         for (i=0; i < br_lck->num_locks; i++) {
     395             :                 /* Do any Windows or POSIX locks conflict ? */
     396      270403 :                 if (brl_conflict(&locks[i], plock)) {
     397        2990 :                         if (!serverid_exists(&locks[i].context.pid)) {
     398           0 :                                 locks[i].context.pid.pid = 0;
     399           0 :                                 br_lck->modified = true;
     400           0 :                                 continue;
     401             :                         }
     402             :                         /* Remember who blocked us. */
     403        2990 :                         plock->context.smblctx = locks[i].context.smblctx;
     404        2990 :                         return NT_STATUS_LOCK_NOT_GRANTED;
     405             :                 }
     406             :         }
     407             : 
     408        2803 :         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
     409             : 
     410             :         /* We can get the Windows lock, now see if it needs to
     411             :            be mapped into a lower level POSIX one, and if so can
     412             :            we get it ? */
     413             : 
     414        2803 :         if (lp_posix_locking(fsp->conn->params)) {
     415          18 :                 int errno_ret;
     416        2455 :                 if (!set_posix_lock_windows_flavour(fsp,
     417             :                                 plock->start,
     418             :                                 plock->size,
     419             :                                 plock->lock_type,
     420        2455 :                                 &plock->context,
     421             :                                 locks,
     422        2455 :                                 br_lck->num_locks,
     423             :                                 &errno_ret)) {
     424             : 
     425             :                         /* We don't know who blocked us. */
     426         110 :                         plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
     427             : 
     428         110 :                         if (errno_ret == EACCES || errno_ret == EAGAIN) {
     429         110 :                                 status = NT_STATUS_LOCK_NOT_GRANTED;
     430         110 :                                 goto fail;
     431             :                         } else {
     432           0 :                                 status = map_nt_error_from_unix(errno);
     433           0 :                                 goto fail;
     434             :                         }
     435             :                 }
     436             :         }
     437             : 
     438             :         /* no conflicts - add it to the list of locks */
     439        2693 :         locks = talloc_realloc(br_lck, locks, struct lock_struct,
     440             :                                (br_lck->num_locks + 1));
     441        2693 :         if (!locks) {
     442           0 :                 status = NT_STATUS_NO_MEMORY;
     443           0 :                 goto fail;
     444             :         }
     445             : 
     446        2693 :         memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct));
     447        2693 :         br_lck->num_locks += 1;
     448        2693 :         br_lck->lock_data = locks;
     449        2693 :         br_lck->modified = True;
     450             : 
     451        2693 :         return NT_STATUS_OK;
     452         110 :  fail:
     453         110 :         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WINDOWS_BRL);
     454         110 :         return status;
     455             : }
     456             : 
     457             : /****************************************************************************
     458             :  Cope with POSIX range splits and merges.
     459             : ****************************************************************************/
     460             : 
     461         958 : static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,       /* Output array. */
     462             :                                                 struct lock_struct *ex,         /* existing lock. */
     463             :                                                 struct lock_struct *plock)      /* proposed lock. */
     464             : {
     465         958 :         bool lock_types_differ = (ex->lock_type != plock->lock_type);
     466             : 
     467             :         /* We can't merge non-conflicting locks on different context - ignore fnum. */
     468             : 
     469         958 :         if (!brl_same_context(&ex->context, &plock->context)) {
     470             :                 /* Just copy. */
     471          22 :                 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     472          22 :                 return 1;
     473             :         }
     474             : 
     475             :         /* We now know we have the same context. */
     476             : 
     477             :         /* Did we overlap ? */
     478             : 
     479             : /*********************************************
     480             :                                         +---------+
     481             :                                         | ex      |
     482             :                                         +---------+
     483             :                          +-------+
     484             :                          | plock |
     485             :                          +-------+
     486             : OR....
     487             :         +---------+
     488             :         |  ex     |
     489             :         +---------+
     490             : **********************************************/
     491             : 
     492         936 :         if ( (ex->start > (plock->start + plock->size)) ||
     493         924 :                 (plock->start > (ex->start + ex->size))) {
     494             : 
     495             :                 /* No overlap with this lock - copy existing. */
     496             : 
     497          20 :                 memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     498          20 :                 return 1;
     499             :         }
     500             : 
     501             : /*********************************************
     502             :         +---------------------------+
     503             :         |          ex               |
     504             :         +---------------------------+
     505             :         +---------------------------+
     506             :         |       plock               | -> replace with plock.
     507             :         +---------------------------+
     508             : OR
     509             :              +---------------+
     510             :              |       ex      |
     511             :              +---------------+
     512             :         +---------------------------+
     513             :         |       plock               | -> replace with plock.
     514             :         +---------------------------+
     515             : 
     516             : **********************************************/
     517             : 
     518         916 :         if ( (ex->start >= plock->start) &&
     519         912 :                 (ex->start + ex->size <= plock->start + plock->size) ) {
     520             : 
     521             :                 /* Replace - discard existing lock. */
     522             : 
     523         472 :                 return 0;
     524             :         }
     525             : 
     526             : /*********************************************
     527             : Adjacent after.
     528             :                         +-------+
     529             :                         |  ex   |
     530             :                         +-------+
     531             :         +---------------+
     532             :         |   plock       |
     533             :         +---------------+
     534             : 
     535             : BECOMES....
     536             :         +---------------+-------+
     537             :         |   plock       | ex    | - different lock types.
     538             :         +---------------+-------+
     539             : OR.... (merge)
     540             :         +-----------------------+
     541             :         |   plock               | - same lock type.
     542             :         +-----------------------+
     543             : **********************************************/
     544             : 
     545         444 :         if (plock->start + plock->size == ex->start) {
     546             : 
     547             :                 /* If the lock types are the same, we merge, if different, we
     548             :                    add the remainder of the old lock. */
     549             : 
     550         440 :                 if (lock_types_differ) {
     551             :                         /* Add existing. */
     552           0 :                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     553           0 :                         return 1;
     554             :                 } else {
     555             :                         /* Merge - adjust incoming lock as we may have more
     556             :                          * merging to come. */
     557         440 :                         plock->size += ex->size;
     558         440 :                         return 0;
     559             :                 }
     560             :         }
     561             : 
     562             : /*********************************************
     563             : Adjacent before.
     564             :         +-------+
     565             :         |  ex   |
     566             :         +-------+
     567             :                 +---------------+
     568             :                 |   plock       |
     569             :                 +---------------+
     570             : BECOMES....
     571             :         +-------+---------------+
     572             :         | ex    |   plock       | - different lock types
     573             :         +-------+---------------+
     574             : 
     575             : OR.... (merge)
     576             :         +-----------------------+
     577             :         |      plock            | - same lock type.
     578             :         +-----------------------+
     579             : 
     580             : **********************************************/
     581             : 
     582           4 :         if (ex->start + ex->size == plock->start) {
     583             : 
     584             :                 /* If the lock types are the same, we merge, if different, we
     585             :                    add the existing lock. */
     586             : 
     587           0 :                 if (lock_types_differ) {
     588           0 :                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     589           0 :                         return 1;
     590             :                 } else {
     591             :                         /* Merge - adjust incoming lock as we may have more
     592             :                          * merging to come. */
     593           0 :                         plock->start = ex->start;
     594           0 :                         plock->size += ex->size;
     595           0 :                         return 0;
     596             :                 }
     597             :         }
     598             : 
     599             : /*********************************************
     600             : Overlap after.
     601             :         +-----------------------+
     602             :         |          ex           |
     603             :         +-----------------------+
     604             :         +---------------+
     605             :         |   plock       |
     606             :         +---------------+
     607             : OR
     608             :                +----------------+
     609             :                |       ex       |
     610             :                +----------------+
     611             :         +---------------+
     612             :         |   plock       |
     613             :         +---------------+
     614             : 
     615             : BECOMES....
     616             :         +---------------+-------+
     617             :         |   plock       | ex    | - different lock types.
     618             :         +---------------+-------+
     619             : OR.... (merge)
     620             :         +-----------------------+
     621             :         |   plock               | - same lock type.
     622             :         +-----------------------+
     623             : **********************************************/
     624             : 
     625           4 :         if ( (ex->start >= plock->start) &&
     626           0 :                 (ex->start <= plock->start + plock->size) &&
     627           0 :                 (ex->start + ex->size > plock->start + plock->size) ) {
     628             : 
     629             :                 /* If the lock types are the same, we merge, if different, we
     630             :                    add the remainder of the old lock. */
     631             : 
     632           0 :                 if (lock_types_differ) {
     633             :                         /* Add remaining existing. */
     634           0 :                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     635             :                         /* Adjust existing start and size. */
     636           0 :                         lck_arr[0].start = plock->start + plock->size;
     637           0 :                         lck_arr[0].size = (ex->start + ex->size) - (plock->start + plock->size);
     638           0 :                         return 1;
     639             :                 } else {
     640             :                         /* Merge - adjust incoming lock as we may have more
     641             :                          * merging to come. */
     642           0 :                         plock->size += (ex->start + ex->size) - (plock->start + plock->size);
     643           0 :                         return 0;
     644             :                 }
     645             :         }
     646             : 
     647             : /*********************************************
     648             : Overlap before.
     649             :         +-----------------------+
     650             :         |  ex                   |
     651             :         +-----------------------+
     652             :                 +---------------+
     653             :                 |   plock       |
     654             :                 +---------------+
     655             : OR
     656             :         +-------------+
     657             :         |  ex         |
     658             :         +-------------+
     659             :                 +---------------+
     660             :                 |   plock       |
     661             :                 +---------------+
     662             : 
     663             : BECOMES....
     664             :         +-------+---------------+
     665             :         | ex    |   plock       | - different lock types
     666             :         +-------+---------------+
     667             : 
     668             : OR.... (merge)
     669             :         +-----------------------+
     670             :         |      plock            | - same lock type.
     671             :         +-----------------------+
     672             : 
     673             : **********************************************/
     674             : 
     675           4 :         if ( (ex->start < plock->start) &&
     676           4 :                         (ex->start + ex->size >= plock->start) &&
     677           4 :                         (ex->start + ex->size <= plock->start + plock->size) ) {
     678             : 
     679             :                 /* If the lock types are the same, we merge, if different, we
     680             :                    add the truncated old lock. */
     681             : 
     682           0 :                 if (lock_types_differ) {
     683           0 :                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     684             :                         /* Adjust existing size. */
     685           0 :                         lck_arr[0].size = plock->start - ex->start;
     686           0 :                         return 1;
     687             :                 } else {
     688             :                         /* Merge - adjust incoming lock as we may have more
     689             :                          * merging to come. MUST ADJUST plock SIZE FIRST ! */
     690           0 :                         plock->size += (plock->start - ex->start);
     691           0 :                         plock->start = ex->start;
     692           0 :                         return 0;
     693             :                 }
     694             :         }
     695             : 
     696             : /*********************************************
     697             : Complete overlap.
     698             :         +---------------------------+
     699             :         |        ex                 |
     700             :         +---------------------------+
     701             :                 +---------+
     702             :                 |  plock  |
     703             :                 +---------+
     704             : BECOMES.....
     705             :         +-------+---------+---------+
     706             :         | ex    |  plock  | ex      | - different lock types.
     707             :         +-------+---------+---------+
     708             : OR
     709             :         +---------------------------+
     710             :         |        plock              | - same lock type.
     711             :         +---------------------------+
     712             : **********************************************/
     713             : 
     714           4 :         if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) {
     715             : 
     716           4 :                 if (lock_types_differ) {
     717             : 
     718             :                         /* We have to split ex into two locks here. */
     719             : 
     720           4 :                         memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
     721           4 :                         memcpy(&lck_arr[1], ex, sizeof(struct lock_struct));
     722             : 
     723             :                         /* Adjust first existing size. */
     724           4 :                         lck_arr[0].size = plock->start - ex->start;
     725             : 
     726             :                         /* Adjust second existing start and size. */
     727           4 :                         lck_arr[1].start = plock->start + plock->size;
     728           4 :                         lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size);
     729           4 :                         return 2;
     730             :                 } else {
     731             :                         /* Just eat the existing locks, merge them into plock. */
     732           0 :                         plock->start = ex->start;
     733           0 :                         plock->size = ex->size;
     734           0 :                         return 0;
     735             :                 }
     736             :         }
     737             : 
     738             :         /* Never get here. */
     739           0 :         smb_panic("brlock_posix_split_merge");
     740             :         /* Notreached. */
     741             : 
     742             :         /* Keep some compilers happy. */
     743             :         return 0;
     744             : }
     745             : 
     746             : /****************************************************************************
     747             :  Lock a range of bytes - POSIX lock semantics.
     748             :  We must cope with range splits and merges.
     749             : ****************************************************************************/
     750             : 
     751         916 : static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
     752             :                                struct lock_struct *plock)
     753             : {
     754           0 :         unsigned int i, count, posix_count;
     755         916 :         struct lock_struct *locks = br_lck->lock_data;
     756           0 :         struct lock_struct *tp;
     757         916 :         bool break_oplocks = false;
     758           0 :         NTSTATUS status;
     759             : 
     760             :         /* No zero-zero locks for POSIX. */
     761         916 :         if (plock->start == 0 && plock->size == 0) {
     762           0 :                 return NT_STATUS_INVALID_PARAMETER;
     763             :         }
     764             : 
     765             :         /* Don't allow 64-bit lock wrap. */
     766         916 :         if (plock->start + plock->size - 1 < plock->start) {
     767           0 :                 return NT_STATUS_INVALID_PARAMETER;
     768             :         }
     769             : 
     770             :         /* The worst case scenario here is we have to split an
     771             :            existing POSIX lock range into two, and add our lock,
     772             :            so we need at most 2 more entries. */
     773             : 
     774         916 :         tp = talloc_array(br_lck, struct lock_struct, br_lck->num_locks + 2);
     775         916 :         if (!tp) {
     776           0 :                 return NT_STATUS_NO_MEMORY;
     777             :         }
     778             : 
     779         916 :         count = posix_count = 0;
     780             : 
     781        1388 :         for (i=0; i < br_lck->num_locks; i++) {
     782         480 :                 struct lock_struct *curr_lock = &locks[i];
     783             : 
     784         480 :                 if (curr_lock->lock_flav == WINDOWS_LOCK) {
     785             :                         /* Do any Windows flavour locks conflict ? */
     786           0 :                         if (brl_conflict(curr_lock, plock)) {
     787           0 :                                 if (!serverid_exists(&curr_lock->context.pid)) {
     788           0 :                                         curr_lock->context.pid.pid = 0;
     789           0 :                                         br_lck->modified = true;
     790           0 :                                         continue;
     791             :                                 }
     792             :                                 /* No games with error messages. */
     793           0 :                                 TALLOC_FREE(tp);
     794             :                                 /* Remember who blocked us. */
     795           0 :                                 plock->context.smblctx = curr_lock->context.smblctx;
     796           0 :                                 return NT_STATUS_LOCK_NOT_GRANTED;
     797             :                         }
     798             :                         /* Just copy the Windows lock into the new array. */
     799           0 :                         memcpy(&tp[count], curr_lock, sizeof(struct lock_struct));
     800           0 :                         count++;
     801             :                 } else {
     802         480 :                         unsigned int tmp_count = 0;
     803             : 
     804             :                         /* POSIX conflict semantics are different. */
     805         480 :                         if (brl_conflict_posix(curr_lock, plock)) {
     806           8 :                                 if (!serverid_exists(&curr_lock->context.pid)) {
     807           0 :                                         curr_lock->context.pid.pid = 0;
     808           0 :                                         br_lck->modified = true;
     809           0 :                                         continue;
     810             :                                 }
     811             :                                 /* Can't block ourselves with POSIX locks. */
     812             :                                 /* No games with error messages. */
     813           8 :                                 TALLOC_FREE(tp);
     814             :                                 /* Remember who blocked us. */
     815           8 :                                 plock->context.smblctx = curr_lock->context.smblctx;
     816           8 :                                 return NT_STATUS_LOCK_NOT_GRANTED;
     817             :                         }
     818             : 
     819             :                         /* Work out overlaps. */
     820         472 :                         tmp_count += brlock_posix_split_merge(&tp[count], curr_lock, plock);
     821         472 :                         posix_count += tmp_count;
     822         472 :                         count += tmp_count;
     823             :                 }
     824             :         }
     825             : 
     826             :         /*
     827             :          * Break oplocks while we hold a brl. Since lock() and unlock() calls
     828             :          * are not symmetric with POSIX semantics, we cannot guarantee our
     829             :          * contend_level2_oplocks_begin/end calls will be acquired and
     830             :          * released one-for-one as with Windows semantics. Therefore we only
     831             :          * call contend_level2_oplocks_begin if this is the first POSIX brl on
     832             :          * the file.
     833             :          */
     834         908 :         break_oplocks = (posix_count == 0);
     835         908 :         if (break_oplocks) {
     836         876 :                 contend_level2_oplocks_begin(br_lck->fsp,
     837             :                                              LEVEL2_CONTEND_POSIX_BRL);
     838             :         }
     839             : 
     840             :         /* Try and add the lock in order, sorted by lock start. */
     841         940 :         for (i=0; i < count; i++) {
     842          32 :                 struct lock_struct *curr_lock = &tp[i];
     843             : 
     844          32 :                 if (curr_lock->start <= plock->start) {
     845          26 :                         continue;
     846             :                 }
     847             :         }
     848             : 
     849         908 :         if (i < count) {
     850           0 :                 memmove(&tp[i+1], &tp[i],
     851           0 :                         (count - i)*sizeof(struct lock_struct));
     852             :         }
     853         908 :         memcpy(&tp[i], plock, sizeof(struct lock_struct));
     854         908 :         count++;
     855             : 
     856             :         /* We can get the POSIX lock, now see if it needs to
     857             :            be mapped into a lower level POSIX one, and if so can
     858             :            we get it ? */
     859             : 
     860         908 :         if (lp_posix_locking(br_lck->fsp->conn->params)) {
     861           0 :                 int errno_ret;
     862             : 
     863             :                 /* The lower layer just needs to attempt to
     864             :                    get the system POSIX lock. We've weeded out
     865             :                    any conflicts above. */
     866             : 
     867         908 :                 if (!set_posix_lock_posix_flavour(br_lck->fsp,
     868             :                                 plock->start,
     869             :                                 plock->size,
     870             :                                 plock->lock_type,
     871         908 :                                 &plock->context,
     872             :                                 &errno_ret)) {
     873             : 
     874             :                         /* We don't know who blocked us. */
     875           0 :                         plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
     876             : 
     877           0 :                         if (errno_ret == EACCES || errno_ret == EAGAIN) {
     878           0 :                                 TALLOC_FREE(tp);
     879           0 :                                 status = NT_STATUS_LOCK_NOT_GRANTED;
     880           0 :                                 goto fail;
     881             :                         } else {
     882           0 :                                 TALLOC_FREE(tp);
     883           0 :                                 status = map_nt_error_from_unix(errno);
     884           0 :                                 goto fail;
     885             :                         }
     886             :                 }
     887             :         }
     888             : 
     889             :         /* If we didn't use all the allocated size,
     890             :          * Realloc so we don't leak entries per lock call. */
     891         908 :         if (count < br_lck->num_locks + 2) {
     892         908 :                 tp = talloc_realloc(br_lck, tp, struct lock_struct, count);
     893         908 :                 if (!tp) {
     894           0 :                         status = NT_STATUS_NO_MEMORY;
     895           0 :                         goto fail;
     896             :                 }
     897             :         }
     898             : 
     899         908 :         br_lck->num_locks = count;
     900         908 :         TALLOC_FREE(br_lck->lock_data);
     901         908 :         br_lck->lock_data = tp;
     902         908 :         locks = tp;
     903         908 :         br_lck->modified = True;
     904             : 
     905             :         /* A successful downgrade from write to read lock can trigger a lock
     906             :            re-evalutation where waiting readers can now proceed. */
     907             : 
     908         908 :         return NT_STATUS_OK;
     909           0 :  fail:
     910           0 :         if (break_oplocks) {
     911           0 :                 contend_level2_oplocks_end(br_lck->fsp,
     912             :                                            LEVEL2_CONTEND_POSIX_BRL);
     913             :         }
     914           0 :         return status;
     915             : }
     916             : 
     917             : /****************************************************************************
     918             :  Lock a range of bytes.
     919             : ****************************************************************************/
     920             : 
     921        6753 : NTSTATUS brl_lock(
     922             :         struct byte_range_lock *br_lck,
     923             :         uint64_t smblctx,
     924             :         struct server_id pid,
     925             :         br_off start,
     926             :         br_off size,
     927             :         enum brl_type lock_type,
     928             :         enum brl_flavour lock_flav,
     929             :         struct server_id *blocker_pid,
     930             :         uint64_t *psmblctx)
     931             : {
     932          26 :         NTSTATUS ret;
     933          26 :         struct lock_struct lock;
     934             : 
     935        6753 :         ZERO_STRUCT(lock);
     936             : 
     937        6753 :         lock = (struct lock_struct) {
     938             :                 .context.smblctx = smblctx,
     939             :                 .context.pid = pid,
     940        6753 :                 .context.tid = br_lck->fsp->conn->cnum,
     941             :                 .start = start,
     942             :                 .size = size,
     943        6753 :                 .fnum = br_lck->fsp->fnum,
     944             :                 .lock_type = lock_type,
     945             :                 .lock_flav = lock_flav
     946             :         };
     947             : 
     948        6753 :         if (lock_flav == WINDOWS_LOCK) {
     949        5837 :                 ret = SMB_VFS_BRL_LOCK_WINDOWS(
     950             :                         br_lck->fsp->conn, br_lck, &lock);
     951             :         } else {
     952         916 :                 ret = brl_lock_posix(br_lck, &lock);
     953             :         }
     954             : 
     955             :         /* If we're returning an error, return who blocked us. */
     956        6753 :         if (!NT_STATUS_IS_OK(ret) && psmblctx) {
     957        3152 :                 *blocker_pid = lock.context.pid;
     958        3152 :                 *psmblctx = lock.context.smblctx;
     959             :         }
     960        6753 :         return ret;
     961             : }
     962             : 
     963             : /****************************************************************************
     964             :  Unlock a range of bytes - Windows semantics.
     965             : ****************************************************************************/
     966             : 
     967        2889 : bool brl_unlock_windows_default(struct byte_range_lock *br_lck,
     968             :                                 const struct lock_struct *plock)
     969             : {
     970          22 :         unsigned int i;
     971        2889 :         struct lock_struct *locks = br_lck->lock_data;
     972        2889 :         enum brl_type deleted_lock_type = READ_LOCK; /* shut the compiler up.... */
     973             : 
     974        2889 :         SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
     975             : 
     976             : 
     977        4512 :         for (i = 0; i < br_lck->num_locks; i++) {
     978        4308 :                 struct lock_struct *lock = &locks[i];
     979             : 
     980             :                 /* Only remove our own locks that match in start, size, and flavour. */
     981        4308 :                 if (brl_same_context(&lock->context, &plock->context) &&
     982        3416 :                                         lock->fnum == plock->fnum &&
     983        3360 :                                         lock->lock_flav == WINDOWS_LOCK &&
     984        3360 :                                         lock->start == plock->start &&
     985        2711 :                                         lock->size == plock->size ) {
     986        2685 :                         deleted_lock_type = lock->lock_type;
     987        2685 :                         break;
     988             :                 }
     989             :         }
     990             : 
     991        2889 :         if (i == br_lck->num_locks) {
     992             :                 /* we didn't find it */
     993         200 :                 return False;
     994             :         }
     995             : 
     996        2685 :         ARRAY_DEL_ELEMENT(locks, i, br_lck->num_locks);
     997        2685 :         br_lck->num_locks -= 1;
     998        2685 :         br_lck->modified = True;
     999             : 
    1000             :         /* Unlock the underlying POSIX regions. */
    1001        2685 :         if(lp_posix_locking(br_lck->fsp->conn->params)) {
    1002        2337 :                 release_posix_lock_windows_flavour(br_lck->fsp,
    1003        2337 :                                 plock->start,
    1004        2337 :                                 plock->size,
    1005             :                                 deleted_lock_type,
    1006             :                                 &plock->context,
    1007             :                                 locks,
    1008        2337 :                                 br_lck->num_locks);
    1009             :         }
    1010             : 
    1011        2685 :         contend_level2_oplocks_end(br_lck->fsp, LEVEL2_CONTEND_WINDOWS_BRL);
    1012        2685 :         return True;
    1013             : }
    1014             : 
    1015             : /****************************************************************************
    1016             :  Unlock a range of bytes - POSIX semantics.
    1017             : ****************************************************************************/
    1018             : 
    1019         476 : static bool brl_unlock_posix(struct byte_range_lock *br_lck,
    1020             :                              struct lock_struct *plock)
    1021             : {
    1022           0 :         unsigned int i, count;
    1023           0 :         struct lock_struct *tp;
    1024         476 :         struct lock_struct *locks = br_lck->lock_data;
    1025         476 :         bool overlap_found = False;
    1026             : 
    1027             :         /* No zero-zero locks for POSIX. */
    1028         476 :         if (plock->start == 0 && plock->size == 0) {
    1029           0 :                 return False;
    1030             :         }
    1031             : 
    1032             :         /* Don't allow 64-bit lock wrap. */
    1033         476 :         if (plock->start + plock->size < plock->start ||
    1034         476 :                         plock->start + plock->size < plock->size) {
    1035           0 :                 DEBUG(10,("brl_unlock_posix: lock wrap\n"));
    1036           0 :                 return False;
    1037             :         }
    1038             : 
    1039             :         /* The worst case scenario here is we have to split an
    1040             :            existing POSIX lock range into two, so we need at most
    1041             :            1 more entry. */
    1042             : 
    1043         476 :         tp = talloc_array(br_lck, struct lock_struct, br_lck->num_locks + 1);
    1044         476 :         if (!tp) {
    1045           0 :                 DEBUG(10,("brl_unlock_posix: malloc fail\n"));
    1046           0 :                 return False;
    1047             :         }
    1048             : 
    1049         476 :         count = 0;
    1050         976 :         for (i = 0; i < br_lck->num_locks; i++) {
    1051         504 :                 struct lock_struct *lock = &locks[i];
    1052           0 :                 unsigned int tmp_count;
    1053             : 
    1054             :                 /* Only remove our own locks - ignore fnum. */
    1055         504 :                 if (!brl_same_context(&lock->context, &plock->context)) {
    1056          14 :                         memcpy(&tp[count], lock, sizeof(struct lock_struct));
    1057          14 :                         count++;
    1058          14 :                         continue;
    1059             :                 }
    1060             : 
    1061         490 :                 if (lock->lock_flav == WINDOWS_LOCK) {
    1062             :                         /* Do any Windows flavour locks conflict ? */
    1063           4 :                         if (brl_conflict(lock, plock)) {
    1064           0 :                                 TALLOC_FREE(tp);
    1065           0 :                                 return false;
    1066             :                         }
    1067             :                         /* Just copy the Windows lock into the new array. */
    1068           4 :                         memcpy(&tp[count], lock, sizeof(struct lock_struct));
    1069           4 :                         count++;
    1070           4 :                         continue;
    1071             :                 }
    1072             : 
    1073             :                 /* Work out overlaps. */
    1074         486 :                 tmp_count = brlock_posix_split_merge(&tp[count], lock, plock);
    1075             : 
    1076         486 :                 if (tmp_count == 0) {
    1077             :                         /* plock overlapped the existing lock completely,
    1078             :                            or replaced it. Don't copy the existing lock. */
    1079         472 :                         overlap_found = true;
    1080          14 :                 } else if (tmp_count == 1) {
    1081             :                         /* Either no overlap, (simple copy of existing lock) or
    1082             :                          * an overlap of an existing lock. */
    1083             :                         /* If the lock changed size, we had an overlap. */
    1084          10 :                         if (tp[count].size != lock->size) {
    1085           0 :                                 overlap_found = true;
    1086             :                         }
    1087          10 :                         count += tmp_count;
    1088           4 :                 } else if (tmp_count == 2) {
    1089             :                         /* We split a lock range in two. */
    1090           4 :                         overlap_found = true;
    1091           4 :                         count += tmp_count;
    1092             : 
    1093             :                         /* Optimisation... */
    1094             :                         /* We know we're finished here as we can't overlap any
    1095             :                            more POSIX locks. Copy the rest of the lock array. */
    1096             : 
    1097           4 :                         if (i < br_lck->num_locks - 1) {
    1098           0 :                                 memcpy(&tp[count], &locks[i+1],
    1099           0 :                                         sizeof(*locks)*((br_lck->num_locks-1) - i));
    1100           0 :                                 count += ((br_lck->num_locks-1) - i);
    1101             :                         }
    1102           4 :                         break;
    1103             :                 }
    1104             : 
    1105             :         }
    1106             : 
    1107         476 :         if (!overlap_found) {
    1108             :                 /* Just ignore - no change. */
    1109           0 :                 TALLOC_FREE(tp);
    1110           0 :                 DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n"));
    1111           0 :                 return True;
    1112             :         }
    1113             : 
    1114             :         /* Unlock any POSIX regions. */
    1115         476 :         if(lp_posix_locking(br_lck->fsp->conn->params)) {
    1116         476 :                 release_posix_lock_posix_flavour(br_lck->fsp,
    1117             :                                                 plock->start,
    1118             :                                                 plock->size,
    1119         476 :                                                 &plock->context,
    1120             :                                                 tp,
    1121             :                                                 count);
    1122             :         }
    1123             : 
    1124             :         /* Realloc so we don't leak entries per unlock call. */
    1125         476 :         if (count) {
    1126          30 :                 tp = talloc_realloc(br_lck, tp, struct lock_struct, count);
    1127          30 :                 if (!tp) {
    1128           0 :                         DEBUG(10,("brl_unlock_posix: realloc fail\n"));
    1129           0 :                         return False;
    1130             :                 }
    1131             :         } else {
    1132             :                 /* We deleted the last lock. */
    1133         446 :                 TALLOC_FREE(tp);
    1134         446 :                 tp = NULL;
    1135             :         }
    1136             : 
    1137         476 :         contend_level2_oplocks_end(br_lck->fsp,
    1138             :                                    LEVEL2_CONTEND_POSIX_BRL);
    1139             : 
    1140         476 :         br_lck->num_locks = count;
    1141         476 :         TALLOC_FREE(br_lck->lock_data);
    1142         476 :         locks = tp;
    1143         476 :         br_lck->lock_data = tp;
    1144         476 :         br_lck->modified = True;
    1145             : 
    1146         476 :         return True;
    1147             : }
    1148             : 
    1149             : /****************************************************************************
    1150             :  Unlock a range of bytes.
    1151             : ****************************************************************************/
    1152             : 
    1153        3365 : bool brl_unlock(struct byte_range_lock *br_lck,
    1154             :                 uint64_t smblctx,
    1155             :                 struct server_id pid,
    1156             :                 br_off start,
    1157             :                 br_off size,
    1158             :                 enum brl_flavour lock_flav)
    1159             : {
    1160          22 :         struct lock_struct lock;
    1161             : 
    1162        3365 :         lock.context.smblctx = smblctx;
    1163        3365 :         lock.context.pid = pid;
    1164        3365 :         lock.context.tid = br_lck->fsp->conn->cnum;
    1165        3365 :         lock.start = start;
    1166        3365 :         lock.size = size;
    1167        3365 :         lock.fnum = br_lck->fsp->fnum;
    1168        3365 :         lock.lock_type = UNLOCK_LOCK;
    1169        3365 :         lock.lock_flav = lock_flav;
    1170             : 
    1171        3365 :         if (lock_flav == WINDOWS_LOCK) {
    1172        2889 :                 return SMB_VFS_BRL_UNLOCK_WINDOWS(
    1173             :                         br_lck->fsp->conn, br_lck, &lock);
    1174             :         } else {
    1175         476 :                 return brl_unlock_posix(br_lck, &lock);
    1176             :         }
    1177             : }
    1178             : 
    1179             : /****************************************************************************
    1180             :  Test if we could add a lock if we wanted to.
    1181             :  Returns True if the region required is currently unlocked, False if locked.
    1182             : ****************************************************************************/
    1183             : 
    1184      203861 : bool brl_locktest(struct byte_range_lock *br_lck,
    1185             :                   const struct lock_struct *rw_probe)
    1186             : {
    1187      203861 :         bool ret = True;
    1188         119 :         unsigned int i;
    1189      203861 :         struct lock_struct *locks = br_lck->lock_data;
    1190      203861 :         files_struct *fsp = br_lck->fsp;
    1191             : 
    1192             :         /* Make sure existing locks don't conflict */
    1193      205782 :         for (i=0; i < br_lck->num_locks; i++) {
    1194             :                 /*
    1195             :                  * Our own locks don't conflict.
    1196             :                  */
    1197        2175 :                 if (brl_conflict_other(&locks[i], rw_probe)) {
    1198         258 :                         if (br_lck->record == NULL) {
    1199             :                                 /* readonly */
    1200         126 :                                 return false;
    1201             :                         }
    1202             : 
    1203         129 :                         if (!serverid_exists(&locks[i].context.pid)) {
    1204           4 :                                 locks[i].context.pid.pid = 0;
    1205           4 :                                 br_lck->modified = true;
    1206           4 :                                 continue;
    1207             :                         }
    1208             : 
    1209         122 :                         return False;
    1210             :                 }
    1211             :         }
    1212             : 
    1213             :         /*
    1214             :          * There is no lock held by an SMB daemon, check to
    1215             :          * see if there is a POSIX lock from a UNIX or NFS process.
    1216             :          * This only conflicts with Windows locks, not POSIX locks.
    1217             :          */
    1218             : 
    1219      203607 :         if(lp_posix_locking(fsp->conn->params) &&
    1220      203389 :            (rw_probe->lock_flav == WINDOWS_LOCK)) {
    1221             :                 /*
    1222             :                  * Make copies -- is_posix_locked might modify the values
    1223             :                  */
    1224             : 
    1225      202869 :                 br_off start = rw_probe->start;
    1226      202869 :                 br_off size = rw_probe->size;
    1227      202869 :                 enum brl_type lock_type = rw_probe->lock_type;
    1228             : 
    1229      202869 :                 ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK);
    1230             : 
    1231      202869 :                 DEBUG(10, ("brl_locktest: posix start=%ju len=%ju %s for %s "
    1232             :                            "file %s\n", (uintmax_t)start, (uintmax_t)size,
    1233             :                            ret ? "locked" : "unlocked",
    1234             :                            fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
    1235             : 
    1236             :                 /* We need to return the inverse of is_posix_locked. */
    1237      202869 :                 ret = !ret;
    1238             :         }
    1239             : 
    1240             :         /* no conflicts - we could have added it */
    1241      203494 :         return ret;
    1242             : }
    1243             : 
    1244             : /****************************************************************************
    1245             :  Query for existing locks.
    1246             : ****************************************************************************/
    1247             : 
    1248           0 : NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
    1249             :                 uint64_t *psmblctx,
    1250             :                 struct server_id pid,
    1251             :                 br_off *pstart,
    1252             :                 br_off *psize,
    1253             :                 enum brl_type *plock_type,
    1254             :                 enum brl_flavour lock_flav)
    1255             : {
    1256           0 :         unsigned int i;
    1257           0 :         struct lock_struct lock;
    1258           0 :         const struct lock_struct *locks = br_lck->lock_data;
    1259           0 :         files_struct *fsp = br_lck->fsp;
    1260             : 
    1261           0 :         lock.context.smblctx = *psmblctx;
    1262           0 :         lock.context.pid = pid;
    1263           0 :         lock.context.tid = br_lck->fsp->conn->cnum;
    1264           0 :         lock.start = *pstart;
    1265           0 :         lock.size = *psize;
    1266           0 :         lock.fnum = fsp->fnum;
    1267           0 :         lock.lock_type = *plock_type;
    1268           0 :         lock.lock_flav = lock_flav;
    1269             : 
    1270             :         /* Make sure existing locks don't conflict */
    1271           0 :         for (i=0; i < br_lck->num_locks; i++) {
    1272           0 :                 const struct lock_struct *exlock = &locks[i];
    1273           0 :                 bool conflict = False;
    1274             : 
    1275           0 :                 if (exlock->lock_flav == WINDOWS_LOCK) {
    1276           0 :                         conflict = brl_conflict(exlock, &lock);
    1277             :                 } else {
    1278           0 :                         conflict = brl_conflict_posix(exlock, &lock);
    1279             :                 }
    1280             : 
    1281           0 :                 if (conflict) {
    1282           0 :                         *psmblctx = exlock->context.smblctx;
    1283           0 :                         *pstart = exlock->start;
    1284           0 :                         *psize = exlock->size;
    1285           0 :                         *plock_type = exlock->lock_type;
    1286           0 :                         return NT_STATUS_LOCK_NOT_GRANTED;
    1287             :                 }
    1288             :         }
    1289             : 
    1290             :         /*
    1291             :          * There is no lock held by an SMB daemon, check to
    1292             :          * see if there is a POSIX lock from a UNIX or NFS process.
    1293             :          */
    1294             : 
    1295           0 :         if(lp_posix_locking(fsp->conn->params)) {
    1296           0 :                 bool ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK);
    1297             : 
    1298           0 :                 DEBUG(10, ("brl_lockquery: posix start=%ju len=%ju %s for %s "
    1299             :                            "file %s\n", (uintmax_t)*pstart,
    1300             :                            (uintmax_t)*psize, ret ? "locked" : "unlocked",
    1301             :                            fsp_fnum_dbg(fsp), fsp_str_dbg(fsp)));
    1302             : 
    1303           0 :                 if (ret) {
    1304             :                         /* Hmmm. No clue what to set smblctx to - use -1. */
    1305           0 :                         *psmblctx = 0xFFFFFFFFFFFFFFFFLL;
    1306           0 :                         return NT_STATUS_LOCK_NOT_GRANTED;
    1307             :                 }
    1308             :         }
    1309             : 
    1310           0 :         return NT_STATUS_OK;
    1311             : }
    1312             : 
    1313             : 
    1314             : /****************************************************************************
    1315             :  Remove any locks associated with a open file.
    1316             :  We return True if this process owns any other Windows locks on this
    1317             :  fd and so we should not immediately close the fd.
    1318             : ****************************************************************************/
    1319             : 
    1320         899 : void brl_close_fnum(struct byte_range_lock *br_lck)
    1321             : {
    1322         899 :         files_struct *fsp = br_lck->fsp;
    1323         899 :         uint32_t tid = fsp->conn->cnum;
    1324         899 :         uint64_t fnum = fsp->fnum;
    1325           6 :         unsigned int i;
    1326         899 :         struct lock_struct *locks = br_lck->lock_data;
    1327         899 :         struct server_id pid = messaging_server_id(fsp->conn->sconn->msg_ctx);
    1328           6 :         struct lock_struct *locks_copy;
    1329           6 :         unsigned int num_locks_copy;
    1330             : 
    1331             :         /* Copy the current lock array. */
    1332         899 :         if (br_lck->num_locks) {
    1333         803 :                 locks_copy = (struct lock_struct *)talloc_memdup(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct));
    1334         803 :                 if (!locks_copy) {
    1335           0 :                         smb_panic("brl_close_fnum: talloc failed");
    1336             :                         }
    1337             :         } else {
    1338          96 :                 locks_copy = NULL;
    1339             :         }
    1340             : 
    1341         899 :         num_locks_copy = br_lck->num_locks;
    1342             : 
    1343        2068 :         for (i=0; i < num_locks_copy; i++) {
    1344        1169 :                 struct lock_struct *lock = &locks_copy[i];
    1345             : 
    1346        2290 :                 if (lock->context.tid == tid &&
    1347        1121 :                     server_id_equal(&lock->context.pid, &pid) &&
    1348        1121 :                                 (lock->fnum == fnum)) {
    1349        1003 :                         brl_unlock(
    1350             :                                 br_lck,
    1351             :                                 lock->context.smblctx,
    1352             :                                 pid,
    1353             :                                 lock->start,
    1354             :                                 lock->size,
    1355             :                                 lock->lock_flav);
    1356             :                 }
    1357             :         }
    1358         899 : }
    1359             : 
    1360         160 : bool brl_mark_disconnected(struct files_struct *fsp)
    1361             : {
    1362         160 :         uint32_t tid = fsp->conn->cnum;
    1363           0 :         uint64_t smblctx;
    1364         160 :         uint64_t fnum = fsp->fnum;
    1365           0 :         unsigned int i;
    1366         160 :         struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
    1367         160 :         struct byte_range_lock *br_lck = NULL;
    1368             : 
    1369         160 :         if (fsp->op == NULL) {
    1370           0 :                 return false;
    1371             :         }
    1372             : 
    1373         160 :         smblctx = fsp->op->global->open_persistent_id;
    1374             : 
    1375         160 :         if (!fsp->op->global->durable) {
    1376           0 :                 return false;
    1377             :         }
    1378             : 
    1379         160 :         if (fsp->current_lock_count == 0) {
    1380         154 :                 return true;
    1381             :         }
    1382             : 
    1383           6 :         br_lck = brl_get_locks(talloc_tos(), fsp);
    1384           6 :         if (br_lck == NULL) {
    1385           0 :                 return false;
    1386             :         }
    1387             : 
    1388          12 :         for (i=0; i < br_lck->num_locks; i++) {
    1389           6 :                 struct lock_struct *lock = &br_lck->lock_data[i];
    1390             : 
    1391             :                 /*
    1392             :                  * as this is a durable handle, we only expect locks
    1393             :                  * of the current file handle!
    1394             :                  */
    1395             : 
    1396           6 :                 if (lock->context.smblctx != smblctx) {
    1397           0 :                         TALLOC_FREE(br_lck);
    1398           0 :                         return false;
    1399             :                 }
    1400             : 
    1401           6 :                 if (lock->context.tid != tid) {
    1402           0 :                         TALLOC_FREE(br_lck);
    1403           0 :                         return false;
    1404             :                 }
    1405             : 
    1406           6 :                 if (!server_id_equal(&lock->context.pid, &self)) {
    1407           0 :                         TALLOC_FREE(br_lck);
    1408           0 :                         return false;
    1409             :                 }
    1410             : 
    1411           6 :                 if (lock->fnum != fnum) {
    1412           0 :                         TALLOC_FREE(br_lck);
    1413           0 :                         return false;
    1414             :                 }
    1415             : 
    1416           6 :                 server_id_set_disconnected(&lock->context.pid);
    1417           6 :                 lock->context.tid = TID_FIELD_INVALID;
    1418           6 :                 lock->fnum = FNUM_FIELD_INVALID;
    1419             :         }
    1420             : 
    1421           6 :         br_lck->modified = true;
    1422           6 :         TALLOC_FREE(br_lck);
    1423           6 :         return true;
    1424             : }
    1425             : 
    1426         130 : bool brl_reconnect_disconnected(struct files_struct *fsp)
    1427             : {
    1428         130 :         uint32_t tid = fsp->conn->cnum;
    1429           0 :         uint64_t smblctx;
    1430         130 :         uint64_t fnum = fsp->fnum;
    1431           0 :         unsigned int i;
    1432         130 :         struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
    1433         130 :         struct byte_range_lock *br_lck = NULL;
    1434             : 
    1435         130 :         if (fsp->op == NULL) {
    1436           0 :                 return false;
    1437             :         }
    1438             : 
    1439         130 :         smblctx = fsp->op->global->open_persistent_id;
    1440             : 
    1441         130 :         if (!fsp->op->global->durable) {
    1442           0 :                 return false;
    1443             :         }
    1444             : 
    1445             :         /*
    1446             :          * When reconnecting, we do not want to validate the brlock entries
    1447             :          * and thereby remove our own (disconnected) entries but reactivate
    1448             :          * them instead.
    1449             :          */
    1450             : 
    1451         130 :         br_lck = brl_get_locks(talloc_tos(), fsp);
    1452         130 :         if (br_lck == NULL) {
    1453           0 :                 return false;
    1454             :         }
    1455             : 
    1456         130 :         if (br_lck->num_locks == 0) {
    1457         124 :                 TALLOC_FREE(br_lck);
    1458         124 :                 return true;
    1459             :         }
    1460             : 
    1461          12 :         for (i=0; i < br_lck->num_locks; i++) {
    1462           6 :                 struct lock_struct *lock = &br_lck->lock_data[i];
    1463             : 
    1464             :                 /*
    1465             :                  * as this is a durable handle we only expect locks
    1466             :                  * of the current file handle!
    1467             :                  */
    1468             : 
    1469           6 :                 if (lock->context.smblctx != smblctx) {
    1470           0 :                         TALLOC_FREE(br_lck);
    1471           0 :                         return false;
    1472             :                 }
    1473             : 
    1474           6 :                 if (lock->context.tid != TID_FIELD_INVALID) {
    1475           0 :                         TALLOC_FREE(br_lck);
    1476           0 :                         return false;
    1477             :                 }
    1478             : 
    1479           6 :                 if (!server_id_is_disconnected(&lock->context.pid)) {
    1480           0 :                         TALLOC_FREE(br_lck);
    1481           0 :                         return false;
    1482             :                 }
    1483             : 
    1484           6 :                 if (lock->fnum != FNUM_FIELD_INVALID) {
    1485           0 :                         TALLOC_FREE(br_lck);
    1486           0 :                         return false;
    1487             :                 }
    1488             : 
    1489           6 :                 lock->context.pid = self;
    1490           6 :                 lock->context.tid = tid;
    1491           6 :                 lock->fnum = fnum;
    1492             :         }
    1493             : 
    1494           6 :         fsp->current_lock_count = br_lck->num_locks;
    1495           6 :         br_lck->modified = true;
    1496           6 :         TALLOC_FREE(br_lck);
    1497           6 :         return true;
    1498             : }
    1499             : 
    1500             : struct brl_forall_cb {
    1501             :         void (*fn)(struct file_id id, struct server_id pid,
    1502             :                    enum brl_type lock_type,
    1503             :                    enum brl_flavour lock_flav,
    1504             :                    br_off start, br_off size,
    1505             :                    void *private_data);
    1506             :         void *private_data;
    1507             : };
    1508             : 
    1509             : /****************************************************************************
    1510             :  Traverse the whole database with this function, calling traverse_callback
    1511             :  on each lock.
    1512             : ****************************************************************************/
    1513             : 
    1514           0 : static int brl_traverse_fn(struct db_record *rec, void *state)
    1515             : {
    1516           0 :         struct brl_forall_cb *cb = (struct brl_forall_cb *)state;
    1517           0 :         struct lock_struct *locks;
    1518           0 :         struct file_id *key;
    1519           0 :         unsigned int i;
    1520           0 :         unsigned int num_locks = 0;
    1521           0 :         TDB_DATA dbkey;
    1522           0 :         TDB_DATA value;
    1523             : 
    1524           0 :         dbkey = dbwrap_record_get_key(rec);
    1525           0 :         value = dbwrap_record_get_value(rec);
    1526             : 
    1527             :         /* In a traverse function we must make a copy of
    1528             :            dbuf before modifying it. */
    1529             : 
    1530           0 :         locks = (struct lock_struct *)talloc_memdup(
    1531             :                 talloc_tos(), value.dptr, value.dsize);
    1532           0 :         if (!locks) {
    1533           0 :                 return -1; /* Terminate traversal. */
    1534             :         }
    1535             : 
    1536           0 :         key = (struct file_id *)dbkey.dptr;
    1537           0 :         num_locks = value.dsize/sizeof(*locks);
    1538             : 
    1539           0 :         if (cb->fn) {
    1540           0 :                 for ( i=0; i<num_locks; i++) {
    1541           0 :                         cb->fn(*key,
    1542           0 :                                 locks[i].context.pid,
    1543           0 :                                 locks[i].lock_type,
    1544           0 :                                 locks[i].lock_flav,
    1545           0 :                                 locks[i].start,
    1546           0 :                                 locks[i].size,
    1547             :                                 cb->private_data);
    1548             :                 }
    1549             :         }
    1550             : 
    1551           0 :         TALLOC_FREE(locks);
    1552           0 :         return 0;
    1553             : }
    1554             : 
    1555             : /*******************************************************************
    1556             :  Call the specified function on each lock in the database.
    1557             : ********************************************************************/
    1558             : 
    1559           2 : int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
    1560             :                           enum brl_type lock_type,
    1561             :                           enum brl_flavour lock_flav,
    1562             :                           br_off start, br_off size,
    1563             :                           void *private_data),
    1564             :                void *private_data)
    1565             : {
    1566           0 :         struct brl_forall_cb cb;
    1567           0 :         NTSTATUS status;
    1568           2 :         int count = 0;
    1569             : 
    1570           2 :         if (!brlock_db) {
    1571           0 :                 return 0;
    1572             :         }
    1573           2 :         cb.fn = fn;
    1574           2 :         cb.private_data = private_data;
    1575           2 :         status = dbwrap_traverse(brlock_db, brl_traverse_fn, &cb, &count);
    1576             : 
    1577           2 :         if (!NT_STATUS_IS_OK(status)) {
    1578           0 :                 return -1;
    1579             :         } else {
    1580           2 :                 return count;
    1581             :         }
    1582             : }
    1583             : 
    1584             : /*******************************************************************
    1585             :  Store a potentially modified set of byte range lock data back into
    1586             :  the database.
    1587             :  Unlock the record.
    1588             : ********************************************************************/
    1589             : 
    1590       10281 : static void byte_range_lock_flush(struct byte_range_lock *br_lck)
    1591             : {
    1592          49 :         unsigned i;
    1593       10281 :         struct lock_struct *locks = br_lck->lock_data;
    1594             : 
    1595       10281 :         if (!br_lck->modified) {
    1596        3731 :                 DEBUG(10, ("br_lck not modified\n"));
    1597        3731 :                 goto done;
    1598             :         }
    1599             : 
    1600        6516 :         i = 0;
    1601             : 
    1602      176157 :         while (i < br_lck->num_locks) {
    1603      169607 :                 if (locks[i].context.pid.pid == 0) {
    1604             :                         /*
    1605             :                          * Autocleanup, the process conflicted and does not
    1606             :                          * exist anymore.
    1607             :                          */
    1608           4 :                         locks[i] = locks[br_lck->num_locks-1];
    1609           4 :                         br_lck->num_locks -= 1;
    1610             :                 } else {
    1611      169603 :                         i += 1;
    1612             :                 }
    1613             :         }
    1614             : 
    1615        6550 :         if (br_lck->num_locks == 0) {
    1616             :                 /* No locks - delete this entry. */
    1617        1536 :                 NTSTATUS status = dbwrap_record_delete(br_lck->record);
    1618        1536 :                 if (!NT_STATUS_IS_OK(status)) {
    1619           0 :                         DEBUG(0, ("delete_rec returned %s\n",
    1620             :                                   nt_errstr(status)));
    1621           0 :                         smb_panic("Could not delete byte range lock entry");
    1622             :                 }
    1623             :         } else {
    1624        5014 :                 TDB_DATA data = {
    1625        5014 :                         .dsize = br_lck->num_locks * sizeof(struct lock_struct),
    1626        4993 :                         .dptr = (uint8_t *)br_lck->lock_data,
    1627             :                 };
    1628          21 :                 NTSTATUS status;
    1629             : 
    1630        5014 :                 status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE);
    1631        5014 :                 if (!NT_STATUS_IS_OK(status)) {
    1632           0 :                         DEBUG(0, ("store returned %s\n", nt_errstr(status)));
    1633           0 :                         smb_panic("Could not store byte range mode entry");
    1634             :                 }
    1635             :         }
    1636             : 
    1637        6550 :         DEBUG(10, ("seqnum=%d\n", dbwrap_get_seqnum(brlock_db)));
    1638             : 
    1639       10281 :  done:
    1640       10281 :         br_lck->modified = false;
    1641       10281 :         TALLOC_FREE(br_lck->record);
    1642       10281 : }
    1643             : 
    1644       10281 : static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
    1645             : {
    1646       10281 :         byte_range_lock_flush(br_lck);
    1647       10281 :         return 0;
    1648             : }
    1649             : 
    1650       10541 : static bool brl_parse_data(struct byte_range_lock *br_lck, TDB_DATA data)
    1651             : {
    1652          60 :         size_t data_len;
    1653             : 
    1654       10541 :         if (data.dsize == 0) {
    1655        1985 :                 return true;
    1656             :         }
    1657        8539 :         if (data.dsize % sizeof(struct lock_struct) != 0) {
    1658           0 :                 DEBUG(1, ("Invalid data size: %u\n", (unsigned)data.dsize));
    1659           0 :                 return false;
    1660             :         }
    1661             : 
    1662        8539 :         br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
    1663        8539 :         data_len = br_lck->num_locks * sizeof(struct lock_struct);
    1664             : 
    1665        8539 :         br_lck->lock_data = talloc_memdup(br_lck, data.dptr, data_len);
    1666        8539 :         if (br_lck->lock_data == NULL) {
    1667           0 :                 DEBUG(1, ("talloc_memdup failed\n"));
    1668           0 :                 return false;
    1669             :         }
    1670        8496 :         return true;
    1671             : }
    1672             : 
    1673             : /*******************************************************************
    1674             :  Fetch a set of byte range lock data from the database.
    1675             :  Leave the record locked.
    1676             :  TALLOC_FREE(brl) will release the lock in the destructor.
    1677             : ********************************************************************/
    1678             : 
    1679       10281 : struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp)
    1680             : {
    1681          49 :         TDB_DATA key, data;
    1682          49 :         struct byte_range_lock *br_lck;
    1683             : 
    1684       10281 :         br_lck = talloc_zero(mem_ctx, struct byte_range_lock);
    1685       10281 :         if (br_lck == NULL) {
    1686           0 :                 return NULL;
    1687             :         }
    1688             : 
    1689       10281 :         br_lck->fsp = fsp;
    1690             : 
    1691       10281 :         key.dptr = (uint8_t *)&fsp->file_id;
    1692       10281 :         key.dsize = sizeof(struct file_id);
    1693             : 
    1694       10281 :         br_lck->record = dbwrap_fetch_locked(brlock_db, br_lck, key);
    1695             : 
    1696       10281 :         if (br_lck->record == NULL) {
    1697           0 :                 DEBUG(3, ("Could not lock byte range lock entry\n"));
    1698           0 :                 TALLOC_FREE(br_lck);
    1699           0 :                 return NULL;
    1700             :         }
    1701             : 
    1702       10281 :         data = dbwrap_record_get_value(br_lck->record);
    1703             : 
    1704       10281 :         if (!brl_parse_data(br_lck, data)) {
    1705           0 :                 TALLOC_FREE(br_lck);
    1706           0 :                 return NULL;
    1707             :         }
    1708             : 
    1709       10281 :         talloc_set_destructor(br_lck, byte_range_lock_destructor);
    1710             : 
    1711       10281 :         if (DEBUGLEVEL >= 10) {
    1712           0 :                 unsigned int i;
    1713           0 :                 struct file_id_buf buf;
    1714           0 :                 struct lock_struct *locks = br_lck->lock_data;
    1715           0 :                 DBG_DEBUG("%u current locks on file_id %s\n",
    1716             :                           br_lck->num_locks,
    1717             :                           file_id_str_buf(fsp->file_id, &buf));
    1718           0 :                 for( i = 0; i < br_lck->num_locks; i++) {
    1719           0 :                         print_lock_struct(i, &locks[i]);
    1720             :                 }
    1721             :         }
    1722             : 
    1723       10232 :         return br_lck;
    1724             : }
    1725             : 
    1726        6753 : struct byte_range_lock *brl_get_locks_for_locking(TALLOC_CTX *mem_ctx,
    1727             :                                                   files_struct *fsp,
    1728             :                                                   TALLOC_CTX *req_mem_ctx,
    1729             :                                                   const struct GUID *req_guid)
    1730             : {
    1731        6753 :         struct byte_range_lock *br_lck = NULL;
    1732             : 
    1733        6753 :         br_lck = brl_get_locks(mem_ctx, fsp);
    1734        6753 :         if (br_lck == NULL) {
    1735           0 :                 return NULL;
    1736             :         }
    1737        6753 :         SMB_ASSERT(req_mem_ctx != NULL);
    1738        6753 :         br_lck->req_mem_ctx = req_mem_ctx;
    1739        6753 :         SMB_ASSERT(req_guid != NULL);
    1740        6753 :         br_lck->req_guid = req_guid;
    1741             : 
    1742        6753 :         return br_lck;
    1743             : }
    1744             : 
    1745             : struct brl_get_locks_readonly_state {
    1746             :         TALLOC_CTX *mem_ctx;
    1747             :         struct byte_range_lock **br_lock;
    1748             : };
    1749             : 
    1750         260 : static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data,
    1751             :                                           void *private_data)
    1752             : {
    1753         260 :         struct brl_get_locks_readonly_state *state =
    1754             :                 (struct brl_get_locks_readonly_state *)private_data;
    1755          11 :         struct byte_range_lock *br_lck;
    1756             : 
    1757         260 :         br_lck = talloc_pooled_object(
    1758             :                 state->mem_ctx, struct byte_range_lock, 1, data.dsize);
    1759         260 :         if (br_lck == NULL) {
    1760           0 :                 *state->br_lock = NULL;
    1761           0 :                 return;
    1762             :         }
    1763         260 :         *br_lck = (struct byte_range_lock) { 0 };
    1764         260 :         if (!brl_parse_data(br_lck, data)) {
    1765           0 :                 *state->br_lock = NULL;
    1766           0 :                 return;
    1767             :         }
    1768         260 :         *state->br_lock = br_lck;
    1769             : }
    1770             : 
    1771      554029 : struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
    1772             : {
    1773      554029 :         struct byte_range_lock *br_lock = NULL;
    1774         706 :         struct brl_get_locks_readonly_state state;
    1775         706 :         NTSTATUS status;
    1776             : 
    1777      554029 :         DEBUG(10, ("seqnum=%d, fsp->brlock_seqnum=%d\n",
    1778             :                    dbwrap_get_seqnum(brlock_db), fsp->brlock_seqnum));
    1779             : 
    1780      554029 :         if ((fsp->brlock_rec != NULL)
    1781      203603 :             && (dbwrap_get_seqnum(brlock_db) == fsp->brlock_seqnum)) {
    1782             :                 /*
    1783             :                  * We have cached the brlock_rec and the database did not
    1784             :                  * change.
    1785             :                  */
    1786      203383 :                 return fsp->brlock_rec;
    1787             :         }
    1788             : 
    1789             :         /*
    1790             :          * Parse the record fresh from the database
    1791             :          */
    1792             : 
    1793      350646 :         state.mem_ctx = fsp;
    1794      350646 :         state.br_lock = &br_lock;
    1795             : 
    1796      350646 :         status = dbwrap_parse_record(
    1797             :                 brlock_db,
    1798      350646 :                 make_tdb_data((uint8_t *)&fsp->file_id,
    1799             :                               sizeof(fsp->file_id)),
    1800             :                 brl_get_locks_readonly_parser, &state);
    1801             : 
    1802      350646 :         if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_FOUND)) {
    1803             :                 /*
    1804             :                  * No locks on this file. Return an empty br_lock.
    1805             :                  */
    1806      350386 :                 br_lock = talloc_zero(fsp, struct byte_range_lock);
    1807      350386 :                 if (br_lock == NULL) {
    1808           0 :                         return NULL;
    1809             :                 }
    1810             : 
    1811         260 :         } else if (!NT_STATUS_IS_OK(status)) {
    1812           0 :                 DEBUG(3, ("Could not parse byte range lock record: "
    1813             :                           "%s\n", nt_errstr(status)));
    1814           0 :                 return NULL;
    1815             :         }
    1816      350646 :         if (br_lock == NULL) {
    1817           0 :                 return NULL;
    1818             :         }
    1819             : 
    1820      350646 :         br_lock->fsp = fsp;
    1821      350646 :         br_lock->modified = false;
    1822      350646 :         br_lock->record = NULL;
    1823             : 
    1824             :         /*
    1825             :          * Cache the brlock struct, invalidated when the dbwrap_seqnum
    1826             :          * changes. See beginning of this routine.
    1827             :          */
    1828      350646 :         TALLOC_FREE(fsp->brlock_rec);
    1829      350646 :         fsp->brlock_rec = br_lock;
    1830      350646 :         fsp->brlock_seqnum = dbwrap_get_seqnum(brlock_db);
    1831             : 
    1832      350646 :         return br_lock;
    1833             : }
    1834             : 
    1835           2 : bool brl_cleanup_disconnected(struct file_id fid, uint64_t open_persistent_id)
    1836             : {
    1837           2 :         bool ret = false;
    1838           2 :         TALLOC_CTX *frame = talloc_stackframe();
    1839           0 :         TDB_DATA key, val;
    1840           0 :         struct db_record *rec;
    1841           0 :         struct lock_struct *lock;
    1842           0 :         unsigned n, num;
    1843           0 :         struct file_id_buf buf;
    1844           0 :         NTSTATUS status;
    1845             : 
    1846           2 :         key = make_tdb_data((void*)&fid, sizeof(fid));
    1847             : 
    1848           2 :         rec = dbwrap_fetch_locked(brlock_db, frame, key);
    1849           2 :         if (rec == NULL) {
    1850           0 :                 DBG_INFO("failed to fetch record for file %s\n",
    1851             :                          file_id_str_buf(fid, &buf));
    1852           0 :                 goto done;
    1853             :         }
    1854             : 
    1855           2 :         val = dbwrap_record_get_value(rec);
    1856           2 :         lock = (struct lock_struct*)val.dptr;
    1857           2 :         num = val.dsize / sizeof(struct lock_struct);
    1858           2 :         if (lock == NULL) {
    1859           2 :                 DBG_DEBUG("no byte range locks for file %s\n",
    1860             :                           file_id_str_buf(fid, &buf));
    1861           2 :                 ret = true;
    1862           2 :                 goto done;
    1863             :         }
    1864             : 
    1865           0 :         for (n=0; n<num; n++) {
    1866           0 :                 struct lock_context *ctx = &lock[n].context;
    1867             : 
    1868           0 :                 if (!server_id_is_disconnected(&ctx->pid)) {
    1869           0 :                         struct server_id_buf tmp;
    1870           0 :                         DBG_INFO("byte range lock "
    1871             :                                  "%s used by server %s, do not cleanup\n",
    1872             :                                  file_id_str_buf(fid, &buf),
    1873             :                                  server_id_str_buf(ctx->pid, &tmp));
    1874           0 :                         goto done;
    1875             :                 }
    1876             : 
    1877           0 :                 if (ctx->smblctx != open_persistent_id)      {
    1878           0 :                         DBG_INFO("byte range lock %s expected smblctx %"PRIu64" "
    1879             :                                  "but found %"PRIu64", do not cleanup\n",
    1880             :                                  file_id_str_buf(fid, &buf),
    1881             :                                  open_persistent_id,
    1882             :                                  ctx->smblctx);
    1883           0 :                         goto done;
    1884             :                 }
    1885             :         }
    1886             : 
    1887           0 :         status = dbwrap_record_delete(rec);
    1888           0 :         if (!NT_STATUS_IS_OK(status)) {
    1889           0 :                 DBG_INFO("failed to delete record "
    1890             :                          "for file %s from %s, open %"PRIu64": %s\n",
    1891             :                          file_id_str_buf(fid, &buf),
    1892             :                          dbwrap_name(brlock_db),
    1893             :                          open_persistent_id,
    1894             :                          nt_errstr(status));
    1895           0 :                 goto done;
    1896             :         }
    1897             : 
    1898           0 :         DBG_DEBUG("file %s cleaned up %u entries from open %"PRIu64"\n",
    1899             :                   file_id_str_buf(fid, &buf),
    1900             :                   num,
    1901             :                   open_persistent_id);
    1902             : 
    1903           0 :         ret = true;
    1904           2 : done:
    1905           2 :         talloc_free(frame);
    1906           2 :         return ret;
    1907             : }

Generated by: LCOV version 1.14