opendb_tdb: attribute only opens doesn't conflict with BATCH oplocks
authorStefan Metzmacher <metze@samba.org>
Fri, 22 Feb 2008 16:26:40 +0000 (17:26 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 26 Feb 2008 08:29:41 +0000 (09:29 +0100)
metze
(This used to be commit 7872b05abe7532676c4cc25620b96ea5d59117d2)

source4/ntvfs/common/opendb_tdb.c

index 33105324069d787190714a40e303bfaa21356254..b445981b57c97e8003a30357a0045d1316e04aa0 100644 (file)
@@ -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<file.num_entries;i++) {
                if (file.entries[i].oplock_level == OPLOCK_BATCH) {
+                       /* 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
@@ -370,7 +400,10 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle,
          possibly grant an exclusive, batch or level2 oplock
        */
        if (oplock_granted) {
-               if (oplock_level == OPLOCK_EXCLUSIVE) {
+               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;