LCOV - code coverage report
Current view: top level - source3/locking - posix.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 148 372 39.8 %
Date: 2024-06-13 04:01:37 Functions: 19 28 67.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Locking functions
       4             :    Copyright (C) Jeremy Allison 1992-2006
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : 
      19             :    Revision History:
      20             : 
      21             :    POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "system/filesys.h"
      26             : #include "lib/util/server_id.h"
      27             : #include "locking/proto.h"
      28             : #include "dbwrap/dbwrap.h"
      29             : #include "dbwrap/dbwrap_rbt.h"
      30             : #include "util_tdb.h"
      31             : #include "smbd/fd_handle.h"
      32             : 
      33             : #undef DBGC_CLASS
      34             : #define DBGC_CLASS DBGC_LOCKING
      35             : 
      36             : /*
      37             :  * The pending close database handle.
      38             :  */
      39             : 
      40             : static struct db_context *posix_pending_close_db;
      41             : 
      42             : /****************************************************************************
      43             :  First - the functions that deal with the underlying system locks - these
      44             :  functions are used no matter if we're mapping CIFS Windows locks or CIFS
      45             :  POSIX locks onto POSIX.
      46             : ****************************************************************************/
      47             : 
      48             : /****************************************************************************
      49             :  Utility function to map a lock type correctly depending on the open
      50             :  mode of a file.
      51             : ****************************************************************************/
      52             : 
      53         797 : static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
      54             : {
      55         797 :         if ((lock_type == WRITE_LOCK) && !fsp->fsp_flags.can_write) {
      56             :                 /*
      57             :                  * Many UNIX's cannot get a write lock on a file opened read-only.
      58             :                  * Win32 locking semantics allow this.
      59             :                  * Do the best we can and attempt a read-only lock.
      60             :                  */
      61           0 :                 DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
      62           0 :                 return F_RDLCK;
      63             :         }
      64             : 
      65             :         /*
      66             :          * This return should be the most normal, as we attempt
      67             :          * to always open files read/write.
      68             :          */
      69             : 
      70         797 :         return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
      71             : }
      72             : 
      73             : /****************************************************************************
      74             :  Debugging aid :-).
      75             : ****************************************************************************/
      76             : 
      77           0 : static const char *posix_lock_type_name(int lock_type)
      78             : {
      79           0 :         return (lock_type == F_RDLCK) ? "READ" : "WRITE";
      80             : }
      81             : 
      82             : /****************************************************************************
      83             :  Check to see if the given unsigned lock range is within the possible POSIX
      84             :  range. Modifies the given args to be in range if possible, just returns
      85             :  False if not.
      86             : ****************************************************************************/
      87             : 
      88             : #define SMB_OFF_T_BITS (sizeof(off_t)*8)
      89             : 
      90         802 : static bool posix_lock_in_range(off_t *offset_out, off_t *count_out,
      91             :                                 uint64_t u_offset, uint64_t u_count)
      92             : {
      93         802 :         off_t offset = (off_t)u_offset;
      94         802 :         off_t count = (off_t)u_count;
      95             : 
      96             :         /*
      97             :          * For the type of system we are, attempt to
      98             :          * find the maximum positive lock offset as an off_t.
      99             :          */
     100             : 
     101             : #if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */
     102             : 
     103             :         off_t max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
     104             : #else
     105             :         /*
     106             :          * In this case off_t is 64 bits,
     107             :          * and the underlying system can handle 64 bit signed locks.
     108             :          */
     109             : 
     110         802 :         off_t mask2 = ((off_t)0x4) << (SMB_OFF_T_BITS-4);
     111         802 :         off_t mask = (mask2<<1);
     112         802 :         off_t max_positive_lock_offset = ~mask;
     113             : 
     114             : #endif
     115             :         /*
     116             :          * POSIX locks of length zero mean lock to end-of-file.
     117             :          * Win32 locks of length zero are point probes. Ignore
     118             :          * any Win32 locks of length zero. JRA.
     119             :          */
     120             : 
     121         802 :         if (count == 0) {
     122           0 :                 DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
     123           0 :                 return False;
     124             :         }
     125             : 
     126             :         /*
     127             :          * If the given offset was > max_positive_lock_offset then we cannot map this at all
     128             :          * ignore this lock.
     129             :          */
     130             : 
     131         802 :         if (u_offset & ~((uint64_t)max_positive_lock_offset)) {
     132           0 :                 DEBUG(10, ("posix_lock_in_range: (offset = %ju) offset > %ju "
     133             :                            "and we cannot handle this. Ignoring lock.\n",
     134             :                            (uintmax_t)u_offset,
     135             :                            (uintmax_t)max_positive_lock_offset));
     136           0 :                 return False;
     137             :         }
     138             : 
     139             :         /*
     140             :          * We must truncate the count to less than max_positive_lock_offset.
     141             :          */
     142             : 
     143         802 :         if (u_count & ~((uint64_t)max_positive_lock_offset)) {
     144           0 :                 count = max_positive_lock_offset;
     145             :         }
     146             : 
     147             :         /*
     148             :          * Truncate count to end at max lock offset.
     149             :          */
     150             : 
     151        1560 :         if (offset > INT64_MAX - count ||
     152         802 :             offset + count > max_positive_lock_offset) {
     153           0 :                 count = max_positive_lock_offset - offset;
     154             :         }
     155             : 
     156             :         /*
     157             :          * If we ate all the count, ignore this lock.
     158             :          */
     159             : 
     160         802 :         if (count == 0) {
     161           0 :                 DEBUG(10, ("posix_lock_in_range: Count = 0. Ignoring lock "
     162             :                            "u_offset = %ju, u_count = %ju\n",
     163             :                            (uintmax_t)u_offset,
     164             :                            (uintmax_t)u_count));
     165           0 :                 return False;
     166             :         }
     167             : 
     168             :         /*
     169             :          * The mapping was successful.
     170             :          */
     171             : 
     172         802 :         DEBUG(10, ("posix_lock_in_range: offset_out = %ju, "
     173             :                    "count_out = %ju\n",
     174             :                    (uintmax_t)offset, (uintmax_t)count));
     175             : 
     176         802 :         *offset_out = offset;
     177         802 :         *count_out = count;
     178             :         
     179         802 :         return True;
     180             : }
     181             : 
     182          30 : bool smb_vfs_call_lock(struct vfs_handle_struct *handle,
     183             :                        struct files_struct *fsp, int op, off_t offset,
     184             :                        off_t count, int type)
     185             : {
     186          46 :         VFS_FIND(lock);
     187          30 :         return handle->fns->lock_fn(handle, fsp, op, offset, count, type);
     188             : }
     189             : 
     190             : /****************************************************************************
     191             :  Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
     192             :  broken NFS implementations.
     193             : ****************************************************************************/
     194             : 
     195          10 : static bool posix_fcntl_lock(files_struct *fsp, int op, off_t offset, off_t count, int type)
     196             : {
     197             :         bool ret;
     198             : 
     199          10 :         DEBUG(8,("posix_fcntl_lock %d %d %jd %jd %d\n",
     200             :                  fsp_get_io_fd(fsp),op,(intmax_t)offset,(intmax_t)count,type));
     201             : 
     202          10 :         ret = SMB_VFS_LOCK(fsp, op, offset, count, type);
     203             : 
     204          10 :         if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
     205             : 
     206           0 :                 if ((errno == EINVAL) &&
     207           0 :                                 (op != F_GETLK &&
     208           0 :                                  op != F_SETLK &&
     209             :                                  op != F_SETLKW)) {
     210           0 :                         DEBUG(0,("WARNING: OFD locks in use and no kernel "
     211             :                                 "support. Try setting "
     212             :                                 "'smbd:force process locks = true' "
     213             :                                 "in smb.conf\n"));
     214             :                 } else {
     215           0 :                         DEBUG(0, ("WARNING: lock request at offset "
     216             :                           "%ju, length %ju returned\n",
     217             :                           (uintmax_t)offset, (uintmax_t)count));
     218           0 :                         DEBUGADD(0, ("an %s error. This can happen when using 64 bit "
     219             :                              "lock offsets\n", strerror(errno)));
     220           0 :                         DEBUGADD(0, ("on 32 bit NFS mounted file systems.\n"));
     221             :                 }
     222             : 
     223             :                 /*
     224             :                  * If the offset is > 0x7FFFFFFF then this will cause problems on
     225             :                  * 32 bit NFS mounted filesystems. Just ignore it.
     226             :                  */
     227             : 
     228           0 :                 if (offset & ~((off_t)0x7fffffff)) {
     229           0 :                         DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
     230           0 :                         return True;
     231             :                 }
     232             : 
     233           0 :                 if (count & ~((off_t)0x7fffffff)) {
     234             :                         /* 32 bit NFS file system, retry with smaller offset */
     235           0 :                         DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
     236           0 :                         errno = 0;
     237           0 :                         count &= 0x7fffffff;
     238           0 :                         ret = SMB_VFS_LOCK(fsp, op, offset, count, type);
     239             :                 }
     240             :         }
     241             : 
     242          10 :         DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
     243          10 :         return ret;
     244             : }
     245             : 
     246         968 : bool smb_vfs_call_getlock(struct vfs_handle_struct *handle,
     247             :                           struct files_struct *fsp, off_t *poffset,
     248             :                           off_t *pcount, int *ptype, pid_t *ppid)
     249             : {
     250        1128 :         VFS_FIND(getlock);
     251         968 :         return handle->fns->getlock_fn(handle, fsp, poffset, pcount, ptype, 
     252             :                                        ppid);
     253             : }
     254             : 
     255             : /****************************************************************************
     256             :  Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
     257             :  broken NFS implementations.
     258             : ****************************************************************************/
     259             : 
     260         792 : static bool posix_fcntl_getlock(files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype)
     261             : {
     262             :         pid_t pid;
     263             :         bool ret;
     264             : 
     265         792 :         DEBUG(8, ("posix_fcntl_getlock %d %ju %ju %d\n",
     266             :                   fsp_get_io_fd(fsp), (uintmax_t)*poffset, (uintmax_t)*pcount,
     267             :                   *ptype));
     268             : 
     269         792 :         ret = SMB_VFS_GETLOCK(fsp, poffset, pcount, ptype, &pid);
     270             : 
     271         792 :         if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
     272             : 
     273           0 :                 DEBUG(0, ("posix_fcntl_getlock: WARNING: lock request at "
     274             :                           "offset %ju, length %ju returned\n",
     275             :                           (uintmax_t)*poffset, (uintmax_t)*pcount));
     276           0 :                 DEBUGADD(0, ("an %s error. This can happen when using 64 bit "
     277             :                              "lock offsets\n", strerror(errno)));
     278           0 :                 DEBUGADD(0, ("on 32 bit NFS mounted file systems.\n"));
     279             : 
     280             :                 /*
     281             :                  * If the offset is > 0x7FFFFFFF then this will cause problems on
     282             :                  * 32 bit NFS mounted filesystems. Just ignore it.
     283             :                  */
     284             : 
     285           0 :                 if (*poffset & ~((off_t)0x7fffffff)) {
     286           0 :                         DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
     287           0 :                         return True;
     288             :                 }
     289             : 
     290           0 :                 if (*pcount & ~((off_t)0x7fffffff)) {
     291             :                         /* 32 bit NFS file system, retry with smaller offset */
     292           0 :                         DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
     293           0 :                         errno = 0;
     294           0 :                         *pcount &= 0x7fffffff;
     295           0 :                         ret = SMB_VFS_GETLOCK(fsp,poffset,pcount,ptype,&pid);
     296             :                 }
     297             :         }
     298             : 
     299         792 :         DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
     300         792 :         return ret;
     301             : }
     302             : 
     303             : /****************************************************************************
     304             :  POSIX function to see if a file region is locked. Returns True if the
     305             :  region is locked, False otherwise.
     306             : ****************************************************************************/
     307             : 
     308         792 : bool is_posix_locked(files_struct *fsp,
     309             :                         uint64_t *pu_offset,
     310             :                         uint64_t *pu_count,
     311             :                         enum brl_type *plock_type,
     312             :                         enum brl_flavour lock_flav)
     313             : {
     314             :         off_t offset;
     315             :         off_t count;
     316         792 :         int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
     317             : 
     318         792 :         DEBUG(10, ("is_posix_locked: File %s, offset = %ju, count = %ju, "
     319             :                    "type = %s\n", fsp_str_dbg(fsp), (uintmax_t)*pu_offset,
     320             :                    (uintmax_t)*pu_count,  posix_lock_type_name(*plock_type)));
     321             : 
     322             :         /*
     323             :          * If the requested lock won't fit in the POSIX range, we will
     324             :          * never set it, so presume it is not locked.
     325             :          */
     326             : 
     327         792 :         if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
     328           0 :                 return False;
     329             :         }
     330             : 
     331         792 :         if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
     332           0 :                 return False;
     333             :         }
     334             : 
     335         792 :         if (posix_lock_type == F_UNLCK) {
     336         792 :                 return False;
     337             :         }
     338             : 
     339           0 :         if (lock_flav == POSIX_LOCK) {
     340             :                 /* Only POSIX lock queries need to know the details. */
     341           0 :                 *pu_offset = (uint64_t)offset;
     342           0 :                 *pu_count = (uint64_t)count;
     343           0 :                 *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
     344             :         }
     345           0 :         return True;
     346             : }
     347             : 
     348             : /****************************************************************************
     349             :  Next - the functions that deal with in memory database storing representations
     350             :  of either Windows CIFS locks or POSIX CIFS locks.
     351             : ****************************************************************************/
     352             : 
     353             : /* The key used in the in-memory POSIX databases. */
     354             : 
     355             : struct lock_ref_count_key {
     356             :         struct file_id id;
     357             :         char r;
     358             : }; 
     359             : 
     360             : /*******************************************************************
     361             :  Form a static locking key for a dev/inode pair for the lock ref count
     362             : ******************************************************************/
     363             : 
     364        2088 : static TDB_DATA locking_ref_count_key_fsp(const files_struct *fsp,
     365             :                                           struct lock_ref_count_key *tmp)
     366             : {
     367        2088 :         ZERO_STRUCTP(tmp);
     368        2088 :         tmp->id = fsp->file_id;
     369        2088 :         tmp->r = 'r';
     370        2088 :         return make_tdb_data((uint8_t *)tmp, sizeof(*tmp));
     371             : }
     372             : 
     373             : /*******************************************************************
     374             :  Convenience function to get an fd_array key from an fsp.
     375             : ******************************************************************/
     376             : 
     377        1039 : static TDB_DATA fd_array_key_fsp(const files_struct *fsp)
     378             : {
     379        1039 :         return make_tdb_data((const uint8_t *)&fsp->file_id, sizeof(fsp->file_id));
     380             : }
     381             : 
     382             : /*******************************************************************
     383             :  Create the in-memory POSIX lock databases.
     384             : ********************************************************************/
     385             : 
     386        1592 : bool posix_locking_init(bool read_only)
     387             : {
     388        1592 :         if (posix_pending_close_db != NULL) {
     389        1444 :                 return true;
     390             :         }
     391             : 
     392         148 :         posix_pending_close_db = db_open_rbt(NULL);
     393             : 
     394         148 :         if (posix_pending_close_db == NULL) {
     395           0 :                 DEBUG(0,("Failed to open POSIX pending close database.\n"));
     396           0 :                 return false;
     397             :         }
     398             : 
     399         148 :         return true;
     400             : }
     401             : 
     402             : /*******************************************************************
     403             :  Delete the in-memory POSIX lock databases.
     404             : ********************************************************************/
     405             : 
     406           0 : bool posix_locking_end(void)
     407             : {
     408             :         /*
     409             :          * Shouldn't we close all fd's here?
     410             :          */
     411           0 :         TALLOC_FREE(posix_pending_close_db);
     412           0 :         return true;
     413             : }
     414             : 
     415             : /****************************************************************************
     416             :  Next - the functions that deal with reference count of number of locks open
     417             :  on a dev/ino pair.
     418             : ****************************************************************************/
     419             : 
     420             : /****************************************************************************
     421             :  Increase the lock ref count. Creates lock_ref_count entry if it doesn't exist.
     422             : ****************************************************************************/
     423             : 
     424           5 : static void increment_lock_ref_count(const files_struct *fsp)
     425             : {
     426             :         struct lock_ref_count_key tmp;
     427           5 :         int32_t lock_ref_count = 0;
     428             :         NTSTATUS status;
     429             : 
     430           5 :         status = dbwrap_change_int32_atomic(
     431             :                 posix_pending_close_db, locking_ref_count_key_fsp(fsp, &tmp),
     432             :                 &lock_ref_count, 1);
     433             : 
     434           5 :         SMB_ASSERT(NT_STATUS_IS_OK(status));
     435           5 :         SMB_ASSERT(lock_ref_count < INT32_MAX);
     436             : 
     437           5 :         DEBUG(10,("lock_ref_count for file %s = %d\n",
     438             :                   fsp_str_dbg(fsp), (int)(lock_ref_count + 1)));
     439           5 : }
     440             : 
     441             : /****************************************************************************
     442             :  Reduce the lock ref count.
     443             : ****************************************************************************/
     444             : 
     445           5 : static void decrement_lock_ref_count(const files_struct *fsp)
     446             : {
     447             :         struct lock_ref_count_key tmp;
     448           5 :         int32_t lock_ref_count = 0;
     449             :         NTSTATUS status;
     450             : 
     451           5 :         status = dbwrap_change_int32_atomic(
     452             :                 posix_pending_close_db, locking_ref_count_key_fsp(fsp, &tmp),
     453             :                 &lock_ref_count, -1);
     454             : 
     455           5 :         SMB_ASSERT(NT_STATUS_IS_OK(status));
     456           5 :         SMB_ASSERT(lock_ref_count > 0);
     457             : 
     458           5 :         DEBUG(10,("lock_ref_count for file %s = %d\n",
     459             :                   fsp_str_dbg(fsp), (int)(lock_ref_count - 1)));
     460           5 : }
     461             : 
     462             : /****************************************************************************
     463             :  Fetch the lock ref count.
     464             : ****************************************************************************/
     465             : 
     466        1039 : static int32_t get_lock_ref_count(const files_struct *fsp)
     467             : {
     468             :         struct lock_ref_count_key tmp;
     469             :         NTSTATUS status;
     470        1039 :         int32_t lock_ref_count = 0;
     471             : 
     472        1039 :         status = dbwrap_fetch_int32(
     473             :                 posix_pending_close_db, locking_ref_count_key_fsp(fsp, &tmp),
     474             :                 &lock_ref_count);
     475             : 
     476        1878 :         if (!NT_STATUS_IS_OK(status) &&
     477        1039 :             !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     478           0 :                 DEBUG(0, ("Error fetching "
     479             :                           "lock ref count for file %s: %s\n",
     480             :                           fsp_str_dbg(fsp), nt_errstr(status)));
     481             :         }
     482        1039 :         return lock_ref_count;
     483             : }
     484             : 
     485             : /****************************************************************************
     486             :  Delete a lock_ref_count entry.
     487             : ****************************************************************************/
     488             : 
     489        1039 : static void delete_lock_ref_count(const files_struct *fsp)
     490             : {
     491             :         struct lock_ref_count_key tmp;
     492             : 
     493             :         /* Not a bug if it doesn't exist - no locks were ever granted. */
     494             : 
     495        1039 :         dbwrap_delete(posix_pending_close_db,
     496             :                       locking_ref_count_key_fsp(fsp, &tmp));
     497             : 
     498        1039 :         DEBUG(10,("delete_lock_ref_count for file %s\n",
     499             :                   fsp_str_dbg(fsp)));
     500        1039 : }
     501             : 
     502             : /****************************************************************************
     503             :  Next - the functions that deal with storing fd's that have outstanding
     504             :  POSIX locks when closed.
     505             : ****************************************************************************/
     506             : 
     507             : /****************************************************************************
     508             :  The records in posix_pending_close_db are composed of an array of
     509             :  ints keyed by dev/ino pair. Those ints are the fd's that were open on
     510             :  this dev/ino pair that should have been closed, but can't as the lock
     511             :  ref count is non zero.
     512             : ****************************************************************************/
     513             : 
     514             : struct add_fd_to_close_entry_state {
     515             :         const struct files_struct *fsp;
     516             : };
     517             : 
     518           0 : static void add_fd_to_close_entry_fn(
     519             :         struct db_record *rec,
     520             :         TDB_DATA value,
     521             :         void *private_data)
     522             : {
     523           0 :         struct add_fd_to_close_entry_state *state = private_data;
     524           0 :         int fd = fsp_get_pathref_fd(state->fsp);
     525           0 :         TDB_DATA values[] = {
     526             :                 value,
     527             :                 { .dptr = (uint8_t *)&fd,
     528             :                   .dsize = sizeof(fd) },
     529             :         };
     530             :         NTSTATUS status;
     531             : 
     532           0 :         SMB_ASSERT((values[0].dsize % sizeof(int)) == 0);
     533             : 
     534           0 :         status = dbwrap_record_storev(rec, values, ARRAY_SIZE(values), 0);
     535           0 :         SMB_ASSERT(NT_STATUS_IS_OK(status));
     536           0 : }
     537             : 
     538             : /****************************************************************************
     539             :  Add an fd to the pending close db.
     540             : ****************************************************************************/
     541             : 
     542           0 : static void add_fd_to_close_entry(const files_struct *fsp)
     543             : {
     544           0 :         struct add_fd_to_close_entry_state state = { .fsp = fsp };
     545             :         NTSTATUS status;
     546             : 
     547           0 :         status = dbwrap_do_locked(
     548             :                 posix_pending_close_db,
     549             :                 fd_array_key_fsp(fsp),
     550             :                 add_fd_to_close_entry_fn,
     551             :                 &state);
     552           0 :         SMB_ASSERT(NT_STATUS_IS_OK(status));
     553             : 
     554           0 :         DBG_DEBUG("added fd %d file %s\n",
     555             :                   fsp_get_pathref_fd(fsp),
     556             :                   fsp_str_dbg(fsp));
     557           0 : }
     558             : 
     559        1039 : static void fd_close_posix_fn(
     560             :         struct db_record *rec,
     561             :         TDB_DATA data,
     562             :         void *private_data)
     563             : {
     564             :         size_t num_fds, i;
     565             : 
     566        1039 :         SMB_ASSERT((data.dsize % sizeof(int)) == 0);
     567        1039 :         num_fds = data.dsize / sizeof(int);
     568             : 
     569        1039 :         for (i=0; i<num_fds; i++) {
     570             :                 int fd;
     571           0 :                 memcpy(&fd, data.dptr, sizeof(int));
     572           0 :                 close(fd);
     573           0 :                 data.dptr += sizeof(int);
     574             :         }
     575        1039 :         dbwrap_record_delete(rec);
     576        1039 : }
     577             : 
     578             : /****************************************************************************
     579             :  Deal with pending closes needed by POSIX locking support.
     580             :  Note that locking_close_file() is expected to have been called
     581             :  to delete all locks on this fsp before this function is called.
     582             : ****************************************************************************/
     583             : 
     584      117650 : int fd_close_posix(const struct files_struct *fsp)
     585             : {
     586             :         NTSTATUS status;
     587             : 
     588      209914 :         if (!lp_locking(fsp->conn->params) ||
     589      209914 :             !lp_posix_locking(fsp->conn->params) ||
     590             :             fsp->fsp_flags.use_ofd_locks)
     591             :         {
     592             :                 /*
     593             :                  * No locking or POSIX to worry about or we are using POSIX
     594             :                  * open file description lock semantics which only removes
     595             :                  * locks on the file descriptor we're closing. Just close.
     596             :                  */
     597      116611 :                 return close(fsp_get_pathref_fd(fsp));
     598             :         }
     599             : 
     600        1039 :         if (get_lock_ref_count(fsp)) {
     601             : 
     602             :                 /*
     603             :                  * There are outstanding locks on this dev/inode pair on
     604             :                  * other fds. Add our fd to the pending close db. We also
     605             :                  * set fsp_get_io_fd(fsp) to -1 inside fd_close() after returning
     606             :                  * from VFS layer.
     607             :                  */
     608             : 
     609           0 :                 add_fd_to_close_entry(fsp);
     610           0 :                 return 0;
     611             :         }
     612             : 
     613        1039 :         status = dbwrap_do_locked(
     614             :                 posix_pending_close_db,
     615             :                 fd_array_key_fsp(fsp),
     616             :                 fd_close_posix_fn,
     617             :                 NULL);
     618        1039 :         if (!NT_STATUS_IS_OK(status)) {
     619           0 :                 DBG_WARNING("dbwrap_do_locked failed: %s\n",
     620             :                             nt_errstr(status));
     621             :         }
     622             : 
     623             :         /* Don't need a lock ref count on this dev/ino anymore. */
     624        1039 :         delete_lock_ref_count(fsp);
     625             : 
     626             :         /*
     627             :          * Finally close the fd associated with this fsp.
     628             :          */
     629             : 
     630        1039 :         return close(fsp_get_pathref_fd(fsp));
     631             : }
     632             : 
     633             : /****************************************************************************
     634             :  Next - the functions that deal with the mapping CIFS Windows locks onto
     635             :  the underlying system POSIX locks.
     636             : ****************************************************************************/
     637             : 
     638             : /*
     639             :  * Structure used when splitting a lock range
     640             :  * into a POSIX lock range. Doubly linked list.
     641             :  */
     642             : 
     643             : struct lock_list {
     644             :         struct lock_list *next;
     645             :         struct lock_list *prev;
     646             :         off_t start;
     647             :         off_t size;
     648             : };
     649             : 
     650             : /****************************************************************************
     651             :  Create a list of lock ranges that don't overlap a given range. Used in calculating
     652             :  POSIX locks and unlocks. This is a difficult function that requires ASCII art to
     653             :  understand it :-).
     654             : ****************************************************************************/
     655             : 
     656          10 : static struct lock_list *posix_lock_list(TALLOC_CTX *ctx,
     657             :                                                 struct lock_list *lhead,
     658             :                                                 const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */
     659             :                                                 const struct lock_struct *plocks,
     660             :                                                 int num_locks)
     661             : {
     662             :         int i;
     663             : 
     664             :         /*
     665             :          * Check the current lock list on this dev/inode pair.
     666             :          * Quit if the list is deleted.
     667             :          */
     668             : 
     669          10 :         DEBUG(10, ("posix_lock_list: curr: start=%ju,size=%ju\n",
     670             :                    (uintmax_t)lhead->start, (uintmax_t)lhead->size ));
     671             : 
     672          10 :         for (i=0; i<num_locks && lhead; i++) {
     673           0 :                 const struct lock_struct *lock = &plocks[i];
     674             :                 struct lock_list *l_curr;
     675             : 
     676             :                 /* Ignore all but read/write locks. */
     677           0 :                 if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
     678           0 :                         continue;
     679             :                 }
     680             : 
     681             :                 /* Ignore locks not owned by this process. */
     682           0 :                 if (!server_id_equal(&lock->context.pid, &lock_ctx->pid)) {
     683           0 :                         continue;
     684             :                 }
     685             : 
     686             :                 /*
     687             :                  * Walk the lock list, checking for overlaps. Note that
     688             :                  * the lock list can expand within this loop if the current
     689             :                  * range being examined needs to be split.
     690             :                  */
     691             : 
     692           0 :                 for (l_curr = lhead; l_curr;) {
     693             : 
     694           0 :                         DEBUG(10, ("posix_lock_list: lock: fnum=%ju: "
     695             :                                    "start=%ju,size=%ju:type=%s",
     696             :                                    (uintmax_t)lock->fnum,
     697             :                                    (uintmax_t)lock->start,
     698             :                                    (uintmax_t)lock->size,
     699             :                                    posix_lock_type_name(lock->lock_type) ));
     700             : 
     701           0 :                         if ( (l_curr->start >= (lock->start + lock->size)) ||
     702           0 :                                  (lock->start >= (l_curr->start + l_curr->size))) {
     703             : 
     704             :                                 /* No overlap with existing lock - leave this range alone. */
     705             : /*********************************************
     706             :                                              +---------+
     707             :                                              | l_curr  |
     708             :                                              +---------+
     709             :                                 +-------+
     710             :                                 | lock  |
     711             :                                 +-------+
     712             : OR....
     713             :              +---------+
     714             :              |  l_curr |
     715             :              +---------+
     716             : **********************************************/
     717             : 
     718           0 :                                 DEBUG(10,(" no overlap case.\n" ));
     719             : 
     720           0 :                                 l_curr = l_curr->next;
     721             : 
     722           0 :                         } else if ( (l_curr->start >= lock->start) &&
     723           0 :                                                 (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
     724             : 
     725             :                                 /*
     726             :                                  * This range is completely overlapped by this existing lock range
     727             :                                  * and thus should have no effect. Delete it from the list.
     728             :                                  */
     729             : /*********************************************
     730             :                 +---------+
     731             :                 |  l_curr |
     732             :                 +---------+
     733             :         +---------------------------+
     734             :         |       lock                |
     735             :         +---------------------------+
     736             : **********************************************/
     737             :                                 /* Save the next pointer */
     738           0 :                                 struct lock_list *ul_next = l_curr->next;
     739             : 
     740           0 :                                 DEBUG(10,(" delete case.\n" ));
     741             : 
     742           0 :                                 DLIST_REMOVE(lhead, l_curr);
     743           0 :                                 if(lhead == NULL) {
     744           0 :                                         break; /* No more list... */
     745             :                                 }
     746             : 
     747           0 :                                 l_curr = ul_next;
     748             :                                 
     749           0 :                         } else if ( (l_curr->start >= lock->start) &&
     750           0 :                                                 (l_curr->start < lock->start + lock->size) &&
     751           0 :                                                 (l_curr->start + l_curr->size > lock->start + lock->size) ) {
     752             : 
     753             :                                 /*
     754             :                                  * This range overlaps the existing lock range at the high end.
     755             :                                  * Truncate by moving start to existing range end and reducing size.
     756             :                                  */
     757             : /*********************************************
     758             :                 +---------------+
     759             :                 |  l_curr       |
     760             :                 +---------------+
     761             :         +---------------+
     762             :         |    lock       |
     763             :         +---------------+
     764             : BECOMES....
     765             :                         +-------+
     766             :                         | l_curr|
     767             :                         +-------+
     768             : **********************************************/
     769             : 
     770           0 :                                 l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size);
     771           0 :                                 l_curr->start = lock->start + lock->size;
     772             : 
     773           0 :                                 DEBUG(10, (" truncate high case: start=%ju,"
     774             :                                            "size=%ju\n",
     775             :                                            (uintmax_t)l_curr->start,
     776             :                                            (uintmax_t)l_curr->size ));
     777             : 
     778           0 :                                 l_curr = l_curr->next;
     779             : 
     780           0 :                         } else if ( (l_curr->start < lock->start) &&
     781           0 :                                                 (l_curr->start + l_curr->size > lock->start) &&
     782           0 :                                                 (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
     783             : 
     784             :                                 /*
     785             :                                  * This range overlaps the existing lock range at the low end.
     786             :                                  * Truncate by reducing size.
     787             :                                  */
     788             : /*********************************************
     789             :    +---------------+
     790             :    |  l_curr       |
     791             :    +---------------+
     792             :            +---------------+
     793             :            |    lock       |
     794             :            +---------------+
     795             : BECOMES....
     796             :    +-------+
     797             :    | l_curr|
     798             :    +-------+
     799             : **********************************************/
     800             : 
     801           0 :                                 l_curr->size = lock->start - l_curr->start;
     802             : 
     803           0 :                                 DEBUG(10, (" truncate low case: start=%ju,"
     804             :                                            "size=%ju\n",
     805             :                                            (uintmax_t)l_curr->start,
     806             :                                            (uintmax_t)l_curr->size ));
     807             : 
     808           0 :                                 l_curr = l_curr->next;
     809             :                 
     810           0 :                         } else if ( (l_curr->start < lock->start) &&
     811           0 :                                                 (l_curr->start + l_curr->size > lock->start + lock->size) ) {
     812             :                                 /*
     813             :                                  * Worst case scenario. Range completely overlaps an existing
     814             :                                  * lock range. Split the request into two, push the new (upper) request
     815             :                                  * into the dlink list, and continue with the entry after l_new (as we
     816             :                                  * know that l_new will not overlap with this lock).
     817             :                                  */
     818             : /*********************************************
     819             :         +---------------------------+
     820             :         |        l_curr             |
     821             :         +---------------------------+
     822             :                 +---------+
     823             :                 | lock    |
     824             :                 +---------+
     825             : BECOMES.....
     826             :         +-------+         +---------+
     827             :         | l_curr|         | l_new   |
     828             :         +-------+         +---------+
     829             : **********************************************/
     830           0 :                                 struct lock_list *l_new = talloc(ctx, struct lock_list);
     831             : 
     832           0 :                                 if(l_new == NULL) {
     833           0 :                                         DEBUG(0,("posix_lock_list: talloc fail.\n"));
     834           0 :                                         return NULL; /* The talloc_destroy takes care of cleanup. */
     835             :                                 }
     836             : 
     837           0 :                                 ZERO_STRUCTP(l_new);
     838           0 :                                 l_new->start = lock->start + lock->size;
     839           0 :                                 l_new->size = l_curr->start + l_curr->size - l_new->start;
     840             : 
     841             :                                 /* Truncate the l_curr. */
     842           0 :                                 l_curr->size = lock->start - l_curr->start;
     843             : 
     844           0 :                                 DEBUG(10, (" split case: curr: start=%ju,"
     845             :                                            "size=%ju new: start=%ju,"
     846             :                                            "size=%ju\n",
     847             :                                            (uintmax_t)l_curr->start,
     848             :                                            (uintmax_t)l_curr->size,
     849             :                                            (uintmax_t)l_new->start,
     850             :                                            (uintmax_t)l_new->size ));
     851             : 
     852             :                                 /*
     853             :                                  * Add into the dlink list after the l_curr point - NOT at lhead. 
     854             :                                  */
     855           0 :                                 DLIST_ADD_AFTER(lhead, l_new, l_curr);
     856             : 
     857             :                                 /* And move after the link we added. */
     858           0 :                                 l_curr = l_new->next;
     859             : 
     860             :                         } else {
     861             : 
     862             :                                 /*
     863             :                                  * This logic case should never happen. Ensure this is the
     864             :                                  * case by forcing an abort.... Remove in production.
     865             :                                  */
     866           0 :                                 char *msg = NULL;
     867             : 
     868           0 :                                 if (asprintf(&msg, "logic flaw in cases: "
     869             :                                              "l_curr: start = %ju, "
     870             :                                              "size = %ju : lock: "
     871             :                                              "start = %ju, size = %ju",
     872           0 :                                              (uintmax_t)l_curr->start,
     873           0 :                                              (uintmax_t)l_curr->size,
     874           0 :                                              (uintmax_t)lock->start,
     875           0 :                                              (uintmax_t)lock->size ) != -1) {
     876           0 :                                         smb_panic(msg);
     877             :                                 } else {
     878           0 :                                         smb_panic("posix_lock_list");
     879             :                                 }
     880             :                         }
     881             :                 } /* end for ( l_curr = lhead; l_curr;) */
     882             :         } /* end for (i=0; i<num_locks && ul_head; i++) */
     883             : 
     884          10 :         return lhead;
     885             : }
     886             : 
     887             : /****************************************************************************
     888             :  POSIX function to acquire a lock. Returns True if the
     889             :  lock could be granted, False if not.
     890             : ****************************************************************************/
     891             : 
     892           5 : bool set_posix_lock_windows_flavour(files_struct *fsp,
     893             :                         uint64_t u_offset,
     894             :                         uint64_t u_count,
     895             :                         enum brl_type lock_type,
     896             :                         const struct lock_context *lock_ctx,
     897             :                         const struct lock_struct *plocks,
     898             :                         int num_locks,
     899             :                         int *errno_ret)
     900             : {
     901             :         off_t offset;
     902             :         off_t count;
     903           5 :         int posix_lock_type = map_posix_lock_type(fsp,lock_type);
     904           5 :         bool ret = True;
     905             :         size_t lock_count;
     906           5 :         TALLOC_CTX *l_ctx = NULL;
     907           5 :         struct lock_list *llist = NULL;
     908           5 :         struct lock_list *ll = NULL;
     909             : 
     910           5 :         DEBUG(5, ("set_posix_lock_windows_flavour: File %s, offset = %ju, "
     911             :                   "count = %ju, type = %s\n", fsp_str_dbg(fsp),
     912             :                   (uintmax_t)u_offset, (uintmax_t)u_count,
     913             :                   posix_lock_type_name(lock_type)));
     914             : 
     915             :         /*
     916             :          * If the requested lock won't fit in the POSIX range, we will
     917             :          * pretend it was successful.
     918             :          */
     919             : 
     920           5 :         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
     921           0 :                 increment_lock_ref_count(fsp);
     922           0 :                 return True;
     923             :         }
     924             : 
     925             :         /*
     926             :          * Windows is very strange. It allows read locks to be overlayed
     927             :          * (even over a write lock), but leaves the write lock in force until the first
     928             :          * unlock. It also reference counts the locks. This means the following sequence :
     929             :          *
     930             :          * process1                                      process2
     931             :          * ------------------------------------------------------------------------
     932             :          * WRITE LOCK : start = 2, len = 10
     933             :          *                                            READ LOCK: start =0, len = 10 - FAIL
     934             :          * READ LOCK : start = 0, len = 14 
     935             :          *                                            READ LOCK: start =0, len = 10 - FAIL
     936             :          * UNLOCK : start = 2, len = 10
     937             :          *                                            READ LOCK: start =0, len = 10 - OK
     938             :          *
     939             :          * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but
     940             :          * would leave a single read lock over the 0-14 region.
     941             :          */
     942             :         
     943           5 :         if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {
     944           0 :                 DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n"));
     945           0 :                 return False;
     946             :         }
     947             : 
     948           5 :         if ((ll = talloc(l_ctx, struct lock_list)) == NULL) {
     949           0 :                 DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
     950           0 :                 talloc_destroy(l_ctx);
     951           0 :                 return False;
     952             :         }
     953             : 
     954             :         /*
     955             :          * Create the initial list entry containing the
     956             :          * lock we want to add.
     957             :          */
     958             : 
     959           5 :         ZERO_STRUCTP(ll);
     960           5 :         ll->start = offset;
     961           5 :         ll->size = count;
     962             : 
     963           5 :         DLIST_ADD(llist, ll);
     964             : 
     965             :         /*
     966             :          * The following call calculates if there are any
     967             :          * overlapping locks held by this process on
     968             :          * fd's open on the same file and splits this list
     969             :          * into a list of lock ranges that do not overlap with existing
     970             :          * POSIX locks.
     971             :          */
     972             : 
     973           5 :         llist = posix_lock_list(l_ctx,
     974             :                                 llist,
     975             :                                 lock_ctx, /* Lock context llist belongs to. */
     976             :                                 plocks,
     977             :                                 num_locks);
     978             : 
     979             :         /*
     980             :          * Add the POSIX locks on the list of ranges returned.
     981             :          * As the lock is supposed to be added atomically, we need to
     982             :          * back out all the locks if any one of these calls fail.
     983             :          */
     984             : 
     985          10 :         for (lock_count = 0, ll = llist; ll; ll = ll->next, lock_count++) {
     986           5 :                 offset = ll->start;
     987           5 :                 count = ll->size;
     988             : 
     989           5 :                 DEBUG(5, ("set_posix_lock_windows_flavour: Real lock: "
     990             :                           "Type = %s: offset = %ju, count = %ju\n",
     991             :                           posix_lock_type_name(posix_lock_type),
     992             :                           (uintmax_t)offset, (uintmax_t)count ));
     993             : 
     994           5 :                 if (!posix_fcntl_lock(fsp,F_SETLK,offset,count,posix_lock_type)) {
     995           0 :                         *errno_ret = errno;
     996           0 :                         DEBUG(5, ("set_posix_lock_windows_flavour: Lock "
     997             :                                   "fail !: Type = %s: offset = %ju, "
     998             :                                   "count = %ju. Errno = %s\n",
     999             :                                   posix_lock_type_name(posix_lock_type),
    1000             :                                   (uintmax_t)offset, (uintmax_t)count,
    1001             :                                   strerror(errno) ));
    1002           0 :                         ret = False;
    1003           0 :                         break;
    1004             :                 }
    1005             :         }
    1006             : 
    1007           5 :         if (!ret) {
    1008             : 
    1009             :                 /*
    1010             :                  * Back out all the POSIX locks we have on fail.
    1011             :                  */
    1012             : 
    1013           0 :                 for (ll = llist; lock_count; ll = ll->next, lock_count--) {
    1014           0 :                         offset = ll->start;
    1015           0 :                         count = ll->size;
    1016             : 
    1017           0 :                         DEBUG(5, ("set_posix_lock_windows_flavour: Backing "
    1018             :                                   "out locks: Type = %s: offset = %ju, "
    1019             :                                   "count = %ju\n",
    1020             :                                   posix_lock_type_name(posix_lock_type),
    1021             :                                   (uintmax_t)offset, (uintmax_t)count ));
    1022             : 
    1023           0 :                         posix_fcntl_lock(fsp,F_SETLK,offset,count,F_UNLCK);
    1024             :                 }
    1025             :         } else {
    1026             :                 /* Remember the number of locks we have on this dev/ino pair. */
    1027           5 :                 increment_lock_ref_count(fsp);
    1028             :         }
    1029             : 
    1030           5 :         talloc_destroy(l_ctx);
    1031           5 :         return ret;
    1032             : }
    1033             : 
    1034             : /****************************************************************************
    1035             :  POSIX function to release a lock. Returns True if the
    1036             :  lock could be released, False if not.
    1037             : ****************************************************************************/
    1038             : 
    1039           5 : bool release_posix_lock_windows_flavour(files_struct *fsp,
    1040             :                                 uint64_t u_offset,
    1041             :                                 uint64_t u_count,
    1042             :                                 enum brl_type deleted_lock_type,
    1043             :                                 const struct lock_context *lock_ctx,
    1044             :                                 const struct lock_struct *plocks,
    1045             :                                 int num_locks)
    1046             : {
    1047             :         off_t offset;
    1048             :         off_t count;
    1049           5 :         bool ret = True;
    1050           5 :         TALLOC_CTX *ul_ctx = NULL;
    1051           5 :         struct lock_list *ulist = NULL;
    1052           5 :         struct lock_list *ul = NULL;
    1053             : 
    1054           5 :         DEBUG(5, ("release_posix_lock_windows_flavour: File %s, offset = %ju, "
    1055             :                   "count = %ju\n", fsp_str_dbg(fsp),
    1056             :                   (uintmax_t)u_offset, (uintmax_t)u_count));
    1057             : 
    1058             :         /* Remember the number of locks we have on this dev/ino pair. */
    1059           5 :         decrement_lock_ref_count(fsp);
    1060             : 
    1061             :         /*
    1062             :          * If the requested lock won't fit in the POSIX range, we will
    1063             :          * pretend it was successful.
    1064             :          */
    1065             : 
    1066           5 :         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
    1067           0 :                 return True;
    1068             :         }
    1069             : 
    1070           5 :         if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
    1071           0 :                 DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
    1072           0 :                 return False;
    1073             :         }
    1074             : 
    1075           5 :         if ((ul = talloc(ul_ctx, struct lock_list)) == NULL) {
    1076           0 :                 DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
    1077           0 :                 talloc_destroy(ul_ctx);
    1078           0 :                 return False;
    1079             :         }
    1080             : 
    1081             :         /*
    1082             :          * Create the initial list entry containing the
    1083             :          * lock we want to remove.
    1084             :          */
    1085             : 
    1086           5 :         ZERO_STRUCTP(ul);
    1087           5 :         ul->start = offset;
    1088           5 :         ul->size = count;
    1089             : 
    1090           5 :         DLIST_ADD(ulist, ul);
    1091             : 
    1092             :         /*
    1093             :          * The following call calculates if there are any
    1094             :          * overlapping locks held by this process on
    1095             :          * fd's open on the same file and creates a
    1096             :          * list of unlock ranges that will allow
    1097             :          * POSIX lock ranges to remain on the file whilst the
    1098             :          * unlocks are performed.
    1099             :          */
    1100             : 
    1101           5 :         ulist = posix_lock_list(ul_ctx,
    1102             :                                 ulist,
    1103             :                                 lock_ctx, /* Lock context ulist belongs to. */
    1104             :                                 plocks,
    1105             :                                 num_locks);
    1106             : 
    1107             :         /*
    1108             :          * If there were any overlapped entries (list is > 1 or size or start have changed),
    1109             :          * and the lock_type we just deleted from
    1110             :          * the upper layer tdb was a write lock, then before doing the unlock we need to downgrade
    1111             :          * the POSIX lock to a read lock. This allows any overlapping read locks
    1112             :          * to be atomically maintained.
    1113             :          */
    1114             : 
    1115           5 :         if (deleted_lock_type == WRITE_LOCK &&
    1116           5 :                         (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) {
    1117             : 
    1118           0 :                 DEBUG(5, ("release_posix_lock_windows_flavour: downgrading "
    1119             :                           "lock to READ: offset = %ju, count = %ju\n",
    1120             :                           (uintmax_t)offset, (uintmax_t)count ));
    1121             : 
    1122           0 :                 if (!posix_fcntl_lock(fsp,F_SETLK,offset,count,F_RDLCK)) {
    1123           0 :                         DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) ));
    1124           0 :                         talloc_destroy(ul_ctx);
    1125           0 :                         return False;
    1126             :                 }
    1127             :         }
    1128             : 
    1129             :         /*
    1130             :          * Release the POSIX locks on the list of ranges returned.
    1131             :          */
    1132             : 
    1133          10 :         for(; ulist; ulist = ulist->next) {
    1134           5 :                 offset = ulist->start;
    1135           5 :                 count = ulist->size;
    1136             : 
    1137           5 :                 DEBUG(5, ("release_posix_lock_windows_flavour: Real unlock: "
    1138             :                           "offset = %ju, count = %ju\n",
    1139             :                           (uintmax_t)offset, (uintmax_t)count ));
    1140             : 
    1141           5 :                 if (!posix_fcntl_lock(fsp,F_SETLK,offset,count,F_UNLCK)) {
    1142           0 :                         ret = False;
    1143             :                 }
    1144             :         }
    1145             : 
    1146           5 :         talloc_destroy(ul_ctx);
    1147           5 :         return ret;
    1148             : }
    1149             : 
    1150             : /****************************************************************************
    1151             :  Next - the functions that deal with mapping CIFS POSIX locks onto
    1152             :  the underlying system POSIX locks.
    1153             : ****************************************************************************/
    1154             : 
    1155             : /****************************************************************************
    1156             :  We only increment the lock ref count when we see a POSIX lock on a context
    1157             :  that doesn't already have them.
    1158             : ****************************************************************************/
    1159             : 
    1160           0 : static void increment_posix_lock_count(const files_struct *fsp,
    1161             :                                         uint64_t smblctx)
    1162             : {
    1163             :         NTSTATUS status;
    1164             :         TDB_DATA ctx_key;
    1165           0 :         TDB_DATA val = { 0 };
    1166             : 
    1167           0 :         ctx_key.dptr = (uint8_t *)&smblctx;
    1168           0 :         ctx_key.dsize = sizeof(smblctx);
    1169             : 
    1170             :         /*
    1171             :          * Don't increment if we already have any POSIX flavor
    1172             :          * locks on this context.
    1173             :          */
    1174           0 :         if (dbwrap_exists(posix_pending_close_db, ctx_key)) {
    1175           0 :                 return;
    1176             :         }
    1177             : 
    1178             :         /* Remember that we have POSIX flavor locks on this context. */
    1179           0 :         status = dbwrap_store(posix_pending_close_db, ctx_key, val, 0);
    1180           0 :         SMB_ASSERT(NT_STATUS_IS_OK(status));
    1181             : 
    1182           0 :         increment_lock_ref_count(fsp);
    1183             : 
    1184           0 :         DEBUG(10,("posix_locks set for file %s\n",
    1185             :                 fsp_str_dbg(fsp)));
    1186             : }
    1187             : 
    1188           0 : static void decrement_posix_lock_count(const files_struct *fsp, uint64_t smblctx)
    1189             : {
    1190             :         NTSTATUS status;
    1191             :         TDB_DATA ctx_key;
    1192             : 
    1193           0 :         ctx_key.dptr = (uint8_t *)&smblctx;
    1194           0 :         ctx_key.dsize = sizeof(smblctx);
    1195             : 
    1196           0 :         status = dbwrap_delete(posix_pending_close_db, ctx_key);
    1197           0 :         SMB_ASSERT(NT_STATUS_IS_OK(status));
    1198             : 
    1199           0 :         decrement_lock_ref_count(fsp);
    1200             : 
    1201           0 :         DEBUG(10,("posix_locks deleted for file %s\n",
    1202             :                 fsp_str_dbg(fsp)));
    1203           0 : }
    1204             : 
    1205             : /****************************************************************************
    1206             :  Return true if any locks exist on the given lock context.
    1207             : ****************************************************************************/
    1208             : 
    1209           0 : static bool locks_exist_on_context(const struct lock_struct *plocks,
    1210             :                                 int num_locks,
    1211             :                                 const struct lock_context *lock_ctx)
    1212             : {
    1213             :         int i;
    1214             : 
    1215           0 :         for (i=0; i < num_locks; i++) {
    1216           0 :                 const struct lock_struct *lock = &plocks[i];
    1217             : 
    1218             :                 /* Ignore all but read/write locks. */
    1219           0 :                 if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
    1220           0 :                         continue;
    1221             :                 }
    1222             : 
    1223             :                 /* Ignore locks not owned by this process. */
    1224           0 :                 if (!server_id_equal(&lock->context.pid, &lock_ctx->pid)) {
    1225           0 :                         continue;
    1226             :                 }
    1227             : 
    1228           0 :                 if (lock_ctx->smblctx == lock->context.smblctx) {
    1229           0 :                         return true;
    1230             :                 }
    1231             :         }
    1232           0 :         return false;
    1233             : }
    1234             : 
    1235             : /****************************************************************************
    1236             :  POSIX function to acquire a lock. Returns True if the
    1237             :  lock could be granted, False if not.
    1238             :  As POSIX locks don't stack or conflict (they just overwrite)
    1239             :  we can map the requested lock directly onto a system one. We
    1240             :  know it doesn't conflict with locks on other contexts as the
    1241             :  upper layer would have refused it.
    1242             : ****************************************************************************/
    1243             : 
    1244           0 : bool set_posix_lock_posix_flavour(files_struct *fsp,
    1245             :                         uint64_t u_offset,
    1246             :                         uint64_t u_count,
    1247             :                         enum brl_type lock_type,
    1248             :                         const struct lock_context *lock_ctx,
    1249             :                         int *errno_ret)
    1250             : {
    1251             :         off_t offset;
    1252             :         off_t count;
    1253           0 :         int posix_lock_type = map_posix_lock_type(fsp,lock_type);
    1254             : 
    1255           0 :         DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %ju, count "
    1256             :                  "= %ju, type = %s\n", fsp_str_dbg(fsp),
    1257             :                  (uintmax_t)u_offset, (uintmax_t)u_count,
    1258             :                  posix_lock_type_name(lock_type)));
    1259             : 
    1260             :         /*
    1261             :          * If the requested lock won't fit in the POSIX range, we will
    1262             :          * pretend it was successful.
    1263             :          */
    1264             : 
    1265           0 :         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
    1266           0 :                 increment_posix_lock_count(fsp, lock_ctx->smblctx);
    1267           0 :                 return True;
    1268             :         }
    1269             : 
    1270           0 :         if (!posix_fcntl_lock(fsp,F_SETLK,offset,count,posix_lock_type)) {
    1271           0 :                 *errno_ret = errno;
    1272           0 :                 DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %ju, count = %ju. Errno = %s\n",
    1273             :                         posix_lock_type_name(posix_lock_type), (intmax_t)offset, (intmax_t)count, strerror(errno) ));
    1274           0 :                 return False;
    1275             :         }
    1276           0 :         increment_posix_lock_count(fsp, lock_ctx->smblctx);
    1277           0 :         return True;
    1278             : }
    1279             : 
    1280             : /****************************************************************************
    1281             :  POSIX function to release a lock. Returns True if the
    1282             :  lock could be released, False if not.
    1283             :  We are given a complete lock state from the upper layer which is what the lock
    1284             :  state should be after the unlock has already been done, so what
    1285             :  we do is punch out holes in the unlock range where locks owned by this process
    1286             :  have a different lock context.
    1287             : ****************************************************************************/
    1288             : 
    1289           0 : bool release_posix_lock_posix_flavour(files_struct *fsp,
    1290             :                                 uint64_t u_offset,
    1291             :                                 uint64_t u_count,
    1292             :                                 const struct lock_context *lock_ctx,
    1293             :                                 const struct lock_struct *plocks,
    1294             :                                 int num_locks)
    1295             : {
    1296           0 :         bool ret = True;
    1297             :         off_t offset;
    1298             :         off_t count;
    1299           0 :         TALLOC_CTX *ul_ctx = NULL;
    1300           0 :         struct lock_list *ulist = NULL;
    1301           0 :         struct lock_list *ul = NULL;
    1302             : 
    1303           0 :         DEBUG(5, ("release_posix_lock_posix_flavour: File %s, offset = %ju, "
    1304             :                   "count = %ju\n", fsp_str_dbg(fsp),
    1305             :                   (uintmax_t)u_offset, (uintmax_t)u_count));
    1306             : 
    1307             :         /*
    1308             :          * If the requested lock won't fit in the POSIX range, we will
    1309             :          * pretend it was successful.
    1310             :          */
    1311             : 
    1312           0 :         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
    1313           0 :                 if (!locks_exist_on_context(plocks, num_locks, lock_ctx)) {
    1314           0 :                         decrement_posix_lock_count(fsp, lock_ctx->smblctx);
    1315             :                 }
    1316           0 :                 return True;
    1317             :         }
    1318             : 
    1319           0 :         if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
    1320           0 :                 DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
    1321           0 :                 return False;
    1322             :         }
    1323             : 
    1324           0 :         if ((ul = talloc(ul_ctx, struct lock_list)) == NULL) {
    1325           0 :                 DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
    1326           0 :                 talloc_destroy(ul_ctx);
    1327           0 :                 return False;
    1328             :         }
    1329             : 
    1330             :         /*
    1331             :          * Create the initial list entry containing the
    1332             :          * lock we want to remove.
    1333             :          */
    1334             : 
    1335           0 :         ZERO_STRUCTP(ul);
    1336           0 :         ul->start = offset;
    1337           0 :         ul->size = count;
    1338             : 
    1339           0 :         DLIST_ADD(ulist, ul);
    1340             : 
    1341             :         /*
    1342             :          * Walk the given array creating a linked list
    1343             :          * of unlock requests.
    1344             :          */
    1345             : 
    1346           0 :         ulist = posix_lock_list(ul_ctx,
    1347             :                                 ulist,
    1348             :                                 lock_ctx, /* Lock context ulist belongs to. */
    1349             :                                 plocks,
    1350             :                                 num_locks);
    1351             : 
    1352             :         /*
    1353             :          * Release the POSIX locks on the list of ranges returned.
    1354             :          */
    1355             : 
    1356           0 :         for(; ulist; ulist = ulist->next) {
    1357           0 :                 offset = ulist->start;
    1358           0 :                 count = ulist->size;
    1359             : 
    1360           0 :                 DEBUG(5, ("release_posix_lock_posix_flavour: Real unlock: "
    1361             :                           "offset = %ju, count = %ju\n",
    1362             :                           (uintmax_t)offset, (uintmax_t)count ));
    1363             : 
    1364           0 :                 if (!posix_fcntl_lock(fsp,F_SETLK,offset,count,F_UNLCK)) {
    1365           0 :                         ret = False;
    1366             :                 }
    1367             :         }
    1368             : 
    1369           0 :         if (!locks_exist_on_context(plocks, num_locks, lock_ctx)) {
    1370           0 :                 decrement_posix_lock_count(fsp, lock_ctx->smblctx);
    1371             :         }
    1372           0 :         talloc_destroy(ul_ctx);
    1373           0 :         return ret;
    1374             : }

Generated by: LCOV version 1.13