LCOV - code coverage report
Current view: top level - source3/locking - brlock.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 212 707 30.0 %
Date: 2024-06-13 04:01:37 Functions: 21 38 55.3 %

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

Generated by: LCOV version 1.13