/usr/bin/lfs_migrate is in lustre-utils 1.8.5+dfsg-3ubuntu1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | #!/bin/bash
# set -x
set -e
# lfs_migrate: a simple tool to copy and check files.
#
# To avoid allocating objects on one or more OSTs, they should be
# deactivated on the MDS via "lctl --device {device_number} deactivate",
# where {device_number} is from the output of "lctl dl" on the MDS.
#
# To guard against corruption, the file is compared after migration
# to verify the copy is correct and the file has not been modified.
# This is not a protection against the file being open by another
# process, but it would catch the worst cases of in-use files, but
# to be 100% safe the administrator needs to ensure this is safe.
RSYNC=${RSYNC:-rsync}
ECHO=echo
LFS=${LFS:-lfs}
usage() {
cat -- <<USAGE 1>&2
usage: lfs_migrate [-c|-s] [-h] [-l] [-n] [-y] [file|dir ...]
-c compare file data after migrate (default)
-s skip file data comparison after migrate
-h show this usage message
-l migrate files with hard links (skip by default)
-n only print the names of files to be migrated
-q run quietly (don't print filenames or status)
-y answer 'y' to usage question
If a directory is an argument, all files in the directory are migrated.
If no file/directory is given, the file list is read from standard input.
e.g.: lfs_migrate /mnt/lustre/file
lfs find /test -O test-OST0004 -size +4G | lfs_migrate -y
USAGE
exit 1
}
OPT_CHECK=y
while getopts "chlnqsy" opt $*; do
case $opt in
c) OPT_CHECK=y;;
l) OPT_NLINK=y;;
n) OPT_DRYRUN=n; OPT_YES=y;;
q) ECHO=:;;
s) OPT_CHECK="";;
y) OPT_YES=y;;
h|\?) usage;;
esac
done
shift $((OPTIND - 1))
if [ -z "$OPT_YES" ]; then
echo ""
echo "lfs_migrate is currently NOT SAFE for moving in-use files." 1>&2
echo "Use it only when you are sure migrated files are unused." 1>&2
echo "" 1>&2
echo "If emptying OST(s) that are not disabled on the MDS, new" 1>&2
echo "files may use them. To prevent MDS allocating any files on" 1>&2
echo "OSTNNNN run 'lctl --device %{fsname}-OSTNNNN-osc deactivate'" 1>&2
echo "on the MDS." 1>&2
echo -n "Continue? (y/n) "
read CHECK
[ "$CHECK" != "y" -a "$CHECK" != "yes" ] && exit 1
fi
# if rsync has --xattr support, then try to copy the xattrs.
$RSYNC --help 2>&1 | grep -q xattr && RSYNC_OPTS="$RSYNC_OPTS -X"
$RSYNC --help 2>&1 | grep -q acls && RSYNC_OPTS="$RSYNC_OPTS -A"
# If rsync copies lustre xattrs in the future, then we can skip lfs (bug 22189)
strings $(which $RSYNC) 2>&1 | grep -q lustre && LFS=:
lfs_migrate() {
while read OLDNAME; do
$ECHO -n "$OLDNAME: "
# avoid duplicate stat if possible
TYPE_LINK=($(stat -c "%h %F" "$OLDNAME" || true))
# skip non-regular files, since they don't have any objects
# and there is no point in trying to migrate them.
if [ "${TYPE_LINK[1]}" != "regular" ]; then
echo -e "not a regular file, skipped"
continue
fi
if [ -z "$OPT_NLINK" -a ${TYPE_LINK[0]} -gt 1 ]; then
echo -e "multiple hard links, skipped"
continue
fi
# working out write perms is hard, let the shell do it
if [ ! -w "$OLDNAME" ]; then
echo -e "no write permission, skipped"
continue
fi
if [ "$OPT_DRYRUN" ]; then
echo -e "dry run, skipped"
continue
fi
# if rsync copies Lustre xattrs properly in the future
# (i.e. before the file data, so that it preserves striping)
# then we don't need to do this getstripe/mktemp stuff.
UNLINK="-u"
COUNT=$($LFS getstripe -c "$OLDNAME" 2> /dev/null)
SIZE=$($LFS getstripe -s "$OLDNAME" 2> /dev/null)
[ -z "$COUNT" -o -z "$SIZE" ] && UNLINK=""
NEWNAME=$(mktemp $UNLINK "$OLDNAME.tmp.XXXXXX")
if [ $? -ne 0 -o -z "$NEWNAME" ]; then
echo -e "\r$OLDNAME: can't make temp file, skipped" 1>&2
continue
fi
[ "$UNLINK" ] && $LFS setstripe -c${COUNT} -s${SIZE} "$NEWNAME"
# we use --inplace, since we created our own temp file already
if ! $RSYNC -a --inplace $RSYNC_OPTS "$OLDNAME" "$NEWNAME";then
echo -e "\r$OLDNAME: copy error, exiting" 1>&2
rm -f "$NEWNAME"
exit 4
fi
if [ "$OPT_CHECK" ] && ! cmp "$OLDNAME" "$NEWNAME"; then
echo -e "\r$NEWNAME: compare failed, exiting" 1>&2
exit 8
fi
if ! mv "$NEWNAME" "$OLDNAME"; then
echo -e "\r$OLDNAME: rename error, exiting" 1>&2
exit 12
fi
$ECHO "done"
done
}
if [ "$#" -eq 0 ]; then
lfs_migrate
else
while [ "$1" ]; do
if [ -d "$1" ]; then
lfs find "$1" -type f | lfs_migrate
else
echo $1 | lfs_migrate
fi
shift
done
fi
|