From 0ead434b84a7c3226ac223acc79ad0e794da3877 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 20 Jun 2014 14:12:14 +0000 Subject: [PATCH] smbd: Store "struct deferred_open_record" instead of anonymous data on pml The main point is to get a talloc parent that will go away when the request is cancelled Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/smbd/globals.h | 13 +++++++------ source3/smbd/open.c | 24 ++++++++++++++++-------- source3/smbd/process.c | 30 +++++++++++------------------- source3/smbd/proto.h | 14 +++++++------- source3/smbd/smb2_create.c | 19 +++++++------------ 5 files changed, 48 insertions(+), 52 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index cd99fe72ca1..28e4f944303 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -287,6 +287,8 @@ void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx, struct tevent_immediate *im, void *private_data); +struct deferred_open_record; + /* SMB1 -> SMB2 glue. */ void send_break_message_smb2(files_struct *fsp, int level); struct blocking_lock_record *get_pending_smb2req_blr(struct smbd_smb2_request *smb2req); @@ -310,7 +312,7 @@ void cancel_pending_lock_requests_by_fid_smb2(files_struct *fsp, int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level); bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req, struct timeval *p_request_time, - void **pp_state); + struct deferred_open_record **open_rec); bool open_was_deferred_smb2(struct smbd_server_connection *sconn, uint64_t mid); void remove_deferred_open_message_smb2( @@ -318,11 +320,10 @@ void remove_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, - struct timeval timeout, - struct file_id id, - char *private_data, - size_t priv_len); + struct timeval request_time, + struct timeval timeout, + struct file_id id, + struct deferred_open_record *open_rec); struct smbXsrv_connection { struct smbd_server_connection *sconn; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 237e90cfd3e..c0f4dea3ac9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1564,14 +1564,24 @@ static void defer_open(struct share_mode_lock *lck, struct smb_request *req, struct deferred_open_record *state) { + struct deferred_open_record *open_rec; + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " "open entry for mid %llu\n", (unsigned int)request_time.tv_sec, (unsigned int)request_time.tv_usec, (unsigned long long)req->mid)); + open_rec = talloc(NULL, struct deferred_open_record); + if (open_rec == NULL) { + TALLOC_FREE(lck); + exit_server("talloc failed"); + } + + *open_rec = *state; + if (!push_deferred_open_message_smb(req, request_time, timeout, - state->id, (char *)state, sizeof(*state))) { + state->id, open_rec)) { TALLOC_FREE(lck); exit_server("push_deferred_open_message_smb failed"); } @@ -1930,11 +1940,9 @@ NTSTATUS smbd_calculate_access_mask(connection_struct *conn, Return true if this is a state pointer to an asynchronous create. ****************************************************************************/ -bool is_deferred_open_async(const void *ptr) +bool is_deferred_open_async(const struct deferred_open_record *rec) { - const struct deferred_open_record *state = (const struct deferred_open_record *)ptr; - - return state->async_open; + return rec->async_open; } static bool clear_ads(uint32_t create_disposition) @@ -2143,10 +2151,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, */ if (req) { - void *ptr; + struct deferred_open_record *open_rec; if (get_deferred_open_message_state(req, &request_time, - &ptr)) { + &open_rec)) { /* Remember the absolute time of the original request with this mid. We'll use it later to see if this has timed out. */ @@ -2154,7 +2162,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, /* If it was an async create retry, the file didn't exist. */ - if (is_deferred_open_async(ptr)) { + if (is_deferred_open_async(open_rec)) { SET_STAT_INVALID(smb_fname->st); file_existed = false; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8a1d1d67704..b1d522dbc34 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -52,7 +52,7 @@ struct pending_message_list { bool encrypted; bool processed; DATA_BLOB buf; - DATA_BLOB private_data; + struct deferred_open_record *open_rec; }; static void construct_reply_common(struct smb_request *req, const char *inbuf, @@ -635,7 +635,7 @@ static void smbd_deferred_open_timer(struct tevent_context *ev, static bool push_queued_message(struct smb_request *req, struct timeval request_time, struct timeval end_time, - char *private_data, size_t private_len) + struct deferred_open_record *open_rec) { int msg_len = smb_len(req->inbuf) + 4; struct pending_message_list *msg; @@ -661,14 +661,8 @@ static bool push_queued_message(struct smb_request *req, msg->processed = false; SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd); - if (private_data) { - msg->private_data = data_blob_talloc(msg, private_data, - private_len); - if (msg->private_data.data == NULL) { - DEBUG(0,("push_message: malloc fail (3)\n")); - TALLOC_FREE(msg); - return False; - } + if (open_rec) { + msg->open_rec = talloc_move(msg, &open_rec); } #if 0 @@ -828,14 +822,14 @@ static struct pending_message_list *get_deferred_open_message_smb( bool get_deferred_open_message_state(struct smb_request *smbreq, struct timeval *p_request_time, - void **pp_state) + struct deferred_open_record **open_rec) { struct pending_message_list *pml; if (smbreq->sconn->using_smb2) { return get_deferred_open_message_state_smb2(smbreq->smb2req, p_request_time, - pp_state); + open_rec); } pml = get_deferred_open_message_smb(smbreq->sconn, smbreq->mid); @@ -845,8 +839,8 @@ bool get_deferred_open_message_state(struct smb_request *smbreq, if (p_request_time) { *p_request_time = pml->request_time; } - if (pp_state) { - *pp_state = (void *)pml->private_data.data; + if (open_rec != NULL) { + *open_rec = pml->open_rec; } return true; } @@ -860,7 +854,7 @@ 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 deferred_open_record *open_rec) { struct timeval end_time; @@ -869,8 +863,7 @@ bool push_deferred_open_message_smb(struct smb_request *req, request_time, timeout, id, - private_data, - priv_len); + open_rec); } if (req->unread_bytes) { @@ -890,8 +883,7 @@ bool push_deferred_open_message_smb(struct smb_request *req, (unsigned int)end_time.tv_sec, (unsigned int)end_time.tv_usec)); - return push_queued_message(req, request_time, end_time, - private_data, priv_len); + return push_queued_message(req, request_time, end_time, open_rec); } static void smbd_sig_term_handler(struct tevent_context *ev, diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 1e17f5b741a..b25ef7b159f 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -620,7 +620,8 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf); bool is_stat_open(uint32 access_mask); -bool is_deferred_open_async(const void *ptr); +struct deferred_open_record; +bool is_deferred_open_async(const struct deferred_open_record *rec); NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, struct smb_filename *smb_dname); void msg_file_was_renamed(struct messaging_context *msg, @@ -764,13 +765,12 @@ bool schedule_deferred_open_message_smb(struct smbd_server_connection *sconn, bool open_was_deferred(struct smbd_server_connection *sconn, uint64_t mid); bool get_deferred_open_message_state(struct smb_request *smbreq, struct timeval *p_request_time, - void **pp_state); + struct deferred_open_record **open_rec); 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 request_time, + struct timeval timeout, + struct file_id id, + struct deferred_open_record *open_rec); NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid); void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes); void smb_request_done(struct smb_request *req); diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 4e2e6bc3ffd..976e81a33a1 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -382,7 +382,7 @@ struct smbd_smb2_create_state { struct tevent_immediate *im; struct timeval request_time; struct file_id id; - DATA_BLOB private_data; + struct deferred_open_record *open_rec; uint8_t out_oplock_level; uint32_t out_create_action; struct timespec out_creation_ts; @@ -1177,7 +1177,7 @@ static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req, bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req, struct timeval *p_request_time, - void **pp_state) + struct deferred_open_record **open_rec) { struct smbd_smb2_create_state *state = NULL; struct tevent_req *req = NULL; @@ -1199,8 +1199,8 @@ bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req, if (p_request_time) { *p_request_time = state->request_time; } - if (pp_state) { - *pp_state = (void *)state->private_data.data; + if (open_rec != NULL) { + *open_rec = state->open_rec; } return true; } @@ -1409,7 +1409,7 @@ 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)) { + if (is_deferred_open_async(state->open_rec)) { /* Can't cancel an async create. */ return false; } @@ -1425,8 +1425,7 @@ 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) + struct deferred_open_record *open_rec) { struct tevent_req *req = NULL; struct smbd_smb2_create_state *state = NULL; @@ -1445,11 +1444,7 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req, } state->id = id; state->request_time = request_time; - state->private_data = data_blob_talloc(state, private_data, - priv_len); - if (!state->private_data.data) { - return false; - } + state->open_rec = talloc_move(state, &open_rec); /* Re-schedule us to retry on timer expiry. */ end_time = timeval_sum(&request_time, &timeout); -- 2.11.4.GIT