[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Apr 23 14:20:58 MDT 2010


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 <jra at 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


More information about the samba-cvs mailing list