Whamcloud - gitweb
LU-1527 clio: check if lock is freed in cl_lock_peek()
authorAndriy Skulysh <Andriy_Skulysh@xyratex.com>
Thu, 4 Oct 2012 14:20:05 +0000 (17:20 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 7 Nov 2012 02:56:53 +0000 (21:56 -0500)
The lock may have been freed between cl_lock_lookup() and
cl_lock_mutex_get() so we should check lock state after grabbing
lock mutex.

Xyratex-bug-id: MRP-665
Change-Id: Id3562b3dd8bd052b74ad7840f08b904ca38a6746
Signed-off-by: Andriy Skulysh <Andriy_Skulysh@xyratex.com>
Reviewed-by: Andrew Perepechko <andrew_perepechko@xyratex.com>
Reviewed-by: Vitaly Fertman <vitaly_fertman@xyratex.com>
Reviewed-on: http://review.whamcloud.com/3117
Reviewed-by: Jinshan Xiong <jinshan.xiong@whamcloud.com>
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Niu Yawei <niu@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/obdclass/cl_lock.c

index 84ee04f..c3ad51e 100644 (file)
@@ -593,16 +593,24 @@ struct cl_lock *cl_lock_peek(const struct lu_env *env, const struct cl_io *io,
         obj  = need->cld_obj;
         head = cl_object_header(obj);
 
-        cfs_spin_lock(&head->coh_lock_guard);
-        lock = cl_lock_lookup(env, obj, io, need);
-        cfs_spin_unlock(&head->coh_lock_guard);
-
-        if (lock == NULL)
-                return NULL;
+       do {
+               cfs_spin_lock(&head->coh_lock_guard);
+               lock = cl_lock_lookup(env, obj, io, need);
+               cfs_spin_unlock(&head->coh_lock_guard);
+               if (lock == NULL)
+                       return NULL;
+
+               cl_lock_mutex_get(env, lock);
+               if (lock->cll_state == CLS_INTRANSIT)
+                       /* Don't care return value. */
+                       cl_lock_state_wait(env, lock);
+               if (lock->cll_state == CLS_FREEING) {
+                       cl_lock_mutex_put(env, lock);
+                       cl_lock_put(env, lock);
+                       lock = NULL;
+               }
+       } while (lock == NULL);
 
-        cl_lock_mutex_get(env, lock);
-        if (lock->cll_state == CLS_INTRANSIT)
-                cl_lock_state_wait(env, lock); /* Don't care return value. */
        cl_lock_hold_add(env, lock, scope, source);
        cl_lock_user_add(env, lock);
        if (lock->cll_state == CLS_CACHED)