smbd: Fix the extended *.oplock.doc1 tests
authorVolker Lendecke <vl@samba.org>
Thu, 26 Sep 2013 01:41:07 +0000 (18:41 -0700)
committerJeremy Allison <jra@samba.org>
Fri, 11 Oct 2013 23:56:18 +0000 (01:56 +0200)
We need to check for DELETE_PENDING before the first oplock break

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sat Oct 12 01:56:18 CEST 2013 on sn-devel-104

source3/smbd/open.c

index 5024c902858314532842124fcbbf2ac2ee774272..6255180ad12f356e377493bae7c93fa155e4e237 100644 (file)
@@ -1093,6 +1093,26 @@ bool is_stat_open(uint32 access_mask)
                ((access_mask & ~stat_open_bits) == 0));
 }
 
+static bool has_delete_on_close(struct share_mode_lock *lck,
+                               uint32_t name_hash)
+{
+       struct share_mode_data *d = lck->data;
+       uint32_t i;
+
+       if (d->num_share_modes == 0) {
+               return false;
+       }
+       if (!is_delete_on_close_set(lck, name_hash)) {
+               return false;
+       }
+       for (i=0; i<d->num_share_modes; i++) {
+               if (!share_mode_stale_pid(d, i)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
 /****************************************************************************
  Deal with share modes
  Invarient: Share mode must be locked on entry and exit.
@@ -1113,25 +1133,6 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                return NT_STATUS_OK;
        }
 
-       /* A delete on close prohibits everything */
-
-       if (is_delete_on_close_set(lck, name_hash)) {
-               /*
-                * Check the delete on close token
-                * is valid. It could have been left
-                * after a server crash.
-                */
-               for(i = 0; i < lck->data->num_share_modes; i++) {
-                       if (!share_mode_stale_pid(lck->data, i)) {
-
-                               *file_existed = true;
-
-                               return NT_STATUS_DELETE_PENDING;
-                       }
-               }
-               return NT_STATUS_OK;
-       }
-
        if (is_stat_open(access_mask)) {
                /* Stat open that doesn't trigger oplock breaks or share mode
                 * checks... ! JRA. */
@@ -2416,6 +2417,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                          &got_level2_oplock,
                          &got_a_none_oplock);
 
+       if (has_delete_on_close(lck, fsp->name_hash)) {
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               return NT_STATUS_DELETE_PENDING;
+       }
+
        /* First pass - send break only on batch oplocks. */
        if ((req != NULL) &&
            delay_for_batch_oplocks(fsp,
@@ -2450,13 +2457,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                }
        }
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
-               /* DELETE_PENDING is not deferred for a second */
-               TALLOC_FREE(lck);
-               fd_close(fsp);
-               return status;
-       }
-
        if (!NT_STATUS_IS_OK(status)) {
                uint32 can_access_mask;
                bool can_access = True;
@@ -3166,6 +3166,13 @@ static NTSTATUS open_directory(connection_struct *conn,
                return NT_STATUS_SHARING_VIOLATION;
        }
 
+       if (has_delete_on_close(lck, fsp->name_hash)) {
+               TALLOC_FREE(lck);
+               fd_close(fsp);
+               file_free(req, fsp);
+               return NT_STATUS_DELETE_PENDING;
+       }
+
        status = open_mode_check(conn, lck, fsp->name_hash,
                                access_mask, share_access,
                                 create_options, &dir_existed);