Whamcloud - gitweb
LU-16335 test: add fail_abort_cleanup()
[fs/lustre-release.git] / lustre / scripts / remove_changelog
1 #!/bin/bash
2
3 # remove_changelog: emergency remove changelog files from server.
4 #
5 # This is emergency tool to cleanup changelogs in server if changelog
6 # records cannot be removed by regular means, e.g. due to llog corruptions
7 #
8 # Tool goes through changelog_catalog and removes all plain llogs listed
9 # then removes changelog_catalog itself and changelog_users
10 # Script accept single parameter which is mount point of server FS mounted
11 # locally, script accepts also --dry-run option to emulate files removal
12 #
13 # Steps to cleanup problematic llogs:
14 #
15 # 1. mount MDT filesystem locally on server as ldiskfs mount
16 # 2. run script first in dry-run mode to make sure it parses llogs as needed:
17 #    # bash remove_changelog -n <ldiskfs_mount>
18 # 3. save all llogs for analysis:
19 #    # bash remove_changelog -n -z /tmp/llogs_saved <ldiskfs_mount>
20 # 4. check that /tmp/llogs_saved.tar.gz exists and has all llogs inside:
21 #    # ls -ali /tmp/llogs_saved.tar.gz
22 #    # tar -tf /tmp/llog_saved.tar.gz
23 # 5. finally run script to delete all llogs:
24 #    # bash remove_changelog <ldiskfs_mount>
25 #
26 # For better llogs compression xz can be used as well, pass it to the script
27 # via GZIP env variable:
28 #    # GZIP=xz bash remove_changelog -n -z /tmp/llogs_saved <ldiskfs_mount>
29 # Archive name will ends with .xz in that case instead of .gz
30
31
32
33
34 ECHO=echo
35 PROG=$(basename $0)
36 LLOG_READER=${LLOG_READER:-llog_reader}
37 GZIP=${GZIP:-gzip}
38
39 usage() {
40     cat -- <<USAGE 1>&2
41 usage: remove_changelog [--dry-run|-n] [--help|-h] [--quiet|-q]
42                         [--zip}-z] <archive> <localmount>
43         --help|-h       show this usage message
44         --dry-run|-n    only print the names of files to be removed
45         --quiet|-q      run quietly (don't print filenames or status)
46         --zip|-z <name_prefix>
47                         save all llogs into compressed tar archive with given
48                         name prefix using gzip by default. Other compression
49                         tools can be used via GZIP env variable.
50
51 The 'localmount' argument should be an ldiskfs mounted MDT device mountpoint.
52
53 Examples:
54       remove_changelog /mnt/mdt0
55       remove_changelog --dry-run /mnt/mdt0
56       remove_changelog -z /tmp/llogs /mnt/mdt0
57 USAGE
58     exit 1
59 }
60
61 OPT_DRYRUN=false
62 OPT_ARCH=""
63 OPT_MOUNT=""
64
65 # Examine any long options and arguments
66 while [ -n "$*" ]; do
67         arg="$1"
68         case "$arg" in
69         -h|--help) usage;;
70         -n|--dry-run) OPT_DRYRUN=true;;
71         -q|--quiet) ECHO=:;;
72         -z|--zip) OPT_ARCH="$2.tar"; shift;;
73         *)
74            [ -e "$arg" ] && OPT_MOUNT="$arg" && break
75         esac
76         shift
77 done
78
79 remove_changelog() {
80         local mntpoint=$OPT_MOUNT
81         local catalog=${mntpoint}/changelog_catalog
82         local users=${mntpoint}/changelog_users
83         local arch=$OPT_ARCH
84
85         if [[ -z $(df -t ldiskfs $mntpoint 2>/dev/null) ]] ; then
86                 echo "$PROG: '$mntpoint' is not ldiskfs mount."
87                 exit 1
88         fi
89
90         if $OPT_DRYRUN; then
91                 $ECHO "Dry run was requested, no changes will be applied"
92         fi
93
94         $ECHO "Scan changelog_catalog at '$mntpoint':"
95         if [[ ! -f $catalog ]] ; then
96                 echo "$PROG: $catalog doesn't exist already."
97         else
98                 if [[ ! $(which $LLOG_READER 2>/dev/null) ]] ; then
99                         echo "$PROG: $LLOG_READER is missing."
100                         exit 1
101                 fi
102                 [[ -z $arch ]] || tar -cf $arch $catalog 2>/dev/null
103                 if (( $(stat -c %s $catalog) >= 8192 )) ; then
104                         while read -r path ; do
105                                 [[ -z $arch ]] ||
106                                         tar -rf $arch ${mntpoint}/$path 2>/dev/null
107                                 $ECHO "rm ${mntpoint}/$path"
108                                 $OPT_DRYRUN || rm -f ${mntpoint}/$path
109                         done < <($LLOG_READER $catalog |
110                                  awk -F "path=" '/path=/ { print $2 }')
111                 else
112                         echo "$PROG: $catalog is too small."
113                 fi
114                 $ECHO "> $catalog"
115                 $OPT_DRYRUN || > $catalog
116         fi
117
118         if [[ -f $users ]] ; then
119                 [[ -z $arch ]] || tar -rf $arch $users 2>/dev/null
120                 $ECHO "> $users"
121                 $OPT_DRYRUN || > $users
122         else
123                 echo "$PROG: $user doesn't exist."
124         fi
125         if [[ "$arch" ]] ; then
126                 $GZIP -3 $arch
127                 $ECHO "llog archive was created by $GZIP"
128         fi
129 }
130
131 if [ -z $OPT_MOUNT ] ; then
132         echo "Mount is not specified, exiting"
133         exit 1
134 fi
135 remove_changelog
136
137