Whamcloud - gitweb
LU-11510 lfs: migrate a composite layout file correctly 82/36082/10
authorEmoly Liu <emoly@whamcloud.com>
Wed, 26 Feb 2020 14:12:59 +0000 (22:12 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 5 Mar 2020 22:35:54 +0000 (22:35 +0000)
The patch fixes the following issues:
- in function migrate_open_files(), "layout" pointer should be used
  instead of "param" pointer to tell whether a comp file should be
  created or not, because "param" pointer is always not null and
  the composite layout file will never be created;
- make --copy and --yaml options work correctly in lfs_migrate tool;
- when a composite layout file is migrated, "--copy" option will be
  added to preserve its layout in both lfs_migrate and "lfs migrate",
  and in such situation, pool name will be saved as well;
- when a file is restriped with -R option by lfs_migrate, the file
  will be set with its parent's stripe by default, by adding
  "--copy $parent_dir" option;
- do some code cleanup in lfs_migrate and sanity.sh test_56wb/c

sanity.sh test_56xd/xe are added to verify this patch.

Signed-off-by: Emoly Liu <emoly@whamcloud.com>
Change-Id: I85779c69e74444eb869f28add4363ad3a6835b97
Reviewed-on: https://review.whamcloud.com/36082
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/scripts/lfs_migrate
lustre/tests/sanity.sh
lustre/utils/lfs.c

index 939349c..6e78e99 100755 (executable)
@@ -113,6 +113,7 @@ OPT_DEBUG=false
 OPT_DRYRUN=false
 OPT_FILE=()
 OPT_LAYOUT=()
 OPT_DRYRUN=false
 OPT_FILE=()
 OPT_LAYOUT=()
+OPT_COMP=false
 OPT_NO_RSYNC=false
 OPT_NO_DIRECT=false
 OPT_NULL=false
 OPT_NO_RSYNC=false
 OPT_NO_DIRECT=false
 OPT_NULL=false
@@ -151,7 +152,7 @@ while [ -n "$*" ]; do
           OPT_PASSTHROUGH+=("$arg");;
        --rsync) OPT_RSYNC=true;;
        --no-rsync) OPT_NO_RSYNC=true;;
           OPT_PASSTHROUGH+=("$arg");;
        --rsync) OPT_RSYNC=true;;
        --no-rsync) OPT_NO_RSYNC=true;;
-       --copy|--yaml|--file)
+       --copy|--yaml|--file) OPT_COMP=true;
           # these options have files as arguments, pass both through
           OPT_LAYOUT+="$arg $2 "; shift;;
        --auto-stripe|-A) OPT_AUTOSTRIPE=true;;
           # these options have files as arguments, pass both through
           OPT_LAYOUT+="$arg $2 "; shift;;
        --auto-stripe|-A) OPT_AUTOSTRIPE=true;;
@@ -167,22 +168,18 @@ while [ -n "$*" ]; do
        shift
 done
 
        shift
 done
 
-if $OPT_RESTRIPE && [ -n "$OPT_LAYOUT" ]; then
-       echo "$PROG: Options $OPT_LAYOUT cannot be used with the -R option" 1>&2
+if $OPT_RESTRIPE || $OPT_AUTOSTRIPE && [ -n "$OPT_LAYOUT" ]; then
+       echo "$PROG error: Options '$OPT_LAYOUT' can't be used with -R or -A" \
+               1>&2
        exit 1
 elif $OPT_RESTRIPE && [[ "$OPT_STRIPE_COUNT" || "$OPT_STRIPE_SIZE" ]]; then
        exit 1
 elif $OPT_RESTRIPE && [[ "$OPT_STRIPE_COUNT" || "$OPT_STRIPE_SIZE" ]]; then
-       echo "$(basename $0): Options -c <stripe_count> and -S <stripe_size> "\
-       "may not be specified at the same time as the -R option." 1>&2
+       echo "$PROG error: Option -R can't be used with -c or -S" 1>&2
        exit 1
 elif $OPT_AUTOSTRIPE && [ -n "$OPT_STRIPE_COUNT" ]; then
        exit 1
 elif $OPT_AUTOSTRIPE && [ -n "$OPT_STRIPE_COUNT" ]; then
-       echo ""
-       echo "$(basename $0) error: The -c <stripe_count> option may not" 1>&2
-       echo "be specified at the same time as the -A option." 1>&2
+       echo "$PROG error: Option -A can't be used with -c" 1>&2
        exit 1
 elif $OPT_AUTOSTRIPE && $OPT_RESTRIPE; then
        exit 1
 elif $OPT_AUTOSTRIPE && $OPT_RESTRIPE; then
-       echo ""
-       echo "$(basename $0) error: The -A option may not be specified at" 1>&2
-       echo "the same time as the -R option." 1>&2
+       echo "$PROG error: Option -A can't be used with -R" 1>&2
        exit 1
 fi
 
        exit 1
 fi
 
@@ -292,12 +289,6 @@ lfs_migrate() {
 
        while IFS='' read -d '' OLDNAME; do
                local hlinks=()
 
        while IFS='' read -d '' OLDNAME; do
                local hlinks=()
-               local stripe_size="$OPT_STRIPE_SIZE"
-               local stripe_count="$OPT_STRIPE_COUNT"
-               local parent_count=""
-               local parent_size=""
-               local stripe_pool="${OPT_POOL#-p }"
-               local mirror_count
                local layout
                local fid
 
                local layout
                local fid
 
@@ -373,8 +364,34 @@ lfs_migrate() {
                        fi
                fi
 
                        fi
                fi
 
+               local stripe_size="$OPT_STRIPE_SIZE"
+               local stripe_count="$OPT_STRIPE_COUNT"
+               local stripe_opts="-N --comp-count -c -S -p -y"
+               local parent_count=""
+               local parent_size=""
+               local stripe_pool="${OPT_POOL#-p }"
+               local mirror_count=1
+               local comp_count=0
+               # avoid multiple getstripe calls
+               #   lcm_mirror_count:  1
+               #   lcm_entry_count:   0
+               #      lmm_stripe_count:  1
+               #      lmm_stripe_size:   1048576
+               #      lmm_pool:          pool_abc
+               local l_mirror_count=0
+               local l_comp_count=1
+               local l_stripe_count=2
+               local l_stripe_size=3
+               local l_stripe_pool=4
+               local layout_info=($($LFS getstripe $stripe_opts $OLDNAME \
+                       2>/dev/null | awk '{ print $2 }'))
+
+               layout="${OPT_PASSTHROUGH[@]} "
+
                if $OPT_RESTRIPE; then
                        UNLINK=""
                if $OPT_RESTRIPE; then
                        UNLINK=""
+                       layout+="--copy $(dirname $OLDNAME)"
+                       OPT_COMP=true
                else
                        # If rsync copies Lustre xattrs properly in the future
                        # (i.e. before the file data, so that it preserves
                else
                        # If rsync copies Lustre xattrs properly in the future
                        # (i.e. before the file data, so that it preserves
@@ -382,8 +399,8 @@ lfs_migrate() {
                        UNLINK="-u"
 
                        [ -n "$OPT_POOL" ] ||
                        UNLINK="-u"
 
                        [ -n "$OPT_POOL" ] ||
-                        stripe_pool=$($LFS getstripe -p "$OLDNAME" 2>/dev/null)
-                       mirror_count=$($LFS getstripe -N "$OLDFILE" 2>/dev/null)
+                               stripe_pool=${layout_info[$l_stripe_pool]}
+                       mirror_count=${layout_info[$l_mirror_count]}
 
                        if $OPT_AUTOSTRIPE; then
                                local filekb=$((${nlink_type[$nlink_idx_size]} /
 
                        if $OPT_AUTOSTRIPE; then
                                local filekb=$((${nlink_type[$nlink_idx_size]} /
@@ -395,11 +412,10 @@ lfs_migrate() {
                                [ $stripe_count -lt 1 ] && stripe_count=1
                        else
                                [ -n "$stripe_count" ] ||
                                [ $stripe_count -lt 1 ] && stripe_count=1
                        else
                                [ -n "$stripe_count" ] ||
-                                       stripe_count=$($LFS getstripe -c "$OLDNAME" \
-                                               2> /dev/null)
+                                       stripe_count=${layout_info[$l_stripe_count]}
                        fi
                        [ -n "$stripe_size" ] ||
                        fi
                        [ -n "$stripe_size" ] ||
-                               stripe_size=$($LFS getstripe -S "$OLDNAME" 2> /dev/null)
+                               stripe_size=${layout_info[$l_stripe_size]}
 
                        [ -z "$stripe_count" -o -z "$stripe_size" ] && UNLINK=""
                fi
 
                        [ -z "$stripe_count" -o -z "$stripe_size" ] && UNLINK=""
                fi
@@ -407,26 +423,22 @@ lfs_migrate() {
                if $OPT_DEBUG; then
                        local parent_count
                        local parent_size
                if $OPT_DEBUG; then
                        local parent_count
                        local parent_size
+                       local parent_layout
 
                        if $OPT_RESTRIPE; then
 
                        if $OPT_RESTRIPE; then
-                               parent_count=$($LFS getstripe -c \
-                                              $(dirname "$OLDNAME") 2> \
-                                              /dev/null)
-                               parent_size=$($LFS getstripe -S \
-                                             $(dirname "$OLDNAME") 2> \
-                                             /dev/null)
-                               stripe_pool=$($LFS getstripe --pool \
-                                             $(dirname "$OLDNAME") 2> \
-                                             /dev/null)
-                               mirror_count=$($LFS getstripe -N \
-                                              $(dirname "$OLDFILE") 2> \
-                                              /dev/null)
+                               parent_layout=($($LFS getstripe $stripe_opts \
+                                       -d $(dirname $OLDNAME) 2>/dev/null |
+                                               awk '{print $2 }'))
+                               parent_count=${parent_layout[$l_stripe_count]}
+                               parent_size=${parent_layout[$l_stripe_size]}
+                               stripe_pool=${parent_layout[$l_stripe_pool]}
+                               mirror_count=${parent_layout[$l_mirror_count]}
                        fi
 
                        $ECHO -n "stripe_count=${stripe_count:-$parent_count},stripe_size=${stripe_size:-$parent_size}"
                        [ -n "$stripe_pool" ] &&
                                $ECHO -n ",pool=${stripe_pool}"
                        fi
 
                        $ECHO -n "stripe_count=${stripe_count:-$parent_count},stripe_size=${stripe_size:-$parent_size}"
                        [ -n "$stripe_pool" ] &&
                                $ECHO -n ",pool=${stripe_pool}"
-                       [ -n "$mirror_count" ] &&
+                       [[ $mirror_count -gt 1 ]] &&
                                $ECHO -n ",mirror_count=${mirror_count}"
                        $ECHO -n " "
                fi
                                $ECHO -n ",mirror_count=${mirror_count}"
                        $ECHO -n " "
                fi
@@ -436,12 +448,17 @@ lfs_migrate() {
                        continue
                fi
 
                        continue
                fi
 
-               layout="${OPT_PASSTHROUGH[@]} "
-               [ -n "$stripe_count" ] && layout+="-c $stripe_count "
-               [ -n "$stripe_size" ] && layout+="-S $stripe_size "
-               [ -z "$OPT_POOL" -a -n "$stripe_pool" ] &&
-                                       layout+="-p $stripe_pool "
-               [ -n "$mirror_count" ] && layout+="-N $mirror_count "
+               if ! $OPT_COMP && [ ${layout_info[$l_comp_count]} -gt 0 ]; then
+                       layout+="--copy $OLDNAME"
+                       OPT_COMP=true
+               fi
+               if ! $OPT_COMP; then
+                       [ -n "$stripe_count" ] && layout+="-c $stripe_count "
+                       [ -n "$stripe_size" ] && layout+="-S $stripe_size "
+                       [ -n "$OPT_POOL" -a -n "$stripe_pool" ] &&
+                                               layout+="-p $stripe_pool "
+                       [[ $mirror_count -gt 1 ]] && layout+="-N $mirror_count "
+               fi
                layout+="$OPT_LAYOUT"
 
                # detect other hard links and store them on a global
                layout+="$OPT_LAYOUT"
 
                # detect other hard links and store them on a global
index 29d5033..c8b399a 100755 (executable)
@@ -6438,7 +6438,9 @@ test_56wb() {
        echo "done."
 
        echo -n "Removing test file from pool '$pool'..."
        echo "done."
 
        echo -n "Removing test file from pool '$pool'..."
-       $LFS migrate $file1 &> /dev/null ||
+       # "lfs migrate $file" won't remove the file from the pool
+       # until some striping information is changed.
+       $LFS migrate -c 1 $file1 &> /dev/null ||
                error "cannot remove from pool"
        [ "$($LFS getstripe -p $file1)" ] &&
                error "pool still set"
                error "cannot remove from pool"
        [ "$($LFS getstripe -p $file1)" ] &&
                error "pool still set"
@@ -6460,19 +6462,23 @@ run_test 56wb "check lfs_migrate pool support"
 
 test_56wc() {
        local file1="$DIR/$tdir/file1"
 
 test_56wc() {
        local file1="$DIR/$tdir/file1"
+       local parent_ssize
+       local parent_scount
+       local cur_ssize
+       local cur_scount
+       local orig_ssize
 
        echo -n "Creating test dir..."
        test_mkdir $DIR/$tdir &> /dev/null || error "cannot create dir"
 
        echo -n "Creating test dir..."
        test_mkdir $DIR/$tdir &> /dev/null || error "cannot create dir"
-       local def_stripe_size=$($LFS getstripe -S $DIR/$tdir 2>/dev/null)
        $LFS setstripe -S 1M -c 1 "$DIR/$tdir" &> /dev/null ||
        $LFS setstripe -S 1M -c 1 "$DIR/$tdir" &> /dev/null ||
-               error "cannot set stripe"
+               error "cannot set stripe by '-S 1M -c 1'"
        echo "done"
 
        echo -n "Setting initial stripe for test file..."
        $LFS setstripe -S 512K -c 1 "$file1" &> /dev/null ||
                error "cannot set stripe"
        echo "done"
 
        echo -n "Setting initial stripe for test file..."
        $LFS setstripe -S 512K -c 1 "$file1" &> /dev/null ||
                error "cannot set stripe"
-       [ $($LFS getstripe -S "$file1") -eq 524288 ] ||
-               error "stripe size not set"
+       cur_ssize=$($LFS getstripe -S "$file1")
+       [ $cur_ssize -eq 524288 ] || error "setstripe -S $cur_ssize != 524288"
        echo "done."
 
        # File currently set to -S 512K -c 1
        echo "done."
 
        # File currently set to -S 512K -c 1
@@ -6489,8 +6495,8 @@ test_56wc() {
        echo -n "Verifying -S option is passed through to lfs migrate..."
        $LFS_MIGRATE -y -S 1M "$file1" &> /dev/null ||
                error "migration failed"
        echo -n "Verifying -S option is passed through to lfs migrate..."
        $LFS_MIGRATE -y -S 1M "$file1" &> /dev/null ||
                error "migration failed"
-       [ $($LFS getstripe -S "$file1") -eq 1048576 ] ||
-               error "file was not restriped"
+       cur_ssize=$($LFS getstripe -S "$file1")
+       [ $cur_ssize -eq 1048576 ] || error "migrate -S $cur_ssize != 1048576"
        echo "done."
 
        # File currently set to -S 1M -c 1
        echo "done."
 
        # File currently set to -S 1M -c 1
@@ -6501,8 +6507,9 @@ test_56wc() {
                error "long option without argument not supported"
        $LFS_MIGRATE -y --stripe-size 512K "$file1" &> /dev/null ||
                error "long option with argument not supported"
                error "long option without argument not supported"
        $LFS_MIGRATE -y --stripe-size 512K "$file1" &> /dev/null ||
                error "long option with argument not supported"
-       [ $($LFS getstripe -S "$file1") -eq 524288 ] ||
-               error "file not restriped with --stripe-size option"
+       cur_ssize=$($LFS getstripe -S "$file1")
+       [ $cur_ssize -eq 524288 ] ||
+               error "migrate --stripe-size $cur_ssize != 524288"
        echo "done."
 
        # File currently set to -S 512K -c 1
        echo "done."
 
        # File currently set to -S 512K -c 1
@@ -6511,8 +6518,8 @@ test_56wc() {
                echo -n "Verifying explicit stripe count can be set..."
                $LFS_MIGRATE -y -c 2 "$file1" &> /dev/null ||
                        error "migrate failed"
                echo -n "Verifying explicit stripe count can be set..."
                $LFS_MIGRATE -y -c 2 "$file1" &> /dev/null ||
                        error "migrate failed"
-               [ $($LFS getstripe -c "$file1") -eq 2 ] ||
-                       error "file not restriped to explicit count"
+               cur_scount=$($LFS getstripe -c "$file1")
+               [ $cur_scount -eq 2 ] || error "migrate -c $cur_scount != 2"
                echo "done."
        fi
 
                echo "done."
        fi
 
@@ -6521,17 +6528,21 @@ test_56wc() {
        # Ensure parent striping is used if -R is set, and no stripe
        # count or size is specified
        echo -n "Setting stripe for parent directory..."
        # Ensure parent striping is used if -R is set, and no stripe
        # count or size is specified
        echo -n "Setting stripe for parent directory..."
-       $LFS setstripe -S 1M -c 1 "$DIR/$tdir" &> /dev/null ||
-               error "cannot set stripe"
+       $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
+               error "cannot set stripe '-S 2M -c 1'"
        echo "done."
 
        echo -n "Verifying restripe option uses parent stripe settings..."
        echo "done."
 
        echo -n "Verifying restripe option uses parent stripe settings..."
+       parent_ssize=$($LFS getstripe -S $DIR/$tdir 2>/dev/null)
+       parent_scount=$($LFS getstripe -c $DIR/$tdir 2>/dev/null)
        $LFS_MIGRATE -y -R "$file1" &> /dev/null ||
                error "migrate failed"
        $LFS_MIGRATE -y -R "$file1" &> /dev/null ||
                error "migrate failed"
-       [ $($LFS getstripe -S "$file1") -eq $def_stripe_size ] ||
-               error "file not restriped to parent settings"
-       [ $($LFS getstripe -c "$file1") -eq 1 ] ||
-               error "file not restriped to parent settings"
+       cur_ssize=$($LFS getstripe -S "$file1")
+       [ $cur_ssize -eq $parent_ssize ] ||
+               error "migrate -R stripe_size $cur_ssize != $parent_ssize"
+       cur_scount=$($LFS getstripe -c "$file1")
+       [ $cur_scount -eq $parent_scount ] ||
+               error "migrate -R stripe_count $cur_scount != $parent_scount"
        echo "done."
 
        # File currently set to -S 1M -c 1
        echo "done."
 
        # File currently set to -S 1M -c 1
@@ -6539,13 +6550,14 @@ test_56wc() {
        # Ensure striping is preserved if -R is not set, and no stripe
        # count or size is specified
        echo -n "Verifying striping size preserved when not specified..."
        # Ensure striping is preserved if -R is not set, and no stripe
        # count or size is specified
        echo -n "Verifying striping size preserved when not specified..."
-       local orig_stripe_size=$($LFS getstripe -S "$file1" 2>/dev/null)
+       orig_ssize=$($LFS getstripe -S "$file1" 2>/dev/null)
        $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
                error "cannot set stripe on parent directory"
        $LFS_MIGRATE -y "$file1" &> /dev/null ||
                error "migrate failed"
        $LFS setstripe -S 2M -c 1 "$DIR/$tdir" &> /dev/null ||
                error "cannot set stripe on parent directory"
        $LFS_MIGRATE -y "$file1" &> /dev/null ||
                error "migrate failed"
-       [ $($LFS getstripe -S "$file1") -eq $orig_stripe_size ] ||
-               error "file was restriped"
+       cur_ssize=$($LFS getstripe -S "$file1")
+       [ $cur_ssize -eq $orig_ssize ] ||
+               error "migrate by default $cur_ssize != $orig_ssize"
        echo "done."
 
        # Ensure file name properly detected when final option has no argument
        echo "done."
 
        # Ensure file name properly detected when final option has no argument
@@ -6833,6 +6845,75 @@ test_56xc() {
 }
 run_test 56xc "lfs migration autostripe"
 
 }
 run_test 56xc "lfs migration autostripe"
 
+test_56xd() {
+       [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
+
+       local dir=$DIR/$tdir
+       local f_mgrt=$dir/$tfile.mgrt
+       local f_yaml=$dir/$tfile.yaml
+       local f_copy=$dir/$tfile.copy
+       local layout_yaml="-E 1M -S 512K -c 1 -E -1 -S 1M -c 2 -i 0"
+       local layout_copy="-c 2 -S 2M -i 1"
+       local yamlfile=$dir/yamlfile
+       local layout_before;
+       local layout_after;
+
+       test_mkdir "$dir" || error "cannot create dir $dir"
+       $LFS setstripe $layout_yaml $f_yaml ||
+               error "cannot setstripe $f_yaml with layout $layout_yaml"
+       $LFS getstripe --yaml $f_yaml > $yamlfile
+       $LFS setstripe $layout_copy $f_copy ||
+               error "cannot setstripe $f_copy with layout $layout_copy"
+       touch $f_mgrt
+       dd if=/dev/zero of=$f_mgrt bs=1M count=4
+
+       # 1. test option --yaml
+       $LFS_MIGRATE -y --yaml $yamlfile $f_mgrt ||
+               error "cannot migrate $f_mgrt with --yaml $yamlfile"
+       layout_before=$(get_layout_param $f_yaml)
+       layout_after=$(get_layout_param $f_mgrt)
+       [ "$layout_after" == "$layout_before" ] ||
+               error "lfs_migrate --yaml: $layout_after != $layout_before"
+
+       # 2. test option --copy
+       $LFS_MIGRATE -y --copy $f_copy $f_mgrt ||
+               error "cannot migrate $f_mgrt with --copy $f_copy"
+       layout_before=$(get_layout_param $f_copy)
+       layout_after=$(get_layout_param $f_mgrt)
+       [ "$layout_after" == "$layout_before" ] ||
+               error "lfs_migrate --copy: $layout_after != $layout_before"
+}
+run_test 56xd "check lfs_migrate --yaml and --copy support"
+
+test_56xe() {
+       [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
+
+       local dir=$DIR/$tdir
+       local f_comp=$dir/$tfile
+       local layout="-E 1M -S 512K -c 1 -E -1 -S 1M -c 2 -i 0"
+       local layout_before=""
+       local layout_after=""
+
+       test_mkdir "$dir" || error "cannot create dir $dir"
+       $LFS setstripe $layout $f_comp ||
+               error "cannot setstripe $f_comp with layout $layout"
+       layout_before=$(get_layout_param $f_comp)
+       dd if=/dev/zero of=$f_comp bs=1M count=4
+
+       # 1. migrate a comp layout file by lfs_migrate
+       $LFS_MIGRATE -y $f_comp || error "cannot migrate $f_comp by lfs_migrate"
+       layout_after=$(get_layout_param $f_comp)
+       [ "$layout_before" == "$layout_after" ] ||
+               error "lfs_migrate: $layout_before != $layout_after"
+
+       # 2. migrate a comp layout file by lfs migrate
+       $LFS migrate $f_comp || error "cannot migrate $f_comp by lfs migrate"
+       layout_after=$(get_layout_param $f_comp)
+       [ "$layout_before" == "$layout_after" ] ||
+               error "lfs migrate: $layout_before != $layout_after"
+}
+run_test 56xe "migrate a composite layout file"
+
 test_56y() {
        [ $MDS1_VERSION -lt $(version_code 2.4.53) ] &&
                skip "No HSM $(lustre_build_version $SINGLEMDS) MDS < 2.4.53"
 test_56y() {
        [ $MDS1_VERSION -lt $(version_code 2.4.53) ] &&
                skip "No HSM $(lustre_build_version $SINGLEMDS) MDS < 2.4.53"
index 1eb8b1f..2bd4468 100644 (file)
@@ -821,12 +821,12 @@ migrate_open_files(const char *name, __u64 migration_flags,
                }
 
                /* create, open a volatile file, use caching (ie no directio) */
                }
 
                /* create, open a volatile file, use caching (ie no directio) */
-               if (param != NULL)
-                       fdv = llapi_file_open_param(volatile_file, open_flags,
-                                                   open_mode, param);
-               else
+               if (layout)
                        fdv = lfs_component_create(volatile_file, open_flags,
                                                   open_mode, layout);
                        fdv = lfs_component_create(volatile_file, open_flags,
                                                   open_mode, layout);
+               else
+                       fdv = llapi_file_open_param(volatile_file, open_flags,
+                                                   open_mode, param);
        } while (fdv < 0 && (rc = fdv) == -EEXIST);
 
        if (rc < 0) {
        } while (fdv < 0 && (rc = fdv) == -EEXIST);
 
        if (rc < 0) {
@@ -3582,6 +3582,11 @@ static int lfs_setstripe_internal(int argc, char **argv,
                goto usage_error;
        }
 
                goto usage_error;
        }
 
+       /* lfs migrate $filename should keep the file's layout by default */
+       if (migrate_mode && !setstripe_args_specified(&lsa) && !layout &&
+           !from_yaml)
+               from_copy = true;
+
        if (xattr && !foreign_mode) {
                /* only print a warning as this is harmless and will be ignored
                 */
        if (xattr && !foreign_mode) {
                /* only print a warning as this is harmless and will be ignored
                 */
@@ -3732,8 +3737,8 @@ static int lfs_setstripe_internal(int argc, char **argv,
 
        if ((from_yaml || from_copy) &&
            (setstripe_args_specified(&lsa) || layout != NULL)) {
 
        if ((from_yaml || from_copy) &&
            (setstripe_args_specified(&lsa) || layout != NULL)) {
-               fprintf(stderr, "error: %s: can't specify --yaml with "
-                       "-c, -S, -i, -o, -p or -E options.\n",
+               fprintf(stderr, "error: %s: can't specify --yaml or --copy with"
+                       " -c, -S, -i, -o, -p or -E options.\n",
                        argv[0]);
                goto error;
        }
                        argv[0]);
                goto error;
        }
@@ -3873,17 +3878,19 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                argv[0], template);
                        goto error;
                }
                                argv[0], template);
                        goto error;
                }
-       } else if (from_copy) {
-               layout = llapi_layout_get_by_path(template, 0);
-               if (layout == NULL) {
-                       fprintf(stderr,
-                           "%s: can't create composite layout from file %s.\n",
-                               progname, template);
-                       goto error;
-               }
        }
 
        for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) {
        }
 
        for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) {
+               if (from_copy) {
+                       layout = llapi_layout_get_by_path(template ?: fname, 0);
+                       if (layout == NULL) {
+                               fprintf(stderr, "%s: can't create composite "
+                                       "layout from file %s.\n",
+                                       progname, template ?: fname);
+                               goto error;
+                       }
+               }
+
                if (migrate_mdt_mode) {
                        result = llapi_migrate_mdt(fname, &migrate_mdt_param);
                } else if (migrate_mode) {
                if (migrate_mdt_mode) {
                        result = llapi_migrate_mdt(fname, &migrate_mdt_param);
                } else if (migrate_mode) {