#!/bin/bash
+# -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*-
+# vim:shiftwidth=4:softtabstop=4:tabstop=4:
#
# test e2fsck and lfsck to detect and fix filesystem corruption
#
[ -d "$SHARED_DIRECTORY" ] || \
{ skip "SHARED_DIRECTORY should be specified with a shared directory \
which can be accessable on all of the nodes" && exit 0; }
+[[ $(facet_fstype $SINGLEMDS) != ldiskfs ]] &&
+ skip "Only applicable to ldiskfs-based MDTs" && exit 0
+[[ $(facet_fstype OST) != ldiskfs ]] &&
+ skip "Only applicable to ldiskfs-based OST" && exit 0
-which getfattr > /dev/null 2>&1 || { skip "could not find getfattr" && exit 0; }
-which setfattr > /dev/null 2>&1 || { skip "could not find setfattr" && exit 0; }
+which getfattr &>/dev/null || { skip_env "could not find getfattr" && exit 0; }
+which setfattr &>/dev/null || { skip_env "could not find setfattr" && exit 0; }
+
+if [ ! -x `which $LFSCK_BIN` ]; then
+ log "$($E2FSCK -V)"
+ error "e2fsprogs does not support lfsck"
+fi
MOUNT_2=""
check_and_setup_lustre
assert_DIR
+SAMPLE_FILE=$TMP/$TESTSUITE.junk
+dd if=/dev/urandom of=$SAMPLE_FILE bs=1M count=1
+
# Create some dirs and files on the filesystem.
create_files_sub() {
local test_dir=$1
# create files to be modified
for f in $(seq -f $test_dir/testfile.%g $((num_files * 3))); do
echo "creating $f"
- cp /etc/termcap $f || error "cp /etc/termcap $f failed"
+ cp $SAMPLE_FILE $f || error "cp $SAMPLE_FILE $f failed"
done
# create some more files
local ost_node
local node
- ost_uuid=$($LFS osts | grep "^$obdidx: " | cut -d' ' -f2 | head -n1)
+ ost_uuid=$(ostuuid_from_index $obdidx)
for node in $(osts_nodes); do
do_node $node "lctl get_param -n obdfilter.*.uuid" | grep -q $ost_uuid
# Get the OST target device (given the OST facet name and OST index).
get_ost_dev() {
- local node=$1
- local obdidx=$2
- local ost_name
- local ost_dev
-
- ost_name=$($LFS osts | grep "^$obdidx: " | cut -d' ' -f2 | \
- head -n1 | sed -e 's/_UUID$//')
-
- ost_dev=$(do_node $node "lctl get_param -n obdfilter.$ost_name.mntdev")
- [ ${PIPESTATUS[0]} -ne 0 ] && \
- echo "failed to find the OST device with index $obdidx on $facet" && \
- return 1
-
- if [[ $ost_dev = *loop* ]]; then
- ost_dev=$(do_node $node "losetup $ost_dev" | \
- sed -e "s/.*(//" -e "s/).*//")
- fi
+ local node=$1
+ local obdidx=$2
+ local ost_name
+ local ost_dev
+
+ ost_name=$(ostname_from_index $obdidx)
+ ost_dev=$(get_osd_param $node $ost_name mntdev)
+ if [ $? -ne 0 ]; then
+ printf "unable to find OST%04x on $facet\n" $obdidx
+ return 1
+ fi
- echo $ost_dev
+ if [[ $ost_dev = *loop* ]]; then
+ ost_dev=$(do_node $node "losetup $ost_dev" | \
+ sed -e "s/.*(//" -e "s/).*//")
+ fi
+
+ echo $ost_dev
}
# Get the file names to be duplicated or removed on the MDS.
# Remove objects associated with files.
remove_objects() {
- local node=$1
- shift
- local ostdev=$1
- shift
- local group=$1
- shift
- local objids="$@"
- local tmp
- local i
- local rc
-
- echo "removing objects from $ostdev on $facet: $objids"
- tmp=$(mktemp $SHARED_DIRECTORY/debugfs.XXXXXXXXXX)
- for i in $objids; do
- echo "rm O/$group/d$((i % 32))/$i" >> $tmp
- done
-
- do_node $node "$DEBUGFS -w -f $tmp $ostdev"
- rc=${PIPESTATUS[0]}
- rm -f $tmp
-
- return $rc
+ local ostdev=$1
+ shift
+ local group=$1
+ shift
+ local objids="$@"
+ local facet=ost$((OSTIDX + 1))
+ local mntpt=$(facet_mntpt $facet)
+ local opts=$OST_MOUNT_OPTS
+ local i
+ local rc
+
+ echo "removing objects from $ostdev on $facet: $objids"
+ if ! do_facet $facet test -b $ostdev; then
+ opts=$(csa_add "$opts" -o loop)
+ fi
+ mount -t $(facet_fstype $facet) $opts $ostdev $mntpt ||
+ return $?
+ rc=0;
+ for i in $objids; do
+ rm $mntpt/O/$group/d$((i % 32))/$i || { rc=$?; break; }
+ done
+ umount -f $mntpt || return $?
+ return $rc
}
# Remove files from MDS.
# get the server target devices
get_svr_devs
-if [ "$SKIP_LFSCK" = "no" ] && is_empty_fs $MOUNT; then
+if is_empty_fs $MOUNT; then
# create test directory
TESTDIR=$DIR/d0.$TESTSUITE
mkdir -p $TESTDIR || error "mkdir $TESTDIR failed"
# get the node name and target device for the OST with index $OSTIDX
OSTNODE=$(get_ost_node $OSTIDX) || error "get_ost_node by index $OSTIDX failed"
- OSTDEV=$(get_ost_dev $OSTNODE $OSTIDX) || \
+ OSTDEV=$(get_ost_dev $OSTNODE $OSTIDX) ||
error "get_ost_dev $OSTNODE $OSTIDX failed"
# get the file names to be duplicated on the MDS
# remove objects associated with files in group $OBJGRP
# on the OST with index $OSTIDX
- remove_objects $OSTNODE $OSTDEV $OBJGRP $OST_REMOVE || \
+ remove_objects $OSTDEV $OBJGRP $OST_REMOVE ||
error "removing objects failed"
# remove files from MDS
remove_files $SINGLEMDS $MDTDEV $MDS_REMOVE || error "removing files failed"
# create EAs on files so objects are referenced from different files
- duplicate_files $SINGLEMDS $MDTDEV $MDS_DUPE || \
+ duplicate_files $SINGLEMDS $MDTDEV $MDS_DUPE ||
error "duplicating files failed"
FSCK_MAX_ERR=1 # file system errors corrected
-else # I_MOUNTED=no
+else # is_empty_fs $MOUNT
FSCK_MAX_ERR=4 # file system errors left uncorrected
fi
# lfsck will return 1 if the filesystem had errors fixed
# run e2fsck to generate databases used for lfsck
generate_db
-if [ "$SKIP_LFSCK" != "no" ]; then
- echo "skip lfsck"
+
+# remount filesystem
+ORIG_REFORMAT=$REFORMAT
+REFORMAT=""
+check_and_setup_lustre
+REFORMAT=$ORIG_REFORMAT
+
+# run lfsck
+rc=0
+run_lfsck || rc=$?
+if [ $rc -eq 0 ]; then
+ echo "clean after the first check"
else
- # remount filesystem
- REFORMAT=""
- check_and_setup_lustre
+ # run e2fsck again to generate databases used for lfsck
+ generate_db
- # run lfsck
+ # run lfsck again
rc=0
run_lfsck || rc=$?
if [ $rc -eq 0 ]; then
- echo "clean after the first check"
+ echo "clean after the second check"
else
- # run e2fsck again to generate databases used for lfsck
- generate_db
-
- # run lfsck again
- rc=0
- run_lfsck || rc=$?
- if [ $rc -eq 0 ]; then
- echo "clean after the second check"
- else
- error "lfsck test 2 - finished with rc=$rc"
- fi
+ error "lfsck test 2 - finished with rc=$rc"
fi
fi
-equals_msg $(basename $0): test complete, cleaning up
-
-LFSCK_ALWAYS=no
+complete $SECONDS
check_and_cleanup_lustre
-[ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG && \
- grep -q FAIL $TESTSUITELOG && exit 1 || true
-
-echo "$0: completed"
+exit_status