123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- #!/bin/sh
- # Copyright (C) 2005-2009 Junjiro Okajima
- #
- # This program, aufs is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- #
- # The development of this script is sponcered by ASUSTek Computer Inc.
- # Kindly they agreed that I keep my aufs work as free software as it has
- # been.
- #
- set -eu
- #set -x
- me=$(basename $0)
- EEcho() # str
- {
- echo ${me}: $@ 1>&2
- }
- f=/sbin/mount.aufs
- test ! -x $f && EEcho $f is not installed && exit 1
- # special handling for backward compatibility.
- #
- # aufs in the donated eeepc is aufs1 20080211 without CONFIG_AUFS_COMPAT.
- # /etc/default/aufs was introduced in aufs1 20080922.
- # shwh/noshwh was introduced in aufs1 20080310 with CONFIG_AUFS_SHWH.
- # noshwh became always available regardless CONFIG_AUFS_SHWH in aufs1 20081117.
- noshwh=1
- AUFS_VERSION=20080211
- f=/etc/default/aufs
- if [ -s $f ]
- then
- . $f
- else
- echo ${me}: warning, broken $f, assuming aufs is $AUFS_VERSION
- f=/usr/lib/aufs.shlib
- test ! -s $f && EEcho $f is not installed && exit 1
- . $f
- case $AUFS_VERSION in
- 200*) # aufs1
- test $AUFS_VERSION -lt 20081117 && noshwh=0
- ;;
- esac
- AUFS_SUPER_MAGIC=1635083891
- AUFS_SUPER_MAGIC_HEX=0x61756673
- AUFS_WH_PFX=.wh.
- AUFS_WH_PFX2=.wh..wh.
- AUFS_WH_DIROPQ=.wh..wh..opq
- fi
- ########################################
- _Rsync="rsync --exclude=lost+found"
- Rsync="$_Rsync -aHSx --devices --specials --delete-before"
- Copy="$Rsync"
- Move="$Copy"
- RsyncWh="$_Rsync -ptgoHx"
- FindForRm() # rw
- {
- echo "find \"$1\" -xdev -depth \(
- \( ! -type d
- \( -name $AUFS_WH_DIROPQ
- -o ! -name ${AUFS_WH_PFX2}\* \) \)
- -o \( -type d
- ! -name ${AUFS_WH_PFX2}\*
- ! -wholename \"$1\"
- ! -wholename \"$1/lost+found\" \)
- \) -print0"
- }
- MoveWh() # rw ro+wh
- {
- cd "$1"
- find . -xdev -name ${AUFS_WH_PFX}\* ! -name ${AUFS_WH_PFX2}\* \
- -printf '%P\n' |
- while read wh
- do
- f=$(echo "$wh" | sed -e '
- s/^'${AUFS_WH_PFX}'//
- t
- s:/'${AUFS_WH_PFX}':/:
- ')
- test -e "$dst/$f" || echo "$wh"
- done |
- # -v
- $RsyncWh --files-from=- ./ "$2"
- cd "$OLDPWD"
- }
- copy()
- {
- $Copy $@ "$mntpnt"/ "$dst"
- }
- _move()
- {
- set +x
- test $hinotify -ne 1 && echo ${me}: warning, -i is not specified
- src_is_nfs=0
- test $(stat -f -c %T "$src") = nfs && src_is_nfs=1
- set $quiet
- $Move $@ &&
- eval $(FindForRm "$src") |
- {
- if [ $src_is_nfs -eq 1 ]
- then
- mount -o remount "$mntpnt"
- mount -o remount "$src"
- fi
- xargs -r0 rm -fr #-v
- }
- }
- move()
- {
- _move $@ "$mntpnt"/ "$dst"
- }
- move_with_wh()
- {
- {
- set +x
- MoveWh "$src" "$dst"
- set $quiet
- } &&
- move --exclude=${AUFS_WH_PFX}\*
- }
- # backward compatibility
- move_w()
- {
- move_with_wh $@
- }
- Usage()
- {
- t=$(FindForRm src_branch | sed -e '
- s/"//g
- $b
- s/$/ \\/')
- cat <<- EOF
- $me Options move | move_with_wh | copy \\
- mntpnt src_branch dst_branch [ options for rsync ]
- generic form:
- $me [ -w | --wh ] [ -i | --inotify ] Options \\
- mntpnt cmd [ parameters for cmd ]
- Options:
- [ -n | --dry_run ]
- [ -q | --quiet ]
- The dst_branch must be mounted as writable.
- During the operation, the mntpnt is set readonly.
- If you are opening a file for writing on the writable branch,
- you need to close the file before invoking this script.
- The -w or --wh option requires CONFIG_AUFS_SHWH enabled.
- The -i or --inotify option requires CONFIG_AUFS_HINOTIFY enabled.
- 'copy' is a shortcut for
- $me mntpnt \\
- $Copy mntpnt/ dst_branch
- 'move' is a shortcut for
- $me mntpnt \\
- "$Move \\
- mntpnt/ dst_branch && \\
- $t |\\
- xargs -r0 rm -fr"
- Note: in most cases, you will need '-i' option, and
- find(1) is invoked by $me only when rsync(1)
- succeded.
- 'move_with_wh' is a simple variation of 'move' which moves
- whiteouts separately before the actual 'move'.
- If you execute this script under linux-2.6.24 or earlier, the
- kernel may produce a harmless warning "inotify.c:NNN
- set_dentry_child_flags()". The message was already removed in
- linux-2.6.25.
- examples:
- - Copy and reflect all the modification (modifed files, newly
- created and removed ones) in the upper branch to the lower
- branch. This operation is for aufs which has only 2 branches,
- and mainly for a system shutdown script.
- All files on the upper branch remain.
- $ sudo $me copy /your/aufs /your/upper_branch /your/lower_branch
- - Like above (2 branches), move and reflect all modifications
- from upper to lower. Almost all files on the upper branch will
- be removed. You can still use this aufs after the
- operation. But the inode number may be changed. If your
- application which depends upon the inode number was running at
- that time, it may not work correctly.
- $ sudo $me move /your/aufs /your/upper_branch /your/lower_branch
- EOF
- # - Like above (2 branches), generate a new middle layer like a
- # snapshot including whiteouts and make the upper_branch almost
- # empty, but untouch the lower_branch.
- #
- # $ img=/hda1/a.ext2
- # $ dd if=/dev/zero of=\$img bs=4k count=1k
- # $ mkfs -t ext2 -F \$img
- # $ sudo mount -o rw,loop \$img /your/new_branch
- # $ sudo mount -o remount,ins:1:/your/new_branch=ro+wh /your/aufs
- # $ sudo $me _move /your/aufs /your/upper_branch /your/lower_branch \\
- # "--remove-source-files \\
- # --exclude=$AUFS_WH_BASE \\
- # --exclude=$AUFS_WH_PLINKDIR \\
- # --exclude=$AUFS_WH_TMPDIR \\
- # /your/upper_branch/ /your/new_branch; \\
- # mount -o remount,ro /your/new_branch"
- # EOF
- }
- ########################################
- wh=0
- hinotify=0
- quiet=-x
- dry_run=
- cmd=
- cmd_opts=
- for i
- do
- case $i in
- -w|--wh) wh=1;;
- -i|--inotify) hinotify=1;;
- -n|--dry_run) dry_run=echo;;
- -q|--quiet) quiet=+x;;
- -h|--help) Usage; exit 0;;
- --) shift; break;;
- *) break;;
- esac
- shift
- done
- test $# -lt 2 && Usage 1>&2 && exit 1
- case "$1" in
- _move|move|copy|move_w|move_with_wh)
- test $# -lt 4 && Usage 1>&2 && exit 1
- cmd=$1
- SetDir mntpnt "$2"
- SetDir src "$3"
- SetDir dst "$4"
- shift 4
- wh=0
- ;;
- *)
- SetDir mntpnt "$1"
- cmd="$2"
- shift 2
- ;;
- esac
- cmd_opts="$@"
- case $(stat -f -c %T "$mntpnt") in
- aufs|UNKNOWN*${AUFS_SUPER_MAGIC_HEX}*) ;;
- *)
- EEcho "$mntpnt" is not aufs
- exit 1
- ;;
- esac
- cur_opts=$(MntOpts "$mntpnt")
- test ! "$cur_opts" &&
- EEcho bad /proc/mounts or "$mntpnt" is not mounted &&
- exit 1
- cur_opts="udba=reval,noshwh,$cur_opts"
- test $noshwh -eq 0 && cur_opts=$(echo $cur_opts | sed -e 's/,noshwh//')
- # force flushing the pusedo-links
- tmp_opts="remount,ro,udba=reval,noshwh"
- test $noshwh -eq 0 && tmp_opts=$(echo $tmp_opts | sed -e 's/,noshwh//')
- test $wh -eq 1 && tmp_opts="$tmp_opts,shwh"
- test $hinotify -eq 1 && tmp_opts="$tmp_opts,udba=inotify"
- # here we go
- trap "$dry_run mount -o remount,$cur_opts \"$mntpnt\"" EXIT
- set $quiet
- $dry_run mount -o $tmp_opts "$mntpnt"
- eval "$dry_run $cmd $cmd_opts"
|