The branch, master has been updated
       via  5679ba1 Don't allow asynchronous creates to be canceled in SMB2.
       via  6617c2c Make schedule_deferred_open_message_smb() return an 
indication of success.
       via  0d2f6ca Make schedule_deferred_open_message_smb2() return an 
indication of success.
       via  b004121 Allow for async opens.
       via  d1e1aa5 Add new bool field async_open to struct 
deferred_open_record. Not used yet.
       via  0362dcb Fix defer_open() fuction in the open code path to cope with 
a NULL lck parameter.
       via  34bb743 Add uint64_t mid field to the files_struct.
      from  84f29b8 s3:waf add sendfile support for Tru64, which is the same as 
HP-UX's

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


- Log -----------------------------------------------------------------
commit 5679ba10189aaa17023384be869ac600fa24a435
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 14:25:53 2012 -0700

    Don't allow asynchronous creates to be canceled in SMB2.
    
    Autobuild-User(master): Jeremy Allison <[email protected]>
    Autobuild-Date(master): Sat Jun 30 04:10:02 CEST 2012 on sn-devel-104

commit 6617c2c1f586b355950e41edb5ca655b4f6dca54
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 13:56:26 2012 -0700

    Make schedule_deferred_open_message_smb() return an indication of success.

commit 0d2f6cae418706ac2e72632d1b0187cfa66f9ec9
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 13:53:31 2012 -0700

    Make schedule_deferred_open_message_smb2() return an indication of success.

commit b004121d9beb890054b373f96c8145bf8a830065
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 13:14:10 2012 -0700

    Allow for async opens.
    
    If the SMB_VFS_OPEN() function returns -1, EINTR -> NT_STATUS_RETRY,
    then queue the open up to be completed when the async open completes.

commit d1e1aa552d3feb430b6b48c572ba2b713dfffec5
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 13:00:29 2012 -0700

    Add new bool field async_open to struct deferred_open_record. Not used yet.

commit 0362dcbd09f27b33ed8c5264c7f22ee00ddc5d64
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 12:56:57 2012 -0700

    Fix defer_open() fuction in the open code path to cope with a NULL lck 
parameter.

commit 34bb743ce3e24dde8b8fccdccb8f9c443fb2cd6f
Author: Jeremy Allison <[email protected]>
Date:   Fri Jun 29 12:41:47 2012 -0700

    Add uint64_t mid field to the files_struct.
    
    Ensure it is initialized so we know what mid created this file.

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

Summary of changes:
 source3/include/vfs.h      |    1 +
 source3/smbd/files.c       |    1 +
 source3/smbd/globals.h     |    2 +-
 source3/smbd/open.c        |   87 +++++++++++++++++++++++++++++++++++---------
 source3/smbd/process.c     |    9 +++--
 source3/smbd/proto.h       |    3 +-
 source3/smbd/smb2_create.c |   19 +++++++---
 7 files changed, 92 insertions(+), 30 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 754d4e4..be4399f 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -227,6 +227,7 @@ typedef struct files_struct {
        bool is_sparse;
        struct smb_filename *fsp_name;
        uint32_t name_hash;             /* Jenkins hash of full pathname. */
+       uint64_t mid;                   /* Mid of the operation that created 
us. */
 
        struct vfs_fsp_data *vfs_extension;
        struct fake_file_handle *fake_file_handle;
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 0929d99..390718f 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -126,6 +126,7 @@ NTSTATUS file_new(struct smb_request *req, 
connection_struct *conn,
                 fsp_fnum_dbg(fsp), (unsigned int)sconn->num_files));
 
        if (req != NULL) {
+               fsp->mid = req->mid;
                req->chain_fsp = fsp;
        }
 
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 6c1efaf..b07ee3a 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -310,7 +310,7 @@ bool open_was_deferred_smb2(struct smbd_server_connection 
*sconn,
                            uint64_t mid);
 void remove_deferred_open_message_smb2(
        struct smbd_server_connection *sconn, uint64_t mid);
-void schedule_deferred_open_message_smb2(
+bool schedule_deferred_open_message_smb2(
        struct smbd_server_connection *sconn, uint64_t mid);
 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
                        struct timeval request_time,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index f259cc9..c2bf8ed 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -35,6 +35,7 @@ extern const struct generic_mapping file_generic_mapping;
 
 struct deferred_open_record {
         bool delayed_for_oplocks;
+       bool async_open;
         struct file_id id;
 };
 
@@ -1355,20 +1356,23 @@ static void defer_open(struct share_mode_lock *lck,
                       struct deferred_open_record *state)
 {
        struct server_id self = messaging_server_id(req->sconn->msg_ctx);
-       int i;
 
        /* Paranoia check */
 
-       for (i=0; i<lck->data->num_share_modes; i++) {
-               struct share_mode_entry *e = &lck->data->share_modes[i];
+       if (lck) {
+               int i;
 
-               if (is_deferred_open_entry(e) &&
-                   serverid_equal(&self, &e->pid) &&
-                   (e->op_mid == req->mid)) {
-                       DEBUG(0, ("Trying to defer an already deferred "
-                               "request: mid=%llu, exiting\n",
-                               (unsigned long long)req->mid));
-                       exit_server("attempt to defer a deferred request");
+               for (i=0; i<lck->data->num_share_modes; i++) {
+                       struct share_mode_entry *e = &lck->data->share_modes[i];
+
+                       if (is_deferred_open_entry(e) &&
+                           serverid_equal(&self, &e->pid) &&
+                           (e->op_mid == req->mid)) {
+                               DEBUG(0, ("Trying to defer an already deferred "
+                                       "request: mid=%llu, exiting\n",
+                                       (unsigned long long)req->mid));
+                               exit_server("attempt to defer a deferred 
request");
+                       }
                }
        }
 
@@ -1384,7 +1388,9 @@ static void defer_open(struct share_mode_lock *lck,
                                       state->id, (char *)state, 
sizeof(*state))) {
                exit_server("push_deferred_open_message_smb failed");
        }
-       add_deferred_open(lck, req->mid, request_time, self, state->id);
+       if (lck) {
+               add_deferred_open(lck, req->mid, request_time, self, state->id);
+       }
 }
 
 
@@ -1527,6 +1533,7 @@ static void schedule_defer_open(struct share_mode_lock 
*lck,
           a 1 second delay for share mode conflicts. */
 
        state.delayed_for_oplocks = True;
+       state.async_open = false;
        state.id = lck->data->id;
 
        if (!request_timed_out(request_time, timeout)) {
@@ -1535,6 +1542,27 @@ static void schedule_defer_open(struct share_mode_lock 
*lck,
 }
 
 /****************************************************************************
+ Reschedule an open call that went asynchronous.
+****************************************************************************/
+
+static void schedule_async_open(struct timeval request_time,
+                               struct smb_request *req)
+{
+       struct deferred_open_record state;
+       struct timeval timeout;
+
+       timeout = timeval_set(20, 0);
+
+       ZERO_STRUCT(state);
+       state.delayed_for_oplocks = false;
+       state.async_open = true;
+
+       if (!request_timed_out(request_time, timeout)) {
+               defer_open(NULL, request_time, timeout, req, &state);
+       }
+}
+
+/****************************************************************************
  Work out what access_mask to use from what the client sent us.
 ****************************************************************************/
 
@@ -1657,6 +1685,17 @@ void remove_deferred_open_entry(struct file_id id, 
uint64_t mid,
 }
 
 /****************************************************************************
+ Return true if this is a state pointer to an asynchronous create.
+****************************************************************************/
+
+bool is_deferred_open_async(const void *ptr)
+{
+       const struct deferred_open_record *state = (const struct 
deferred_open_record *)ptr;
+
+       return state->async_open;
+}
+
+/****************************************************************************
  Open a file with a share mode. Passed in an already created files_struct *.
 ****************************************************************************/
 
@@ -1760,16 +1799,23 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
                if (get_deferred_open_message_state(req,
                                &request_time,
                                &ptr)) {
-
-                       struct deferred_open_record *state = (struct 
deferred_open_record *)ptr;
                        /* Remember the absolute time of the original
                           request with this mid. We'll use it later to
                           see if this has timed out. */
 
-                       /* Remove the deferred open entry under lock. */
-                       remove_deferred_open_entry(
-                               state->id, req->mid,
-                               messaging_server_id(req->sconn->msg_ctx));
+                       /* If it was an async create retry, the file
+                          didn't exist. */
+
+                       if (is_deferred_open_async(ptr)) {
+                               SET_STAT_INVALID(smb_fname->st);
+                               file_existed = false;
+                       } else {
+                               struct deferred_open_record *state = (struct 
deferred_open_record *)ptr;
+                               /* Remove the deferred open entry under lock. */
+                               remove_deferred_open_entry(
+                                       state->id, req->mid,
+                                       
messaging_server_id(req->sconn->msg_ctx));
+                       }
 
                        /* Ensure we don't reprocess this message. */
                        remove_deferred_open_message_smb(req->sconn, req->mid);
@@ -2161,6 +2207,7 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
                                   a 1 second delay for share mode conflicts. */
 
                                state.delayed_for_oplocks = False;
+                               state.async_open = false;
                                state.id = id;
 
                                if ((req != NULL)
@@ -2215,6 +2262,9 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
                             open_access_mask);
 
        if (!NT_STATUS_IS_OK(fsp_open)) {
+               if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_RETRY)) {
+                       schedule_async_open(request_time, req);
+               }
                TALLOC_FREE(lck);
                return fsp_open;
        }
@@ -2302,6 +2352,7 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
                        struct deferred_open_record state;
 
                        state.delayed_for_oplocks = False;
+                       state.async_open = false;
                        state.id = id;
 
                        /* Do it all over again immediately. In the second
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 55a125f..f8757fa 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -718,15 +718,14 @@ void remove_deferred_open_message_smb(struct 
smbd_server_connection *sconn,
  schedule it for immediate processing.
 ****************************************************************************/
 
-void schedule_deferred_open_message_smb(struct smbd_server_connection *sconn,
+bool schedule_deferred_open_message_smb(struct smbd_server_connection *sconn,
                                        uint64_t mid)
 {
        struct pending_message_list *pml;
        int i = 0;
 
        if (sconn->using_smb2) {
-               schedule_deferred_open_message_smb2(sconn, mid);
-               return;
+               return schedule_deferred_open_message_smb2(sconn, mid);
        }
 
        for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
@@ -768,13 +767,15 @@ void schedule_deferred_open_message_smb(struct 
smbd_server_connection *sconn,
                        TALLOC_FREE(pml->te);
                        pml->te = te;
                        DLIST_PROMOTE(sconn->deferred_open_queue, pml);
-                       return;
+                       return true;
                }
        }
 
        DEBUG(10,("schedule_deferred_open_message_smb: failed to "
                "find message mid %llu\n",
                (unsigned long long)mid ));
+
+       return false;
 }
 
 /****************************************************************************
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 35a677c..1b28c8b 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -616,6 +616,7 @@ bool open_match_attributes(connection_struct *conn,
                           mode_t *returned_unx_mode);
 void remove_deferred_open_entry(struct file_id id, uint64_t mid,
                                struct server_id pid);
+bool is_deferred_open_async(const void *ptr);
 NTSTATUS open_file_fchmod(connection_struct *conn,
                          struct smb_filename *smb_fname,
                          files_struct **result);
@@ -752,7 +753,7 @@ int srv_set_message(char *buf,
                         bool zero);
 void remove_deferred_open_message_smb(struct smbd_server_connection *sconn,
                                      uint64_t mid);
-void schedule_deferred_open_message_smb(struct smbd_server_connection *sconn,
+bool schedule_deferred_open_message_smb(struct smbd_server_connection *sconn,
                                        uint64_t mid);
 bool open_was_deferred(struct smbd_server_connection *sconn, uint64_t mid);
 bool get_deferred_open_message_state(struct smb_request *smbreq,
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 18c3fb9..7b5a262 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1036,7 +1036,7 @@ static void 
smbd_smb2_create_request_dispatch_immediate(struct tevent_context *c
        }
 }
 
-void schedule_deferred_open_message_smb2(
+bool schedule_deferred_open_message_smb2(
        struct smbd_server_connection *sconn, uint64_t mid)
 {
        struct smbd_smb2_create_state *state = NULL;
@@ -1048,18 +1048,18 @@ void schedule_deferred_open_message_smb2(
                DEBUG(10,("schedule_deferred_open_message_smb2: "
                        "can't find mid %llu\n",
                        (unsigned long long)mid ));
-               return;
+               return false;
        }
        if (!smb2req->subreq) {
-               return;
+               return false;
        }
        if (!tevent_req_is_in_progress(smb2req->subreq)) {
-               return;
+               return false;
        }
        state = tevent_req_data(smb2req->subreq,
                        struct smbd_smb2_create_state);
        if (!state) {
-               return;
+               return false;
        }
 
        /* Ensure we don't have any outstanding timer event. */
@@ -1080,7 +1080,7 @@ void schedule_deferred_open_message_smb2(
        if (!state->im) {
                smbd_server_connection_terminate(smb2req->sconn,
                        nt_errstr(NT_STATUS_NO_MEMORY));
-               return;
+               return false;
        }
 
        DEBUG(10,("schedule_deferred_open_message_smb2: "
@@ -1091,6 +1091,8 @@ void schedule_deferred_open_message_smb2(
                        smb2req->sconn->ev_ctx,
                        smbd_smb2_create_request_dispatch_immediate,
                        smb2req);
+
+       return true;
 }
 
 /*********************************************************
@@ -1160,6 +1162,11 @@ static bool smbd_smb2_create_cancel(struct tevent_req 
*req)
        smb2req = state->smb2req;
        mid = get_mid_from_smb2req(smb2req);
 
+       if (is_deferred_open_async(state->private_data.data)) {
+               /* Can't cancel an async create. */
+               return false;
+       }
+
        remove_deferred_open_entry(state->id, mid,
                                   
messaging_server_id(smb2req->sconn->msg_ctx));
        remove_deferred_open_message_smb2_internal(smb2req, mid);


-- 
Samba Shared Repository

Reply via email to