The branch, master has been updated
       via  60433b154dc345f8883b15d657e3f7d5c21fc6a1 (commit)
       via  74c0a7a1d34a75abec32cc46ab0b02b483160215 (commit)
       via  5e9aade51657a22dba2c65ffc1aab1be7c532e61 (commit)
      from  ad96c11182db093fe41a4f6177580e70271574ea (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 60433b154dc345f8883b15d657e3f7d5c21fc6a1
Author: Steven Danneman <steven.danne...@isilon.com>
Date:   Thu May 14 23:14:03 2009 +0000

    s3 onefs: Fix 1 second share mode delay handling
    
    When racing to the open and loosing we may get a share_mode violation.
    In this case handle the 1-second delay via a defferred open properly.
    
    This requires us to retrieve the share_mode_lock before deferring
    open so we don't dereference a NULL pointer assuming we already had
    the lck because we were the first opener.

commit 74c0a7a1d34a75abec32cc46ab0b02b483160215
Author: Steven Danneman <steven.danne...@isilon.com>
Date:   Thu May 14 23:12:23 2009 +0000

    s3 onefs: Fix a race condition exists in onefs_open.c between multiple 
opens to the same file.
    
    Two openers can stat a file at the same time, see that it doesn't exist,
    and then both race to open it first.  The loser will enter
    onefs_open_file_ntcreate believing that the file doesnt exist, and thus
    skip any current state lookups for that file.  This includes setting
    the file_id, and having a valid stat buffer.
    
    Normally on first create the file_id will be set during the open, but
    the second opener in this scenario may fail the open (oplock/share mode)
    and file_id will not be set, nor will the stat buffer be valid.
    
    In the error paths of this patch, we now double check that the file_id
    and the stat buffer are valid before doing other operations.

commit 5e9aade51657a22dba2c65ffc1aab1be7c532e61
Author: Zack Kirsch <zack.kir...@isilon.com>
Date:   Wed Apr 22 23:30:55 2009 +0000

    s3 onefs: Add some debugging/asserts to give more info when there is bad 
deferred open state.
    
    Signed-off-by: Tim Prouty <tpro...@samba.org>

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

Summary of changes:
 source3/modules/onefs_open.c |   93 ++++++++++++++++++++++++++++++++++--------
 source3/smbd/process.c       |    2 +
 2 files changed, 78 insertions(+), 17 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
index 31f27e9..b9a2c30 100644
--- a/source3/modules/onefs_open.c
+++ b/source3/modules/onefs_open.c
@@ -423,6 +423,13 @@ static void schedule_defer_open(struct share_mode_lock 
*lck,
 
        if (!request_timed_out(request_time, timeout)) {
                defer_open(lck, request_time, timeout, req, &state);
+       } else {
+               /* A delayed-for-oplocks deferred open timing out should only
+                * happen if there is a bug or extreme load, since we set the
+                * timeout to 300 seconds. */
+               DEBUG(0, ("Deferred open timeout! request_time=%d.%d, "
+                   "mid=%d\n", request_time.tv_sec, request_time.tv_usec,
+                   req->mid));
        }
 }
 
@@ -817,7 +824,6 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
 
        DEBUG(10, ("fsp = %p\n", fsp));
 
-       fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
        fsp->share_access = share_access;
        fsp->fh->private_options = create_options;
        fsp->access_mask = open_access_mask; /* We change this to the
@@ -885,6 +891,12 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
                 * stat-only open at this point.
                 */
                SMB_ASSERT(fsp->oplock_type == NO_OPLOCK);
+
+               /* The kernel and Samba's version of stat-only differs
+                * slightly: The kernel doesn't think its stat-only if we're
+                * truncating.  We'd better have a req in order to defer the
+                * open. */
+               SMB_ASSERT(!((flags|flags2) & O_TRUNC));
        }
 
        /* Do the open. */
@@ -910,13 +922,22 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
                /* OneFS Oplock Handling */
                if (errno == EINPROGRESS) {
 
+                       /* If we get EINPROGRESS, the kernel will send us an
+                        * asynchronous semlock event back. Ensure we can defer
+                        * the open, by asserting req. */
+                       SMB_ASSERT(req);
+
                        if (lck == NULL) {
+                               /*
+                                * We hit the race that when we did the stat
+                                * on the file it did not exist, and someone
+                                * has created it in between the stat and the
+                                * open_file() call. Defer our open waiting,
+                                * to break the oplock of the first opener.
+                                */
 
-                               struct deferred_open_record state;
                                struct timespec old_write_time;
 
-                               old_write_time = smb_fname->st.st_ex_mtime;
-
                                DEBUG(3, ("Someone created file %s with an "
                                          "oplock after we looked: Retrying\n",
                                          smb_fname_str_dbg(smb_fname)));
@@ -939,17 +960,15 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
                                                  "lock for %s\n",
                                                smb_fname_str_dbg(smb_fname)));
                                        status = NT_STATUS_SHARING_VIOLATION;
+
+                                       /* XXXZLK: This will cause us to get a
+                                        * semlock event when we aren't
+                                        * expecting one. */
                                        goto cleanup_destroy;
                                }
 
-                               state.delayed_for_oplocks = False;
-                               state.id = id;
-
-                               if (req != NULL) {
-                                       defer_open(lck, request_time,
-                                           timeval_zero(), req, &state);
-                               }
-                               goto cleanup_destroy;
+                               schedule_defer_open(lck, request_time, req);
+                               goto cleanup;
                        }
                        /* Waiting for an oplock */
                        DEBUG(5,("Async createfile because a client has an "
@@ -966,6 +985,16 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
                        uint32 can_access_mask;
                        bool can_access = True;
 
+                       /* If we raced on open we may not have a valid file_id
+                        * or stat buf.  Get them again. */
+                       if (SMB_VFS_STAT(conn, fname, psbuf) == -1) {
+                               DEBUG(0,("Error doing stat on file %s "
+                                       "(%s)\n", fname, strerror(errno)));
+                               status = NT_STATUS_SHARING_VIOLATION;
+                               goto cleanup_destroy;
+                       }
+                       id = vfs_file_id_from_sbuf(conn, psbuf);
+
                        /* Check if this can be done with the deny_dos and fcb
                         * calls. */
 
@@ -1066,9 +1095,39 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct 
*conn,
                                state.id = id;
                                state.failed = false;
 
-                               if ((req != NULL)
-                                   && !request_timed_out(request_time,
-                                                         timeout)) {
+                               /*
+                                * We hit the race that when we did the stat
+                                * on the file it did not exist, and someone
+                                * has created it in between the stat and the
+                                * open_file() call.  Retrieve the share_mode
+                                * lock on the newly opened file so we can
+                                * defer our request.
+                                */
+                               if (lck == NULL) {
+                                       struct timespec old_write_time;
+                                       old_write_time = get_mtimespec(psbuf);
+
+                                       lck = get_share_mode_lock(talloc_tos(),
+                                           id, conn->connectpath, fname,
+                                           &old_write_time);
+                                       if (lck == NULL) {
+                                               DEBUG(0,
+                                                   ("onefs_open_file_ntcreate:"
+                                                    " Could not get share "
+                                                    "mode lock for %s\n",
+                                                    fname));
+                                               /* This will cause us to return
+                                                * immediately skipping the
+                                                * the 1 second delay, which
+                                                * isn't a big deal */
+                                               status = 
NT_STATUS_SHARING_VIOLATION;
+                                               goto cleanup_destroy;
+                                       }
+                               }
+
+                               if ((req != NULL) &&
+                                   !request_timed_out(request_time, timeout))
+                               {
                                        defer_open(lck, request_time, timeout,
                                                   req, &state);
                                }
@@ -1120,8 +1179,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
 
                /*
                 * Now the file exists and fsp is successfully opened,
-                * fsp->dev and fsp->inode are valid and should replace the
-                * dev=0,inode=0 from a non existent file. Spotted by
+                * fsp->file_id is valid and should replace the
+                * dev=0, inode=0 from a non existent file. Spotted by
                 * Nadav Danieli <nad...@exanet.com>. JRA.
                 */
 
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index dd58ea8..ccb7f9d 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1306,6 +1306,8 @@ static connection_struct *switch_message(uint8 type, 
struct smb_request *req, in
                }
 
                if (!change_to_user(conn,session_tag)) {
+                       DEBUG(0, ("Error: Could not change to user. Removing "
+                           "deferred open, mid=%d.\n", req->mid));
                        reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
                        remove_deferred_open_smb_message(req->mid);
                        return conn;


-- 
Samba Shared Repository

Reply via email to