Whamcloud - gitweb
LU-10177 lfs: support DOM-to-OST migration 79/32979/8
authorMikhail Pershin <mpershin@whamcloud.com>
Fri, 10 Aug 2018 16:20:52 +0000 (19:20 +0300)
committerOleg Drokin <green@whamcloud.com>
Fri, 5 Oct 2018 22:25:51 +0000 (22:25 +0000)
Migraton of DoM file to an OST file is possible with
'lfs migrate' command in general but would cause space loss
on MDS, because DOM local inode blocks are not deleted.
Patch doesn the following:
- adds truncate for local MDS inode after migration.
- check and prevent migration from non-DOM to DOM file,
  that will be done later with mirroring.
- prohibit 'lfs swap_layouts' command if either file has
  DOM component, 'lfs migrate' should be used instead

Signed-off-by: Mikhail Pershin <mpershin@whamcloud.com>
Change-Id: I1ce7b09eefab5e13f81af30c007475c927bd2874
Reviewed-on: https://review.whamcloud.com/32979
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/mdd/mdd_object.c
lustre/tests/sanity.sh

index e2c39af..2d28256 100644 (file)
@@ -2191,29 +2191,65 @@ static inline int mdd_set_lmm_gen(struct lov_mds_md *lmm, __u32 *gen)
        return mdd_lmm_gen(lmm, gen, false);
 }
 
+static int mdd_dom_data_truncate(const struct lu_env *env,
+                                struct mdd_device *mdd, struct mdd_object *mo)
+{
+       struct thandle *th;
+       struct dt_object *dom;
+       int rc;
+
+       dom = dt_object_locate(mdd_object_child(mo), mdd->mdd_bottom);
+       if (!dom)
+               GOTO(out, rc = -ENODATA);
+
+       th = dt_trans_create(env, mdd->mdd_bottom);
+       if (IS_ERR(th))
+               GOTO(out, rc = PTR_ERR(th));
+
+       rc = dt_declare_punch(env, dom, 0, OBD_OBJECT_EOF, th);
+       if (rc)
+               GOTO(stop, rc);
+
+       rc = dt_trans_start_local(env, mdd->mdd_bottom, th);
+       if (rc != 0)
+               GOTO(stop, rc);
+
+       rc = dt_punch(env, dom, 0, OBD_OBJECT_EOF, th);
+stop:
+       dt_trans_stop(env, mdd->mdd_bottom, th);
+out:
+       /* Ignore failure but report the error */
+       if (rc)
+               CERROR("%s: "DFID" can't truncate DOM inode data, rc = %d\n",
+                      mdd_obj_dev_name(mo), PFID(mdo2fid(mo)), rc);
+       return rc;
+}
+
 /**
  * swap layouts between 2 lustre objects
  */
 static int mdd_swap_layouts(const struct lu_env *env, struct md_object *obj1,
                            struct md_object *obj2, __u64 flags)
 {
-       struct mdd_thread_info  *info = mdd_env_info(env);
-       struct mdd_object       *fst_o = md2mdd_obj(obj1);
-       struct mdd_object       *snd_o = md2mdd_obj(obj2);
-       struct lu_attr          *fst_la = MDD_ENV_VAR(env, cattr);
-       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->mti_buf[0];
-       struct lu_buf           *snd_buf = &info->mti_buf[1];
-       struct lu_buf           *fst_hsm_buf = &info->mti_buf[2];
-       struct lu_buf           *snd_hsm_buf = &info->mti_buf[3];
-       struct ost_id           *saved_oi = NULL;
-       struct thandle          *handle;
-       __u32                    fst_gen, snd_gen, saved_gen;
-       int                      fst_fl;
-       int                      rc;
-       int                      rc2;
+       struct mdd_thread_info *info = mdd_env_info(env);
+       struct mdd_object *fst_o = md2mdd_obj(obj1);
+       struct mdd_object *snd_o = md2mdd_obj(obj2);
+       struct lu_attr *fst_la = MDD_ENV_VAR(env, cattr);
+       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->mti_buf[0];
+       struct lu_buf *snd_buf = &info->mti_buf[1];
+       struct lu_buf *fst_hsm_buf = &info->mti_buf[2];
+       struct lu_buf *snd_hsm_buf = &info->mti_buf[3];
+       struct ost_id *saved_oi = NULL;
+       struct thandle *handle;
+       struct mdd_object *dom_o = NULL;
+       __u64 domsize_dom, domsize_vlt;
+       __u32 fst_gen, snd_gen, saved_gen;
+       int fst_fl;
+       int rc, rc2;
+
        ENTRY;
 
        CLASSERT(ARRAY_SIZE(info->mti_buf) >= 4);
@@ -2257,16 +2293,49 @@ static int mdd_swap_layouts(const struct lu_env *env, struct md_object *obj1,
        if (rc < 0 && rc != -ENODATA)
                GOTO(stop, rc);
 
-       /* check if file is DoM, it can be migrated only to another DoM layout
-        * with the same DoM component size
+       /* check if file has DoM. DoM file can be migrated only to another
+        * DoM layout with the same DoM component size or to an non-DOM
+        * layout. After migration to OSTs layout, local MDT inode data
+        * should be truncated.
+        * Objects are sorted by FIDs, considering that original file's FID
+        * is always smaller the snd_o is always original file we are migrating
+        * from.
+        */
+       domsize_dom = mdd_lmm_dom_size(snd_buf->lb_buf);
+       domsize_vlt = mdd_lmm_dom_size(fst_buf->lb_buf);
+
+       /* Only migration is supported for DoM files, not 'swap_layouts' so
+        * target file must be volatile and orphan.
         */
-       if (mdd_lmm_dom_size(fst_buf->lb_buf) !=
-           mdd_lmm_dom_size(snd_buf->lb_buf)) {
+       if (fst_o->mod_flags & (ORPHAN_OBJ | VOLATILE_OBJ)) {
+               dom_o = domsize_dom ? snd_o : NULL;
+       } else if (snd_o->mod_flags & (ORPHAN_OBJ | VOLATILE_OBJ)) {
+               swap(domsize_dom, domsize_vlt);
+               dom_o = domsize_dom ? fst_o : NULL;
+       } else if (domsize_dom > 0 || domsize_vlt > 0) {
+               /* 'lfs swap_layouts' case, neither file should have DoM */
+               rc = -EOPNOTSUPP;
+               CDEBUG(D_LAYOUT, "cannot swap layouts with DOM component, "
+                      "use migration instead: rc = %d\n", rc);
+               GOTO(stop, rc);
+       }
+
+       if (domsize_vlt > 0 && domsize_dom == 0) {
+               rc = -EOPNOTSUPP;
+               CDEBUG(D_LAYOUT, "cannot swap layout for "DFID": OST to DOM "
+                      "migration is not supported: rc = %d\n",
+                      PFID(mdo2fid(snd_o)), rc);
+               GOTO(stop, rc);
+       } else if (domsize_vlt > 0 && domsize_dom != domsize_vlt) {
                rc = -EOPNOTSUPP;
                CDEBUG(D_LAYOUT, "cannot swap layout for "DFID": new layout "
-                      "must have the same DoM component: rc = %d\n",
+                      "must have the same DoM component size: rc = %d\n",
                       PFID(mdo2fid(fst_o)), rc);
                GOTO(stop, rc);
+       } else if (domsize_vlt > 0) {
+               /* Migration with the same DOM component size, no need to
+                * truncate local data, it is still being used */
+               dom_o = NULL;
        }
 
        /* swapping 2 non existant layouts is a success */
@@ -2471,6 +2540,10 @@ out_restore:
 stop:
        rc = mdd_trans_stop(env, mdd, rc, handle);
 
+       /* Truncate local DOM data if all went well */
+       if (!rc && dom_o)
+               mdd_dom_data_truncate(env, mdd, dom_o);
+
        mdd_write_unlock(env, snd_o);
        mdd_write_unlock(env, fst_o);
 
index 2ddbef3..2ff71db 100755 (executable)
@@ -17286,6 +17286,140 @@ test_271f() {
 }
 run_test 271f "DoM: read on open (200K file and read tail)"
 
+test_272a() {
+       [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.50) ] &&
+               skip "Need MDS version at least 2.11.50"
+
+       local dom=$DIR/$tdir/dom
+       mkdir -p $DIR/$tdir
+
+       $LFS setstripe -E 256K -L mdt -E -1 -c1 $dom
+       dd if=/dev/urandom of=$dom bs=512K count=1 ||
+               error "failed to write data into $dom"
+       local old_md5=$(md5sum $dom)
+
+       $LFS migrate -E 256K -L mdt -E -1 -c2 $dom ||
+               error "failed to migrate to the same DoM component"
+
+       [ $($LFS getstripe -c $dom) -eq 2 ] ||
+               error "layout was not changed silently"
+
+       local new_md5=$(md5sum $dom)
+
+       [ "$old_md5" != "$new_md5" ] &&
+               error "md5sum differ: $old_md5, $new_md5"
+       return 0
+}
+run_test 272a "DoM migration: new layout with the same DOM component"
+
+test_272b() {
+       [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.50) ] &&
+               skip "Need MDS version at least 2.11.50"
+
+       local dom=$DIR/$tdir/dom
+       mkdir -p $DIR/$tdir
+       $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
+
+       local mdtidx=$($LFS getstripe -m $dom)
+       local mdtname=MDT$(printf %04x $mdtidx)
+       local facet=mds$((mdtidx + 1))
+
+       local mdtfree1=$(do_facet $facet \
+               lctl get_param -n osd*.*$mdtname.kbytesfree)
+       dd if=/dev/urandom of=$dom bs=2M count=1 ||
+               error "failed to write data into $dom"
+       local old_md5=$(md5sum $dom)
+       cancel_lru_locks mdc
+       local mdtfree1=$(do_facet $facet \
+               lctl get_param -n osd*.*$mdtname.kbytesfree)
+
+       $LFS migrate -c2 $dom ||
+               error "failed to migrate to the new composite layout"
+       [ $($LFS getstripe -L $dom) == 'mdt' ] &&
+               error "MDT stripe was not removed"
+
+       cancel_lru_locks mdc
+       local new_md5=$(md5sum $dom)
+       [ "$old_md5" != "$new_md5" ] &&
+               error "$old_md5 != $new_md5"
+
+       # Skip free space checks with ZFS
+       if [ "$(facet_fstype $facet)" != "zfs" ]; then
+               local mdtfree2=$(do_facet $facet \
+                               lctl get_param -n osd*.*$mdtname.kbytesfree)
+               [ $mdtfree2 -gt $mdtfree1 ] ||
+                       error "MDT space is not freed after migration"
+       fi
+       return 0
+}
+run_test 272b "DoM migration: DOM file to the OST-striped file (plain)"
+
+test_272c() {
+       [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.50) ] &&
+               skip "Need MDS version at least 2.11.50"
+
+       local dom=$DIR/$tdir/$tfile
+       mkdir -p $DIR/$tdir
+       $LFS setstripe -E 1M -L mdt -E -1 -c1 $dom
+
+       local mdtidx=$($LFS getstripe -m $dom)
+       local mdtname=MDT$(printf %04x $mdtidx)
+       local facet=mds$((mdtidx + 1))
+
+       dd if=/dev/urandom of=$dom bs=2M count=1 oflag=direct ||
+               error "failed to write data into $dom"
+       local old_md5=$(md5sum $dom)
+       cancel_lru_locks mdc
+       local mdtfree1=$(do_facet $facet \
+               lctl get_param -n osd*.*$mdtname.kbytesfree)
+
+       $LFS migrate -E 2M -c1 -E -1 -c2 $dom ||
+               error "failed to migrate to the new composite layout"
+       [ $($LFS getstripe -L $dom) == 'mdt' ] &&
+               error "MDT stripe was not removed"
+
+       cancel_lru_locks mdc
+       local new_md5=$(md5sum $dom)
+       [ "$old_md5" != "$new_md5" ] &&
+               error "$old_md5 != $new_md5"
+
+       # Skip free space checks with ZFS
+       if [ "$(facet_fstype $facet)" != "zfs" ]; then
+               local mdtfree2=$(do_facet $facet \
+                               lctl get_param -n osd*.*$mdtname.kbytesfree)
+               [ $mdtfree2 -gt $mdtfree1 ] ||
+                       error "MDS space is not freed after migration"
+       fi
+       return 0
+}
+run_test 272c "DoM migration: DOM file to the OST-striped file (composite)"
+
+test_273a() {
+       [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.11.50) ] &&
+               skip "Need MDS version at least 2.11.50"
+
+       # Layout swap cannot be done if either file has DOM component,
+       # this will never be supported, migration should be used instead
+
+       local dom=$DIR/$tdir/$tfile
+       mkdir -p $DIR/$tdir
+
+       $LFS setstripe -c2 ${dom}_plain
+       $LFS setstripe -E 1M -L mdt -E -1 -c2 ${dom}_dom
+       $LFS swap_layouts ${dom}_plain ${dom}_dom &&
+               error "can swap layout with DoM component"
+       $LFS swap_layouts ${dom}_dom ${dom}_plain &&
+               error "can swap layout with DoM component"
+
+       $LFS setstripe -E 1M -c1 -E -1 -c2 ${dom}_comp
+       $LFS swap_layouts ${dom}_comp ${dom}_dom &&
+               error "can swap layout with DoM component"
+       $LFS swap_layouts ${dom}_dom ${dom}_comp &&
+               error "can swap layout with DoM component"
+       return 0
+}
+run_test 273a "DoM: layout swapping should fail with DOM"
+
 test_275() {
        remote_ost_nodsh && skip "remote OST with nodsh"
        [ $(lustre_version_code ost1) -lt $(version_code 2.10.57) ] &&