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)
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 &&
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
* 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);
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);