The branch, master has been updated
       via  2bbb8c9... Allow smb2 create requests to be cancelled.
      from  dd20259... Fix bug #7384 - dptr_Close has a bitmap leak.

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


- Log -----------------------------------------------------------------
commit 2bbb8c917e372ceeb1e144259d9d2b0eab7cc212
Author: Jeremy Allison <j...@samba.org>
Date:   Fri Apr 23 13:10:15 2010 -0700

    Allow smb2 create requests to be cancelled.
    
    Jeremy.

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

Summary of changes:
 source3/include/proto.h      |    9 +++--
 source3/modules/onefs_open.c |   11 +-----
 source3/smbd/globals.h       |    1 +
 source3/smbd/open.c          |   27 +++++++++-----
 source3/smbd/process.c       |    2 +
 source3/smbd/smb2_create.c   |   80 ++++++++++++++++++++++++++++++++++++------
 6 files changed, 98 insertions(+), 32 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 073a0dc..d4e7f39 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6658,6 +6658,7 @@ bool map_open_params_to_ntcreate(const struct 
smb_filename *smb_fname,
                                 uint32 *pcreate_disposition,
                                 uint32 *pcreate_options,
                                 uint32_t *pprivate_flags);
+void remove_deferred_open_entry(struct file_id id, uint64_t mid);
 NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
                          struct smb_filename *smb_fname,
                          files_struct **result);
@@ -6819,9 +6820,11 @@ bool get_deferred_open_message_state(struct smb_request 
*smbreq,
                                struct timeval *p_request_time,
                                void **pp_state);
 bool push_deferred_open_message_smb(struct smb_request *req,
-                              struct timeval request_time,
-                              struct timeval timeout,
-                              char *private_data, size_t priv_len);
+                               struct timeval request_time,
+                               struct timeval timeout,
+                               struct file_id id,
+                               char *private_data,
+                               size_t priv_len);
 struct idle_event *event_add_idle(struct event_context *event_ctx,
                                  TALLOC_CTX *mem_ctx,
                                  struct timeval interval,
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
index a1412ef..e97fe9e 100644
--- a/source3/modules/onefs_open.c
+++ b/source3/modules/onefs_open.c
@@ -373,7 +373,7 @@ static void defer_open(struct share_mode_lock *lck,
                  (unsigned long long)req->mid));
 
        if (!push_deferred_open_message_smb(req, request_time, timeout,
-                                      (char *)state, sizeof(*state))) {
+                                      state->id, (char *)state, 
sizeof(*state))) {
                exit_server("push_deferred_open_message_smb failed");
        }
        add_deferred_open(lck, req->mid, request_time, state->id);
@@ -554,14 +554,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
                           see if this has timed out. */
 
                        /* Remove the deferred open entry under lock. */
-                       lck = get_share_mode_lock(talloc_tos(), state->id,
-                                       NULL, NULL, NULL);
-                       if (lck == NULL) {
-                               DEBUG(0, ("could not get share mode lock\n"));
-                       } else {
-                               del_deferred_open_entry(lck, req->mid);
-                               TALLOC_FREE(lck);
-                       }
+                       remove_deferred_open_entry(state->id, req->mid);
 
                        /* Ensure we don't reprocess this message. */
                        remove_deferred_open_message_smb(req->mid);
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index a86f0e9..4d1a13d 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -346,6 +346,7 @@ void schedule_deferred_open_message_smb2(uint64_t mid);
 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
                        struct timeval request_time,
                        struct timeval timeout,
+                       struct file_id id,
                        char *private_data,
                        size_t priv_len);
 
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index e0c24da..f49aca8 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1085,7 +1085,7 @@ static void defer_open(struct share_mode_lock *lck,
                  (unsigned long long)req->mid));
 
        if (!push_deferred_open_message_smb(req, request_time, timeout,
-                                      (char *)state, sizeof(*state))) {
+                                      state->id, (char *)state, 
sizeof(*state))) {
                exit_server("push_deferred_open_message_smb failed");
        }
        add_deferred_open(lck, req->mid, request_time, state->id);
@@ -1449,6 +1449,22 @@ static NTSTATUS calculate_access_mask(connection_struct 
*conn,
 }
 
 /****************************************************************************
+ Remove the deferred open entry under lock.
+****************************************************************************/
+
+void remove_deferred_open_entry(struct file_id id, uint64_t mid)
+{
+       struct share_mode_lock *lck = get_share_mode_lock(talloc_tos(), id,
+                       NULL, NULL, NULL);
+       if (lck == NULL) {
+               DEBUG(0, ("could not get share mode lock\n"));
+       } else {
+               del_deferred_open_entry(lck, mid);
+               TALLOC_FREE(lck);
+       }
+}
+
+/****************************************************************************
  Open a file with a share mode. Passed in an already created files_struct *.
 ****************************************************************************/
 
@@ -1556,14 +1572,7 @@ static NTSTATUS open_file_ntcreate(connection_struct 
*conn,
                           see if this has timed out. */
 
                        /* Remove the deferred open entry under lock. */
-                       lck = get_share_mode_lock(talloc_tos(), state->id,
-                                       NULL, NULL, NULL);
-                       if (lck == NULL) {
-                               DEBUG(0, ("could not get share mode lock\n"));
-                       } else {
-                               del_deferred_open_entry(lck, req->mid);
-                               TALLOC_FREE(lck);
-                       }
+                       remove_deferred_open_entry(state->id, req->mid);
 
                        /* Ensure we don't reprocess this message. */
                        remove_deferred_open_message_smb(req->mid);
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index a483898..bbfa052 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -759,6 +759,7 @@ bool get_deferred_open_message_state(struct smb_request 
*smbreq,
 bool push_deferred_open_message_smb(struct smb_request *req,
                               struct timeval request_time,
                               struct timeval timeout,
+                              struct file_id id,
                               char *private_data, size_t priv_len)
 {
        struct timeval end_time;
@@ -767,6 +768,7 @@ bool push_deferred_open_message_smb(struct smb_request *req,
                return push_deferred_open_message_smb2(req->smb2req,
                                                request_time,
                                                timeout,
+                                               id,
                                                private_data,
                                                priv_len);
        }
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index ec20b7c..d97d4af 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -199,6 +199,12 @@ NTSTATUS smbd_smb2_request_process_create(struct 
smbd_smb2_request *smb2req)
        return smbd_smb2_request_pending_queue(smb2req, tsubreq);
 }
 
+static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
+{
+       uint8_t *reqhdr = (uint8_t 
*)smb2req->out.vector[smb2req->current_idx].iov_base;
+       return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
+}
+
 static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
 {
        struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
@@ -223,6 +229,19 @@ static void smbd_smb2_request_create_done(struct 
tevent_req *tsubreq)
        NTSTATUS status;
        NTSTATUS error; /* transport error */
 
+       if (smb2req->cancelled) {
+               uint64_t mid = get_mid_from_smb2req(smb2req);
+               DEBUG(10,("smbd_smb2_request_create_done: cancelled mid %llu\n",
+                       (unsigned long long)mid ));
+               error = smbd_smb2_request_error(smb2req, NT_STATUS_CANCELLED);
+               if (!NT_STATUS_IS_OK(error)) {
+                       smbd_server_connection_terminate(smb2req->sconn,
+                               nt_errstr(error));
+                       return;
+               }
+               return;
+       }
+
        status = smbd_smb2_create_recv(tsubreq,
                                       smb2req,
                                       &out_oplock_level,
@@ -318,6 +337,7 @@ struct smbd_smb2_create_state {
        struct smb_request *smb1req;
        struct timed_event *te;
        struct timeval request_time;
+       struct file_id id;
        DATA_BLOB private_data;
        uint8_t out_oplock_level;
        uint32_t out_create_action;
@@ -818,8 +838,7 @@ static struct smbd_smb2_request *find_open_smb2req(uint64_t 
mid)
        struct smbd_smb2_request *smb2req;
 
        for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
-               uint8_t *reqhdr = (uint8_t 
*)smb2req->out.vector[smb2req->current_idx].iov_base;
-               uint64_t message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
+               uint64_t message_id = get_mid_from_smb2req(smb2req);
                if (message_id == mid) {
                        return smb2req;
                }
@@ -859,17 +878,11 @@ bool open_was_deferred_smb2(uint64_t mid)
        return true;
 }
 
-void remove_deferred_open_message_smb2(uint64_t mid)
+static void remove_deferred_open_message_smb2_internal(struct 
smbd_smb2_request *smb2req,
+                                                       uint64_t mid)
 {
        struct smbd_smb2_create_state *state = NULL;
-       struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
 
-       if (!smb2req) {
-               DEBUG(10,("remove_deferred_open_message_smb2: "
-                       "can't find mid %llu\n",
-                       (unsigned long long)mid ));
-               return;
-       }
        if (!smb2req->subreq) {
                return;
        }
@@ -882,7 +895,7 @@ void remove_deferred_open_message_smb2(uint64_t mid)
                return;
        }
 
-       DEBUG(10,("remove_deferred_open_message_smb2: "
+       DEBUG(10,("remove_deferred_open_message_smb2_internal: "
                "mid %llu\n",
                (unsigned long long)mid ));
 
@@ -890,6 +903,19 @@ void remove_deferred_open_message_smb2(uint64_t mid)
        TALLOC_FREE(state->te);
 }
 
+void remove_deferred_open_message_smb2(uint64_t mid)
+{
+       struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
+
+       if (!smb2req) {
+               DEBUG(10,("remove_deferred_open_message_smb2: "
+                       "can't find mid %llu\n",
+                       (unsigned long long)mid ));
+               return;
+       }
+       remove_deferred_open_message_smb2_internal(smb2req, mid);
+}
+
 void schedule_deferred_open_message_smb2(uint64_t mid)
 {
        struct tevent_immediate *im = NULL;
@@ -979,9 +1005,36 @@ static void smb2_deferred_open_timer(struct event_context 
*ev,
        }
 }
 
+static bool smbd_smb2_create_cancel(struct tevent_req *req)
+{
+       struct smbd_smb2_request *smb2req = NULL;
+       struct smbd_smb2_create_state *state = tevent_req_data(req,
+                               struct smbd_smb2_create_state);
+       uint64_t mid;
+
+       if (!state) {
+               return false;
+       }
+
+       if (!state->smb2req) {
+               return false;
+       }
+
+       smb2req = state->smb2req;
+       mid = get_mid_from_smb2req(smb2req);
+
+       remove_deferred_open_entry(state->id, mid);
+       remove_deferred_open_message_smb2_internal(smb2req, mid);
+       smb2req->cancelled = true;
+
+       tevent_req_done(req);
+       return true;
+}
+
 bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
                                 struct timeval request_time,
                                 struct timeval timeout,
+                               struct file_id id,
                                 char *private_data,
                                 size_t priv_len)
 {
@@ -1000,6 +1053,7 @@ bool push_deferred_open_message_smb2(struct 
smbd_smb2_request *smb2req,
        if (!state) {
                return false;
        }
+       state->id = id;
        state->request_time = request_time;
        state->private_data = data_blob_talloc(state, private_data,
                                                priv_len);
@@ -1048,5 +1102,9 @@ bool push_deferred_open_message_smb2(struct 
smbd_smb2_request *smb2req,
         if (!state->te) {
                return false;
        }
+
+       /* allow this request to be canceled */
+       tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
+
        return true;
 }


-- 
Samba Shared Repository

Reply via email to