Whamcloud - gitweb
LU-3889 osc: Allow lock to be canceled at ENQ time 05/8405/5
authorAlexander.Boyko <alexander_boyko@xyratex.com>
Tue, 3 Dec 2013 06:00:22 +0000 (10:00 +0400)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 4 Jan 2014 03:19:34 +0000 (03:19 +0000)
A cl_lock can be canceled when it's in CLS_ENQUEUED state.
We can't unuse this kind of lock in lov_lock_unuse() because
it will bring this lock into CLS_NEW state and then confuse
osc_lock_upcall().

Add a regression test case by Alexander Boyko.

Signed-off-by: Jinshan Xiong <jinshan.xiong@intel.com>
Signed-off-by: Alexander Boyko <alexander_boyko@xyratex.com>
Change-Id: I2acc7fd0176280062eb0d25dbe929b5d0144db50
Reviewed-on: http://review.whamcloud.com/8405
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Bobi Jam <bobijam@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/obd_support.h
lustre/lov/lov_lock.c
lustre/osc/osc_request.c
lustre/tests/sanityn.sh

index b4827e0..254a7de 100644 (file)
@@ -343,6 +343,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type,
 #define OBD_FAIL_LDLM_AGL_DELAY          0x31a
 #define OBD_FAIL_LDLM_AGL_NOLOCK         0x31b
 #define OBD_FAIL_LDLM_OST_LVB           0x31c
 #define OBD_FAIL_LDLM_AGL_DELAY          0x31a
 #define OBD_FAIL_LDLM_AGL_NOLOCK         0x31b
 #define OBD_FAIL_LDLM_OST_LVB           0x31c
+#define OBD_FAIL_LDLM_ENQUEUE_HANG      0x31d
 
 /* LOCKLESS IO */
 #define OBD_FAIL_LDLM_SET_CONTENTION     0x385
 
 /* LOCKLESS IO */
 #define OBD_FAIL_LDLM_SET_CONTENTION     0x385
index 547bdca..39a4aaf 100644 (file)
@@ -709,18 +709,26 @@ static int lov_lock_unuse(const struct lu_env *env,
                 if (sub == NULL)
                         continue;
 
                 if (sub == NULL)
                         continue;
 
-                sublock = sub->lss_cl.cls_lock;
-                rc = lov_sublock_lock(env, lck, lls, closure, &subenv);
-                if (rc == 0) {
-                        if (lls->sub_flags & LSF_HELD) {
-                                LASSERT(sublock->cll_state == CLS_HELD ||
-                                        sublock->cll_state == CLS_ENQUEUED);
-                                rc = cl_unuse_try(subenv->lse_env, sublock);
-                                rc = lov_sublock_release(env, lck, i, 0, rc);
-                        }
-                        lov_sublock_unlock(env, sub, closure, subenv);
-                }
-                result = lov_subresult(result, rc);
+               sublock = sub->lss_cl.cls_lock;
+               rc = lov_sublock_lock(env, lck, lls, closure, &subenv);
+               if (rc == 0) {
+                       if (!(lls->sub_flags & LSF_HELD)) {
+                               lov_sublock_unlock(env, sub, closure, subenv);
+                               continue;
+                       }
+
+                       switch(sublock->cll_state) {
+                       case CLS_HELD:
+                               rc = cl_unuse_try(subenv->lse_env, sublock);
+                               lov_sublock_release(env, lck, i, 0, 0);
+                               break;
+                       default:
+                               lov_sublock_release(env, lck, i, 1, 0);
+                               break;
+                       }
+                       lov_sublock_unlock(env, sub, closure, subenv);
+               }
+               result = lov_subresult(result, rc);
         }
 
         if (result == 0 && lck->lls_cancel_race) {
         }
 
         if (result == 0 && lck->lls_cancel_race) {
index 09afa3c..0c14415 100644 (file)
@@ -2438,6 +2438,9 @@ static int osc_enqueue_interpret(const struct lu_env *env,
          * osc_enqueue_fini(). */
         ldlm_lock_addref(&handle, mode);
 
          * osc_enqueue_fini(). */
         ldlm_lock_addref(&handle, mode);
 
+       /* Let cl_lock_state_wait fail with -ERESTARTSYS to unuse sublocks. */
+       OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_ENQUEUE_HANG, 2);
+
         /* Let CP AST to grant the lock first. */
         OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_CP_ENQ_RACE, 1);
 
         /* Let CP AST to grant the lock first. */
         OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_CP_ENQ_RACE, 1);
 
index 16cfedb..9340b37 100644 (file)
@@ -2549,6 +2549,28 @@ test_74() {
 }
 run_test 74 "flock deadlock: different mounts =============="
 
 }
 run_test 74 "flock deadlock: different mounts =============="
 
+# LU-3889
+test_75() {
+       $LFS setstripe -c 2 -S 1m -i 0 $DIR1/$tfile
+       dd if=/dev/zero of=$DIR1/$tfile bs=1M count=2
+       cancel_lru_locks osc
+
+       dd of=$DIR1/$tfile if=/dev/zero bs=1M count=1 seek=1 conv=notrunc
+       sync
+
+       # define OBD_FAIL_LDLM_ENQUEUE_HANG 0x31d
+       $LCTL set_param fail_loc=0x31d
+       stat -c %s $DIR1/$tfile &
+       local pid=$!
+       sleep 1
+       kill -9 $pid
+
+       # For bad lock error handler we should ASSERT and got kernel panic here
+       sleep 4
+       $LCTL set_param fail_loc=0
+}
+run_test 75 "osc: upcall after unuse lock==================="
+
 log "cleanup: ======================================================"
 
 [ "$(mount | grep $MOUNT2)" ] && umount $MOUNT2
 log "cleanup: ======================================================"
 
 [ "$(mount | grep $MOUNT2)" ] && umount $MOUNT2