Whamcloud - gitweb
LU-16958 llite: migrate deadlock on not responding lock cancel
[fs/lustre-release.git] / lustre / lov / lov_object.c
index 787f2e1..a265e6a 100644 (file)
@@ -1310,8 +1310,11 @@ static int lov_layout_change(const struct lu_env *unused,
        new_ops = &lov_dispatch[llt];
 
        rc = cl_object_prune(env, &lov->lo_cl);
-       if (rc != 0)
+       if (rc != 0) {
+               if (rc == -EAGAIN)
+                       set_bit(LO_NEED_INODE_LOCK, &lov->lo_obj_flags);
                GOTO(out, rc);
+       }
 
        rc = old_ops->llo_delete(env, lov, &lov->u);
        if (rc != 0)
@@ -1394,13 +1397,12 @@ out_lsm:
 static int lov_conf_set(const struct lu_env *env, struct cl_object *obj,
                        const struct cl_object_conf *conf)
 {
-       struct lov_stripe_md    *lsm = NULL;
-       struct lov_object       *lov = cl2lov(obj);
-       int                      result = 0;
+       struct lov_stripe_md *lsm = NULL;
+       struct lov_object *lov = cl2lov(obj);
        struct cl_object *top = cl_object_top(obj);
-       bool unlock_inode = false;
-       bool lock_inode_size = false;
-       bool lock_layout = false;
+       bool lock_inode = false;
+       bool inode_size_locked = false;
+       int result = 0;
        ENTRY;
 
        if (conf->coc_opc == OBJECT_CONF_SET &&
@@ -1471,9 +1473,11 @@ retry:
                GOTO(out, result = -ERESTARTSYS);
        }
 
+       clear_bit(LO_NEED_INODE_LOCK, &lov->lo_obj_flags);
        result = lov_layout_change(env, lov, lsm, conf);
        if (result) {
-               if (result == -EAGAIN) {
+               if (result == -EAGAIN &&
+                   test_bit(LO_NEED_INODE_LOCK, &lov->lo_obj_flags)) {
                        /**
                         * we need unlocked lov conf and get inode lock.
                         * It's possible we have already taken inode's size
@@ -1481,42 +1485,28 @@ retry:
                         * order, lest deadlock happens:
                         *   inode lock        (ll_inode_lock())
                         *   inode size lock   (ll_inode_size_lock())
-                        *   inode layout lock (ll_layout_refresh())
                         *   lov conf lock     (lov_conf_lock())
                         *
                         * e.g.
                         *   vfs_setxattr                inode locked
                         *     ll_lov_setstripe_ea_info  inode size locked
                         *       ll_prep_inode
-                        *         ll_file_inode_init
-                        *           cl_conf_set
-                        *             lov_conf_set      lov conf locked
-                        *
-                        *   ll_migrate                  inode locked
-                        *     ...
-                        *       ll_layout_refresh       inode layout locked
-                        *         ll_layout_conf
+                        *         cl_file_inode_init
                         *           cl_conf_set
                         *             lov_conf_set      lov conf locked
                         */
                        lov_conf_unlock(lov);
-                       if (cl_object_inode_ops(env, top, COIO_LAYOUT_UNLOCK,
-                                               NULL) == 0)
-                               lock_layout = true;
                        if (cl_object_inode_ops(env, top, COIO_SIZE_UNLOCK,
                                                NULL) == 0)
-                               lock_inode_size = true;
+                               inode_size_locked = true;
 
                        /* take lock in order */
                        if (cl_object_inode_ops(
                                        env, top, COIO_INODE_LOCK, NULL) == 0)
-                               unlock_inode = true;
-                       if (lock_inode_size)
+                               lock_inode = true;
+                       if (inode_size_locked)
                                cl_object_inode_ops(env, top, COIO_SIZE_LOCK,
                                                    NULL);
-                       if (lock_layout)
-                               cl_object_inode_ops(env, top, COIO_LAYOUT_LOCK,
-                                                   NULL);
                        goto retry;
                }
                set_bit(LO_LAYOUT_INVALID, &lov->lo_obj_flags);
@@ -1527,7 +1517,7 @@ retry:
 
 out:
        lov_conf_unlock(lov);
-       if (unlock_inode)
+       if (lock_inode)
                cl_object_inode_ops(env, top, COIO_INODE_UNLOCK, NULL);
 out_lsm:
        lov_lsm_put(lsm);