From 81b580fd2248221c61e3d4dac03862fb1fd8fde5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Aug 1998 01:30:29 +0000 Subject: Fixes for the problem in blocking locks with file_fsp returning the chain_fsp on close (if you don't know what this means, consider yourself lucky - this one took a day to track down :-). Jeremy. (This used to be commit 193cb5382464173e99a538867a266d793f0ceab5) --- source3/smbd/blocking.c | 69 ++++++++++++++++++++++++++++--------------------- source3/smbd/close.c | 4 +-- source3/smbd/nttrans.c | 10 ++++++- 3 files changed, 51 insertions(+), 32 deletions(-) (limited to 'source3') diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 1aa80b2797..2241b7aa8d 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -33,6 +33,7 @@ extern char *OutBuffer; typedef struct { ubi_slNode msg_next; int com_type; + files_struct *fsp; time_t expire_time; int lock_num; char *inbuf; @@ -51,6 +52,25 @@ static void free_blocking_lock_record(blocking_lock_record *blr) free((char *)blr); } +/**************************************************************************** + Get the files_struct given a particular queued SMB. +*****************************************************************************/ + +static files_struct *get_fsp_from_pkt(char *inbuf) +{ + switch(CVAL(inbuf,smb_com)) { + case SMBlock: + case SMBlockread: + return file_fsp(inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ +} + /**************************************************************************** Determine if this is a secondary element of a chained SMB. **************************************************************************/ @@ -67,7 +87,6 @@ static BOOL in_chained_smb(void) BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num) { blocking_lock_record *blr; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); if(in_chained_smb() ) { DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); @@ -91,6 +110,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int } blr->com_type = CVAL(inbuf,smb_com); + blr->fsp = get_fsp_from_pkt(inbuf); blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; blr->lock_num = lock_num; memcpy(blr->inbuf, inbuf, length); @@ -98,8 +118,10 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int ubi_slAddTail(&blocking_lock_queue, blr); + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d \ -for fnum = %d, name = %s\n", length, (int)blr->expire_time, fsp->fnum, fsp->fsp_name )); +for fnum = %d, name = %s\n", length, (int)blr->expire_time, + blr->fsp->fnum, blr->fsp->fsp_name )); return True; } @@ -170,7 +192,7 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, int eclass, i static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ecode) { char *inbuf = blr->inbuf; - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint32 count, offset; @@ -233,7 +255,7 @@ static BOOL process_lockread(blocking_lock_record *blr) int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = blr->fsp; numtoread = SVAL(inbuf,smb_vwv1); startpos = IVAL(inbuf,smb_vwv2); @@ -298,7 +320,7 @@ static BOOL process_lock(blocking_lock_record *blr) int eclass; uint32 ecode; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); - files_struct *fsp = file_fsp(inbuf,smb_vwv0); + files_struct *fsp = blr->fsp; count = IVAL(inbuf,smb_vwv1); offset = IVAL(inbuf,smb_vwv3); @@ -348,7 +370,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) { char *inbuf = blr->inbuf; unsigned char locktype = CVAL(inbuf,smb_vwv3); - files_struct *fsp = file_fsp(inbuf,smb_vwv2); + files_struct *fsp = blr->fsp; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); @@ -428,25 +450,6 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) return False; /* Keep compiler happy. */ } -/**************************************************************************** - Get the files_struct given a particular queued SMB. -*****************************************************************************/ - -static files_struct *get_fsp_from_blr(blocking_lock_record *blr) -{ - switch(blr->com_type) { - case SMBlock: - case SMBlockread: - return file_fsp(blr->inbuf,smb_vwv0); - case SMBlockingX: - return file_fsp(blr->inbuf,smb_vwv2); - default: - DEBUG(0,("get_fsp_from_blr: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return NULL; /* Keep compiler happy. */ -} - /**************************************************************************** Delete entries by fnum from the blocking lock pending queue. *****************************************************************************/ @@ -457,9 +460,11 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) blocking_lock_record *prev = NULL; while(blr != NULL) { - files_struct *req_fsp = get_fsp_from_blr(blr); + if(blr->fsp->fnum == fsp->fnum) { + + DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ +file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - if(req_fsp == fsp) { free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); continue; @@ -481,6 +486,11 @@ void remove_pending_lock_requests_by_mid(int mid) while(blr != NULL) { if(SVAL(blr->inbuf,smb_mid) == mid) { + files_struct *fsp = blr->fsp; + + DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ +file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); + blocking_lock_reply_error(blr,0,NT_STATUS_CANCELLED); free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev)); blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); @@ -511,14 +521,15 @@ void process_blocking_lock_queue(time_t t) while(blr != NULL) { connection_struct *conn = NULL; uint16 vuid; - files_struct *fsp = get_fsp_from_blr(blr); + files_struct *fsp = NULL; /* - * Ensure we don't have any old chain_fnum values + * Ensure we don't have any old chain_fsp values * sitting around.... */ chain_size = 0; file_chain_reset(); + fsp = blr->fsp; conn = conn_find(SVAL(blr->inbuf,smb_tid)); vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : diff --git a/source3/smbd/close.c b/source3/smbd/close.c index b8063ca3f4..07b000d7ad 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -104,6 +104,8 @@ void close_file(files_struct *fsp, BOOL normal_close) int token; connection_struct *conn = fsp->conn; + remove_pending_lock_requests_by_fid(fsp); + close_filestruct(fsp); #if USE_READ_PREDICTION @@ -142,8 +144,6 @@ void close_file(files_struct *fsp, BOOL normal_close) string_free(&fsp->fsp_name); } - remove_pending_lock_requests_by_fid(fsp); - file_free(fsp); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 236f1e2d30..596d15c2c7 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -28,6 +28,7 @@ extern int Client; extern int oplock_sock; extern int smb_read_error; extern int global_oplock_break; +extern int chain_size; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; @@ -1029,7 +1030,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp) change_notify_buf *prev = NULL; while(cnbp != NULL) { - if(cnbp->fsp == fsp) { + if(cnbp->fsp->fnum == fsp->fnum) { free((char *)ubi_slRemNext( &change_notify_queue, prev)); cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); continue; @@ -1089,6 +1090,13 @@ void process_pending_change_notify_queue(time_t t) uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + if(!become_user(conn,vuid)) { DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", vuid )); -- cgit