From 0a8b1fd092c9a64c04f6f05d41b3d7ecec7ccc6f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 25 Feb 2008 14:03:07 -0500 Subject: Update homepages for talloc, tdb and ldb subprojects (This used to be commit 8cb07814bc6627fc8eba228eafd13336e3ca3758) --- source4/lib/ldb/web/index.html | 24 ++++++++++-------------- source4/lib/talloc/web/index.html | 20 ++++++++------------ source4/lib/tdb/web/index.html | 14 ++++++-------- 3 files changed, 24 insertions(+), 34 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/web/index.html b/source4/lib/ldb/web/index.html index 76dbbdeafb..26dd344527 100644 --- a/source4/lib/ldb/web/index.html +++ b/source4/lib/ldb/web/index.html @@ -42,9 +42,9 @@ The main features that separate ldb from other solutions are: Currently ldb is completely lacking in programmer or user documentation. This is your opportunity to make a contribution! Start with the public functions declared in ldb.h +href="http://samba.org/ftp/unpacked/ldb/include/ldb.h">ldb.h and the example code in the tools +href="http://samba.org/ftp/unpacked/ldb/tools/">tools directory. Documentation in the same docbook format used by Samba would be preferred. @@ -53,21 +53,17 @@ would be preferred. ldb does not currently have its own mailing list or bug tracking system. For now, please use the samba-technical -mailing list, and the Samba -bugzilla bug tracking system. +mailing list or the ldb +mailing list, and the Samba bugzilla bug tracking system.

Download

-You can download the latest release either via rsync or anonymous -svn. To fetch via svn use the following commands: - -
-  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/ldb ldb
-  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb tdb
-  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/talloc talloc
-  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/replace libreplace
-
- +You can download the latest release either via rsync or thtough git.
+
+To fetch via git see the following guide:
+Using Git for Samba Development
+Once you have cloned the tree switch to the v4-0-test branch and cd into the source/lib/ldb directory.
+
To fetch via rsync use these commands:
diff --git a/source4/lib/talloc/web/index.html b/source4/lib/talloc/web/index.html
index 628030ad4c..5deab93665 100644
--- a/source4/lib/talloc/web/index.html
+++ b/source4/lib/talloc/web/index.html
@@ -12,7 +12,7 @@ destructors. It is the core memory allocator used in Samba4, and has
 made a huge difference in many aspects of Samba4 development.

To get started with talloc, I would recommend you read the talloc guide. +href="http://samba.org/ftp/unpacked/talloc/talloc_guide.txt">talloc guide.

Discussion and bug reports

@@ -24,20 +24,16 @@ bugzilla bug tracking system.

Download

-You can download the latest release either via rsync or git. -To fetch via git use the following command: - -
-  git-clone git://git.samba.org/samba.git samba
-  cd samba
-  git checkout -b samba4 origin/v4-0-test
-
- +You can download the latest release either via rsync or git.
+
+To fetch via git see the following guide:
+Using Git for Samba Development
+Once you have cloned the tree switch to the v4-0-test branch and cd into the source/lib/talloc directory.
+
To fetch via rsync use this command:
-  rsync -Pavz samba.org::ftp/unpacked/samba_4_0_test/source/lib/talloc .
-  rsync -Pavz samba.org::ftp/unpacked/samba_4_0_test/source/lib/libreplace .
+  rsync -Pavz samba.org::ftp/unpacked/talloc .
 

diff --git a/source4/lib/tdb/web/index.html b/source4/lib/tdb/web/index.html index 979665ae76..a53da6b8f7 100644 --- a/source4/lib/tdb/web/index.html +++ b/source4/lib/tdb/web/index.html @@ -22,14 +22,12 @@ bugzilla bug tracking system.

Download

-You can download the latest release either via rsync or anonymous -svn. To fetch via svn use the following commands: - -
-  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb tdb
-  svn co svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/replace libreplace
-
- +You can download the latest release either via rsync or git.
+
+To fetch via git see the following guide:
+Using Git for Samba Development
+Once you have cloned the tree switch to the v4-0-test branch and cd into the source/lib/tdb directory.
+
To fetch via rsync use these commands:
-- 
cgit 


From f94008e45a15666439766488edf84b21a86111ee Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Fri, 22 Feb 2008 16:30:13 +0100
Subject: opendb: add odb_break_oplocks() function

This send breaks to none to all level2 holders

metze
(This used to be commit bd3654500b14e4ed8d4a8bb25ff9da5035a16a8b)
---
 source4/cluster/ctdb/opendb_ctdb.c | 13 ++++++++++++-
 source4/ntvfs/common/opendb.c      |  5 +++++
 source4/ntvfs/common/opendb.h      |  1 +
 source4/ntvfs/common/opendb_tdb.c  | 40 +++++++++++++++++++++++++++++++++++++-
 4 files changed, 57 insertions(+), 2 deletions(-)

(limited to 'source4')

diff --git a/source4/cluster/ctdb/opendb_ctdb.c b/source4/cluster/ctdb/opendb_ctdb.c
index 86dc1f50f1..915b760424 100644
--- a/source4/cluster/ctdb/opendb_ctdb.c
+++ b/source4/cluster/ctdb/opendb_ctdb.c
@@ -464,6 +464,16 @@ static NTSTATUS odb_ctdb_update_oplock(struct odb_lock *lck, void *file_handle,
 	return NT_STATUS_FOOBAR;
 }
 
+static NTSTATUS odb_ctdb_break_oplocks(struct odb_lock *lck)
+{
+	/*
+	 * as this file will went away and isn't used yet,
+	 * copy the implementation from the tdb backend
+	 * --metze
+	 */
+	return NT_STATUS_FOOBAR;
+}
+
 /*
   remove a pending opendb entry
 */
@@ -642,7 +652,8 @@ static const struct opendb_ops opendb_ctdb_ops = {
 	.odb_set_delete_on_close = odb_ctdb_set_delete_on_close,
 	.odb_get_delete_on_close = odb_ctdb_get_delete_on_close,
 	.odb_can_open            = odb_ctdb_can_open,
-	.odb_update_oplock       = odb_ctdb_update_oplock
+	.odb_update_oplock       = odb_ctdb_update_oplock,
+	.odb_break_oplocks       = odb_ctdb_break_oplocks
 };
 
 
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index 4ac10806e1..3f5d7210be 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -176,3 +176,8 @@ _PUBLIC_ NTSTATUS odb_update_oplock(struct odb_lock *lck, void *file_handle,
 {
 	return ops->odb_update_oplock(lck, file_handle, oplock_level);
 }
+
+_PUBLIC_ NTSTATUS odb_break_oplocks(struct odb_lock *lck)
+{
+	return ops->odb_break_oplocks(lck);
+}
diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h
index c34a07d6fa..c46390446c 100644
--- a/source4/ntvfs/common/opendb.h
+++ b/source4/ntvfs/common/opendb.h
@@ -43,6 +43,7 @@ struct opendb_ops {
 				 uint32_t access_mask);
 	NTSTATUS (*odb_update_oplock)(struct odb_lock *lck, void *file_handle,
 				      uint32_t oplock_level);
+	NTSTATUS (*odb_break_oplocks)(struct odb_lock *lck);
 };
 
 struct opendb_oplock_break {
diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index 3d4a760e2e..dd2fb138d6 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -503,6 +503,43 @@ static NTSTATUS odb_tdb_update_oplock(struct odb_lock *lck, void *file_handle,
 	return odb_push_record(lck, &file);
 }
 
+/*
+  send oplocks breaks to none to all level2 holders
+*/
+static NTSTATUS odb_tdb_break_oplocks(struct odb_lock *lck)
+{
+	struct odb_context *odb = lck->odb;
+	NTSTATUS status;
+	struct opendb_file file;
+	int i;
+	bool modified = true;
+
+	status = odb_pull_record(lck, &file);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		return NT_STATUS_OK;
+	}
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	/* see if anyone has an oplock, which we need to break */
+	for (i=0;i
Date: Fri, 22 Feb 2008 17:26:40 +0100
Subject: opendb_tdb: grant level2 oplocks

metze
(This used to be commit 57f1b9d11cfcac3b5fdee1ad9e4ba81d0859c8dc)
---
 source4/ntvfs/common/opendb_tdb.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index dd2fb138d6..3310532406 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -367,18 +367,32 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	}
 
 	/*
-	  possibly grant an exclusive or batch oplock if this is the only client
-	  with the file open. We don't yet grant levelII oplocks.
+	  possibly grant an exclusive, batch or level2 oplock
 	*/
-	if (oplock_granted != NULL) {
-		if ((oplock_level == OPLOCK_BATCH ||
-		     oplock_level == OPLOCK_EXCLUSIVE) &&
-		    file.num_entries == 0) {
-			(*oplock_granted) = oplock_level;
+	if (oplock_granted) {
+		if (oplock_level == OPLOCK_EXCLUSIVE) {
+			if (file.num_entries == 0) {
+				e.oplock_level	= OPLOCK_EXCLUSIVE;
+				*oplock_granted	= EXCLUSIVE_OPLOCK_RETURN;
+			} else {
+				e.oplock_level	= OPLOCK_NONE;
+				*oplock_granted	= NO_OPLOCK_RETURN;
+			}
+		} else if (oplock_level == OPLOCK_BATCH) {
+			if (file.num_entries == 0) {
+				e.oplock_level	= OPLOCK_BATCH;
+				*oplock_granted	= BATCH_OPLOCK_RETURN;
+			} else {
+				e.oplock_level	= OPLOCK_LEVEL_II;
+				*oplock_granted	= LEVEL_II_OPLOCK_RETURN;
+			}
+		} else if (oplock_level == OPLOCK_LEVEL_II) {
+			e.oplock_level	= OPLOCK_LEVEL_II;
+			*oplock_granted	= LEVEL_II_OPLOCK_RETURN;
 		} else {
-			(*oplock_granted) = OPLOCK_NONE;
+			e.oplock_level	= OPLOCK_NONE;
+			*oplock_granted	= NO_OPLOCK_RETURN;
 		}
-		e.oplock_level = (*oplock_granted);
 	}
 
 	/* it doesn't conflict, so add it to the end */
-- 
cgit 


From c749b66ead71af3076d4f911aa0cd65e35284ca4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Fri, 22 Feb 2008 17:26:40 +0100
Subject: opendb_tdb: attribute only opens doesn't conflict with BATCH oplocks

metze
(This used to be commit 7872b05abe7532676c4cc25620b96ea5d59117d2)
---
 source4/ntvfs/common/opendb_tdb.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index 3310532406..b445981b57 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -189,7 +189,7 @@ static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
 		   e2->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
 	CHECK_MASK(e2->access_mask, SEC_STD_DELETE,
 		   e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
-
+#undef CHECK_MASK
 	return NT_STATUS_OK;
 }
 
@@ -284,6 +284,25 @@ static NTSTATUS odb_oplock_break_send(struct odb_context *odb,
 	return NT_STATUS_OK;
 }
 
+static bool access_attributes_only(uint32_t access_mask,
+				   uint32_t open_disposition)
+{
+	switch (open_disposition) {
+	case NTCREATEX_DISP_SUPERSEDE:
+	case NTCREATEX_DISP_OVERWRITE_IF:
+	case NTCREATEX_DISP_OVERWRITE:
+		return false;
+	default:
+		break;
+	}
+#define CHECK_MASK(m,g) ((m) && (((m) & ~(g))==0) && (((m) & (g)) != 0))
+	return CHECK_MASK(access_mask,
+			  SEC_STD_SYNCHRONIZE |
+			  SEC_FILE_READ_ATTRIBUTE |
+			  SEC_FILE_WRITE_ATTRIBUTE);
+#undef CHECK_MASK
+}
+
 /*
   register an open file in the open files database. This implements the share_access
   rules
@@ -302,6 +321,8 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	int i;
 	struct opendb_file file;
 	NTSTATUS status;
+	uint32_t open_disposition = 0;
+	bool attrs_only = false;
 
 	if (odb->oplocks == false) {
 		oplock_level = OPLOCK_NONE;
@@ -328,6 +349,15 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	/* see if anyone has an oplock, which we need to break */
 	for (i=0;i
Date: Mon, 25 Feb 2008 16:14:23 +0100
Subject: opendb_tdb: add force break to none logic

metze
(This used to be commit fbfe953ba347a902297bd8eae900ca70efd2db01)
---
 source4/ntvfs/common/opendb_tdb.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index b445981b57..656e113742 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -322,6 +322,7 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	struct opendb_file file;
 	NTSTATUS status;
 	uint32_t open_disposition = 0;
+	bool break_to_none = false;
 	bool attrs_only = false;
 
 	if (odb->oplocks == false) {
@@ -349,6 +350,7 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	/* see if anyone has an oplock, which we need to break */
 	for (i=0;i
Date: Mon, 25 Feb 2008 16:26:04 +0100
Subject: opendb_tdb: move sharemode, oplock logic into
 odb_tdb_open_can_internal()

metze
(This used to be commit 65cfe71b2617598f8e38d04537cfc9ce44a36680)
---
 source4/ntvfs/common/opendb_tdb.c | 191 ++++++++++++++++++++------------------
 1 file changed, 102 insertions(+), 89 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index 656e113742..9c273f9617 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -146,7 +146,10 @@ static DATA_BLOB odb_tdb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck)
 
   return NT_STATUS_OK on no conflict
 */
-static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
+static NTSTATUS share_conflict(struct opendb_entry *e1,
+			       uint32_t stream_id,
+			       uint32_t share_access,
+			       uint32_t access_mask)
 {
 	/* if either open involves no read.write or delete access then
 	   it can't conflict */
@@ -157,18 +160,18 @@ static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
 				 SEC_STD_DELETE))) {
 		return NT_STATUS_OK;
 	}
-	if (!(e2->access_mask & (SEC_FILE_WRITE_DATA |
-				 SEC_FILE_APPEND_DATA |
-				 SEC_FILE_READ_DATA |
-				 SEC_FILE_EXECUTE |
-				 SEC_STD_DELETE))) {
+	if (!(access_mask & (SEC_FILE_WRITE_DATA |
+			     SEC_FILE_APPEND_DATA |
+			     SEC_FILE_READ_DATA |
+			     SEC_FILE_EXECUTE |
+			     SEC_STD_DELETE))) {
 		return NT_STATUS_OK;
 	}
 
 	/* data IO access masks. This is skipped if the two open handles
 	   are on different streams (as in that case the masks don't
 	   interact) */
-	if (e1->stream_id != e2->stream_id) {
+	if (e1->stream_id != stream_id) {
 		return NT_STATUS_OK;
 	}
 
@@ -176,18 +179,18 @@ static NTSTATUS share_conflict(struct opendb_entry *e1, struct opendb_entry *e2)
 	if (((am) & (right)) && !((sa) & (share))) return NT_STATUS_SHARING_VIOLATION
 
 	CHECK_MASK(e1->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
-		   e2->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
-	CHECK_MASK(e2->access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
+		   share_access, NTCREATEX_SHARE_ACCESS_WRITE);
+	CHECK_MASK(access_mask, SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA,
 		   e1->share_access, NTCREATEX_SHARE_ACCESS_WRITE);
 	
 	CHECK_MASK(e1->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
-		   e2->share_access, NTCREATEX_SHARE_ACCESS_READ);
-	CHECK_MASK(e2->access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
+		   share_access, NTCREATEX_SHARE_ACCESS_READ);
+	CHECK_MASK(access_mask, SEC_FILE_READ_DATA | SEC_FILE_EXECUTE,
 		   e1->share_access, NTCREATEX_SHARE_ACCESS_READ);
 
 	CHECK_MASK(e1->access_mask, SEC_STD_DELETE,
-		   e2->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
-	CHECK_MASK(e2->access_mask, SEC_STD_DELETE,
+		   share_access, NTCREATEX_SHARE_ACCESS_DELETE);
+	CHECK_MASK(access_mask, SEC_STD_DELETE,
 		   e1->share_access, NTCREATEX_SHARE_ACCESS_DELETE);
 #undef CHECK_MASK
 	return NT_STATUS_OK;
@@ -303,53 +306,20 @@ static bool access_attributes_only(uint32_t access_mask,
 #undef CHECK_MASK
 }
 
-/*
-  register an open file in the open files database. This implements the share_access
-  rules
-
-  Note that the path is only used by the delete on close logic, not
-  for comparing with other filenames
-*/
-static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
-				  uint32_t stream_id, uint32_t share_access, 
-				  uint32_t access_mask, bool delete_on_close,
-				  const char *path, 
-				  uint32_t oplock_level, uint32_t *oplock_granted)
+static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
+					  const struct opendb_file *file,
+					  uint32_t stream_id, uint32_t share_access,
+					  uint32_t access_mask, bool delete_on_close,
+					  uint32_t open_disposition, bool break_to_none,
+					  bool *_attrs_only)
 {
-	struct odb_context *odb = lck->odb;
-	struct opendb_entry e;
-	int i;
-	struct opendb_file file;
 	NTSTATUS status;
-	uint32_t open_disposition = 0;
-	bool break_to_none = false;
+	uint32_t i;
 	bool attrs_only = false;
 
-	if (odb->oplocks == false) {
-		oplock_level = OPLOCK_NONE;
-	}
-
-	status = odb_pull_record(lck, &file);
-	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-		/* initialise a blank structure */
-		ZERO_STRUCT(file);
-		file.path = path;
-	} else {
-		NT_STATUS_NOT_OK_RETURN(status);
-	}
-
-	/* see if it conflicts */
-	e.server          = odb->ntvfs_ctx->server_id;
-	e.file_handle     = file_handle;
-	e.stream_id       = stream_id;
-	e.share_access    = share_access;
-	e.access_mask     = access_mask;
-	e.delete_on_close = delete_on_close;
-	e.oplock_level    = OPLOCK_NONE;
-		
 	/* see if anyone has an oplock, which we need to break */
-	for (i=0;inum_entries;i++) {
+		if (file->entries[i].oplock_level == OPLOCK_BATCH) {
 			bool oplock_return = OPLOCK_BREAK_TO_LEVEL_II;
 			/* if this is an attribute only access
 			 * it doesn't conflict with a BACTCH oplock
@@ -370,21 +340,22 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 			if (break_to_none) {
 				oplock_return = OPLOCK_BREAK_TO_NONE;
 			}
-			odb_oplock_break_send(odb, &file.entries[i],
+			odb_oplock_break_send(odb, &file->entries[i],
 					      oplock_return);
 			return NT_STATUS_OPLOCK_NOT_GRANTED;
 		}
 	}
 
-	if (file.delete_on_close || 
-	    (file.num_entries != 0 && delete_on_close)) {
+	if (file->delete_on_close ||
+	    (file->num_entries != 0 && delete_on_close)) {
 		/* while delete on close is set, no new opens are allowed */
 		return NT_STATUS_DELETE_PENDING;
 	}
 
 	/* check for sharing violations */
-	for (i=0;inum_entries;i++) {
+		status = share_conflict(&file->entries[i], stream_id,
+					share_access, access_mask);
 		NT_STATUS_NOT_OK_RETURN(status);
 	}
 
@@ -393,14 +364,70 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	   till these are broken. Note that we check for batch oplocks
 	   before checking for sharing violations, and check for
 	   exclusive oplocks afterwards. */
-	for (i=0;inum_entries;i++) {
+		if (file->entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
+			odb_oplock_break_send(odb, &file->entries[i],
 					      OPLOCK_BREAK_TO_NONE);
 			return NT_STATUS_OPLOCK_NOT_GRANTED;
 		}
 	}
 
+	if (_attrs_only) {
+		*_attrs_only = attrs_only;
+	}
+	return NT_STATUS_OK;
+}
+
+/*
+  register an open file in the open files database. This implements the share_access
+  rules
+
+  Note that the path is only used by the delete on close logic, not
+  for comparing with other filenames
+*/
+static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
+				  uint32_t stream_id, uint32_t share_access,
+				  uint32_t access_mask, bool delete_on_close,
+				  const char *path,
+				  uint32_t oplock_level, uint32_t *oplock_granted)
+{
+	struct odb_context *odb = lck->odb;
+	struct opendb_entry e;
+	struct opendb_file file;
+	NTSTATUS status;
+	uint32_t open_disposition = 0;
+	bool break_to_none = false;
+	bool attrs_only = false;
+
+	if (odb->oplocks == false) {
+		oplock_level = OPLOCK_NONE;
+	}
+
+	status = odb_pull_record(lck, &file);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		/* initialise a blank structure */
+		ZERO_STRUCT(file);
+		file.path = path;
+	} else {
+		NT_STATUS_NOT_OK_RETURN(status);
+	}
+
+	/* see if it conflicts */
+	status = odb_tdb_open_can_internal(odb, &file, stream_id,
+					   share_access, access_mask,
+					   delete_on_close, open_disposition,
+					   break_to_none, &attrs_only);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	/* see if it conflicts */
+	e.server          = odb->ntvfs_ctx->server_id;
+	e.file_handle     = file_handle;
+	e.stream_id       = stream_id;
+	e.share_access    = share_access;
+	e.access_mask     = access_mask;
+	e.delete_on_close = delete_on_close;
+	e.oplock_level    = OPLOCK_NONE;
+
 	/*
 	  possibly grant an exclusive, batch or level2 oplock
 	*/
@@ -719,8 +746,11 @@ static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
 	struct odb_context *odb = lck->odb;
 	NTSTATUS status;
 	struct opendb_file file;
-	struct opendb_entry e;
-	int i;
+	uint32_t stream_id = 0;
+	uint32_t open_disposition = 0;
+	bool delete_on_close = false;
+	bool break_to_none = false;
+	bool attrs_only = false;
 
 	status = odb_pull_record(lck, &file);
 	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
@@ -728,32 +758,15 @@ static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
 	}
 	NT_STATUS_NOT_OK_RETURN(status);
 
-	if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && 
-	    file.num_entries != 0) {
-		return NT_STATUS_SHARING_VIOLATION;
+	if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
+		delete_on_close = true;
 	}
 
-	if (file.delete_on_close) {
-		return NT_STATUS_DELETE_PENDING;
-	}
-
-	e.server       = odb->ntvfs_ctx->server_id;
-	e.file_handle  = NULL;
-	e.stream_id    = 0;
-	e.share_access = share_access;
-	e.access_mask  = access_mask;
-		
-	for (i=0;i
Date: Mon, 25 Feb 2008 20:20:35 +0100
Subject: opendb_tdb: only file->delete_on_close == true should give
 DELETE_PENDING

metze
(This used to be commit 5b12157e0f0f1cf6ea90503a72b56ab2032cb6e5)
---
 source4/ntvfs/common/opendb_tdb.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index 9c273f9617..8b5e4850d9 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -346,12 +346,15 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
 		}
 	}
 
-	if (file->delete_on_close ||
-	    (file->num_entries != 0 && delete_on_close)) {
+	if (file->delete_on_close) {
 		/* while delete on close is set, no new opens are allowed */
 		return NT_STATUS_DELETE_PENDING;
 	}
 
+	if (file->num_entries != 0 && delete_on_close) {
+		return NT_STATUS_SHARING_VIOLATION;
+	}
+
 	/* check for sharing violations */
 	for (i=0;inum_entries;i++) {
 		status = share_conflict(&file->entries[i], stream_id,
-- 
cgit 


From 69631a215b655415477ee0e71a08beca86dd5b2f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Tue, 26 Feb 2008 09:14:54 +0100
Subject: pvfs_setfileinfo_rename: map DELETE_PENDING to ACCESS_DENIED

This is needed as odb_can_open/pvfs_can_delete changed the return value.

metze
(This used to be commit 1ba0b9a8f1f84c7c949b3d184843462b87446707)
---
 source4/ntvfs/posix/pvfs_setfileinfo.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index fbbb8c2d4b..c6d014a72f 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -152,6 +152,9 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
 		}
 
 		status = pvfs_can_delete(pvfs, req, name2, NULL);
+		if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
+			return NT_STATUS_ACCESS_DENIED;
+		}
 		if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
 			return NT_STATUS_ACCESS_DENIED;
 		}
-- 
cgit 


From facdc472c7e6dbca0553a5e0dfb100be322339ce Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 16:47:48 +0100
Subject: opendb: pass down open_disposition and break_to_none to
 odb_open_file()

metze
(This used to be commit aaaa26ae5e810495f313dfada771a8de86cedbd4)
---
 source4/cluster/ctdb/opendb_ctdb.c | 12 +++++++-----
 source4/ntvfs/common/opendb.c      | 13 +++++++------
 source4/ntvfs/common/opendb.h      |  7 ++++---
 source4/ntvfs/common/opendb_tdb.c  |  7 +++----
 4 files changed, 21 insertions(+), 18 deletions(-)

(limited to 'source4')

diff --git a/source4/cluster/ctdb/opendb_ctdb.c b/source4/cluster/ctdb/opendb_ctdb.c
index 915b760424..36ae204974 100644
--- a/source4/cluster/ctdb/opendb_ctdb.c
+++ b/source4/cluster/ctdb/opendb_ctdb.c
@@ -279,11 +279,13 @@ static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_ent
   Note that the path is only used by the delete on close logic, not
   for comparing with other filenames
 */
-static NTSTATUS odb_ctdb_open_file(struct odb_lock *lck, void *file_handle,
-				  uint32_t stream_id, uint32_t share_access, 
-				  uint32_t access_mask, bool delete_on_close,
-				  const char *path, 
-				  uint32_t oplock_level, uint32_t *oplock_granted)
+static NTSTATUS odb_ctdb_open_file(struct odb_lock *lck,
+				   void *file_handle, const char *path,
+				   uint32_t stream_id, uint32_t share_access,
+				   uint32_t access_mask, bool delete_on_close,
+				   uint32_t open_disposition, bool break_to_none,
+				   uint32_t oplock_level, uint32_t *oplock_granted)
+
 {
 	struct odb_context *odb = lck->odb;
 	struct opendb_entry e;
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index 3f5d7210be..c380355466 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -93,15 +93,16 @@ _PUBLIC_ DATA_BLOB odb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck)
   Note that the path is only used by the delete on close logic, not
   for comparing with other filenames
 */
-_PUBLIC_ NTSTATUS odb_open_file(struct odb_lock *lck, void *file_handle,
-				uint32_t stream_id, uint32_t share_access, 
+_PUBLIC_ NTSTATUS odb_open_file(struct odb_lock *lck,
+				void *file_handle, const char *path,
+				uint32_t stream_id, uint32_t share_access,
 				uint32_t access_mask, bool delete_on_close,
-				const char *path, 
+				uint32_t open_disposition, bool break_to_none,
 				uint32_t oplock_level, uint32_t *oplock_granted)
 {
-	return ops->odb_open_file(lck, file_handle, stream_id, share_access,
-				  access_mask, delete_on_close, path, oplock_level,
-				  oplock_granted);
+	return ops->odb_open_file(lck, file_handle, path, stream_id, share_access,
+				  access_mask, delete_on_close, open_disposition,
+				  break_to_none, oplock_level, oplock_granted);
 }
 
 
diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h
index c46390446c..205d2228ea 100644
--- a/source4/ntvfs/common/opendb.h
+++ b/source4/ntvfs/common/opendb.h
@@ -25,10 +25,11 @@ struct opendb_ops {
 	struct odb_lock *(*odb_lock)(TALLOC_CTX *mem_ctx,
 				     struct odb_context *odb, DATA_BLOB *file_key);
 	DATA_BLOB (*odb_get_key)(TALLOC_CTX *mem_ctx, struct odb_lock *lck);
-	NTSTATUS (*odb_open_file)(struct odb_lock *lck, void *file_handle,
-				  uint32_t stream_id, uint32_t share_access, 
+	NTSTATUS (*odb_open_file)(struct odb_lock *lck,
+				  void *file_handle, const char *path,
+				  uint32_t stream_id, uint32_t share_access,
 				  uint32_t access_mask, bool delete_on_close,
-				  const char *path, 
+				  uint32_t open_disposition, bool break_to_none,
 				  uint32_t oplock_level, uint32_t *oplock_granted);
 	NTSTATUS (*odb_open_file_pending)(struct odb_lock *lck, void *private);
 	NTSTATUS (*odb_close_file)(struct odb_lock *lck, void *file_handle);
diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index 8b5e4850d9..d41a5c371e 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -388,18 +388,17 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb,
   Note that the path is only used by the delete on close logic, not
   for comparing with other filenames
 */
-static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
+static NTSTATUS odb_tdb_open_file(struct odb_lock *lck,
+				  void *file_handle, const char *path,
 				  uint32_t stream_id, uint32_t share_access,
 				  uint32_t access_mask, bool delete_on_close,
-				  const char *path,
+				  uint32_t open_disposition, bool break_to_none,
 				  uint32_t oplock_level, uint32_t *oplock_granted)
 {
 	struct odb_context *odb = lck->odb;
 	struct opendb_entry e;
 	struct opendb_file file;
 	NTSTATUS status;
-	uint32_t open_disposition = 0;
-	bool break_to_none = false;
 	bool attrs_only = false;
 
 	if (odb->oplocks == false) {
-- 
cgit 


From 9852e0d31582f669179c2a8c8ebdb263fef611f2 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 16:49:40 +0100
Subject: pvfs_open: pass down open_disposition and break_to_none to
 odb_open_file()

metze
(This used to be commit 46500983fe2f63540a67e2e963ab264fa8a090d0)
---
 source4/ntvfs/posix/pvfs_open.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 3a8b17ab16..1b5ea56d64 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -296,9 +296,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
 		}
 		
 		/* see if we are allowed to open at the same time as existing opens */
-		status = odb_open_file(lck, f->handle, f->handle->name->stream_id,
+		status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
 				       share_access, access_mask, del_on_close, 
-				       name->full_name, OPLOCK_NONE, NULL);
+				       io->generic.in.open_disposition,
+				       false, OPLOCK_NONE, NULL);
 
 		if (!NT_STATUS_IS_OK(status)) {
 			talloc_free(lck);
@@ -349,9 +350,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
 		}
 
-		status = odb_open_file(lck, f->handle, f->handle->name->stream_id,
+		status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
 				       share_access, access_mask, del_on_close, 
-				       name->full_name, OPLOCK_NONE, NULL);
+				       io->generic.in.open_disposition,
+				       false, OPLOCK_NONE, NULL);
 
 		if (!NT_STATUS_IS_OK(status)) {
 			goto cleanup_delete;
@@ -669,9 +671,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 		oplock_level = OPLOCK_EXCLUSIVE;
 	}
 
-	status = odb_open_file(lck, f->handle, name->stream_id,
+	status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
 			       share_access, access_mask, del_on_close, 
-			       name->full_name, oplock_level, &oplock_granted);
+			       io->generic.in.open_disposition,
+			       false, oplock_level, &oplock_granted);
 	talloc_free(lck);
 	if (!NT_STATUS_IS_OK(status)) {
 		/* bad news, we must have hit a race - we don't delete the file
@@ -1186,9 +1189,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
 	}
 
 	/* see if we are allowed to open at the same time as existing opens */
-	status = odb_open_file(lck, f->handle, f->handle->name->stream_id,
+	status = odb_open_file(lck, f->handle, name->full_name, name->stream_id,
 			       share_access, access_mask, del_on_close,
-			       name->full_name, oplock_level, &oplock_granted);
+			       io->generic.in.open_disposition,
+			       false, oplock_level, &oplock_granted);
 
 	/* on a sharing violation we need to retry when the file is closed by 
 	   the other user, or after 1 second */
-- 
cgit 


From 7264a8b7ca5f91120dbc30fcbe8e8402f09ae883 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 17:48:13 +0100
Subject: opendb: unify the parameters of odb_open_file() and odb_can_open()

metze
(This used to be commit e6b708a52b0eada3fd374b66292ded3b0f6ce217)
---
 source4/cluster/ctdb/opendb_ctdb.c |  7 ++++---
 source4/ntvfs/common/opendb.c      |  8 +++++---
 source4/ntvfs/common/opendb.h      |  5 +++--
 source4/ntvfs/common/opendb_tdb.c  | 13 +++----------
 4 files changed, 15 insertions(+), 18 deletions(-)

(limited to 'source4')

diff --git a/source4/cluster/ctdb/opendb_ctdb.c b/source4/cluster/ctdb/opendb_ctdb.c
index 36ae204974..3dfc6819b7 100644
--- a/source4/cluster/ctdb/opendb_ctdb.c
+++ b/source4/cluster/ctdb/opendb_ctdb.c
@@ -596,8 +596,9 @@ static NTSTATUS odb_ctdb_get_delete_on_close(struct odb_context *odb,
   create_options and access_mask
 */
 static NTSTATUS odb_ctdb_can_open(struct odb_lock *lck,
-				 uint32_t share_access, uint32_t create_options, 
-				 uint32_t access_mask)
+				  uint32_t stream_id, uint32_t share_access,
+				  uint32_t access_mask, bool delete_on_close,
+				  uint32_t open_disposition, bool break_to_none)
 {
 	struct odb_context *odb = lck->odb;
 	NTSTATUS status;
@@ -611,7 +612,7 @@ static NTSTATUS odb_ctdb_can_open(struct odb_lock *lck,
 	}
 	NT_STATUS_NOT_OK_RETURN(status);
 
-	if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && 
+	if (delete_on_close &&
 	    file.num_entries != 0) {
 		return NT_STATUS_SHARING_VIOLATION;
 	}
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c
index c380355466..36144d0406 100644
--- a/source4/ntvfs/common/opendb.c
+++ b/source4/ntvfs/common/opendb.c
@@ -166,10 +166,12 @@ _PUBLIC_ NTSTATUS odb_get_delete_on_close(struct odb_context *odb,
   create_options and access_mask
 */
 _PUBLIC_ NTSTATUS odb_can_open(struct odb_lock *lck,
-			       uint32_t share_access, uint32_t create_options, 
-			       uint32_t access_mask)
+			       uint32_t stream_id, uint32_t share_access,
+			       uint32_t access_mask, bool delete_on_close,
+			       uint32_t open_disposition, bool break_to_none)
 {
-	return ops->odb_can_open(lck, share_access, create_options, access_mask);
+	return ops->odb_can_open(lck, stream_id, share_access, access_mask,
+				 delete_on_close, open_disposition, break_to_none);
 }
 
 _PUBLIC_ NTSTATUS odb_update_oplock(struct odb_lock *lck, void *file_handle,
diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h
index 205d2228ea..9591bcf6b9 100644
--- a/source4/ntvfs/common/opendb.h
+++ b/source4/ntvfs/common/opendb.h
@@ -40,8 +40,9 @@ struct opendb_ops {
 					    DATA_BLOB *key, bool *del_on_close, 
 					    int *open_count, char **path);
 	NTSTATUS (*odb_can_open)(struct odb_lock *lck,
-				 uint32_t share_access, uint32_t create_options, 
-				 uint32_t access_mask);
+				 uint32_t stream_id, uint32_t share_access,
+				 uint32_t access_mask, bool delete_on_close,
+				 uint32_t open_disposition, bool break_to_none);
 	NTSTATUS (*odb_update_oplock)(struct odb_lock *lck, void *file_handle,
 				      uint32_t oplock_level);
 	NTSTATUS (*odb_break_oplocks)(struct odb_lock *lck);
diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c
index d41a5c371e..73c04b7c4f 100644
--- a/source4/ntvfs/common/opendb_tdb.c
+++ b/source4/ntvfs/common/opendb_tdb.c
@@ -742,16 +742,13 @@ static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb,
   create_options and access_mask
 */
 static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
-				 uint32_t share_access, uint32_t create_options, 
-				 uint32_t access_mask)
+				 uint32_t stream_id, uint32_t share_access,
+				 uint32_t access_mask, bool delete_on_close,
+				 uint32_t open_disposition, bool break_to_none)
 {
 	struct odb_context *odb = lck->odb;
 	NTSTATUS status;
 	struct opendb_file file;
-	uint32_t stream_id = 0;
-	uint32_t open_disposition = 0;
-	bool delete_on_close = false;
-	bool break_to_none = false;
 	bool attrs_only = false;
 
 	status = odb_pull_record(lck, &file);
@@ -760,10 +757,6 @@ static NTSTATUS odb_tdb_can_open(struct odb_lock *lck,
 	}
 	NT_STATUS_NOT_OK_RETURN(status);
 
-	if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
-		delete_on_close = true;
-	}
-
 	status = odb_tdb_open_can_internal(odb, &file, stream_id,
 					   share_access, access_mask,
 					   delete_on_close, open_disposition,
-- 
cgit 


From c93cf42d9fe4f1e382a762e7c1eafef0dff122c1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 17:50:22 +0100
Subject: pvfs_open: fix odb_can_open() callers after prototype change

metze
(This used to be commit 904159327b3cb80fbec6aa5a4feaa141190a3f3a)
---
 source4/ntvfs/posix/pvfs_open.c | 51 ++++++++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 16 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 1b5ea56d64..bbfe4ac733 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -1428,6 +1428,9 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs,
 	NTSTATUS status;
 	DATA_BLOB key;
 	struct odb_lock *lck;
+	uint32_t share_access;
+	uint32_t access_mask;
+	bool delete_on_close;
 
 	status = pvfs_locking_key(name, name, &key);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1440,15 +1443,18 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs,
 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
 	}
 
-	status = odb_can_open(lck,
-			      NTCREATEX_SHARE_ACCESS_READ |
-			      NTCREATEX_SHARE_ACCESS_WRITE | 
-			      NTCREATEX_SHARE_ACCESS_DELETE, 
-			      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 
-			      SEC_STD_DELETE);
+	share_access	= NTCREATEX_SHARE_ACCESS_READ |
+			  NTCREATEX_SHARE_ACCESS_WRITE |
+			  NTCREATEX_SHARE_ACCESS_DELETE;
+	access_mask	= SEC_STD_DELETE;
+	delete_on_close	= true;
+
+	status = odb_can_open(lck, name->stream_id,
+			      share_access, access_mask, delete_on_close,
+			      0, false);
 
 	if (NT_STATUS_IS_OK(status)) {
-		status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE);
+		status = pvfs_access_check_simple(pvfs, req, name, access_mask);
 	}
 
 	/*
@@ -1487,6 +1493,9 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs,
 	NTSTATUS status;
 	DATA_BLOB key;
 	struct odb_lock *lck;
+	uint32_t share_access;
+	uint32_t access_mask;
+	bool delete_on_close;
 
 	status = pvfs_locking_key(name, name, &key);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1499,11 +1508,14 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs,
 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
 	}
 
-	status = odb_can_open(lck,
-			      NTCREATEX_SHARE_ACCESS_READ |
-			      NTCREATEX_SHARE_ACCESS_WRITE,
-			      0,
-			      SEC_STD_DELETE);
+	share_access	= NTCREATEX_SHARE_ACCESS_READ |
+			  NTCREATEX_SHARE_ACCESS_WRITE;
+	access_mask	= SEC_STD_DELETE;
+	delete_on_close	= false;
+
+	status = odb_can_open(lck, name->stream_id,
+			      share_access, access_mask, delete_on_close,
+			      0, false);
 
 	/*
 	 * if it's a sharing violation or we got no oplock
@@ -1540,6 +1552,9 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs,
 	NTSTATUS status;
 	DATA_BLOB key;
 	struct odb_lock *lck;
+	uint32_t share_access;
+	uint32_t access_mask;
+	bool delete_on_close;
 
 	status = pvfs_locking_key(name, name, &key);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1552,10 +1567,14 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs,
 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
 	}
 
-	status = odb_can_open(lck,
-			      NTCREATEX_SHARE_ACCESS_READ |
-			      NTCREATEX_SHARE_ACCESS_WRITE,
-			      0, 0);
+	share_access	= NTCREATEX_SHARE_ACCESS_READ |
+			  NTCREATEX_SHARE_ACCESS_WRITE;
+	access_mask	= 0;
+	delete_on_close	= false;
+
+	status = odb_can_open(lck, name->stream_id,
+			      share_access, access_mask, delete_on_close,
+			      0, false);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		talloc_free(lck);
-- 
cgit 


From d7ea52e9a3cd920f7c8a3b00f7cd28a7f605a993 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Thu, 21 Feb 2008 17:48:13 +0100
Subject: pvfs_open: make the retry logic indepdendent from open and sharing
 violations

metze
(This used to be commit 56bd63a4236ebf360d3e805c8560df86759573f7)
---
 source4/ntvfs/posix/pvfs_open.c | 149 ++++++++++++++++++++++++++--------------
 source4/ntvfs/posix/vfs_posix.h |   5 ++
 2 files changed, 104 insertions(+), 50 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index bbfe4ac733..8e1870fa70 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -751,20 +751,25 @@ cleanup_delete:
 	return status;
 }
 
-
 /*
-  state of a pending open retry
+  state of a pending retry
 */
-struct pvfs_open_retry {
+struct pvfs_odb_retry {
 	struct ntvfs_module_context *ntvfs;
 	struct ntvfs_request *req;
-	union smb_open *io;
-	struct pvfs_wait *wait_handle;
 	DATA_BLOB odb_locking_key;
+	void *io;
+	void *private_data;
+	void (*callback)(struct pvfs_odb_retry *r,
+			 struct ntvfs_module_context *ntvfs,
+			 struct ntvfs_request *req,
+			 void *io,
+			 void *private_data,
+			 enum pvfs_wait_notice reason);
 };
 
-/* destroy a pending open request */
-static int pvfs_retry_destructor(struct pvfs_open_retry *r)
+/* destroy a pending request */
+static int pvfs_odb_retry_destructor(struct pvfs_odb_retry *r)
 {
 	struct pvfs_state *pvfs = r->ntvfs->private_data;
 	if (r->odb_locking_key.data) {
@@ -778,15 +783,92 @@ static int pvfs_retry_destructor(struct pvfs_open_retry *r)
 	return 0;
 }
 
+static void pvfs_odb_retry_callback(void *_r, enum pvfs_wait_notice reason)
+{
+	struct pvfs_odb_retry *r = talloc_get_type(_r, struct pvfs_odb_retry);
+
+	if (reason == PVFS_WAIT_EVENT) {
+		/*
+		 * The pending odb entry is already removed.
+		 * We use a null locking key to indicate this
+		 * to the destructor.
+		 */
+		data_blob_free(&r->odb_locking_key);
+	}
+
+	r->callback(r, r->ntvfs, r->req, r->io, r->private_data, reason);
+}
+
 /*
-  retry an open
+  setup for a retry of a request that was rejected
+  by odb_open_file() or odb_can_open()
 */
-static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason)
+NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs,
+			      struct ntvfs_request *req,
+			      struct odb_lock *lck,
+			      struct timeval end_time,
+			      void *io,
+			      void *private_data,
+			      void (*callback)(struct pvfs_odb_retry *r,
+					       struct ntvfs_module_context *ntvfs,
+					       struct ntvfs_request *req,
+					       void *io,
+					       void *private_data,
+					       enum pvfs_wait_notice reason))
 {
-	struct pvfs_open_retry *r = private;
-	struct ntvfs_module_context *ntvfs = r->ntvfs;
-	struct ntvfs_request *req = r->req;
-	union smb_open *io = r->io;
+	struct pvfs_state *pvfs = ntvfs->private_data;
+	struct pvfs_odb_retry *r;
+	struct pvfs_wait *wait_handle;
+	NTSTATUS status;
+
+	r = talloc(req, struct pvfs_odb_retry);
+	NT_STATUS_HAVE_NO_MEMORY(r);
+
+	r->ntvfs = ntvfs;
+	r->req = req;
+	r->io = io;
+	r->private_data = private_data;
+	r->callback = callback;
+	r->odb_locking_key = odb_get_key(r, lck);
+	if (r->odb_locking_key.data == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/* setup a pending lock */
+	status = odb_open_file_pending(lck, r);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	talloc_free(lck);
+
+	talloc_set_destructor(r, pvfs_odb_retry_destructor);
+
+	wait_handle = pvfs_wait_message(pvfs, req,
+					MSG_PVFS_RETRY_OPEN, end_time,
+					pvfs_odb_retry_callback, r);
+	if (wait_handle == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	talloc_steal(r, wait_handle);
+
+	talloc_steal(pvfs, r);
+
+	return NT_STATUS_OK;
+}
+
+/*
+  retry an open after a sharing violation
+*/
+static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r,
+				    struct ntvfs_module_context *ntvfs,
+				    struct ntvfs_request *req,
+				    void *_io,
+				    void *private_data,
+				    enum pvfs_wait_notice reason)
+{
+	union smb_open *io = talloc_get_type(_io, union smb_open);
 	NTSTATUS status;
 
 	/* w2k3 ignores SMBntcancel for outstanding open requests. It's probably
@@ -795,8 +877,6 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason)
 		return;
 	}
 
-	talloc_free(r->wait_handle);
-
 	if (reason == PVFS_WAIT_TIMEOUT) {
 		/* if it timed out, then give the failure
 		   immediately */
@@ -806,9 +886,6 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason)
 		return;
 	}
 
-	/* the pending odb entry is already removed. We use a null locking
-	   key to indicate this */
-	data_blob_free(&r->odb_locking_key);
 	talloc_free(r);
 
 	/* try the open again, which could trigger another retry setup
@@ -925,7 +1002,6 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
 				      struct odb_lock *lck)
 {
 	struct pvfs_state *pvfs = ntvfs->private_data;
-	struct pvfs_open_retry *r;
 	NTSTATUS status;
 	struct timeval end_time;
 
@@ -939,40 +1015,13 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
 		}
 	}
 
-	r = talloc(req, struct pvfs_open_retry);
-	if (r == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	r->ntvfs = ntvfs;
-	r->req = req;
-	r->io = io;
-	r->odb_locking_key = data_blob_talloc(r, 
-					      f->handle->odb_locking_key.data, 
-					      f->handle->odb_locking_key.length);
-
-	end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay);
-
-	/* setup a pending lock */
-	status = odb_open_file_pending(lck, r);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
-
-	talloc_free(lck);
+	/* the retry should allocate a new file handle */
 	talloc_free(f);
 
-	talloc_set_destructor(r, pvfs_retry_destructor);
-
-	r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, end_time, 
-					   pvfs_open_retry, r);
-	if (r->wait_handle == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	talloc_steal(pvfs, r);
+	end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay);
 
-	return NT_STATUS_OK;
+	return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL,
+				    pvfs_retry_open_sharing);
 }
 
 /*
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 84c456dcfe..50875c3f9b 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -230,6 +230,11 @@ struct pvfs_dir;
 /* types of notification for pvfs wait events */
 enum pvfs_wait_notice {PVFS_WAIT_EVENT, PVFS_WAIT_TIMEOUT, PVFS_WAIT_CANCEL};
 
+/*
+  state of a pending retry
+*/
+struct pvfs_odb_retry;
+
 #define PVFS_EADB			"posix:eadb"
 #define PVFS_XATTR			"posix:xattr"
 #define PVFS_FAKE_OPLOCKS		"posix:fakeoplocks"
-- 
cgit 


From 95fafa694cbb6f695488c750d481bb1e427da6eb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 08:32:35 +0100
Subject: pvfs: add pvfs_setup_oplock() to receive oplock breaks and pass them
 to the client

metze
(This used to be commit b09a2b126723bd75afd245f549703a04e512e129)
---
 source4/ntvfs/posix/config.mk     |   1 +
 source4/ntvfs/posix/pvfs_oplock.c | 136 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+)
 create mode 100644 source4/ntvfs/posix/pvfs_oplock.c

(limited to 'source4')

diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk
index 6879940337..88048c2af7 100644
--- a/source4/ntvfs/posix/config.mk
+++ b/source4/ntvfs/posix/config.mk
@@ -53,6 +53,7 @@ OBJ_FILES = \
 		pvfs_resolve.o \
 		pvfs_shortname.o \
 		pvfs_lock.o \
+		pvfs_oplock.o \
 		pvfs_wait.o \
 		pvfs_seek.o \
 		pvfs_ioctl.o \
diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c
new file mode 100644
index 0000000000..50b1478f13
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_oplock.c
@@ -0,0 +1,136 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - oplock handling
+
+   Copyright (C) Stefan Metzmacher 2008
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see .
+*/
+
+#include "includes.h"
+#include "lib/messaging/messaging.h"
+#include "lib/messaging/irpc.h"
+#include "vfs_posix.h"
+
+
+struct pvfs_oplock {
+	struct pvfs_file_handle *handle;
+	struct pvfs_file *file;
+	uint32_t level;
+	struct messaging_context *msg_ctx;
+};
+
+/*
+  receive oplock breaks and forward them to the client
+*/
+static void pvfs_oplock_break(struct pvfs_oplock *opl, uint8_t level)
+{
+	NTSTATUS status;
+	struct pvfs_file *f = opl->file;
+	struct pvfs_file_handle *h = opl->handle;
+	struct pvfs_state *pvfs = h->pvfs;
+
+	DEBUG(10,("pvfs_oplock_break: sending oplock break level %d for '%s' %p\n",
+		level, h->name->original_name, h));
+	status = ntvfs_send_oplock_break(pvfs->ntvfs, f->ntvfs, level);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(0,("pvfs_oplock_break: sending oplock break failed: %s\n",
+			nt_errstr(status)));
+	}
+}
+
+static void pvfs_oplock_break_dispatch(struct messaging_context *msg,
+				       void *private_data, uint32_t msg_type,
+				       struct server_id src, DATA_BLOB *data)
+{
+	struct pvfs_oplock *opl = talloc_get_type(private_data,
+						  struct pvfs_oplock);
+	struct opendb_oplock_break opb;
+
+	ZERO_STRUCT(opb);
+
+	/* we need to check that this one is for us. See
+	   messaging_send_ptr() for the other side of this.
+	 */
+	if (data->length == sizeof(struct opendb_oplock_break)) {
+		struct opendb_oplock_break *p;
+		p = (struct opendb_oplock_break *)data->data;
+		opb = *p;
+	} else {
+		DEBUG(0,("%s: ignore oplock break with length[%u]\n",
+			__location__, data->length));
+		return;
+	}
+	if (opb.file_handle != opl->handle) {
+		return;
+	}
+
+	/*
+	 * maybe we should use ntvfs_setup_async()
+	 */
+	pvfs_oplock_break(opl, opb.level);
+}
+
+static int pvfs_oplock_destructor(struct pvfs_oplock *opl)
+{
+	messaging_deregister(opl->msg_ctx, MSG_NTVFS_OPLOCK_BREAK, opl);
+	return 0;
+}
+
+NTSTATUS pvfs_setup_oplock(struct pvfs_file *f, uint32_t oplock_granted)
+{
+	NTSTATUS status;
+	struct pvfs_oplock *opl;
+	uint32_t level = OPLOCK_NONE;
+
+	f->handle->oplock = NULL;
+
+	switch (oplock_granted) {
+	case EXCLUSIVE_OPLOCK_RETURN:
+		level = OPLOCK_EXCLUSIVE;
+		break;
+	case BATCH_OPLOCK_RETURN:
+		level = OPLOCK_BATCH;
+		break;
+	case LEVEL_II_OPLOCK_RETURN:
+		level = OPLOCK_LEVEL_II;
+		break;
+	}
+
+	if (level == OPLOCK_NONE) {
+		return NT_STATUS_OK;
+	}
+
+	opl = talloc(f->handle, struct pvfs_oplock);
+	NT_STATUS_HAVE_NO_MEMORY(opl);
+
+	opl->handle	= f->handle;
+	opl->file	= f;
+	opl->level	= level;
+	opl->msg_ctx	= f->pvfs->ntvfs->ctx->msg_ctx;
+
+	status = messaging_register(opl->msg_ctx,
+				    opl,
+				    MSG_NTVFS_OPLOCK_BREAK,
+				    pvfs_oplock_break_dispatch);
+	NT_STATUS_NOT_OK_RETURN(status);
+
+	/* destructor */
+	talloc_set_destructor(opl, pvfs_oplock_destructor);
+
+	f->handle->oplock = opl;
+
+	return NT_STATUS_OK;
+}
-- 
cgit 


From be1ba5b63164e7dab4bf067bc1aac4ed9cece2bc Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 08:39:13 +0100
Subject: pvfs_open: call pvfs_setup_oplock() if an oplock was granted

This is needed to receive oplock breaks from other "processes"

metze
(This used to be commit dd56f55afdc0d114a0b0bceb0e4feb022919323a)
---
 source4/ntvfs/posix/pvfs_open.c | 22 +++++++++++++++++++---
 source4/ntvfs/posix/vfs_posix.h |  8 ++++++++
 2 files changed, 27 insertions(+), 3 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 8e1870fa70..8429c14d1b 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -268,6 +268,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
 	f->handle->seek_offset       = 0;
 	f->handle->position          = 0;
 	f->handle->mode              = 0;
+	f->handle->oplock            = NULL;
 	f->handle->sticky_write_time = false;
 	f->handle->open_completed    = false;
 
@@ -684,9 +685,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 		return status;
 	}
 
-	if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
-		oplock_granted = OPLOCK_BATCH;
-	}
 
 	f->ntvfs             = h;
 	f->pvfs              = pvfs;
@@ -705,12 +703,23 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 	f->handle->seek_offset       = 0;
 	f->handle->position          = 0;
 	f->handle->mode              = 0;
+	f->handle->oplock            = NULL;
 	f->handle->have_opendb_entry = true;
 	f->handle->sticky_write_time = false;
 	f->handle->open_completed    = false;
 
 	DLIST_ADD(pvfs->files.list, f);
 
+	if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
+		oplock_granted = OPLOCK_BATCH;
+	} else if (oplock_granted != OPLOCK_NONE) {
+		status = pvfs_setup_oplock(f, oplock_granted);
+		if (!NT_STATUS_IS_OK(status)) {
+			talloc_free(lck);
+			return status;
+		}
+	}
+
 	/* setup a destructor to avoid file descriptor leaks on
 	   abnormal termination */
 	talloc_set_destructor(f, pvfs_fnum_destructor);
@@ -1185,6 +1194,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
 	f->handle->seek_offset       = 0;
 	f->handle->position          = 0;
 	f->handle->mode              = 0;
+	f->handle->oplock            = NULL;
 	f->handle->have_opendb_entry = false;
 	f->handle->sticky_write_time = false;
 	f->handle->open_completed    = false;
@@ -1257,6 +1267,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
 
 	if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
 		oplock_granted = OPLOCK_BATCH;
+	} else if (oplock_granted != OPLOCK_NONE) {
+		status = pvfs_setup_oplock(f, oplock_granted);
+		if (!NT_STATUS_IS_OK(status)) {
+			talloc_free(lck);
+			return status;
+		}
 	}
 
 	f->handle->have_opendb_entry = true;
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 50875c3f9b..72469505cc 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -29,6 +29,7 @@
 #include "dsdb/samdb/samdb.h"
 
 struct pvfs_wait;
+struct pvfs_oplock;
 
 /* this is the private structure for the posix vfs backend. It is used
    to hold per-connection (per tree connect) state information */
@@ -154,6 +155,13 @@ struct pvfs_file_handle {
 
 	bool have_opendb_entry;
 
+	/*
+	 * we need to wait for oplock break requests from other processes,
+	 * and we need to remember the pvfs_file so we can correctly
+	 * forward the oplock break to the client
+	 */
+	struct pvfs_oplock *oplock;
+
 	/* we need this hook back to our parent for lock destruction */
 	struct pvfs_state *pvfs;
 
-- 
cgit 


From 4ee328d7d26f1a86559993f6533b8a1e12a4c6a1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 09:51:58 +0100
Subject: pvfs: handle oplock releases in its own function
 pvfs_oplock_release()

metze
(This used to be commit 27ec7bfc8b7f46c97e6878caf5cd694c517ce053)
---
 source4/ntvfs/posix/pvfs_lock.c   | 11 +++----
 source4/ntvfs/posix/pvfs_oplock.c | 64 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 7 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c
index df85b2b775..0796286b7e 100644
--- a/source4/ntvfs/posix/pvfs_lock.c
+++ b/source4/ntvfs/posix/pvfs_lock.c
@@ -294,6 +294,10 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
 		return ntvfs_map_lock(ntvfs, req, lck);
 	}
 
+	if (lck->lockx.in.mode & LOCKING_ANDX_OPLOCK_RELEASE) {
+		return pvfs_oplock_release(ntvfs, req, lck);
+	}
+
 	f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.ntvfs);
 	if (!f) {
 		return NT_STATUS_INVALID_HANDLE;
@@ -338,13 +342,6 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
 		return NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks);
 	}
 
-	if (lck->lockx.in.mode & LOCKING_ANDX_OPLOCK_RELEASE) {
-		DEBUG(0,("received unexpected oplock break\n"));
-		talloc_free(pending);
-		return NT_STATUS_NOT_IMPLEMENTED;
-	}
-
-
 	/* the unlocks happen first */
 	locks = lck->lockx.in.locks;
 
diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c
index 50b1478f13..eff9ae1f1d 100644
--- a/source4/ntvfs/posix/pvfs_oplock.c
+++ b/source4/ntvfs/posix/pvfs_oplock.c
@@ -134,3 +134,67 @@ NTSTATUS pvfs_setup_oplock(struct pvfs_file *f, uint32_t oplock_granted)
 
 	return NT_STATUS_OK;
 }
+
+NTSTATUS pvfs_oplock_release(struct ntvfs_module_context *ntvfs,
+			     struct ntvfs_request *req, union smb_lock *lck)
+{
+	struct pvfs_state *pvfs = ntvfs->private_data;
+	struct pvfs_file *f;
+	struct pvfs_file_handle *h;
+	struct odb_lock *olck;
+	uint8_t oplock_break;
+	NTSTATUS status;
+
+	f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.ntvfs);
+	if (!f) {
+		return NT_STATUS_INVALID_HANDLE;
+	}
+
+	h = f->handle;
+
+	if (h->fd == -1) {
+		return NT_STATUS_FILE_IS_A_DIRECTORY;
+	}
+
+	if (!h->have_opendb_entry) {
+		return NT_STATUS_FOOBAR;
+	}
+
+	if (!h->oplock) {
+		return NT_STATUS_FOOBAR;
+	}
+
+	olck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
+	if (olck == NULL) {
+		DEBUG(0,("Unable to lock opendb for oplock update\n"));
+		return NT_STATUS_FOOBAR;
+	}
+
+	oplock_break = (lck->lockx.in.mode >> 8) & 0xFF;
+	if (oplock_break == OPLOCK_BREAK_TO_NONE) {
+		h->oplock->level = OPLOCK_NONE;
+	} else if (oplock_break == OPLOCK_BREAK_TO_LEVEL_II) {
+		h->oplock->level = OPLOCK_LEVEL_II;
+	} else {
+		/* fallback to level II in case of a invalid value */
+		DEBUG(1,("unexpected oplock break level[0x%02X]\n", oplock_break));
+		h->oplock->level = OPLOCK_LEVEL_II;
+	}
+	status = odb_update_oplock(olck, h, h->oplock->level);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(0,("Unable to update oplock level for '%s' - %s\n",
+			 h->name->full_name, nt_errstr(status)));
+		talloc_free(olck);
+		return status;
+	}
+
+	talloc_free(olck);
+
+	/* after a break to none, we no longer have an oplock attached */
+	if (h->oplock->level == OPLOCK_NONE) {
+		talloc_free(h->oplock);
+		h->oplock = NULL;
+	}
+
+	return NT_STATUS_OK;
+}
-- 
cgit 


From 348439e9301fa3b07f5263a6dabc61557a384179 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Fri, 22 Feb 2008 16:34:50 +0100
Subject: pvfs_oplocks: add pvfs_break_level2_oplocks()

metze
(This used to be commit e0837238b6b09143970f03b6a78201c3fe55f3cd)
---
 source4/ntvfs/posix/pvfs_oplock.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c
index eff9ae1f1d..cf30ddbc59 100644
--- a/source4/ntvfs/posix/pvfs_oplock.c
+++ b/source4/ntvfs/posix/pvfs_oplock.c
@@ -198,3 +198,42 @@ NTSTATUS pvfs_oplock_release(struct ntvfs_module_context *ntvfs,
 
 	return NT_STATUS_OK;
 }
+
+NTSTATUS pvfs_break_level2_oplocks(struct pvfs_file *f)
+{
+	struct pvfs_file_handle *h = f->handle;
+	struct odb_lock *olck;
+	NTSTATUS status;
+
+	if (h->oplock && h->oplock->level == OPLOCK_EXCLUSIVE) {
+		return NT_STATUS_OK;
+	}
+
+	olck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
+	if (olck == NULL) {
+		DEBUG(0,("Unable to lock opendb for oplock update\n"));
+		return NT_STATUS_FOOBAR;
+	}
+
+	if (h->oplock && h->oplock->level == OPLOCK_BATCH) {
+		status = odb_update_oplock(olck, h, OPLOCK_LEVEL_II);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0,("Unable to update oplock level for '%s' - %s\n",
+				 h->name->full_name, nt_errstr(status)));
+			talloc_free(olck);
+			return status;
+		}
+	}
+
+	status = odb_break_oplocks(olck);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(0,("Unable to break level2 oplocks to none for '%s' - %s\n",
+			 h->name->full_name, nt_errstr(status)));
+		talloc_free(olck);
+		return status;
+	}
+
+	talloc_free(olck);
+
+	return NT_STATUS_OK;
+}
-- 
cgit 


From 4344ac6209df4be2dad6a8b1c0766101f5972f13 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Fri, 22 Feb 2008 16:34:50 +0100
Subject: pvfs: send oplock breaks to none to level2 holders on write/lock
 requests

metze
(This used to be commit b8c42a1ff8fd4131ef2a1ad92a7405a2e4d335d3)
---
 source4/ntvfs/posix/pvfs_lock.c  | 3 +++
 source4/ntvfs/posix/pvfs_write.c | 5 ++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c
index 0796286b7e..baa92880f1 100644
--- a/source4/ntvfs/posix/pvfs_lock.c
+++ b/source4/ntvfs/posix/pvfs_lock.c
@@ -307,6 +307,9 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
 		return NT_STATUS_FILE_IS_A_DIRECTORY;
 	}
 
+	status = pvfs_break_level2_oplocks(f);
+	NT_STATUS_NOT_OK_RETURN(status);
+
 	if (lck->lockx.in.timeout != 0 && 
 	    (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
 		pending = talloc(f, struct pvfs_pending_lock);
diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c
index 5a11f01952..dda8c83407 100644
--- a/source4/ntvfs/posix/pvfs_write.c
+++ b/source4/ntvfs/posix/pvfs_write.c
@@ -57,7 +57,10 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs,
 				 wr->writex.in.count,
 				 WRITE_LOCK);
 	NT_STATUS_NOT_OK_RETURN(status);
-	
+
+	status = pvfs_break_level2_oplocks(f);
+	NT_STATUS_NOT_OK_RETURN(status);
+
 	if (f->handle->name->stream_name) {
 		ret = pvfs_stream_write(pvfs,
 					f->handle,
-- 
cgit 


From ee81b7a85e8bb749a00c85bfdcf8f1e341ad2eea Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Sat, 23 Feb 2008 11:46:43 +0100
Subject: pvfs_setfileinfo: break level2 oplocks on setfileinfo()
 ALLOCATION_INFO and END_OF_FILE_INFO

metze
(This used to be commit b258f9d8d4bf3606f4884d1bff548f16dadc08aa)
---
 source4/ntvfs/posix/pvfs_setfileinfo.c | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index c6d014a72f..d1d8f819ef 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -355,6 +355,9 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
 
 	case RAW_SFILEINFO_ALLOCATION_INFO:
 	case RAW_SFILEINFO_ALLOCATION_INFORMATION:
+		status = pvfs_break_level2_oplocks(f);
+		NT_STATUS_NOT_OK_RETURN(status);
+
 		newstats.dos.alloc_size = info->allocation_info.in.alloc_size;
 		if (newstats.dos.alloc_size < newstats.st.st_size) {
 			newstats.st.st_size = newstats.dos.alloc_size;
@@ -365,6 +368,9 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
 
 	case RAW_SFILEINFO_END_OF_FILE_INFO:
 	case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
+		status = pvfs_break_level2_oplocks(f);
+		NT_STATUS_NOT_OK_RETURN(status);
+
 		newstats.st.st_size = info->end_of_file_info.in.size;
 		break;
 
-- 
cgit 


From c0d1543a6a5fee3d767a366186dd634a395c8146 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Mon, 25 Feb 2008 19:17:45 +0100
Subject: pvfs: add posix:oplocktimeout=30 option

metze
(This used to be commit 5abc57ddab558c13db3864d13afc2ad3b1641d1c)
---
 source4/ntvfs/posix/vfs_posix.c | 4 ++++
 source4/ntvfs/posix/vfs_posix.h | 9 +++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c
index e058e6f546..ca874d1db1 100644
--- a/source4/ntvfs/posix/vfs_posix.c
+++ b/source4/ntvfs/posix/vfs_posix.c
@@ -91,6 +91,10 @@ static void pvfs_setup_options(struct pvfs_state *pvfs)
 							PVFS_SHARE_DELAY,
 							PVFS_SHARE_DELAY_DEFAULT);
 
+	pvfs->oplock_break_timeout = share_int_option(scfg,
+						      PVFS_OPLOCK_TIMEOUT,
+						      PVFS_OPLOCK_TIMEOUT_DEFAULT);
+
 	pvfs->share_name = talloc_strdup(pvfs, scfg->name);
 
 	pvfs->fs_attribs = 
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 72469505cc..4d22a91714 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -52,9 +52,12 @@ struct pvfs_state {
 	   ntcancel */
 	struct pvfs_wait *wait_list;
 
-	/* the sharing violation timeout */
+	/* the sharing violation timeout (nsecs) */
 	uint_t sharing_violation_delay;
 
+	/* the oplock break timeout (secs) */
+	uint_t oplock_break_timeout;
+
 	/* filesystem attributes (see FS_ATTR_*) */
 	uint32_t fs_attribs;
 
@@ -247,6 +250,7 @@ struct pvfs_odb_retry;
 #define PVFS_XATTR			"posix:xattr"
 #define PVFS_FAKE_OPLOCKS		"posix:fakeoplocks"
 #define PVFS_SHARE_DELAY		"posix:sharedelay"
+#define PVFS_OPLOCK_TIMEOUT		"posix:oplocktimeout"
 #define PVFS_ALLOCATION_ROUNDING	"posix:allocationrounding"
 #define PVFS_SEARCH_INACTIVITY		"posix:searchinactivity"
 #define PVFS_ACL			"posix:acl"
@@ -254,7 +258,8 @@ struct pvfs_odb_retry;
 
 #define PVFS_XATTR_DEFAULT			true
 #define PVFS_FAKE_OPLOCKS_DEFAULT		false
-#define PVFS_SHARE_DELAY_DEFAULT		1000000
+#define PVFS_SHARE_DELAY_DEFAULT		1000000 /* nsecs */
+#define PVFS_OPLOCK_TIMEOUT_DEFAULT		30 /* secs */
 #define PVFS_ALLOCATION_ROUNDING_DEFAULT	512
 #define PVFS_SEARCH_INACTIVITY_DEFAULT		300
 
-- 
cgit 


From 61e17794c394d2c070ce7df9cee6c53d846e7b75 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Fri, 22 Feb 2008 11:52:17 +0100
Subject: pvfs_unlink: retry unlink after oplock not granted

metze
(This used to be commit 746e89ce2e74dbd2cea8f5575c403e4c61f82cb8)
---
 source4/ntvfs/posix/pvfs_open.c   | 26 ++++++++---
 source4/ntvfs/posix/pvfs_unlink.c | 94 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 113 insertions(+), 7 deletions(-)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 8429c14d1b..4110df292d 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -1008,7 +1008,8 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
 				      struct ntvfs_request *req, 
 				      union smb_open *io,
 				      struct pvfs_file *f,
-				      struct odb_lock *lck)
+				      struct odb_lock *lck,
+				      NTSTATUS parent_status)
 {
 	struct pvfs_state *pvfs = ntvfs->private_data;
 	NTSTATUS status;
@@ -1027,7 +1028,15 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
 	/* the retry should allocate a new file handle */
 	talloc_free(f);
 
-	end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay);
+	if (NT_STATUS_EQUAL(parent_status, NT_STATUS_SHARING_VIOLATION)) {
+		end_time = timeval_add(&req->statistics.request_time,
+				       0, pvfs->sharing_violation_delay);
+	} else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
+		end_time = timeval_add(&req->statistics.request_time,
+				       pvfs->oplock_break_timeout, 0);
+	} else {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
 
 	return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL,
 				    pvfs_retry_open_sharing);
@@ -1253,11 +1262,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
 			       io->generic.in.open_disposition,
 			       false, oplock_level, &oplock_granted);
 
-	/* on a sharing violation we need to retry when the file is closed by 
-	   the other user, or after 1 second */
-	if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) &&
+	/*
+	 * on a sharing violation we need to retry when the file is closed by
+	 * the other user, or after 1 second
+	 * on a non granted oplock we need to retry when the file is closed by
+	 * the other user, or after 30 seconds
+	*/
+	if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+	     NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
 	    (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
-		return pvfs_open_setup_retry(ntvfs, req, io, f, lck);
+		return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
 	}
 
 	if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c
index bda4014bee..7a2d964b9d 100644
--- a/source4/ntvfs/posix/pvfs_unlink.c
+++ b/source4/ntvfs/posix/pvfs_unlink.c
@@ -23,6 +23,84 @@
 #include "vfs_posix.h"
 #include "system/dir.h"
 
+/*
+  retry an open after a sharing violation
+*/
+static void pvfs_retry_unlink(struct pvfs_odb_retry *r,
+			      struct ntvfs_module_context *ntvfs,
+			      struct ntvfs_request *req,
+			      void *_io,
+			      void *private_data,
+			      enum pvfs_wait_notice reason)
+{
+	union smb_unlink *io = talloc_get_type(_io, union smb_unlink);
+	NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
+
+	talloc_free(r);
+
+	switch (reason) {
+	case PVFS_WAIT_CANCEL:
+/*TODO*/
+		status = NT_STATUS_CANCELLED;
+		break;
+	case PVFS_WAIT_TIMEOUT:
+		/* if it timed out, then give the failure
+		   immediately */
+/*TODO*/
+		status = NT_STATUS_SHARING_VIOLATION;
+		break;
+	case PVFS_WAIT_EVENT:
+
+		/* try the open again, which could trigger another retry setup
+		   if it wants to, so we have to unmark the async flag so we
+		   will know if it does a second async reply */
+		req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC;
+
+		status = pvfs_unlink(ntvfs, req, io);
+		if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
+			/* the 2nd try also replied async, so we don't send
+			   the reply yet */
+			return;
+		}
+
+		/* re-mark it async, just in case someone up the chain does
+		   paranoid checking */
+		req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+		break;
+	}
+
+	/* send the reply up the chain */
+	req->async_states->status = status;
+	req->async_states->send_fn(req);
+}
+
+/*
+  setup for a unlink retry after a sharing violation
+  or a non granted oplock
+*/
+static NTSTATUS pvfs_unlink_setup_retry(struct ntvfs_module_context *ntvfs,
+					struct ntvfs_request *req,
+					union smb_unlink *io,
+					struct odb_lock *lck,
+					NTSTATUS status)
+{
+	struct pvfs_state *pvfs = ntvfs->private_data;
+	struct timeval end_time;
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+		end_time = timeval_add(&req->statistics.request_time,
+				       0, pvfs->sharing_violation_delay);
+	} else if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
+		end_time = timeval_add(&req->statistics.request_time,
+				       pvfs->oplock_break_timeout, 0);
+	} else {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL,
+				    pvfs_retry_unlink);
+}
+
 
 /*
   unlink a file
@@ -67,6 +145,7 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs,
 				struct pvfs_filename *name)
 {
 	NTSTATUS status;
+	struct odb_lock *lck = NULL;
 
 	/* make sure its matches the given attributes */
 	status = pvfs_match_attrib(pvfs, name,
@@ -75,7 +154,20 @@ static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs,
 		return status;
 	}
 
-	status = pvfs_can_delete(pvfs, req, name, NULL);
+	status = pvfs_can_delete(pvfs, req, name, &lck);
+
+	/*
+	 * on a sharing violation we need to retry when the file is closed by
+	 * the other user, or after 1 second
+	 * on a non granted oplock we need to retry when the file is closed by
+	 * the other user, or after 30 seconds
+	 */
+	if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+	     NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
+	    (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
+		return pvfs_unlink_setup_retry(pvfs->ntvfs, req, unl, lck, status);
+	}
+
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
 	}
-- 
cgit 


From 4eb0fcc5173ddf50305fa5094ec0d87d53d71a33 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Sat, 23 Feb 2008 11:49:39 +0100
Subject: pvfs_open: add pvfs_can_update_file_size()

TODO: this is not complete, we need more tests to trigger this

metze
(This used to be commit 66ad1081f2be8a0caa16fb0d614b857a5bde751c)
---
 source4/ntvfs/posix/pvfs_open.c | 62 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 4110df292d..12b70c00fd 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -1620,6 +1620,68 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs,
 	return status;
 }
 
+/*
+  determine if the file size of a file can be changed,
+  or if it is prevented by an already open file
+*/
+NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs,
+				   struct ntvfs_request *req,
+				   struct pvfs_filename *name,
+				   struct odb_lock **lckp)
+{
+	NTSTATUS status;
+	DATA_BLOB key;
+	struct odb_lock *lck;
+	uint32_t share_access;
+	uint32_t access_mask;
+	bool break_to_none;
+	bool delete_on_close;
+
+	status = pvfs_locking_key(name, name, &key);
+	if (!NT_STATUS_IS_OK(status)) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	lck = odb_lock(req, pvfs->odb_context, &key);
+	if (lck == NULL) {
+		DEBUG(0,("Unable to lock opendb for can_stat\n"));
+		return NT_STATUS_INTERNAL_DB_CORRUPTION;
+	}
+
+	/* TODO: this may needs some more flags */
+	share_access	= NTCREATEX_SHARE_ACCESS_WRITE;
+	access_mask	= 0;
+	delete_on_close	= false;
+	break_to_none	= true;
+
+	status = odb_can_open(lck, name->stream_id,
+			      share_access, access_mask, delete_on_close,
+			      0, break_to_none);
+
+	/*
+	 * if it's a sharing violation or we got no oplock
+	 * only keep the lock if the caller requested access
+	 * to the lock
+	 */
+	if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+	    NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
+		if (lckp) {
+			*lckp = lck;
+		} else {
+			talloc_free(lck);
+		}
+	} else if (!NT_STATUS_IS_OK(status)) {
+		talloc_free(lck);
+		if (lckp) {
+			*lckp = NULL;
+		}
+	} else if (lckp) {
+		*lckp = lck;
+	}
+
+	return status;
+}
+
 /*
   determine if file meta data can be accessed, or if it is prevented by an
   already open file
-- 
cgit 


From fa2e4ba03cd65f850d8f118ce61d5c4a80f0e30a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Sat, 23 Feb 2008 11:50:19 +0100
Subject: pvfs_setpathinfo: retry setpathinfo after oplock not granted on on
 setpathinfo ALLOCATION_INFO and END_OF_FILE_INFO

metze
(This used to be commit 4e27ac8c529d5a1675fb02215191a2be7913ec97)
---
 source4/ntvfs/posix/pvfs_setfileinfo.c | 107 +++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

(limited to 'source4')

diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c
index d1d8f819ef..da1e31e639 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -472,6 +472,84 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
 	return pvfs_dosattrib_save(pvfs, h->name, h->fd);
 }
 
+/*
+  retry an open after a sharing violation
+*/
+static void pvfs_retry_setpathinfo(struct pvfs_odb_retry *r,
+				   struct ntvfs_module_context *ntvfs,
+				   struct ntvfs_request *req,
+				   void *_info,
+				   void *private_data,
+				   enum pvfs_wait_notice reason)
+{
+	union smb_setfileinfo *info = talloc_get_type(_info,
+				      union smb_setfileinfo);
+	NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
+
+	talloc_free(r);
+
+	switch (reason) {
+	case PVFS_WAIT_CANCEL:
+/*TODO*/
+		status = NT_STATUS_CANCELLED;
+		break;
+	case PVFS_WAIT_TIMEOUT:
+		/* if it timed out, then give the failure
+		   immediately */
+/*TODO*/
+		status = NT_STATUS_SHARING_VIOLATION;
+		break;
+	case PVFS_WAIT_EVENT:
+
+		/* try the open again, which could trigger another retry setup
+		   if it wants to, so we have to unmark the async flag so we
+		   will know if it does a second async reply */
+		req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC;
+
+		status = pvfs_setpathinfo(ntvfs, req, info);
+		if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
+			/* the 2nd try also replied async, so we don't send
+			   the reply yet */
+			return;
+		}
+
+		/* re-mark it async, just in case someone up the chain does
+		   paranoid checking */
+		req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+		break;
+	}
+
+	/* send the reply up the chain */
+	req->async_states->status = status;
+	req->async_states->send_fn(req);
+}
+
+/*
+  setup for a unlink retry after a sharing violation
+  or a non granted oplock
+*/
+static NTSTATUS pvfs_setpathinfo_setup_retry(struct ntvfs_module_context *ntvfs,
+					     struct ntvfs_request *req,
+					     union smb_setfileinfo *info,
+					     struct odb_lock *lck,
+					     NTSTATUS status)
+{
+	struct pvfs_state *pvfs = ntvfs->private_data;
+	struct timeval end_time;
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+		end_time = timeval_add(&req->statistics.request_time,
+				       0, pvfs->sharing_violation_delay);
+	} else if (NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
+		end_time = timeval_add(&req->statistics.request_time,
+				       pvfs->oplock_break_timeout, 0);
+	} else {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, info, NULL,
+				    pvfs_retry_setpathinfo);
+}
 
 /*
   set info on a pathname
@@ -486,6 +564,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
 	struct utimbuf unix_times;
 	uint32_t access_needed;
 	uint32_t change_mask = 0;
+	struct odb_lock *lck = NULL;
 
 	/* resolve the cifs name to a posix name */
 	status = pvfs_resolve_name(pvfs, req, info->generic.in.file.path, 
@@ -560,6 +639,20 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
 
 	case RAW_SFILEINFO_ALLOCATION_INFO:
 	case RAW_SFILEINFO_ALLOCATION_INFORMATION:
+		status = pvfs_can_update_file_size(pvfs, req, name, &lck);
+		/*
+		 * on a sharing violation we need to retry when the file is closed by
+		 * the other user, or after 1 second
+		 * on a non granted oplock we need to retry when the file is closed by
+		 * the other user, or after 30 seconds
+		*/
+		if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+		     NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
+		    (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
+			return pvfs_setpathinfo_setup_retry(pvfs->ntvfs, req, info, lck, status);
+		}
+		NT_STATUS_NOT_OK_RETURN(status);
+
 		if (info->allocation_info.in.alloc_size > newstats.dos.alloc_size) {
 			/* strange. Increasing the allocation size via setpathinfo 
 			   should be silently ignored */
@@ -575,6 +668,20 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
 
 	case RAW_SFILEINFO_END_OF_FILE_INFO:
 	case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
+		status = pvfs_can_update_file_size(pvfs, req, name, &lck);
+		/*
+		 * on a sharing violation we need to retry when the file is closed by
+		 * the other user, or after 1 second
+		 * on a non granted oplock we need to retry when the file is closed by
+		 * the other user, or after 30 seconds
+		*/
+		if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
+		     NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
+		    (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
+			return pvfs_setpathinfo_setup_retry(pvfs->ntvfs, req, info, lck, status);
+		}
+		NT_STATUS_NOT_OK_RETURN(status);
+
 		newstats.st.st_size = info->end_of_file_info.in.size;
 		break;
 
-- 
cgit 


From 9ddbdfa02cfaa0df6ce944d6dfecf6850ab0b2f8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Sat, 23 Feb 2008 11:54:01 +0100
Subject: selftest: Samba4 passes all oplocks tests now

The support for oplocks is not completely finished
I believe we will not pass some non existing test.
But it's a good start.

metze
(This used to be commit 278eea57fa9f59908672c935187f942e7780f0aa)
---
 source4/samba4-knownfail          | 1 -
 source4/samba4-skip               | 4 ----
 source4/selftest/target/Samba4.pm | 6 ++++++
 3 files changed, 6 insertions(+), 5 deletions(-)

(limited to 'source4')

diff --git a/source4/samba4-knownfail b/source4/samba4-knownfail
index 18fb4b914b..4d850caae5 100644
--- a/source4/samba4-knownfail
+++ b/source4/samba4-knownfail
@@ -3,7 +3,6 @@ local.iconv.*.next_codepoint()
 base.delaywrite.finfo update on close
 base.delete.*.deltest20a
 base.delete.*.deltest20b
-raw.oplock.*.OPLOCK
 rpc.winreg
 local.registry.*.security # Not implemented yet
 rpc.wkssvc
diff --git a/source4/samba4-skip b/source4/samba4-skip
index 541738ecc4..4d2da6ed64 100644
--- a/source4/samba4-skip
+++ b/source4/samba4-skip
@@ -1,12 +1,10 @@
 base.delaywrite
 raw.composite
-raw.oplock
 base.iometer
 base.casetable
 base.nttrans
 .*base.bench.holdcon.*				# Very slow
 base.scan.maxfid
-raw.bench.oplock
 raw.hold.oplock
 raw.ping.pong
 rpc.samr_accessmask
@@ -25,9 +23,7 @@ ntvfs.cifs.base.scan-maxfid
 ntvfs.cifs.base.utable
 ntvfs.cifs.base.smb
 ntvfs.cifs.raw.composite
-ntvfs.cifs.raw.oplock
 ntvfs.cifs.raw.notify
-ntvfs.cifs.raw.bench-oplock
 ntvfs.cifs.raw.scan-eamax
 ntvfs.cifs.raw.context
 ntvfs.cifs.raw.qfileinfo.ipc
diff --git a/source4/selftest/target/Samba4.pm b/source4/selftest/target/Samba4.pm
index 37e3cbe354..e0be8048a0 100644
--- a/source4/selftest/target/Samba4.pm
+++ b/source4/selftest/target/Samba4.pm
@@ -562,12 +562,16 @@ sub provision($$$$$$)
 	gensec:require_pac = true
 	log level = $smbd_loglevel
 
+	# this is a global option
+	opendb:oplocks = yes
+
 [tmp]
 	path = $tmpdir
 	read only = no
 	ntvfs handler = posix
 	posix:sharedelay = 100000
 	posix:eadb = $lockdir/eadb.tdb
+	posix:oplocktimeout = 3
 
 [test1]
 	path = $tmpdir/test1
@@ -575,6 +579,7 @@ sub provision($$$$$$)
 	ntvfs handler = posix
 	posix:sharedelay = 100000
 	posix:eadb = $lockdir/eadb.tdb
+	posix:oplocktimeout = 3
 
 [test2]
 	path = $tmpdir/test2
@@ -582,6 +587,7 @@ sub provision($$$$$$)
 	ntvfs handler = posix
 	posix:sharedelay = 100000
 	posix:eadb = $lockdir/eadb.tdb
+	posix:oplocktimeout = 3
 
 [cifs]
 	read only = no
-- 
cgit 


From db2a2382d1dfcb9ace4621368feebd700b598625 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher 
Date: Tue, 26 Feb 2008 10:31:37 +0100
Subject: BASE-DEFER_OPEN: be less strict with to late responses

The server might be just busy.

metze
(This used to be commit 16c60cd347a42a2d98753585cbefddc948e2860f)
---
 source4/torture/basic/base.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'source4')

diff --git a/source4/torture/basic/base.c b/source4/torture/basic/base.c
index 42d7ddaaa1..66f9359744 100644
--- a/source4/torture/basic/base.c
+++ b/source4/torture/basic/base.c
@@ -664,7 +664,7 @@ static bool run_deferopen(struct torture_context *tctx, struct smbcli_state *cli
 			}
 			if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
 				double e = timeval_elapsed(&tv);
-				if (e < (0.5 * sec) || e > (1.5 * sec)) {
+				if (e < (0.5 * sec) || e > ((1.5 * sec) + 1)) {
 					torture_comment(tctx,"Timing incorrect %.2f violation 1 sec == %.2f\n",
 						e, sec);
 					return false;
-- 
cgit 


From 901addd4a18a9a166fc3518a7bce70969f884e6f Mon Sep 17 00:00:00 2001
From: Michael Adam 
Date: Tue, 26 Feb 2008 11:18:51 +0100
Subject: Fix build on VOS: socklen_t is needed for rep_inet_ntop: move it up.

Michael
(This used to be commit 8a26a6e8f11aca5119b15e304213548ad608dc5b)
---
 source4/lib/replace/system/network.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'source4')

diff --git a/source4/lib/replace/system/network.h b/source4/lib/replace/system/network.h
index d09e3f71f8..a84b22e5d0 100644
--- a/source4/lib/replace/system/network.h
+++ b/source4/lib/replace/system/network.h
@@ -83,6 +83,11 @@
 #include 
 #endif
 
+#ifndef HAVE_SOCKLEN_T
+#define HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
 #ifdef REPLACE_INET_NTOA
 /* define is in "replace.h" */
 char *rep_inet_ntoa(struct in_addr ip);
@@ -245,11 +250,6 @@ void rep_freeifaddrs(struct ifaddrs *);
 #define HOST_NAME_MAX 256
 #endif
 
-#ifndef HAVE_SOCKLEN_T
-#define HAVE_SOCKLEN_T
-typedef int socklen_t;
-#endif
-
 #ifndef HAVE_SA_FAMILY_T
 #define HAVE_SA_FAMILY_T
 typedef unsigned short int sa_family_t;
-- 
cgit