RETURN(rc);
}
-static bool lod_obj_attr_set_comp_skip_cb(const struct lu_env *env,
- struct lod_object *lo, int comp_idx,
- struct lod_obj_stripe_cb_data *data)
-{
- struct lod_layout_component *lod_comp = &lo->ldo_comp_entries[comp_idx];
- bool skipped = false;
-
- if (!(data->locd_attr->la_valid & LA_LAYOUT_VERSION))
- return skipped;
-
- switch (lo->ldo_flr_state) {
- case LCM_FL_WRITE_PENDING: {
- int i;
-
- /* skip stale components */
- if (lod_comp->llc_flags & LCME_FL_STALE) {
- skipped = true;
- break;
- }
-
- /* skip valid and overlapping components, therefore any
- * attempts to write overlapped components will never succeed
- * because client will get EINPROGRESS. */
- for (i = 0; i < lo->ldo_comp_cnt; i++) {
- if (i == comp_idx)
- continue;
-
- if (lo->ldo_comp_entries[i].llc_flags & LCME_FL_STALE)
- continue;
-
- if (lu_extent_is_overlapped(&lod_comp->llc_extent,
- &lo->ldo_comp_entries[i].llc_extent)) {
- skipped = true;
- break;
- }
- }
- break;
- }
- default:
- LASSERTF(0, "impossible: %d\n", lo->ldo_flr_state);
- case LCM_FL_SYNC_PENDING:
- break;
- }
-
- CDEBUG(D_LAYOUT, DFID": %s to set component %x to version: %u\n",
- PFID(lu_object_fid(&lo->ldo_obj.do_lu)),
- skipped ? "skipped" : "chose", lod_comp->llc_id,
- data->locd_attr->la_layout_version);
-
- return skipped;
-}
-
static inline int
lod_obj_stripe_attr_set_cb(const struct lu_env *env, struct lod_object *lo,
struct dt_object *dt, struct thandle *th,
data.locd_attr = attr;
data.locd_declare = false;
- data.locd_comp_skip_cb = lod_obj_attr_set_comp_skip_cb;
data.locd_stripe_cb = lod_obj_stripe_attr_set_cb;
rc = lod_obj_for_each_stripe(env, lo, th, &data);
}
struct thandle *th)
{
struct lod_thread_info *info = lod_env_info(env);
+ struct lu_attr *layout_attr = &info->lti_layout_attr;
struct lod_layout_component *lod_comp;
struct lu_extent extent = { 0 };
int rc;
if (rc)
GOTO(out, rc);
+ layout_attr->la_valid = LA_LAYOUT_VERSION;
+ layout_attr->la_layout_version = 0;
+ if (mlc->mlc_opc == MD_LAYOUT_RESYNC)
+ layout_attr->la_layout_version = LU_LAYOUT_RESYNC;
+ rc = lod_declare_attr_set(env, &lo->ldo_obj, layout_attr, th);
+ if (rc)
+ GOTO(out, rc);
+
out:
if (rc)
lod_striping_free(env, lo);
struct thandle *th)
{
struct lod_thread_info *info = lod_env_info(env);
+ struct lu_attr *layout_attr = &info->lti_layout_attr;
struct lod_layout_component *lod_comp;
struct lu_extent extent = { 0 };
int primary = -1;
GOTO(out, rc);
lod_obj_inc_layout_gen(lo);
+
+ /* 3. transfer layout version to OST objects.
+ * transfer new layout version to OST objects so that stale writes
+ * can be denied. It also ends an era of writing by setting
+ * LU_LAYOUT_RESYNC. Normal client can never use this bit to
+ * send write RPC; only resync RPCs could do it. */
+ layout_attr->la_valid = LA_LAYOUT_VERSION;
+ layout_attr->la_layout_version = 0;
+ if (mlc->mlc_opc == MD_LAYOUT_RESYNC)
+ layout_attr->la_layout_version = LU_LAYOUT_RESYNC;
+ rc = lod_declare_attr_set(env, &lo->ldo_obj, layout_attr, th);
+ if (rc)
+ GOTO(out, rc);
out:
if (rc)
lod_striping_free(env, lo);
struct thandle *th)
{
struct lod_thread_info *info = lod_env_info(env);
+ struct lu_attr *layout_attr = &info->lti_layout_attr;
unsigned sync_components = 0;
unsigned resync_components = 0;
int i;
lo->ldo_flr_state = LCM_FL_RDONLY;
lod_obj_inc_layout_gen(lo);
+ layout_attr->la_valid = LA_LAYOUT_VERSION;
+ layout_attr->la_layout_version = 0;
+ rc = lod_declare_attr_set(env, &lo->ldo_obj, layout_attr, th);
+ if (rc)
+ GOTO(out, rc);
+
info->lti_buf.lb_len = lod_comp_md_size(lo, false);
rc = lod_sub_declare_xattr_set(env, lod_object_child(lo),
&info->lti_buf, XATTR_NAME_LOV, 0, th);
struct md_layout_change *mlc, struct thandle *th)
{
struct lu_attr *attr = &lod_env_info(env)->lti_attr;
+ struct lu_attr *layout_attr = &lod_env_info(env)->lti_layout_attr;
+ struct lod_object *lo = lod_dt_obj(dt);
int rc;
-
ENTRY;
if (S_ISDIR(dt->do_lu.lo_header->loh_attr)) {
}
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;
+ rc = lod_attr_set(env, dt, layout_attr, th);
+ }
RETURN(rc);
}
PFID(lu_object_fid(&fo->ofo_obj.do_lu)),
ff->ff_layout_version, oa->o_layout_version);
+ /**
+ * resync write from client on non-primary objects and
+ * resync start from MDS on primary objects will contain
+ * LU_LAYOUT_RESYNC flag in the @oa.
+ *
+ * The layout version checking for write/punch from client
+ * happens in ofd_verify_layout_version() before coming to
+ * here, so that resync with smaller layout version client
+ * will be rejected there, the biggest resync version will
+ * be recorded in the OFD objects.
+ */
if (ff->ff_layout_version & LU_LAYOUT_RESYNC) {
/* this opens a new era of writing */
ff->ff_layout_version = 0;
ff->ff_range = 0;
} else if (oa->o_layout_version > ff->ff_layout_version) {
ff->ff_range = max_t(__u32, ff->ff_range,
- oa->o_layout_version -
- ff->ff_layout_version);
+ oa->o_layout_version - ff->ff_layout_version);
}
}
run_test 35 "allow to write to mirrored files"
get_file_layout_version() {
- local tf=$1
- local flv=$($LFS getstripe $tf | awk '/lcm_layout_gen/{print $2}')
-
- echo -n $flv
+ $LFS getstripe $1 | awk '/lcm_layout_gen/{print $2}'
}
get_ost_layout_version() {
- local tf=$1
- local olv=$($MULTIOP $tf oXc | awk '/ostlayoutversion/{print $2}')
-
- echo -n $flv
+ $MULTIOP $1 oXc | awk '/ostlayoutversion/{print $2}'
}
verify_ost_layout_version() {
test_36b() {
local tf=$DIR/$tfile
- (( OSTCOUNT < 2 )) && skip "need >= 2 OSTs" && return
+ (( OST1_VERSION >= $(version_code 2.15.51) ||
+ OST1_VERSION < $(version_code 2.15) &&
+ OST1_VERSION >= $(version_code 2.14.0.43) )) ||
+ skip "Need OST version at least 2.14.0.43(es60) or 2.51.51(master)"
+
+ (( OSTCOUNT >= 2 )) || skip "need >= 2 OSTs"
# create 2 mirrors using different OSTs
$LFS setstripe -N -c1 -i0 --flags=prefer -N -c1 -i1 $tf ||
test_36c() {
local tf=$DIR/$tfile
- (( OSTCOUNT < 2 )) && skip "need >= 2 OSTs" && return
+ (( OST1_VERSION >= $(version_code 2.15.51) ||
+ OST1_VERSION < $(version_code 2.15) &&
+ OST1_VERSION >= $(version_code 2.14.0.43) )) ||
+ skip "Need OST version at least 2.14.0.43(es60) or 2.51.51(master)"
+
+ (( OSTCOUNT >= 2 )) || skip "need >= 2 OSTs"
# create 2 mirrors using different OSTs
$LFS setstripe -N -c1 -i0 --flags=prefer -N -c1 -i1 $tf ||
test_36d() {
local tf=$DIR/$tfile
+ (( OST1_VERSION >= $(version_code 2.15.51) ||
+ OST1_VERSION < $(version_code 2.15) &&
+ OST1_VERSION >= $(version_code 2.14.0.43) )) ||
+ skip "Need OST version at least 2.14.0.43(es60) or 2.51.51(master)"
+
echo " ** create $tf"
$LFS mirror create -N $tf || error "create $tf failed"
for i in 1 2; do
- echo " ** mirror extend $tf"
+ echo " ** mirror extend $tf ($i/2)"
$LFS mirror extend -N $tf || error "mirror extend $tf failed"
flv=$(get_file_layout_version $tf)
olv=$(get_ost_layout_version $tf)
done
for i in 1 2; do
- echo " ** write $tf"
+ echo " ** write $tf ($i/2)"
dd if=/dev/zero of=$tf bs=1k count=1 || error "write $tf failed"
flv=$(get_file_layout_version $tf)
olv=$(get_ost_layout_version $tf)
echo " flv=$flv olv=$olv"
for i in 1 2; do
- echo " ** truncate $tf"
- $TRUNCATE $tf $((1024 * 1024)) || error "truncate $tf fails"
+ echo " ** truncate $tf ($i/2)"
+ $TRUNCATE $tf $((1024 * 1024)) || error "truncate $tf failed"
flv=$(get_file_layout_version $tf)
olv=$(get_ost_layout_version $tf)
echo " flv=$flv olv=$olv"
error "truncate update OST layout failed $flv/$olv"
done
+ echo " ** resync $tf"
+ $LFS mirror resync $tf || error "mirror resync $tf failed"
+ flv=$(get_file_layout_version $tf)
+ olv=$(get_ost_layout_version $tf)
+ echo " flv=$flv olv=$olv"
+
for i in 1 2; do
- echo " ** write $tf"
+ echo " ** write $tf ($i/2)"
dd if=/dev/zero of=$tf bs=1k count=1 || error "write $tf failed"
flv=$(get_file_layout_version $tf)
olv=$(get_ost_layout_version $tf)