LCOV - code coverage report
Current view: top level - source3/locking - posix.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 287 409 70.2 %
Date: 2024-04-21 15:09:00 Functions: 22 26 84.6 %

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

Generated by: LCOV version 1.14