svn commit: samba r3031 - in branches/SAMBA_4_0/source/ntvfs: common posix

tridge at samba.org tridge at samba.org
Mon Oct 18 09:16:55 GMT 2004


Author: tridge
Date: 2004-10-18 09:16:55 +0000 (Mon, 18 Oct 2004)
New Revision: 3031

WebSVN: http://websvn.samba.org/websvn/changeset.php?rep=samba&path=/branches/SAMBA_4_0/source/ntvfs&rev=3031&nolog=1

Log:
added support for lock cancelation, which effectively just triggers an early lock timeout

added support for more of the bizarre special lock offset semantics of w2k3



Modified:
   branches/SAMBA_4_0/source/ntvfs/common/brlock.c
   branches/SAMBA_4_0/source/ntvfs/posix/pvfs_lock.c
   branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c
   branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h


Changeset:
Modified: branches/SAMBA_4_0/source/ntvfs/common/brlock.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/common/brlock.c	2004-10-18 08:41:44 UTC (rev 3030)
+++ branches/SAMBA_4_0/source/ntvfs/common/brlock.c	2004-10-18 09:16:55 UTC (rev 3031)
@@ -117,8 +117,16 @@
 static BOOL brl_overlap(struct lock_struct *lck1, 
 			struct lock_struct *lck2)
 {
-	if (lck1->start >= (lck2->start + lck2->size) ||
-	    lck2->start >= (lck1->start + lck1->size)) {
+	/* this extra check is not redundent - it copes with locks
+	   that go beyond the end of 64 bit file space */
+	if (lck1->size != 0 &&
+	    lck1->start == lck2->start &&
+	    lck1->size == lck2->size) {
+		return True;
+	}
+	    
+	if (lck1->start >= (lck2->start+lck2->size) ||
+	    lck2->start >= (lck1->start+lck1->size)) {
 		return False;
 	}
 	return True;
@@ -193,11 +201,12 @@
 		return NT_STATUS_FILE_LOCK_CONFLICT;
 	}
 	brl->last_lock_failure = *lock;
-	if (lock->start >= 0xEF000000) {
+	if (lock->start >= 0xEF000000 && 
+	    (lock->start >> 63) == 0) {
 		/* amazing the little things you learn with a test
 		   suite. Locks beyond this offset (as a 64 bit
-		   number!) always generate the conflict error
-		   code. */
+		   number!) always generate the conflict error code,
+		   unless the top bit is set */
 		return NT_STATUS_FILE_LOCK_CONFLICT;
 	}
 	return NT_STATUS_LOCK_NOT_GRANTED;

Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_lock.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_lock.c	2004-10-18 08:41:44 UTC (rev 3030)
+++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_lock.c	2004-10-18 09:16:55 UTC (rev 3031)
@@ -45,7 +45,8 @@
 }
 
 /* this state structure holds information about a lock we are waiting on */
-struct pending_state {
+struct pvfs_pending_lock {
+	struct pvfs_pending_lock *next, *prev;
 	struct pvfs_state *pvfs;
 	union smb_lock *lck;
 	struct pvfs_file *f;
@@ -55,7 +56,6 @@
 	time_t end_time;
 };
 
-
 /*
   a secondary attempt to setup a lock has failed - back out
   the locks we did get and send an error
@@ -89,7 +89,7 @@
 */
 static void pvfs_pending_lock_continue(void *private, BOOL timed_out)
 {
-	struct pending_state *pending = private;
+	struct pvfs_pending_lock *pending = private;
 	struct pvfs_state *pvfs = pending->pvfs;
 	struct pvfs_file *f = pending->f;
 	struct smbsrv_request *req = pending->req;
@@ -107,6 +107,8 @@
 		rw = WRITE_LOCK;
 	}
 
+	DLIST_REMOVE(f->pending_list, pending);
+
 	status = brl_lock(pvfs->brl_context,
 			  &f->locking_key,
 			  req->smbpid,
@@ -130,8 +132,10 @@
 		if (timed_out) {
 			/* no more chances */
 			pvfs_lock_async_failed(pvfs, req, f, locks, pending->pending_lock, status);
+		} else {
+			/* we can try again */
+			DLIST_ADD(f->pending_list, pending);
 		}
-		/* we can try again */
 		return;
 	}
 
@@ -170,6 +174,8 @@
 									 pending);
 				if (pending->wait_handle == NULL) {
 					pvfs_lock_async_failed(pvfs, req, f, locks, i, NT_STATUS_NO_MEMORY);
+				} else {
+					DLIST_ADD(f->pending_list, pending);
 				}
 				return;
 			}
@@ -192,6 +198,42 @@
 
 
 /*
+  cancel a set of locks
+*/
+static NTSTATUS pvfs_lock_cancel(struct pvfs_state *pvfs, struct smbsrv_request *req, union smb_lock *lck,
+				 struct pvfs_file *f)
+{
+	struct pvfs_pending_lock *p;
+
+	for (p=f->pending_list;p;p=p->next) {
+		/* check if the lock request matches exactly - you can only cancel with exact matches */
+		if (p->lck->lockx.in.ulock_cnt == lck->lockx.in.ulock_cnt &&
+		    p->lck->lockx.in.lock_cnt  == lck->lockx.in.lock_cnt &&
+		    p->lck->lockx.in.fnum      == lck->lockx.in.fnum &&
+		    p->lck->lockx.in.mode      == (lck->lockx.in.mode & ~LOCKING_ANDX_CANCEL_LOCK)) {
+			int i;
+
+			for (i=0;i<lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;i++) {
+				if (p->lck->lockx.in.locks[i].pid != lck->lockx.in.locks[i].pid ||
+				    p->lck->lockx.in.locks[i].offset != lck->lockx.in.locks[i].offset ||
+				    p->lck->lockx.in.locks[i].count != lck->lockx.in.locks[i].count) {
+					break;
+				}
+			}
+			if (i < lck->lockx.in.ulock_cnt) continue;
+
+			/* an exact match! we can cancel it, which is equivalent
+			   to triggering the timeout early */
+			pvfs_pending_lock_continue(p ,True);
+			return NT_STATUS_OK;
+		}
+	}
+
+	return NT_STATUS_UNSUCCESSFUL;
+}
+
+
+/*
   lock or unlock a byte range
 */
 NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
@@ -202,7 +244,7 @@
 	struct smb_lock_entry *locks;
 	int i;
 	enum brl_type rw;
-	struct pending_state *pending = NULL;
+	struct pvfs_pending_lock *pending = NULL;
 
 	f = pvfs_find_fd(pvfs, req, lck->generic.in.fnum);
 	if (!f) {
@@ -237,7 +279,7 @@
 
 	/* now the lockingX case, most common and also most complex */
 	if (lck->lockx.in.timeout != 0) {
-		pending = talloc_p(req, struct pending_state);
+		pending = talloc_p(req, struct pvfs_pending_lock);
 		if (pending == NULL) {
 			return NT_STATUS_NO_MEMORY;
 		}
@@ -257,6 +299,10 @@
 		rw = pending? PENDING_WRITE_LOCK : WRITE_LOCK;
 	}
 
+	if (lck->lockx.in.mode & LOCKING_ANDX_CANCEL_LOCK) {
+		return pvfs_lock_cancel(pvfs, req, lck, f);
+	}
+
 	if (lck->lockx.in.mode & 
 	    (LOCKING_ANDX_OPLOCK_RELEASE |
 	     LOCKING_ANDX_CHANGE_LOCKTYPE |
@@ -309,6 +355,7 @@
 				if (pending->wait_handle == NULL) {
 					return NT_STATUS_NO_MEMORY;
 				}
+				DLIST_ADD(f->pending_list, pending);
 				return NT_STATUS_OK;
 			}
 			/* undo the locks we just did */

Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c	2004-10-18 08:41:44 UTC (rev 3030)
+++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_open.c	2004-10-18 09:16:55 UTC (rev 3031)
@@ -171,6 +171,7 @@
 	f->session = req->session;
 	f->smbpid = req->smbpid;
 	f->pvfs = pvfs;
+	f->pending_list = NULL;
 
 	/* we must zero here to take account of padding */
 	ZERO_STRUCT(lock_context);

Modified: branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h	2004-10-18 08:41:44 UTC (rev 3030)
+++ branches/SAMBA_4_0/source/ntvfs/posix/vfs_posix.h	2004-10-18 09:16:55 UTC (rev 3031)
@@ -123,8 +123,12 @@
 
 	/* we need this hook back to our parent for lock destruction */
 	struct pvfs_state *pvfs;
+
+	/* a list of pending locks - used for locking cancel operations */
+	struct pvfs_pending_lock *pending_list;
 };
 
+
 struct pvfs_mangle_context {
 	uint8_t char_flags[256];
 	/*



More information about the samba-cvs mailing list