locking/posix.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Locking functions
00004    Copyright (C) Jeremy Allison 1992-2006
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 
00020    Revision History:
00021 
00022    POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
00023 */
00024 
00025 #include "includes.h"
00026 
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_LOCKING
00029 
00030 /*
00031  * The pending close database handle.
00032  */
00033 
00034 static TDB_CONTEXT *posix_pending_close_tdb;
00035 
00036 /****************************************************************************
00037  First - the functions that deal with the underlying system locks - these
00038  functions are used no matter if we're mapping CIFS Windows locks or CIFS
00039  POSIX locks onto POSIX.
00040 ****************************************************************************/
00041 
00042 /****************************************************************************
00043  Utility function to map a lock type correctly depending on the open
00044  mode of a file.
00045 ****************************************************************************/
00046 
00047 static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
00048 {
00049         if((lock_type == WRITE_LOCK) && !fsp->can_write) {
00050                 /*
00051                  * Many UNIX's cannot get a write lock on a file opened read-only.
00052                  * Win32 locking semantics allow this.
00053                  * Do the best we can and attempt a read-only lock.
00054                  */
00055                 DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
00056                 return F_RDLCK;
00057         }
00058 
00059         /*
00060          * This return should be the most normal, as we attempt
00061          * to always open files read/write.
00062          */
00063 
00064         return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
00065 }
00066 
00067 /****************************************************************************
00068  Debugging aid :-).
00069 ****************************************************************************/
00070 
00071 static const char *posix_lock_type_name(int lock_type)
00072 {
00073         return (lock_type == F_RDLCK) ? "READ" : "WRITE";
00074 }
00075 
00076 /****************************************************************************
00077  Check to see if the given unsigned lock range is within the possible POSIX
00078  range. Modifies the given args to be in range if possible, just returns
00079  False if not.
00080 ****************************************************************************/
00081 
00082 static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
00083                                 SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
00084 {
00085         SMB_OFF_T offset = (SMB_OFF_T)u_offset;
00086         SMB_OFF_T count = (SMB_OFF_T)u_count;
00087 
00088         /*
00089          * For the type of system we are, attempt to
00090          * find the maximum positive lock offset as an SMB_OFF_T.
00091          */
00092 
00093 #if defined(MAX_POSITIVE_LOCK_OFFSET) /* Some systems have arbitrary limits. */
00094 
00095         SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
00096 
00097 #elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
00098 
00099         /*
00100          * In this case SMB_OFF_T is 64 bits,
00101          * and the underlying system can handle 64 bit signed locks.
00102          */
00103 
00104         SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
00105         SMB_OFF_T mask = (mask2<<1);
00106         SMB_OFF_T max_positive_lock_offset = ~mask;
00107 
00108 #else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
00109 
00110         /*
00111          * In this case either SMB_OFF_T is 32 bits,
00112          * or the underlying system cannot handle 64 bit signed locks.
00113          * All offsets & counts must be 2^31 or less.
00114          */
00115 
00116         SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
00117 
00118 #endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
00119 
00120         /*
00121          * POSIX locks of length zero mean lock to end-of-file.
00122          * Win32 locks of length zero are point probes. Ignore
00123          * any Win32 locks of length zero. JRA.
00124          */
00125 
00126         if (count == (SMB_OFF_T)0) {
00127                 DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
00128                 return False;
00129         }
00130 
00131         /*
00132          * If the given offset was > max_positive_lock_offset then we cannot map this at all
00133          * ignore this lock.
00134          */
00135 
00136         if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
00137                 DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",
00138                                 (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));
00139                 return False;
00140         }
00141 
00142         /*
00143          * We must truncate the count to less than max_positive_lock_offset.
00144          */
00145 
00146         if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
00147                 count = max_positive_lock_offset;
00148         }
00149 
00150         /*
00151          * Truncate count to end at max lock offset.
00152          */
00153 
00154         if (offset + count < 0 || offset + count > max_positive_lock_offset) {
00155                 count = max_positive_lock_offset - offset;
00156         }
00157 
00158         /*
00159          * If we ate all the count, ignore this lock.
00160          */
00161 
00162         if (count == 0) {
00163                 DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",
00164                                 (double)u_offset, (double)u_count ));
00165                 return False;
00166         }
00167 
00168         /*
00169          * The mapping was successful.
00170          */
00171 
00172         DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
00173                         (double)offset, (double)count ));
00174 
00175         *offset_out = offset;
00176         *count_out = count;
00177         
00178         return True;
00179 }
00180 
00181 /****************************************************************************
00182  Actual function that does POSIX locks. Copes with 64 -> 32 bit cruft and
00183  broken NFS implementations.
00184 ****************************************************************************/
00185 
00186 static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
00187 {
00188         BOOL ret;
00189 
00190         DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
00191 
00192         ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
00193 
00194         if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
00195 
00196                 DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
00197                                         (double)offset,(double)count));
00198                 DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
00199                 DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
00200 
00201                 /*
00202                  * If the offset is > 0x7FFFFFFF then this will cause problems on
00203                  * 32 bit NFS mounted filesystems. Just ignore it.
00204                  */
00205 
00206                 if (offset & ~((SMB_OFF_T)0x7fffffff)) {
00207                         DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
00208                         return True;
00209                 }
00210 
00211                 if (count & ~((SMB_OFF_T)0x7fffffff)) {
00212                         /* 32 bit NFS file system, retry with smaller offset */
00213                         DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
00214                         errno = 0;
00215                         count &= 0x7fffffff;
00216                         ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
00217                 }
00218         }
00219 
00220         DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
00221         return ret;
00222 }
00223 
00224 /****************************************************************************
00225  Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
00226  broken NFS implementations.
00227 ****************************************************************************/
00228 
00229 static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
00230 {
00231         pid_t pid;
00232         BOOL ret;
00233 
00234         DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
00235                 fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
00236 
00237         ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
00238 
00239         if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno ==  EINVAL))) {
00240 
00241                 DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
00242                                         (double)*poffset,(double)*pcount));
00243                 DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
00244                 DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
00245 
00246                 /*
00247                  * If the offset is > 0x7FFFFFFF then this will cause problems on
00248                  * 32 bit NFS mounted filesystems. Just ignore it.
00249                  */
00250 
00251                 if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
00252                         DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
00253                         return True;
00254                 }
00255 
00256                 if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
00257                         /* 32 bit NFS file system, retry with smaller offset */
00258                         DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
00259                         errno = 0;
00260                         *pcount &= 0x7fffffff;
00261                         ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
00262                 }
00263         }
00264 
00265         DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
00266         return ret;
00267 }
00268 
00269 /****************************************************************************
00270  POSIX function to see if a file region is locked. Returns True if the
00271  region is locked, False otherwise.
00272 ****************************************************************************/
00273 
00274 BOOL is_posix_locked(files_struct *fsp,
00275                         SMB_BIG_UINT *pu_offset,
00276                         SMB_BIG_UINT *pu_count,
00277                         enum brl_type *plock_type,
00278                         enum brl_flavour lock_flav)
00279 {
00280         SMB_OFF_T offset;
00281         SMB_OFF_T count;
00282         int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
00283 
00284         DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
00285                 fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
00286 
00287         /*
00288          * If the requested lock won't fit in the POSIX range, we will
00289          * never set it, so presume it is not locked.
00290          */
00291 
00292         if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
00293                 return False;
00294         }
00295 
00296         if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
00297                 return False;
00298         }
00299 
00300         if (posix_lock_type == F_UNLCK) {
00301                 return False;
00302         }
00303 
00304         if (lock_flav == POSIX_LOCK) {
00305                 /* Only POSIX lock queries need to know the details. */
00306                 *pu_offset = (SMB_BIG_UINT)offset;
00307                 *pu_count = (SMB_BIG_UINT)count;
00308                 *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
00309         }
00310         return True;
00311 }
00312 
00313 /****************************************************************************
00314  Next - the functions that deal with in memory database storing representations
00315  of either Windows CIFS locks or POSIX CIFS locks.
00316 ****************************************************************************/
00317 
00318 /* The key used in the in-memory POSIX databases. */
00319 
00320 struct lock_ref_count_key {
00321         SMB_DEV_T device;
00322         SMB_INO_T inode;
00323         char r;
00324 }; 
00325 
00326 struct fd_key {
00327         SMB_DEV_T device;
00328         SMB_INO_T inode;
00329 }; 
00330 
00331 /*******************************************************************
00332  Form a static locking key for a dev/inode pair for the fd array.
00333 ******************************************************************/
00334 
00335 static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode)
00336 {
00337         static struct fd_key key;
00338         TDB_DATA kbuf;
00339 
00340         memset(&key, '\0', sizeof(key));
00341         key.device = dev;
00342         key.inode = inode;
00343         kbuf.dptr = (char *)&key;
00344         kbuf.dsize = sizeof(key);
00345         return kbuf;
00346 }
00347 
00348 /*******************************************************************
00349  Form a static locking key for a dev/inode pair for the lock ref count
00350 ******************************************************************/
00351 
00352 static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode)
00353 {
00354         static struct lock_ref_count_key key;
00355         TDB_DATA kbuf;
00356 
00357         memset(&key, '\0', sizeof(key));
00358         key.device = dev;
00359         key.inode = inode;
00360         key.r = 'r';
00361         kbuf.dptr = (char *)&key;
00362         kbuf.dsize = sizeof(key);
00363         return kbuf;
00364 }
00365 
00366 /*******************************************************************
00367  Convenience function to get an fd_array key from an fsp.
00368 ******************************************************************/
00369 
00370 static TDB_DATA fd_array_key_fsp(files_struct *fsp)
00371 {
00372         return fd_array_key(fsp->dev, fsp->inode);
00373 }
00374 
00375 /*******************************************************************
00376  Convenience function to get a lock ref count key from an fsp.
00377 ******************************************************************/
00378 
00379 static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp)
00380 {
00381         return locking_ref_count_key(fsp->dev, fsp->inode);
00382 }
00383 
00384 /*******************************************************************
00385  Create the in-memory POSIX lock databases.
00386 ********************************************************************/
00387 
00388 BOOL posix_locking_init(int read_only)
00389 {
00390         if (posix_pending_close_tdb) {
00391                 return True;
00392         }
00393         
00394         if (!posix_pending_close_tdb) {
00395                 posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
00396                                                    read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
00397         }
00398         if (!posix_pending_close_tdb) {
00399                 DEBUG(0,("Failed to open POSIX pending close database.\n"));
00400                 return False;
00401         }
00402 
00403         return True;
00404 }
00405 
00406 /*******************************************************************
00407  Delete the in-memory POSIX lock databases.
00408 ********************************************************************/
00409 
00410 BOOL posix_locking_end(void)
00411 {
00412         if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) {
00413                 return False;
00414         }
00415         return True;
00416 }
00417 
00418 /****************************************************************************
00419  Next - the functions that deal with storing fd's that have outstanding
00420  POSIX locks when closed.
00421 ****************************************************************************/
00422 
00423 /****************************************************************************
00424  The records in posix_pending_close_tdb are composed of an array of ints
00425  keyed by dev/ino pair.
00426  The first int is a reference count of the number of outstanding locks on
00427  all open fd's on this dev/ino pair. Any subsequent ints are the fd's that
00428  were open on this dev/ino pair that should have been closed, but can't as
00429  the lock ref count is non zero.
00430 ****************************************************************************/
00431 
00432 /****************************************************************************
00433  Keep a reference count of the number of Windows locks open on this dev/ino
00434  pair. Creates entry if it doesn't exist.
00435 ****************************************************************************/
00436 
00437 static void increment_windows_lock_ref_count(files_struct *fsp)
00438 {
00439         TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00440         TDB_DATA dbuf;
00441         int lock_ref_count;
00442 
00443         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00444         if (dbuf.dptr == NULL) {
00445                 dbuf.dptr = (char *)SMB_MALLOC_P(int);
00446                 if (!dbuf.dptr) {
00447                         smb_panic("increment_windows_lock_ref_count: malloc fail.\n");
00448                 }
00449                 memset(dbuf.dptr, '\0', sizeof(int));
00450                 dbuf.dsize = sizeof(int);
00451         }
00452 
00453         memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00454         lock_ref_count++;
00455         memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
00456         
00457         if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00458                 smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n");
00459         }
00460         SAFE_FREE(dbuf.dptr);
00461 
00462         DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n",
00463                 fsp->fsp_name, lock_ref_count ));
00464 }
00465 
00466 static void decrement_windows_lock_ref_count(files_struct *fsp)
00467 {
00468         TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00469         TDB_DATA dbuf;
00470         int lock_ref_count;
00471 
00472         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00473         if (!dbuf.dptr) {
00474                 smb_panic("decrement_windows_lock_ref_count: logic error.\n");
00475         }
00476 
00477         memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00478         lock_ref_count--;
00479         memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
00480 
00481         if (lock_ref_count < 0) {
00482                 smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n");
00483         }
00484 
00485         if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00486                 smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n");
00487         }
00488         SAFE_FREE(dbuf.dptr);
00489 
00490         DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n",
00491                 fsp->fsp_name, lock_ref_count ));
00492 }
00493 
00494 /****************************************************************************
00495  Bulk delete - subtract as many locks as we've just deleted.
00496 ****************************************************************************/
00497 
00498 void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount)
00499 {
00500         TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00501         TDB_DATA dbuf;
00502         int lock_ref_count;
00503 
00504         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00505         if (!dbuf.dptr) {
00506                 return;
00507         }
00508 
00509         memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00510         lock_ref_count -= dcount;
00511 
00512         if (lock_ref_count < 0) {
00513                 smb_panic("reduce_windows_lock_ref_count: lock_count logic error.\n");
00514         }
00515         memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
00516         
00517         if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00518                 smb_panic("reduce_windows_lock_ref_count: tdb_store_fail.\n");
00519         }
00520         SAFE_FREE(dbuf.dptr);
00521 
00522         DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n",
00523                 fsp->fsp_name, lock_ref_count ));
00524 }
00525 
00526 /****************************************************************************
00527  Fetch the lock ref count.
00528 ****************************************************************************/
00529 
00530 static int get_windows_lock_ref_count(files_struct *fsp)
00531 {
00532         TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00533         TDB_DATA dbuf;
00534         int lock_ref_count;
00535 
00536         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00537         if (!dbuf.dptr) {
00538                 lock_ref_count = 0;
00539         } else {
00540                 memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00541         }
00542         SAFE_FREE(dbuf.dptr);
00543 
00544         DEBUG(10,("get_windows_lock_count for file %s = %d\n",
00545                 fsp->fsp_name, lock_ref_count ));
00546         return lock_ref_count;
00547 }
00548 
00549 /****************************************************************************
00550  Delete a lock_ref_count entry.
00551 ****************************************************************************/
00552 
00553 static void delete_windows_lock_ref_count(files_struct *fsp)
00554 {
00555         TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00556 
00557         /* Not a bug if it doesn't exist - no locks were ever granted. */
00558         tdb_delete(posix_pending_close_tdb, kbuf);
00559         DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name));
00560 }
00561 
00562 /****************************************************************************
00563  Add an fd to the pending close tdb.
00564 ****************************************************************************/
00565 
00566 static void add_fd_to_close_entry(files_struct *fsp)
00567 {
00568         TDB_DATA kbuf = fd_array_key_fsp(fsp);
00569         TDB_DATA dbuf;
00570 
00571         dbuf.dptr = NULL;
00572         dbuf.dsize = 0;
00573 
00574         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00575 
00576         dbuf.dptr = (char *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
00577         if (!dbuf.dptr) {
00578                 smb_panic("add_fd_to_close_entry: Realloc fail !\n");
00579         }
00580 
00581         memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
00582         dbuf.dsize += sizeof(int);
00583 
00584         if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00585                 smb_panic("add_fd_to_close_entry: tdb_store_fail.\n");
00586         }
00587 
00588         DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n",
00589                 fsp->fh->fd, fsp->fsp_name ));
00590 
00591         SAFE_FREE(dbuf.dptr);
00592 }
00593 
00594 /****************************************************************************
00595  Remove all fd entries for a specific dev/inode pair from the tdb.
00596 ****************************************************************************/
00597 
00598 static void delete_close_entries(files_struct *fsp)
00599 {
00600         TDB_DATA kbuf = fd_array_key_fsp(fsp);
00601 
00602         if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) {
00603                 smb_panic("delete_close_entries: tdb_delete fail !\n");
00604         }
00605 }
00606 
00607 /****************************************************************************
00608  Get the array of POSIX pending close records for an open fsp. Caller must
00609  free. Returns number of entries.
00610 ****************************************************************************/
00611 
00612 static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
00613 {
00614         TDB_DATA kbuf = fd_array_key_fsp(fsp);
00615         TDB_DATA dbuf;
00616         size_t count = 0;
00617 
00618         *entries = NULL;
00619         dbuf.dptr = NULL;
00620 
00621         dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00622 
00623         if (!dbuf.dptr) {
00624                 return 0;
00625         }
00626 
00627         *entries = (int *)dbuf.dptr;
00628         count = (size_t)(dbuf.dsize / sizeof(int));
00629 
00630         return count;
00631 }
00632 
00633 /****************************************************************************
00634  Deal with pending closes needed by POSIX locking support.
00635  Note that posix_locking_close_file() is expected to have been called
00636  to delete all locks on this fsp before this function is called.
00637 ****************************************************************************/
00638 
00639 NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp)
00640 {
00641         int saved_errno = 0;
00642         int ret;
00643         int *fd_array = NULL;
00644         size_t count, i;
00645 
00646         if (!lp_locking(fsp->conn->params) || !lp_posix_locking(conn->params)) {
00647                 /*
00648                  * No locking or POSIX to worry about or we want POSIX semantics
00649                  * which will lose all locks on all fd's open on this dev/inode,
00650                  * just close.
00651                  */
00652                 ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
00653                 fsp->fh->fd = -1;
00654                 if (ret == -1) {
00655                         return map_nt_error_from_unix(errno);
00656                 }
00657                 return NT_STATUS_OK;
00658         }
00659 
00660         if (get_windows_lock_ref_count(fsp)) {
00661 
00662                 /*
00663                  * There are outstanding locks on this dev/inode pair on other fds.
00664                  * Add our fd to the pending close tdb and set fsp->fh->fd to -1.
00665                  */
00666 
00667                 add_fd_to_close_entry(fsp);
00668                 fsp->fh->fd = -1;
00669                 return NT_STATUS_OK;
00670         }
00671 
00672         /*
00673          * No outstanding locks. Get the pending close fd's
00674          * from the tdb and close them all.
00675          */
00676 
00677         count = get_posix_pending_close_entries(fsp, &fd_array);
00678 
00679         if (count) {
00680                 DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
00681 
00682                 for(i = 0; i < count; i++) {
00683                         if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
00684                                 saved_errno = errno;
00685                         }
00686                 }
00687 
00688                 /*
00689                  * Delete all fd's stored in the tdb
00690                  * for this dev/inode pair.
00691                  */
00692 
00693                 delete_close_entries(fsp);
00694         }
00695 
00696         SAFE_FREE(fd_array);
00697 
00698         /* Don't need a lock ref count on this dev/ino anymore. */
00699         delete_windows_lock_ref_count(fsp);
00700 
00701         /*
00702          * Finally close the fd associated with this fsp.
00703          */
00704 
00705         ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
00706 
00707         if (ret == 0 && saved_errno != 0) {
00708                 errno = saved_errno;
00709                 ret = -1;
00710         } 
00711 
00712         fsp->fh->fd = -1;
00713 
00714         if (ret == -1) {
00715                 return map_nt_error_from_unix(errno);
00716         }
00717 
00718         return NT_STATUS_OK;
00719 }
00720 
00721 /****************************************************************************
00722  Next - the functions that deal with the mapping CIFS Windows locks onto
00723  the underlying system POSIX locks.
00724 ****************************************************************************/
00725 
00726 /*
00727  * Structure used when splitting a lock range
00728  * into a POSIX lock range. Doubly linked list.
00729  */
00730 
00731 struct lock_list {
00732         struct lock_list *next;
00733         struct lock_list *prev;
00734         SMB_OFF_T start;
00735         SMB_OFF_T size;
00736 };
00737 
00738 /****************************************************************************
00739  Create a list of lock ranges that don't overlap a given range. Used in calculating
00740  POSIX locks and unlocks. This is a difficult function that requires ASCII art to
00741  understand it :-).
00742 ****************************************************************************/
00743 
00744 static struct lock_list *posix_lock_list(TALLOC_CTX *ctx,
00745                                                 struct lock_list *lhead,
00746                                                 const struct lock_context *lock_ctx, /* Lock context lhead belongs to. */
00747                                                 files_struct *fsp,
00748                                                 const struct lock_struct *plocks,
00749                                                 int num_locks)
00750 {
00751         int i;
00752 
00753         /*
00754          * Check the current lock list on this dev/inode pair.
00755          * Quit if the list is deleted.
00756          */
00757 
00758         DEBUG(10,("posix_lock_list: curr: start=%.0f,size=%.0f\n",
00759                 (double)lhead->start, (double)lhead->size ));
00760 
00761         for (i=0; i<num_locks && lhead; i++) {
00762                 const struct lock_struct *lock = &plocks[i];
00763                 struct lock_list *l_curr;
00764 
00765                 /* Ignore all but read/write locks. */
00766                 if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
00767                         continue;
00768                 }
00769 
00770                 /* Ignore locks not owned by this process. */
00771                 if (!procid_equal(&lock->context.pid, &lock_ctx->pid)) {
00772                         continue;
00773                 }
00774 
00775                 /*
00776                  * Walk the lock list, checking for overlaps. Note that
00777                  * the lock list can expand within this loop if the current
00778                  * range being examined needs to be split.
00779                  */
00780 
00781                 for (l_curr = lhead; l_curr;) {
00782 
00783                         DEBUG(10,("posix_lock_list: lock: fnum=%d: start=%.0f,size=%.0f:type=%s", lock->fnum,
00784                                 (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) ));
00785 
00786                         if ( (l_curr->start >= (lock->start + lock->size)) ||
00787                                  (lock->start >= (l_curr->start + l_curr->size))) {
00788 
00789                                 /* No overlap with existing lock - leave this range alone. */
00790 /*********************************************
00791                                              +---------+
00792                                              | l_curr  |
00793                                              +---------+
00794                                 +-------+
00795                                 | lock  |
00796                                 +-------+
00797 OR....
00798              +---------+
00799              |  l_curr |
00800              +---------+
00801 **********************************************/
00802 
00803                                 DEBUG(10,(" no overlap case.\n" ));
00804 
00805                                 l_curr = l_curr->next;
00806 
00807                         } else if ( (l_curr->start >= lock->start) &&
00808                                                 (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
00809 
00810                                 /*
00811                                  * This range is completely overlapped by this existing lock range
00812                                  * and thus should have no effect. Delete it from the list.
00813                                  */
00814 /*********************************************
00815                 +---------+
00816                 |  l_curr |
00817                 +---------+
00818         +---------------------------+
00819         |       lock                |
00820         +---------------------------+
00821 **********************************************/
00822                                 /* Save the next pointer */
00823                                 struct lock_list *ul_next = l_curr->next;
00824 
00825                                 DEBUG(10,(" delete case.\n" ));
00826 
00827                                 DLIST_REMOVE(lhead, l_curr);
00828                                 if(lhead == NULL) {
00829                                         break; /* No more list... */
00830                                 }
00831 
00832                                 l_curr = ul_next;
00833                                 
00834                         } else if ( (l_curr->start >= lock->start) &&
00835                                                 (l_curr->start < lock->start + lock->size) &&
00836                                                 (l_curr->start + l_curr->size > lock->start + lock->size) ) {
00837 
00838                                 /*
00839                                  * This range overlaps the existing lock range at the high end.
00840                                  * Truncate by moving start to existing range end and reducing size.
00841                                  */
00842 /*********************************************
00843                 +---------------+
00844                 |  l_curr       |
00845                 +---------------+
00846         +---------------+
00847         |    lock       |
00848         +---------------+
00849 BECOMES....
00850                         +-------+
00851                         | l_curr|
00852                         +-------+
00853 **********************************************/
00854 
00855                                 l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size);
00856                                 l_curr->start = lock->start + lock->size;
00857 
00858                                 DEBUG(10,(" truncate high case: start=%.0f,size=%.0f\n",
00859                                                                 (double)l_curr->start, (double)l_curr->size ));
00860 
00861                                 l_curr = l_curr->next;
00862 
00863                         } else if ( (l_curr->start < lock->start) &&
00864                                                 (l_curr->start + l_curr->size > lock->start) &&
00865                                                 (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
00866 
00867                                 /*
00868                                  * This range overlaps the existing lock range at the low end.
00869                                  * Truncate by reducing size.
00870                                  */
00871 /*********************************************
00872    +---------------+
00873    |  l_curr       |
00874    +---------------+
00875            +---------------+
00876            |    lock       |
00877            +---------------+
00878 BECOMES....
00879    +-------+
00880    | l_curr|
00881    +-------+
00882 **********************************************/
00883 
00884                                 l_curr->size = lock->start - l_curr->start;
00885 
00886                                 DEBUG(10,(" truncate low case: start=%.0f,size=%.0f\n",
00887                                                                 (double)l_curr->start, (double)l_curr->size ));
00888 
00889                                 l_curr = l_curr->next;
00890                 
00891                         } else if ( (l_curr->start < lock->start) &&
00892                                                 (l_curr->start + l_curr->size > lock->start + lock->size) ) {
00893                                 /*
00894                                  * Worst case scenario. Range completely overlaps an existing
00895                                  * lock range. Split the request into two, push the new (upper) request
00896                                  * into the dlink list, and continue with the entry after l_new (as we
00897                                  * know that l_new will not overlap with this lock).
00898                                  */
00899 /*********************************************
00900         +---------------------------+
00901         |        l_curr             |
00902         +---------------------------+
00903                 +---------+
00904                 | lock    |
00905                 +---------+
00906 BECOMES.....
00907         +-------+         +---------+
00908         | l_curr|         | l_new   |
00909         +-------+         +---------+
00910 **********************************************/
00911                                 struct lock_list *l_new = TALLOC_P(ctx, struct lock_list);
00912 
00913                                 if(l_new == NULL) {
00914                                         DEBUG(0,("posix_lock_list: talloc fail.\n"));
00915                                         return NULL; /* The talloc_destroy takes care of cleanup. */
00916                                 }
00917 
00918                                 ZERO_STRUCTP(l_new);
00919                                 l_new->start = lock->start + lock->size;
00920                                 l_new->size = l_curr->start + l_curr->size - l_new->start;
00921 
00922                                 /* Truncate the l_curr. */
00923                                 l_curr->size = lock->start - l_curr->start;
00924 
00925                                 DEBUG(10,(" split case: curr: start=%.0f,size=%.0f \
00926 new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size,
00927                                                                 (double)l_new->start, (double)l_new->size ));
00928 
00929                                 /*
00930                                  * Add into the dlink list after the l_curr point - NOT at lhead. 
00931                                  * Note we can't use DLINK_ADD here as this inserts at the head of the given list.
00932                                  */
00933 
00934                                 l_new->prev = l_curr;
00935                                 l_new->next = l_curr->next;
00936                                 l_curr->next = l_new;
00937 
00938                                 /* And move after the link we added. */
00939                                 l_curr = l_new->next;
00940 
00941                         } else {
00942 
00943                                 /*
00944                                  * This logic case should never happen. Ensure this is the
00945                                  * case by forcing an abort.... Remove in production.
00946                                  */
00947                                 pstring msg;
00948 
00949                                 slprintf(msg, sizeof(msg)-1, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \
00950 lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size );
00951 
00952                                 smb_panic(msg);
00953                         }
00954                 } /* end for ( l_curr = lhead; l_curr;) */
00955         } /* end for (i=0; i<num_locks && ul_head; i++) */
00956 
00957         return lhead;
00958 }
00959 
00960 /****************************************************************************
00961  POSIX function to acquire a lock. Returns True if the
00962  lock could be granted, False if not.
00963 ****************************************************************************/
00964 
00965 BOOL set_posix_lock_windows_flavour(files_struct *fsp,
00966                         SMB_BIG_UINT u_offset,
00967                         SMB_BIG_UINT u_count,
00968                         enum brl_type lock_type,
00969                         const struct lock_context *lock_ctx,
00970                         const struct lock_struct *plocks,
00971                         int num_locks,
00972                         int *errno_ret)
00973 {
00974         SMB_OFF_T offset;
00975         SMB_OFF_T count;
00976         int posix_lock_type = map_posix_lock_type(fsp,lock_type);
00977         BOOL ret = True;
00978         size_t lock_count;
00979         TALLOC_CTX *l_ctx = NULL;
00980         struct lock_list *llist = NULL;
00981         struct lock_list *ll = NULL;
00982 
00983         DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
00984                         fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
00985 
00986         /*
00987          * If the requested lock won't fit in the POSIX range, we will
00988          * pretend it was successful.
00989          */
00990 
00991         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
00992                 increment_windows_lock_ref_count(fsp);
00993                 return True;
00994         }
00995 
00996         /*
00997          * Windows is very strange. It allows read locks to be overlayed
00998          * (even over a write lock), but leaves the write lock in force until the first
00999          * unlock. It also reference counts the locks. This means the following sequence :
01000          *
01001          * process1                                      process2
01002          * ------------------------------------------------------------------------
01003          * WRITE LOCK : start = 2, len = 10
01004          *                                            READ LOCK: start =0, len = 10 - FAIL
01005          * READ LOCK : start = 0, len = 14 
01006          *                                            READ LOCK: start =0, len = 10 - FAIL
01007          * UNLOCK : start = 2, len = 10
01008          *                                            READ LOCK: start =0, len = 10 - OK
01009          *
01010          * Under POSIX, the same sequence in steps 1 and 2 would not be reference counted, but
01011          * would leave a single read lock over the 0-14 region.
01012          */
01013         
01014         if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {
01015                 DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n"));
01016                 return False;
01017         }
01018 
01019         if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) {
01020                 DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
01021                 talloc_destroy(l_ctx);
01022                 return False;
01023         }
01024 
01025         /*
01026          * Create the initial list entry containing the
01027          * lock we want to add.
01028          */
01029 
01030         ZERO_STRUCTP(ll);
01031         ll->start = offset;
01032         ll->size = count;
01033 
01034         DLIST_ADD(llist, ll);
01035 
01036         /*
01037          * The following call calculates if there are any
01038          * overlapping locks held by this process on
01039          * fd's open on the same file and splits this list
01040          * into a list of lock ranges that do not overlap with existing
01041          * POSIX locks.
01042          */
01043 
01044         llist = posix_lock_list(l_ctx,
01045                                 llist,
01046                                 lock_ctx, /* Lock context llist belongs to. */
01047                                 fsp,
01048                                 plocks,
01049                                 num_locks);
01050 
01051         /*
01052          * Add the POSIX locks on the list of ranges returned.
01053          * As the lock is supposed to be added atomically, we need to
01054          * back out all the locks if any one of these calls fail.
01055          */
01056 
01057         for (lock_count = 0, ll = llist; ll; ll = ll->next, lock_count++) {
01058                 offset = ll->start;
01059                 count = ll->size;
01060 
01061                 DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
01062                         posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
01063 
01064                 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
01065                         *errno_ret = errno;
01066                         DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
01067                                 posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
01068                         ret = False;
01069                         break;
01070                 }
01071         }
01072 
01073         if (!ret) {
01074 
01075                 /*
01076                  * Back out all the POSIX locks we have on fail.
01077                  */
01078 
01079                 for (ll = llist; lock_count; ll = ll->next, lock_count--) {
01080                         offset = ll->start;
01081                         count = ll->size;
01082 
01083                         DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
01084                                 posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
01085 
01086                         posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK);
01087                 }
01088         } else {
01089                 /* Remember the number of Windows locks we have on this dev/ino pair. */
01090                 increment_windows_lock_ref_count(fsp);
01091         }
01092 
01093         talloc_destroy(l_ctx);
01094         return ret;
01095 }
01096 
01097 /****************************************************************************
01098  POSIX function to release a lock. Returns True if the
01099  lock could be released, False if not.
01100 ****************************************************************************/
01101 
01102 BOOL release_posix_lock_windows_flavour(files_struct *fsp,
01103                                 SMB_BIG_UINT u_offset,
01104                                 SMB_BIG_UINT u_count,
01105                                 enum brl_type deleted_lock_type,
01106                                 const struct lock_context *lock_ctx,
01107                                 const struct lock_struct *plocks,
01108                                 int num_locks)
01109 {
01110         SMB_OFF_T offset;
01111         SMB_OFF_T count;
01112         BOOL ret = True;
01113         TALLOC_CTX *ul_ctx = NULL;
01114         struct lock_list *ulist = NULL;
01115         struct lock_list *ul = NULL;
01116 
01117         DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n",
01118                 fsp->fsp_name, (double)u_offset, (double)u_count ));
01119 
01120         /* Remember the number of Windows locks we have on this dev/ino pair. */
01121         decrement_windows_lock_ref_count(fsp);
01122 
01123         /*
01124          * If the requested lock won't fit in the POSIX range, we will
01125          * pretend it was successful.
01126          */
01127 
01128         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
01129                 return True;
01130         }
01131 
01132         if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
01133                 DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
01134                 return False;
01135         }
01136 
01137         if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
01138                 DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
01139                 talloc_destroy(ul_ctx);
01140                 return False;
01141         }
01142 
01143         /*
01144          * Create the initial list entry containing the
01145          * lock we want to remove.
01146          */
01147 
01148         ZERO_STRUCTP(ul);
01149         ul->start = offset;
01150         ul->size = count;
01151 
01152         DLIST_ADD(ulist, ul);
01153 
01154         /*
01155          * The following call calculates if there are any
01156          * overlapping locks held by this process on
01157          * fd's open on the same file and creates a
01158          * list of unlock ranges that will allow
01159          * POSIX lock ranges to remain on the file whilst the
01160          * unlocks are performed.
01161          */
01162 
01163         ulist = posix_lock_list(ul_ctx,
01164                                 ulist,
01165                                 lock_ctx, /* Lock context ulist belongs to. */
01166                                 fsp,
01167                                 plocks,
01168                                 num_locks);
01169 
01170         /*
01171          * If there were any overlapped entries (list is > 1 or size or start have changed),
01172          * and the lock_type we just deleted from
01173          * the upper layer tdb was a write lock, then before doing the unlock we need to downgrade
01174          * the POSIX lock to a read lock. This allows any overlapping read locks
01175          * to be atomically maintained.
01176          */
01177 
01178         if (deleted_lock_type == WRITE_LOCK &&
01179                         (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) {
01180 
01181                 DEBUG(5,("release_posix_lock_windows_flavour: downgrading lock to READ: offset = %.0f, count = %.0f\n",
01182                         (double)offset, (double)count ));
01183 
01184                 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
01185                         DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) ));
01186                         talloc_destroy(ul_ctx);
01187                         return False;
01188                 }
01189         }
01190 
01191         /*
01192          * Release the POSIX locks on the list of ranges returned.
01193          */
01194 
01195         for(; ulist; ulist = ulist->next) {
01196                 offset = ulist->start;
01197                 count = ulist->size;
01198 
01199                 DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n",
01200                         (double)offset, (double)count ));
01201 
01202                 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
01203                         ret = False;
01204                 }
01205         }
01206 
01207         talloc_destroy(ul_ctx);
01208         return ret;
01209 }
01210 
01211 /****************************************************************************
01212  Next - the functions that deal with mapping CIFS POSIX locks onto
01213  the underlying system POSIX locks.
01214 ****************************************************************************/
01215 
01216 /****************************************************************************
01217  POSIX function to acquire a lock. Returns True if the
01218  lock could be granted, False if not.
01219  As POSIX locks don't stack or conflict (they just overwrite)
01220  we can map the requested lock directly onto a system one. We
01221  know it doesn't conflict with locks on other contexts as the
01222  upper layer would have refused it.
01223 ****************************************************************************/
01224 
01225 BOOL set_posix_lock_posix_flavour(files_struct *fsp,
01226                         SMB_BIG_UINT u_offset,
01227                         SMB_BIG_UINT u_count,
01228                         enum brl_type lock_type,
01229                         int *errno_ret)
01230 {
01231         SMB_OFF_T offset;
01232         SMB_OFF_T count;
01233         int posix_lock_type = map_posix_lock_type(fsp,lock_type);
01234 
01235         DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
01236                         fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
01237 
01238         /*
01239          * If the requested lock won't fit in the POSIX range, we will
01240          * pretend it was successful.
01241          */
01242 
01243         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
01244                 return True;
01245         }
01246 
01247         if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
01248                 *errno_ret = errno;
01249                 DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
01250                         posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
01251                 return False;
01252         }
01253         return True;
01254 }
01255 
01256 /****************************************************************************
01257  POSIX function to release a lock. Returns True if the
01258  lock could be released, False if not.
01259  We are given a complete lock state from the upper layer which is what the lock
01260  state should be after the unlock has already been done, so what
01261  we do is punch out holes in the unlock range where locks owned by this process
01262  have a different lock context.
01263 ****************************************************************************/
01264 
01265 BOOL release_posix_lock_posix_flavour(files_struct *fsp,
01266                                 SMB_BIG_UINT u_offset,
01267                                 SMB_BIG_UINT u_count,
01268                                 const struct lock_context *lock_ctx,
01269                                 const struct lock_struct *plocks,
01270                                 int num_locks)
01271 {
01272         BOOL ret = True;
01273         SMB_OFF_T offset;
01274         SMB_OFF_T count;
01275         TALLOC_CTX *ul_ctx = NULL;
01276         struct lock_list *ulist = NULL;
01277         struct lock_list *ul = NULL;
01278 
01279         DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n",
01280                 fsp->fsp_name, (double)u_offset, (double)u_count ));
01281 
01282         /*
01283          * If the requested lock won't fit in the POSIX range, we will
01284          * pretend it was successful.
01285          */
01286 
01287         if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
01288                 return True;
01289         }
01290 
01291         if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
01292                 DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
01293                 return False;
01294         }
01295 
01296         if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
01297                 DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
01298                 talloc_destroy(ul_ctx);
01299                 return False;
01300         }
01301 
01302         /*
01303          * Create the initial list entry containing the
01304          * lock we want to remove.
01305          */
01306 
01307         ZERO_STRUCTP(ul);
01308         ul->start = offset;
01309         ul->size = count;
01310 
01311         DLIST_ADD(ulist, ul);
01312 
01313         /*
01314          * Walk the given array creating a linked list
01315          * of unlock requests.
01316          */
01317 
01318         ulist = posix_lock_list(ul_ctx,
01319                                 ulist,
01320                                 lock_ctx, /* Lock context ulist belongs to. */
01321                                 fsp,
01322                                 plocks,
01323                                 num_locks);
01324 
01325         /*
01326          * Release the POSIX locks on the list of ranges returned.
01327          */
01328 
01329         for(; ulist; ulist = ulist->next) {
01330                 offset = ulist->start;
01331                 count = ulist->size;
01332 
01333                 DEBUG(5,("release_posix_lock_posix_flavour: Real unlock: offset = %.0f, count = %.0f\n",
01334                         (double)offset, (double)count ));
01335 
01336                 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
01337                         ret = False;
01338                 }
01339         }
01340 
01341         talloc_destroy(ul_ctx);
01342         return ret;
01343 }

Sambaに対してSat Aug 29 21:23:06 2009に生成されました。  doxygen 1.4.7