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();
+
        }
 }
 

Reply via email to