const char *name, int fl,
struct thandle *th)
{
+ struct lod_thread_info *info = lod_env_info(env);
struct dt_object *next = dt_object_child(dt);
- struct lu_attr *attr = &lod_env_info(env)->lti_attr;
+ struct lu_attr *attr = &info->lti_attr;
+ struct lod_object *lo = lod_dt_obj(dt);
__u32 mode;
int rc;
ENTRY;
rc = lod_sub_declare_xattr_set(env, next, buf, name, fl, th);
}
+ if (rc == 0 &&
+ (strcmp(name, XATTR_NAME_LOV) == 0 ||
+ strcmp(name, XATTR_LUSTRE_LOV) == 0 || allowed_lustre_lov(name)))
+ rc = lod_save_layout_gen_intrans(info, lo);
+
RETURN(rc);
}
struct dt_object *dt, const struct lu_buf *buf,
const char *name, int fl, struct thandle *th)
{
+ struct lod_thread_info *info = lod_env_info(env);
struct dt_object *next = dt_object_child(dt);
- struct lu_attr *layout_attr = &lod_env_info(env)->lti_layout_attr;
+ struct lu_attr *layout_attr = &info->lti_layout_attr;
struct lod_object *lo = lod_dt_obj(dt);
struct lod_obj_stripe_cb_data data = { {0} };
int rc = 0;
(strcmp(name, XATTR_NAME_LOV) == 0 ||
strcmp(name, XATTR_LUSTRE_LOV) == 0 ||
allowed_lustre_lov(name))) {
+ /* layout has been changed by others in the transaction */
+ rc = lod_check_layout_gen_intrans(info, lo);
+ if (rc > 0) {
+ CDEBUG(D_LAYOUT,
+ "%s: obj "DFID" gen changed from %d to %d in transaction, retry the transaction\n",
+ dt->do_lu.lo_dev->ld_obd->obd_name,
+ PFID(lu_object_fid(&dt->do_lu)),
+ info->lti_gen[rc - 1], lo->ldo_layout_gen);
+ RETURN(-EAGAIN);
+ }
+
/* in case of lov EA swap, just set it
* if not, it is a replay so check striping match what we
* already have during req replay, declare_xattr_set()
} else {
/*
* When 'name' is XATTR_LUSTRE_LOV or XATTR_NAME_LOV,
- * it's going to create create file with specified
+ * it's going to create file with specified
* component(s), the striping must have not being
* cached in this case;
*
* an existing file, the striping must have been cached
* in this case.
*/
- LASSERT(equi(!strcmp(name, XATTR_LUSTRE_LOV) ||
- !strcmp(name, XATTR_NAME_LOV),
- !lod_dt_obj(dt)->ldo_comp_cached));
+ if (!(fl & LU_XATTR_MERGE))
+ LASSERT(equi(!strcmp(name, XATTR_LUSTRE_LOV) ||
+ !strcmp(name, XATTR_NAME_LOV),
+ !lod_dt_obj(dt)->ldo_comp_cached));
rc = lod_striped_create(env, dt, NULL, NULL, th);
if (rc)
ENTRY;
/* This makes us work on the components of the chosen mirror */
- start_index = lo->ldo_mirrors[pick].lme_start;
- max_comp = lo->ldo_mirrors[pick].lme_end + 1;
+ if (lo->ldo_mirrors) {
+ start_index = lo->ldo_mirrors[pick].lme_start;
+ max_comp = lo->ldo_mirrors[pick].lme_end + 1;
+ } else {
+ start_index = 0;
+ max_comp = lo->ldo_comp_cnt;
+ }
if (lo->ldo_flr_state == LCM_FL_NONE)
LASSERT(start_index == 0 && max_comp == lo->ldo_comp_cnt);
/* We may have added or removed components. If so, we must update the
* start & ends of all the mirrors after the current one, and the end
* of the current mirror. */
- change = max_comp - 1 - lo->ldo_mirrors[pick].lme_end;
- if (change) {
- lo->ldo_mirrors[pick].lme_end += change;
- for (i = pick + 1; i < lo->ldo_mirror_count; i++) {
- lo->ldo_mirrors[i].lme_start += change;
- lo->ldo_mirrors[i].lme_end += change;
+ if (lo->ldo_mirrors) {
+ change = max_comp - 1 - lo->ldo_mirrors[pick].lme_end;
+ if (change) {
+ lo->ldo_mirrors[pick].lme_end += change;
+ for (i = pick + 1; i < lo->ldo_mirror_count; i++) {
+ lo->ldo_mirrors[i].lme_start += change;
+ lo->ldo_mirrors[i].lme_end += change;
+ }
}
}
rc = -ENOTSUPP;
break;
}
+ if (rc == 0)
+ rc = lod_save_layout_gen_intrans(info, lo);
+
out:
RETURN(rc);
}
static int lod_layout_change(const struct lu_env *env, struct dt_object *dt,
struct md_layout_change *mlc, struct thandle *th)
{
+ struct lod_thread_info *info = lod_env_info(env);
struct lu_attr *attr = &lod_env_info(env)->lti_attr;
- struct lu_attr *layout_attr = &lod_env_info(env)->lti_layout_attr;
+ struct lu_attr *layout_attr = &info->lti_layout_attr;
struct lod_object *lo = lod_dt_obj(dt);
int rc;
RETURN(rc);
}
+ rc = lod_check_layout_gen_intrans(info, lo);
+ if (rc > 0) {
+ CDEBUG(D_LAYOUT,
+ "%s: obj "DFID" gen changed from %d to %d in transaction, retry the transaction \n",
+ dt->do_lu.lo_dev->ld_obd->obd_name,
+ PFID(lu_object_fid(&dt->do_lu)),
+ info->lti_gen[rc - 1], lo->ldo_layout_gen);
+ RETURN(-EAGAIN);
+ }
+
rc = lod_striped_create(env, dt, attr, NULL, th);
if (!rc && layout_attr->la_valid & LA_LAYOUT_VERSION) {
layout_attr->la_layout_version |= lo->ldo_layout_gen;
struct mdd_device *mdd = mdo2mdd(md_obj);
struct mdd_object *obj = md2mdd_obj(md_obj);
struct mdd_object *vic = md2mdd_obj(md_vic);
- struct lu_buf *buf = &mdd_env_info(env)->mdi_buf[0];
- struct lu_buf *buf_vic = &mdd_env_info(env)->mdi_buf[1];
+ struct lu_buf *buf;
+ struct lu_buf *buf_vic;
struct lov_mds_md *lmm;
struct thandle *handle;
struct lu_attr *cattr = MDD_ENV_VAR(env, cattr);
struct lu_attr *tattr = MDD_ENV_VAR(env, tattr);
bool is_same_projid;
- int rc, lock_order;
+ int rc;
+ int retried = 0;
+
ENTRY;
rc = mdd_la_get(env, obj, cattr);
is_same_projid = cattr->la_projid == tattr->la_projid;
- lock_order = lu_fid_cmp(mdd_object_fid(obj), mdd_object_fid(vic));
- if (lock_order == 0) /* same fid */
+ if (lu_fid_cmp(mdd_object_fid(obj), mdd_object_fid(vic)) == 0)
RETURN(-EPERM);
-
+retry:
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
+ buf = &mdd_env_info(env)->mdi_buf[0];
+ buf_vic = &mdd_env_info(env)->mdi_buf[1];
+
if (!is_same_projid) {
rc = mdd_declare_attr_set(env, mdd, vic, cattr, handle);
if (rc)
if (rc != 0)
GOTO(stop, rc);
- if (lock_order > 0) {
- mdd_write_lock(env, obj, DT_TGT_CHILD);
- mdd_write_lock(env, vic, DT_TGT_CHILD);
- } else {
- mdd_write_lock(env, vic, DT_TGT_CHILD);
- mdd_write_lock(env, obj, DT_TGT_CHILD);
- }
+ rc = mdd_write_lock_two_objects(env, obj, vic);
+ if (rc)
+ GOTO(stop, rc);
if (!is_same_projid) {
cattr->la_valid = LA_PROJID;
NULL);
(void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle,
NULL);
- EXIT;
out_restore:
if (rc) {
}
out:
- mdd_write_unlock(env, obj);
- mdd_write_unlock(env, vic);
+ mdd_write_unlock_two_objects(env, obj, vic);
stop:
mdd_trans_stop(env, mdd, rc, handle);
lu_buf_free(buf);
lu_buf_free(buf_vic);
+ /**
+ * -EAGAIN means transaction execution phase detect the layout
+ * has been changed by others.
+ */
if (!rc)
(void) mdd_object_pfid_replace(env, obj);
+ else if (rc == -EAGAIN && retried++ < MAX_TRANS_RETRIED)
+ GOTO(retry, retried);
- return rc;
+ RETURN(rc);
}
/**
struct mdd_device *mdd = mdo2mdd(md_obj);
struct mdd_object *obj = md2mdd_obj(md_obj);
struct mdd_object *vic = NULL;
- struct lu_buf *buf = &mdd_env_info(env)->mdi_buf[0];
- struct lu_buf *buf_save = &mdd_env_info(env)->mdi_buf[1];
- struct lu_buf *buf_vic = &mdd_env_info(env)->mdi_buf[2];
+ struct lu_buf *buf;
+ struct lu_buf *buf_save;
+ struct lu_buf *buf_vic;
struct lov_comp_md_v1 *lcm;
struct thandle *handle;
int rc;
bool dom_stripe = false;
+ int retried = 0;
ENTRY;
if (mrd->mrd_obj)
vic = md2mdd_obj(mrd->mrd_obj);
+retry:
+ buf = &mdd_env_info(env)->mdi_buf[0];
+ buf_save = &mdd_env_info(env)->mdi_buf[1];
+ buf_vic = &mdd_env_info(env)->mdi_buf[2];
+
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
if (rc)
GOTO(stop, rc);
- if (vic) {
- /* don't use the same file to save the splitted mirror */
- rc = lu_fid_cmp(mdd_object_fid(obj), mdd_object_fid(vic));
- if (rc == 0)
- GOTO(stop, rc = -EPERM);
-
- if (rc > 0) {
- mdd_write_lock(env, obj, DT_TGT_CHILD);
- mdd_write_lock(env, vic, DT_TGT_CHILD);
- } else {
- mdd_write_lock(env, vic, DT_TGT_CHILD);
- mdd_write_lock(env, obj, DT_TGT_CHILD);
- }
- } else {
- mdd_write_lock(env, obj, DT_TGT_CHILD);
- }
+ rc = mdd_write_lock_two_objects(env, obj, vic);
+ if (rc)
+ GOTO(stop, rc);
/* set obj's layout in @buf */
rc = mdo_xattr_set(env, obj, buf, XATTR_NAME_LOV, LU_XATTR_SPLIT,
}
unlock:
- mdd_write_unlock(env, obj);
- if (vic)
- mdd_write_unlock(env, vic);
+ mdd_write_unlock_two_objects(env, obj, vic);
stop:
rc = mdd_trans_stop(env, mdd, rc, handle);
lu_buf_free(buf);
lu_buf_free(buf_vic);
+ /**
+ * -EAGAIN means transaction execution phase detect the layout
+ * has been changed by others.
+ */
if (!rc)
(void) mdd_object_pfid_replace(env, obj);
+ else if (rc == -EAGAIN && retried++ < MAX_TRANS_RETRIED)
+ GOTO(retry, retried);
- return rc;
+ RETURN(rc);
}
static int mdd_layout_merge_allowed(const struct lu_env *env,
struct thandle *handle;
enum changelog_rec_type cl_type;
enum changelog_rec_flags clf_flags = 0;
+ int retried = 0;
int rc;
+
ENTRY;
+retry:
rc = mdd_la_get(env, mdd_obj, attr);
if (rc)
RETURN(rc);
if (strcmp(XATTR_NAME_HSM, name) == 0) {
rc = mdd_hsm_update_locked(env, obj, buf, handle, &clf_flags);
- if (rc) {
- mdd_write_unlock(env, mdd_obj);
- GOTO(stop, rc);
- }
+ if (rc)
+ GOTO(out_unlock, rc);
}
rc = mdo_xattr_set(env, mdd_obj, buf, name, fl, handle);
+out_unlock:
mdd_write_unlock(env, mdd_obj);
if (rc)
GOTO(stop, rc);
cl_type = mdd_xattr_changelog_type(env, mdd, name);
- if (cl_type < 0)
- GOTO(stop, rc = 0);
-
- rc = mdd_changelog_data_store_xattr(env, mdd, cl_type, clf_flags,
- mdd_obj, name, handle);
+ if (cl_type != CL_NONE)
+ rc = mdd_changelog_data_store_xattr(env, mdd, cl_type,
+ clf_flags, mdd_obj, name,
+ handle);
- EXIT;
stop:
- return mdd_trans_stop(env, mdd, rc, handle);
+ rc = mdd_trans_stop(env, mdd, rc, handle);
+
+ /**
+ * -EAGAIN means transaction execution phase detect the layout
+ * has been changed by others.
+ */
+ if (rc == -EAGAIN && retried++ < MAX_TRANS_RETRIED)
+ GOTO(retry, retried);
+
+ RETURN(rc);
}
static int mdd_declare_xattr_del(const struct lu_env *env,
struct lu_attr *snd_la = MDD_ENV_VAR(env, tattr);
struct mdd_device *mdd = mdo2mdd(obj1);
struct lov_mds_md *fst_lmm, *snd_lmm;
- struct lu_buf *fst_buf = &info->mdi_buf[0];
- struct lu_buf *snd_buf = &info->mdi_buf[1];
- struct lu_buf *fst_hsm_buf = &info->mdi_buf[2];
- struct lu_buf *snd_hsm_buf = &info->mdi_buf[3];
+ struct lu_buf *fst_buf;
+ struct lu_buf *snd_buf;
+ struct lu_buf *fst_hsm_buf;
+ struct lu_buf *snd_hsm_buf;
struct ost_id *saved_oi = NULL;
struct thandle *handle;
struct mdd_object *dom_o = NULL, *vlt_o = NULL;
__u32 fst_gen, snd_gen, saved_gen;
int fst_fl;
int rc, rc2;
+ int retried = 0;
ENTRY;
BUILD_BUG_ON(ARRAY_SIZE(info->mdi_buf) < 4);
+retry:
+ fst_buf = &info->mdi_buf[0];
+ snd_buf = &info->mdi_buf[1];
+ fst_hsm_buf = &info->mdi_buf[2];
+ snd_hsm_buf = &info->mdi_buf[3];
+
memset(info->mdi_buf, 0, sizeof(info->mdi_buf));
/* we have to sort the 2 obj, so locking will always
if (rc != 0)
GOTO(stop, rc);
- /* objects are already sorted */
- mdd_write_lock(env, fst_o, DT_TGT_CHILD);
- mdd_write_lock(env, snd_o, DT_TGT_CHILD);
+ rc = mdd_write_lock_two_objects(env, fst_o, snd_o);
+ if (rc < 0)
+ GOTO(stop, rc);
if (!mdd_object_exists(fst_o))
GOTO(unlock, rc = -ENOENT);
}
unlock:
- mdd_write_unlock(env, snd_o);
- mdd_write_unlock(env, fst_o);
+ mdd_write_unlock_two_objects(env, fst_o, snd_o);
stop:
rc = mdd_trans_stop(env, mdd, rc, handle);
if (!rc) {
(void) mdd_object_pfid_replace(env, fst_o);
(void) mdd_object_pfid_replace(env, snd_o);
+ } else if (rc == -EAGAIN && retried++ < MAX_TRANS_RETRIED) {
+ /**
+ * -EAGAIN means transaction execution phase detect the layout
+ * has been changed by others.
+ */
+ GOTO(retry, retried);
}
- return rc;
+
+ RETURN(rc);
}
static int mdd_declare_layout_change(const struct lu_env *env,
GOTO(out, rc);
rc = mdd_changelog_data_store(env, mdd, CL_FLRW, 0, obj, handle, NULL);
- if (rc)
- GOTO(out, rc);
-
- EXIT;
out:
- return rc;
+ RETURN(rc);
}
/**
fl, handle);
}
mdd_write_unlock(env, obj);
- if (rc)
- GOTO(out, rc);
-
- EXIT;
out:
- return rc;
+ RETURN(rc);
}
/**
/* it needs a sync tx to make FLR to work properly */
handle->th_sync = 1;
+ mdd_write_lock(env, obj, DT_TGT_CHILD);
rc = mdo_layout_change(env, obj, mlc, handle);
+ mdd_write_unlock(env, obj);
if (rc)
GOTO(out, rc);
rc = mdd_changelog_data_store(env, mdd, CL_RESYNC, 0, obj, handle,
NULL);
- if (rc)
- GOTO(out, rc);
- EXIT;
out:
- return rc;
+ RETURN(rc);
}
/**
struct lov_comp_md_v1 *lcm;
struct thandle *handle;
int flr_state;
+ int retried = 0;
int rc;
ENTRY;
RETURN(-ENOTSUPP);
}
+retry:
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
RETURN(PTR_ERR(handle));
out:
mdd_trans_stop(env, mdd, rc, handle);
lu_buf_free(buf);
+
+ /**
+ * -EAGAIN means transaction execution phase detect the layout
+ * has been changed by others.
+ */
+ if (rc == -EAGAIN && retried++ < MAX_TRANS_RETRIED)
+ GOTO(retry, retried);
+
return rc;
}