Author: jra Date: 2007-08-29 20:36:42 +0000 (Wed, 29 Aug 2007) New Revision: 24790
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=24790 Log: Fix logic error in timeout of blocking lock processing found by Volker. If a lock timeout expires, we must check we can get the lock before responding with failure. I'll port this to 3.2.x next. Volker is writing a torture test. Jeremy. Modified: branches/SAMBA_3_0_25/source/smbd/blocking.c Changeset: Modified: branches/SAMBA_3_0_25/source/smbd/blocking.c =================================================================== --- branches/SAMBA_3_0_25/source/smbd/blocking.c 2007-08-29 19:55:13 UTC (rev 24789) +++ branches/SAMBA_3_0_25/source/smbd/blocking.c 2007-08-29 20:36:42 UTC (rev 24790) @@ -685,18 +685,14 @@ DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", fsp->fnum, fsp->fsp_name )); - if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { + if(!change_to_user(conn,vuid)) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* - * Lock expired - throw away all previously - * obtained locks and return lock error. + * Remove the entry and return an error to the client. */ if (br_lck) { - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); - brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), @@ -706,13 +702,15 @@ TALLOC_FREE(br_lck); } - blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); continue; } - if(!change_to_user(conn,vuid)) { + if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); /* @@ -729,21 +727,23 @@ TALLOC_FREE(br_lck); } - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); + change_to_root_user(); continue; } - if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { + /* + * Go through the remaining locks and try and obtain them. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. + */ + + if(blocking_lock_record_process(blr)) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); - /* - * Remove the entry and return an error to the client. - */ - if (br_lck) { brl_lock_cancel(br_lck, blr->lock_pid, @@ -754,24 +754,31 @@ TALLOC_FREE(br_lck); } - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); change_to_root_user(); continue; } + change_to_root_user(); + /* - * Go through the remaining locks and try and obtain them. - * The call returns True if all locks were obtained successfully - * and False if we still need to wait. + * We couldn't get the locks for this record on the list. + * If the time has expired, return a lock error. */ - if(blocking_lock_record_process(blr)) { + if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp); + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + if (br_lck) { + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), @@ -781,10 +788,12 @@ TALLOC_FREE(br_lck); } + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); DLIST_REMOVE(blocking_lock_queue, blr); free_blocking_lock_record(blr); + continue; } - change_to_root_user(); + } }