[SCM] Samba Shared Repository - branch v4-0-test updated - release-4-0-0alpha2-1034-g278eea5

Stefan Metzmacher metze at samba.org
Tue Feb 26 08:37:46 GMT 2008


The branch, v4-0-test has been updated
       via  278eea57fa9f59908672c935187f942e7780f0aa (commit)
       via  4e27ac8c529d5a1675fb02215191a2be7913ec97 (commit)
       via  66ad1081f2be8a0caa16fb0d614b857a5bde751c (commit)
       via  746e89ce2e74dbd2cea8f5575c403e4c61f82cb8 (commit)
       via  5abc57ddab558c13db3864d13afc2ad3b1641d1c (commit)
       via  b258f9d8d4bf3606f4884d1bff548f16dadc08aa (commit)
       via  b8c42a1ff8fd4131ef2a1ad92a7405a2e4d335d3 (commit)
       via  e0837238b6b09143970f03b6a78201c3fe55f3cd (commit)
       via  27ec7bfc8b7f46c97e6878caf5cd694c517ce053 (commit)
       via  dd56f55afdc0d114a0b0bceb0e4feb022919323a (commit)
       via  b09a2b126723bd75afd245f549703a04e512e129 (commit)
       via  56bd63a4236ebf360d3e805c8560df86759573f7 (commit)
       via  904159327b3cb80fbec6aa5a4feaa141190a3f3a (commit)
       via  e6b708a52b0eada3fd374b66292ded3b0f6ce217 (commit)
       via  46500983fe2f63540a67e2e963ab264fa8a090d0 (commit)
       via  aaaa26ae5e810495f313dfada771a8de86cedbd4 (commit)
       via  1ba0b9a8f1f84c7c949b3d184843462b87446707 (commit)
       via  5b12157e0f0f1cf6ea90503a72b56ab2032cb6e5 (commit)
       via  65cfe71b2617598f8e38d04537cfc9ce44a36680 (commit)
       via  fbfe953ba347a902297bd8eae900ca70efd2db01 (commit)
       via  7872b05abe7532676c4cc25620b96ea5d59117d2 (commit)
       via  57f1b9d11cfcac3b5fdee1ad9e4ba81d0859c8dc (commit)
       via  bd3654500b14e4ed8d4a8bb25ff9da5035a16a8b (commit)
      from  f68fc4582d446bbf48ebafcbd4a0e1862b1e9aae (commit)

http://gitweb.samba.org/?samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit 278eea57fa9f59908672c935187f942e7780f0aa
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Feb 23 11:54:01 2008 +0100

    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

commit 4e27ac8c529d5a1675fb02215191a2be7913ec97
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Feb 23 11:50:19 2008 +0100

    pvfs_setpathinfo: retry setpathinfo after oplock not granted on on setpathinfo ALLOCATION_INFO and END_OF_FILE_INFO
    
    metze

commit 66ad1081f2be8a0caa16fb0d614b857a5bde751c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Feb 23 11:49:39 2008 +0100

    pvfs_open: add pvfs_can_update_file_size()
    
    TODO: this is not complete, we need more tests to trigger this
    
    metze

commit 746e89ce2e74dbd2cea8f5575c403e4c61f82cb8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 22 11:52:17 2008 +0100

    pvfs_unlink: retry unlink after oplock not granted
    
    metze

commit 5abc57ddab558c13db3864d13afc2ad3b1641d1c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 19:17:45 2008 +0100

    pvfs: add posix:oplocktimeout=30 option
    
    metze

commit b258f9d8d4bf3606f4884d1bff548f16dadc08aa
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Feb 23 11:46:43 2008 +0100

    pvfs_setfileinfo: break level2 oplocks on setfileinfo() ALLOCATION_INFO and END_OF_FILE_INFO
    
    metze

commit b8c42a1ff8fd4131ef2a1ad92a7405a2e4d335d3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 22 16:34:50 2008 +0100

    pvfs: send oplock breaks to none to level2 holders on write/lock requests
    
    metze

commit e0837238b6b09143970f03b6a78201c3fe55f3cd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 22 16:34:50 2008 +0100

    pvfs_oplocks: add pvfs_break_level2_oplocks()
    
    metze

commit 27ec7bfc8b7f46c97e6878caf5cd694c517ce053
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 09:51:58 2008 +0100

    pvfs: handle oplock releases in its own function pvfs_oplock_release()
    
    metze

commit dd56f55afdc0d114a0b0bceb0e4feb022919323a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 08:39:13 2008 +0100

    pvfs_open: call pvfs_setup_oplock() if an oplock was granted
    
    This is needed to receive oplock breaks from other "processes"
    
    metze

commit b09a2b126723bd75afd245f549703a04e512e129
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 08:32:35 2008 +0100

    pvfs: add pvfs_setup_oplock() to receive oplock breaks and pass them to the client
    
    metze

commit 56bd63a4236ebf360d3e805c8560df86759573f7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 21 17:48:13 2008 +0100

    pvfs_open: make the retry logic indepdendent from open and sharing violations
    
    metze

commit 904159327b3cb80fbec6aa5a4feaa141190a3f3a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 17:50:22 2008 +0100

    pvfs_open: fix odb_can_open() callers after prototype change
    
    metze

commit e6b708a52b0eada3fd374b66292ded3b0f6ce217
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 17:48:13 2008 +0100

    opendb: unify the parameters of odb_open_file() and odb_can_open()
    
    metze

commit 46500983fe2f63540a67e2e963ab264fa8a090d0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 16:49:40 2008 +0100

    pvfs_open: pass down open_disposition and break_to_none to odb_open_file()
    
    metze

commit aaaa26ae5e810495f313dfada771a8de86cedbd4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 16:47:48 2008 +0100

    opendb: pass down open_disposition and break_to_none to odb_open_file()
    
    metze

commit 1ba0b9a8f1f84c7c949b3d184843462b87446707
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Feb 26 09:14:54 2008 +0100

    pvfs_setfileinfo_rename: map DELETE_PENDING to ACCESS_DENIED
    
    This is needed as odb_can_open/pvfs_can_delete changed the return value.
    
    metze

commit 5b12157e0f0f1cf6ea90503a72b56ab2032cb6e5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 20:20:35 2008 +0100

    opendb_tdb: only file->delete_on_close == true should give DELETE_PENDING
    
    metze

commit 65cfe71b2617598f8e38d04537cfc9ce44a36680
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 16:26:04 2008 +0100

    opendb_tdb: move sharemode, oplock logic into odb_tdb_open_can_internal()
    
    metze

commit fbfe953ba347a902297bd8eae900ca70efd2db01
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 25 16:14:23 2008 +0100

    opendb_tdb: add force break to none logic
    
    metze

commit 7872b05abe7532676c4cc25620b96ea5d59117d2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 22 17:26:40 2008 +0100

    opendb_tdb: attribute only opens doesn't conflict with BATCH oplocks
    
    metze

commit 57f1b9d11cfcac3b5fdee1ad9e4ba81d0859c8dc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 22 17:26:40 2008 +0100

    opendb_tdb: grant level2 oplocks
    
    metze

commit bd3654500b14e4ed8d4a8bb25ff9da5035a16a8b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 22 16:30:13 2008 +0100

    opendb: add odb_break_oplocks() function
    
    This send breaks to none to all level2 holders
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source/cluster/ctdb/opendb_ctdb.c     |   32 +++-
 source/ntvfs/common/opendb.c          |   26 ++-
 source/ntvfs/common/opendb.h          |   13 +-
 source/ntvfs/common/opendb_tdb.c      |  296 ++++++++++++++++++++----------
 source/ntvfs/posix/config.mk          |    1 +
 source/ntvfs/posix/pvfs_lock.c        |   14 +-
 source/ntvfs/posix/pvfs_open.c        |  326 +++++++++++++++++++++++++--------
 source/ntvfs/posix/pvfs_oplock.c      |  239 ++++++++++++++++++++++++
 source/ntvfs/posix/pvfs_setfileinfo.c |  116 ++++++++++++
 source/ntvfs/posix/pvfs_unlink.c      |   94 ++++++++++-
 source/ntvfs/posix/pvfs_write.c       |    5 +-
 source/ntvfs/posix/vfs_posix.c        |    4 +
 source/ntvfs/posix/vfs_posix.h        |   22 ++-
 source/samba4-knownfail               |    1 -
 source/samba4-skip                    |    4 -
 source/selftest/target/Samba4.pm      |    6 +
 16 files changed, 980 insertions(+), 219 deletions(-)
 create mode 100644 source/ntvfs/posix/pvfs_oplock.c


Changeset truncated at 500 lines:

diff --git a/source/cluster/ctdb/opendb_ctdb.c b/source/cluster/ctdb/opendb_ctdb.c
index 86dc1f5..3dfc681 100644
--- a/source/cluster/ctdb/opendb_ctdb.c
+++ b/source/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;
@@ -464,6 +466,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
 */
@@ -584,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;
@@ -599,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;
 	}
@@ -642,7 +655,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/source/ntvfs/common/opendb.c b/source/ntvfs/common/opendb.c
index 4ac1080..36144d0 100644
--- a/source/ntvfs/common/opendb.c
+++ b/source/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);
 }
 
 
@@ -165,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,
@@ -176,3 +179,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/source/ntvfs/common/opendb.h b/source/ntvfs/common/opendb.h
index c34a07d..9591bcf 100644
--- a/source/ntvfs/common/opendb.h
+++ b/source/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);
@@ -39,10 +40,12 @@ 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);
 };
 
 struct opendb_oplock_break {
diff --git a/source/ntvfs/common/opendb_tdb.c b/source/ntvfs/common/opendb_tdb.c
index 3d4a760..73c04b7 100644
--- a/source/ntvfs/common/opendb_tdb.c
+++ b/source/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,20 +179,20 @@ 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;
 }
 
@@ -284,6 +287,100 @@ 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
+}
+
+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)
+{
+	NTSTATUS status;
+	uint32_t i;
+	bool attrs_only = false;
+
+	/* see if anyone has an oplock, which we need to break */
+	for (i=0;i<file->num_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
+			 * but we'll not grant the oplock below
+			 */
+			attrs_only = access_attributes_only(access_mask,
+							    open_disposition);
+			if (attrs_only) {
+				break;
+			}
+			/* a batch oplock caches close calls, which
+			   means the client application might have
+			   already closed the file. We have to allow
+			   this close to propogate by sending a oplock
+			   break request and suspending this call
+			   until the break is acknowledged or the file
+			   is closed */
+			if (break_to_none) {
+				oplock_return = OPLOCK_BREAK_TO_NONE;
+			}
+			odb_oplock_break_send(odb, &file->entries[i],
+					      oplock_return);
+			return NT_STATUS_OPLOCK_NOT_GRANTED;
+		}
+	}
+
+	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;i<file->num_entries;i++) {
+		status = share_conflict(&file->entries[i], stream_id,
+					share_access, access_mask);
+		NT_STATUS_NOT_OK_RETURN(status);
+	}
+
+	/* we now know the open could succeed, but we need to check
+	   for any exclusive oplocks. We can't grant a second open
+	   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;i<file->num_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
@@ -291,17 +388,18 @@ static NTSTATUS odb_oplock_break_send(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,
-				  uint32_t stream_id, uint32_t share_access, 
+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;
-	int i;
 	struct opendb_file file;
 	NTSTATUS status;
+	bool attrs_only = false;
 
 	if (odb->oplocks == false) {
 		oplock_level = OPLOCK_NONE;
@@ -317,6 +415,13 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	}
 
 	/* 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;
@@ -324,61 +429,37 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
 	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;i<file.num_entries;i++) {
-		if (file.entries[i].oplock_level == OPLOCK_BATCH) {
-			/* a batch oplock caches close calls, which
-			   means the client application might have
-			   already closed the file. We have to allow
-			   this close to propogate by sending a oplock
-			   break request and suspending this call
-			   until the break is acknowledged or the file
-			   is closed */
-			odb_oplock_break_send(odb, &file.entries[i],
-					      OPLOCK_BREAK_TO_LEVEL_II/*TODO*/);
-			return NT_STATUS_OPLOCK_NOT_GRANTED;
-		}
-	}
-
-	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;i<file.num_entries;i++) {
-		status = share_conflict(&file.entries[i], &e);
-		NT_STATUS_NOT_OK_RETURN(status);
-	}
-
-	/* we now know the open could succeed, but we need to check
-	   for any exclusive oplocks. We can't grant a second open
-	   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;i<file.num_entries;i++) {
-		if (file.entries[i].oplock_level == OPLOCK_EXCLUSIVE) {
-			odb_oplock_break_send(odb, &file.entries[i],
-					      OPLOCK_BREAK_TO_NONE/*TODO*/);
-			return NT_STATUS_OPLOCK_NOT_GRANTED;
-		}
-	}
 
 	/*
-	  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 (attrs_only) {
+			e.oplock_level	= OPLOCK_NONE;
+			*oplock_granted	= NO_OPLOCK_RETURN;
+		} else 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 */
@@ -503,6 +584,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<file.num_entries;i++) {
+		if (file.entries[i].oplock_level == OPLOCK_LEVEL_II) {
+			/*
+			 * there could be multiple level2 oplocks
+			 * and we just send a break to none to all of them
+			 * without waiting for a release
+			 */
+			odb_oplock_break_send(odb, &file.entries[i],
+					      OPLOCK_BREAK_TO_NONE);
+			file.entries[i].oplock_level = OPLOCK_NONE;
+			modified = true;
+		}
+	}
+
+	if (modified) {
+		return odb_push_record(lck, &file);
+	}
+	return NT_STATUS_OK;
+}
 
 /*
   remove a pending opendb entry
@@ -624,14 +742,14 @@ 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,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list