]>
Commit | Line | Data |
---|---|---|
a089aec3 DW |
1 | #!/bin/bash |
2 | ||
3 | # Copyright (C) 2018 Oracle. All Rights Reserved. | |
4 | # | |
5 | # Author: Darrick J. Wong <darrick.wong@oracle.com> | |
6 | # | |
7 | # This program is free software; you can redistribute it and/or | |
8 | # modify it under the terms of the GNU General Public License | |
9 | # as published by the Free Software Foundation; either version 2 | |
10 | # of the License, or (at your option) any later version. | |
11 | # | |
12 | # This program is distributed in the hope that it would be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | # GNU General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU General Public License | |
18 | # along with this program; if not, write the Free Software Foundation, | |
19 | # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | ||
21 | scrub_all=0 | |
22 | conffile="@root_sysconfdir@/e2scrub.conf" | |
23 | ||
24 | test -f "${conffile}" && . "${conffile}" | |
25 | ||
26 | scrub_args="" | |
27 | ||
28 | print_help() { | |
29 | echo "Usage: $0 [OPTIONS]" | |
30 | echo " -A: Scrub all ext[234] filesystems even if not mounted." | |
31 | echo " -r: Remove e2scrub snapshots." | |
32 | echo " -V: Print version information and exit." | |
33 | } | |
34 | ||
35 | print_version() { | |
36 | echo "e2scrub_all @E2FSPROGS_VERSION@ (@E2FSPROGS_DATE@)" | |
37 | } | |
38 | ||
a2df5894 DW |
39 | exitcode() { |
40 | ret="$1" | |
41 | ||
42 | # If we're being run as a service, the return code must fit the LSB | |
43 | # init script action error guidelines, which is to say that we | |
44 | # compress all errors to 1 ("generic or unspecified error", LSB 5.0 | |
45 | # section 22.2) and hope the admin will scan the log for what | |
46 | # actually happened. | |
47 | ||
48 | # We have to sleep 2 seconds here because journald uses the pid to | |
49 | # connect our log messages to the systemd service. This is critical | |
50 | # for capturing all the log messages if the scrub fails, because the | |
51 | # fail service uses the service name to gather log messages for the | |
52 | # error report. | |
53 | if [ -n "${SERVICE_MODE}" ]; then | |
54 | test "${ret}" -ne 0 && ret=1 | |
55 | sleep 2 | |
56 | fi | |
57 | ||
58 | exit "${ret}" | |
59 | } | |
60 | ||
a089aec3 DW |
61 | while getopts "ArV" opt; do |
62 | case "${opt}" in | |
63 | "A") scrub_all=1;; | |
64 | "r") scrub_args="${scrub_args} -r";; | |
a2df5894 DW |
65 | "V") print_version; exitcode 0;; |
66 | *) print_help; exitcode 2;; | |
a089aec3 DW |
67 | esac |
68 | done | |
69 | shift "$((OPTIND - 1))" | |
70 | ||
71 | # Find scrub targets, make sure we only do this once. | |
72 | ls_scrub_targets() { | |
73 | lsblk -o NAME,FSTYPE,MOUNTPOINT -p -P -n | while read vars; do | |
74 | eval "${vars}" | |
75 | ||
76 | # Skip non-ext[234] | |
77 | case "${FSTYPE}" in | |
78 | ext[234]) ;; | |
79 | *) continue;; | |
80 | esac | |
81 | ||
82 | # Skip unmounted filesystems unless -A | |
83 | if [ "${scrub_all}" -eq 0 ] && [ -z "${MOUNTPOINT}" ]; then | |
84 | continue; | |
85 | fi | |
86 | ||
87 | # Skip non-lvm devices and lvm snapshots | |
88 | lvm_vars="$(lvs --nameprefixes -o vg_name,lv_name,lv_role --noheadings "${NAME}" 2> /dev/null)" | |
89 | test $? -ne 0 && continue | |
90 | eval "${lvm_vars}" | |
91 | echo "${LVM2_LV_ROLE}" | grep -q "snapshot" && continue | |
92 | ||
93 | if [ -n "${MOUNTPOINT}" ]; then | |
94 | echo "${MOUNTPOINT}" | |
95 | else | |
96 | echo "${NAME}" | |
97 | fi | |
98 | done | sort | uniq | |
99 | } | |
100 | ||
a2df5894 DW |
101 | # systemd doesn't know to do path escaping on the instance variable we pass |
102 | # to the e2scrub service, which breaks things if there is a dash in the path | |
103 | # name. Therefore, do the path escaping ourselves if needed. | |
104 | escape_path_for_systemd() { | |
105 | local path="$1" | |
106 | ||
107 | if echo "${path}" | grep -q -- "-"; then | |
108 | echo "-$(systemd-escape --path "${path}")" | |
109 | else | |
110 | echo "${path}" | |
111 | fi | |
112 | } | |
113 | ||
a089aec3 DW |
114 | # Scrub any mounted fs on lvm by creating a snapshot and fscking that. |
115 | stdin="$(realpath /dev/stdin)" | |
116 | ls_scrub_targets | while read tgt; do | |
a2df5894 DW |
117 | # If we're not reaping and systemd is present, try invoking the |
118 | # systemd service. | |
119 | if [ -z "${scrub_args}" ] && type systemctl > /dev/null 2>&1; then | |
120 | tgt_esc="$(escape_path_for_systemd "${tgt}")" | |
121 | ${DBG} systemctl start "e2scrub@${tgt_esc}" 2> /dev/null < "${stdin}" | |
122 | res=$? | |
123 | if [ "${res}" -eq 0 ] || [ "${res}" -eq 1 ]; then | |
124 | continue; | |
125 | fi | |
126 | fi | |
127 | ||
128 | # Otherwise use direct invocation | |
a089aec3 DW |
129 | ${DBG} "@root_sbindir@/e2scrub" ${scrub_args} "${tgt}" < "${stdin}" |
130 | done | |
131 | ||
a2df5894 | 132 | exitcode 0 |