1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

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 commit is contained in:
Jeremy Allison 0001-01-01 00:00:00 +00:00
parent e1dd03ecda
commit 193cb53824
3 changed files with 51 additions and 32 deletions

View File

@ -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 :

View File

@ -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);
}

View File

@ -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 ));