Whamcloud - gitweb
LU-68 Fix a race between lock cancel and write
authorOleg Drokin <green@whamcloud.com>
Mon, 14 Mar 2011 22:46:17 +0000 (18:46 -0400)
committerOleg Drokin <green@whamcloud.com>
Wed, 16 Mar 2011 15:46:21 +0000 (08:46 -0700)
A race in osc_lock_detach due to disconnect between reading
kms from lock resource and write updating kms in the resource
could lead to loss of the update.
Lock the object across entire kms access to avert the issue.

Change-Id: I4b15e611b91b7a4a6b69f5c9fa9b6bd0a1f8cac9
Signed-off-by: Oleg Drokin <green@whamcloud.com>
Reviewed-on: http://review.whamcloud.com/327
Tested-by: Hudson
Reviewed-by: wangdi <di.wang@whamcloud.com>
Reviewed-by: Jinshan Xiong <jay@whamcloud.com>
lustre/osc/osc_lock.c

index 5776426..0b03ea7 100644 (file)
@@ -155,18 +155,19 @@ static void osc_lock_detach(const struct lu_env *env, struct osc_lock *olck)
         if (dlmlock->l_granted_mode == dlmlock->l_req_mode) {
                 struct cl_object *obj = olck->ols_cl.cls_obj;
                 struct cl_attr *attr  = &osc_env_info(env)->oti_attr;
         if (dlmlock->l_granted_mode == dlmlock->l_req_mode) {
                 struct cl_object *obj = olck->ols_cl.cls_obj;
                 struct cl_attr *attr  = &osc_env_info(env)->oti_attr;
-                __u64 old_kms = cl2osc(obj)->oo_oinfo->loi_kms;
+                __u64 old_kms;
 
 
+                cl_object_attr_lock(obj);
+                /* Must get the value under the lock to avoid possible races. */
+                old_kms = cl2osc(obj)->oo_oinfo->loi_kms;
                 /* Update the kms. Need to loop all granted locks.
                  * Not a problem for the client */
                 attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms);
                 /* Update the kms. Need to loop all granted locks.
                  * Not a problem for the client */
                 attr->cat_kms = ldlm_extent_shift_kms(dlmlock, old_kms);
-                unlock_res_and_lock(dlmlock);
 
 
-                cl_object_attr_lock(obj);
                 cl_object_attr_set(env, obj, attr, CAT_KMS);
                 cl_object_attr_unlock(obj);
                 cl_object_attr_set(env, obj, attr, CAT_KMS);
                 cl_object_attr_unlock(obj);
-        } else
-                unlock_res_and_lock(dlmlock);
+        }
+        unlock_res_and_lock(dlmlock);
 
         /* release a reference taken in osc_lock_upcall0(). */
         LASSERT(olck->ols_has_ref);
 
         /* release a reference taken in osc_lock_upcall0(). */
         LASSERT(olck->ols_has_ref);