Whamcloud - gitweb
LU-13124 scrub: check for multiple linked file
[fs/lustre-release.git] / lustre / tests / sanity-scrub.sh
index dae61a3..80f78b7 100644 (file)
@@ -38,8 +38,8 @@ SAVED_OSTCOUNT=${OSTCOUNT}
 # use small MDS + OST size to speed formatting time
 # do not use too small MDSSIZE/OSTSIZE, which affect the default journal size
 # 400M MDT device can guarantee uninitialized groups during the OI scrub
-MDSSIZE=400000
-OSTSIZE=200000
+[[ $MDSSIZE < 400000 || "$mds1_FSTYPE" == ldiskfs ]] && MDSSIZE=400000
+[[ $OSTSIZE < 400000 || "$ost1_FSTYPE" == ldiskfs ]] && OSTSIZE=400000
 
 # no need too many OSTs, to reduce the format/start/stop overhead
 [ $OSTCOUNT -gt 4 ] && OSTCOUNT=4
@@ -86,8 +86,8 @@ SHOW_SCRUB="do_facet $SINGLEMDS \
                $LCTL get_param -n osd-*.${MDT_DEV}.oi_scrub"
 SHOW_SCRUB_ON_OST="do_facet ost1 \
                $LCTL get_param -n osd-*.${OST_DEV}.oi_scrub"
-MOUNT_OPTS_SCRUB="-o user_xattr"
-MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub"
+MOUNT_OPTS_SCRUB="$MDS_MOUNT_OPTS -o user_xattr"
+MOUNT_OPTS_NOSCRUB="$MDS_MOUNT_OPTS -o user_xattr,noscrub"
 
 scrub_prep() {
        local nfiles=$1
@@ -130,7 +130,7 @@ scrub_prep() {
        }
 
        [ ! -z $inject ] && [ $inject -eq 1 ] &&
-               [ $(facet_fstype $SINGLEMDS) = "zfs" ] && {
+               [ "$mds1_FSTYPE" = "zfs" ] && {
                #define OBD_FAIL_OSD_FID_MAPPING        0x193
                do_nodes $(comma_list $(mdts_nodes)) \
                        $LCTL set_param fail_loc=0x193
@@ -161,7 +161,7 @@ scrub_prep() {
                stop mds$n > /dev/null || error "Fail to stop MDS$n!"
        done
 
-       [ ! -z $inject ] && [ $(facet_fstype $SINGLEMDS) = "ldiskfs" ] && {
+       [ ! -z $inject ] && [ "$mds1_FSTYPE" = "ldiskfs" ] && {
                if [ $inject -eq 1 ]; then
                        for n in $(seq $MDSCOUNT); do
                                mds_backup_restore mds$n ||
@@ -296,7 +296,7 @@ scrub_check_data2() {
 }
 
 scrub_remove_ois() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] && return
 
        local error_id=$1
        local index=$2
@@ -314,7 +314,7 @@ scrub_enable_auto() {
 }
 
 full_scrub_ratio() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] && return
 
        local ratio=$1
 
@@ -323,7 +323,7 @@ full_scrub_ratio() {
 }
 
 full_scrub_threshold_rate() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] && return
 
        local rate=$1
 
@@ -356,7 +356,7 @@ test_1a() {
        [ -n "$FILESET" ] && skip "Not functional for FILESET set"
 
        scrub_prep 0
-       echo "start $SINGLEMDS without disabling OI scrub"
+       echo "start $SINGLEMDS without disabling OI scrub: $MOUNT_OPTS_SCRUB"
        scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
 
        local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }')
@@ -373,7 +373,7 @@ test_1a() {
        echo "stop $SINGLEMDS"
        stop $SINGLEMDS > /dev/null || error "(6) Fail to stop MDS!"
 
-       echo "start $SINGLEMDS with disabling OI scrub"
+       echo "start $SINGLEMDS with disabling OI scrub: $MOUNT_OPTS_NOSCRUB"
        start $SINGLEMDS $(mdsdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
                error "(7) Fail to start MDS!"
 
@@ -387,7 +387,7 @@ test_1b() {
        scrub_prep 0 2
        echo "start MDTs without disabling OI scrub"
        scrub_start_mds 2 "$MOUNT_OPTS_SCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_status 3 completed
        mount_client $MOUNT || error "(4) Fail to start client!"
        scrub_check_data2 runas 5
@@ -396,8 +396,8 @@ test_1b() {
 run_test 1b "Trigger OI scrub when MDT mounts for OI files remove/recreate case"
 
 test_1c() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
-               skip "ldiskfs special test" && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
+               skip "ldiskfs special test"
 
        local index
 
@@ -419,8 +419,8 @@ test_1c() {
 run_test 1c "Auto detect kinds of OI file(s) removed/recreated cases"
 
 test_2() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
-               skip "ldiskfs special test" && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
+               skip "ldiskfs special test"
 
        scrub_prep 0 1
        echo "starting MDTs without disabling OI scrub"
@@ -440,7 +440,7 @@ test_3() {
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
        scrub_check_status 3 init
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
 }
 #run_test 3 "Do not trigger OI scrub when MDT mounts if 'noscrub' specified"
@@ -449,7 +449,7 @@ test_4a() {
        scrub_prep 0 1
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
        mount_client $MOUNT || error "(5) Fail to start client!"
        scrub_enable_auto
@@ -480,8 +480,8 @@ test_4a() {
 run_test 4a "Auto trigger OI scrub if bad OI mapping was found (1)"
 
 test_4b() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
-               skip "ldiskfs special test" && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
+               skip "ldiskfs special test"
 
        scrub_prep 5 1
        echo "starting MDTs with OI scrub disabled"
@@ -567,8 +567,8 @@ test_4b() {
 run_test 4b "Auto trigger OI scrub if bad OI mapping was found (2)"
 
 test_4c() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
-               skip "ldiskfs special test" && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
+               skip "ldiskfs special test"
 
        scrub_prep 500 1
        echo "starting MDTs with OI scrub disabled"
@@ -654,7 +654,7 @@ test_4c() {
 run_test 4c "Auto trigger OI scrub if bad OI mapping was found (3)"
 
 test_4d() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] && skip "ldiskfs only test"
+       [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test"
 
        check_mount_and_prep
 
@@ -683,7 +683,7 @@ test_5() {
        echo "starting MDTs with OI scrub disabled (1)"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
        scrub_check_status 3 init
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
        mount_client $MOUNT || error "(5) Fail to start client!"
        scrub_enable_auto
@@ -751,7 +751,7 @@ test_6() {
        scrub_prep 100 1
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
        mount_client $MOUNT || error "(5) Fail to start client!"
        scrub_enable_auto
@@ -829,7 +829,7 @@ test_7() {
        scrub_prep 500 1
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
        mount_client $MOUNT || error "(5) Fail to start client!"
        scrub_enable_auto
@@ -848,7 +848,7 @@ test_7() {
        done
 
        scrub_check_status 8 scanning
-       if [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ]; then
+       if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
                scrub_check_flags 9 inconsistent,auto
        else
                scrub_check_flags 9 recreated,inconsistent,auto
@@ -866,7 +866,7 @@ test_8() {
        scrub_prep 128 1
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
 
        #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
@@ -890,12 +890,11 @@ run_test 8 "Control OI scrub manually"
 
 test_9() {
        # Skip scrub speed test for ZFS because of performance unstable
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
-               skip "test scrub speed only on ldiskfs" && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
+               skip "test scrub speed only on ldiskfs"
 
        if [ -z "$(grep "processor.*: 1" /proc/cpuinfo)" ]; then
                skip "Testing on UP system, the speed may be inaccurate."
-               return 0
        fi
 
        scrub_prep 6000 1
@@ -912,6 +911,7 @@ test_9() {
        sleep $RUN_TIME1
        scrub_check_status 6 completed
        scrub_check_flags 7 ""
+
        # OI scrub should run with limited speed under non-inconsistent case
        scrub_start 8 -s $BASE_SPEED1 -r
 
@@ -944,16 +944,17 @@ test_9() {
        done
        sleep $RUN_TIME2
 
-       # MIN_MARGIN = 0.8 = 8 / 10
+       # 30% margin
+       local MARGIN=3
        local MIN_SPEED=$(((PRE_FETCHED + \
                            BASE_SPEED1 * (RUN_TIME1 - TIME_DIFF) + \
                            BASE_SPEED2 * (RUN_TIME2 - TIME_DIFF)) / \
-                          (RUN_TIME1 + RUN_TIME2) * 8 / 10))
+                          (RUN_TIME1 + RUN_TIME2) * (10 - MARGIN) / 10))
        # MAX_MARGIN = 1.2 = 12 / 10
        MAX_SPEED=$(((PRE_FETCHED + \
                      BASE_SPEED1 * (RUN_TIME1 + TIME_DIFF) + \
                      BASE_SPEED2 * (RUN_TIME2 + TIME_DIFF)) / \
-                    (RUN_TIME1 + RUN_TIME2) * 12 / 10))
+                    (RUN_TIME1 + RUN_TIME2) * (10 + MARGIN) / 10))
        for n in $(seq $MDSCOUNT); do
                SPEED=$(scrub_status $n | awk '/^average_speed/ { print $2 }')
                [ $SPEED -gt $MIN_SPEED ] ||
@@ -975,7 +976,7 @@ test_10a() {
        scrub_prep 0 1
        echo "starting mds$n with OI scrub disabled (1)"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
        mount_client $MOUNT || error "(5) Fail to start client!"
        scrub_enable_auto
@@ -1010,7 +1011,7 @@ test_10b() {
        scrub_prep 0 1
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
 
        #define OBD_FAIL_OSD_SCRUB_DELAY         0x190
@@ -1037,8 +1038,8 @@ test_10b() {
 #run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)"
 
 test_11() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
-               skip "ldiskfs special test" && return
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
+               skip "ldiskfs special test"
 
        local CREATED=100
        local n
@@ -1162,7 +1163,7 @@ test_13() {
 run_test 13 "OI scrub can rebuild missed /O entries"
 
 test_14() {
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] &&
+       [ "$mds1_FSTYPE" != "ldiskfs" ] &&
                skip "ldiskfs special test"
 
        check_mount_and_prep
@@ -1213,13 +1214,13 @@ test_15() {
        echo "starting MDTs with OI scrub disabled"
        scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB"
        scrub_check_status 3 init
-       [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] ||
+       [ "$mds1_FSTYPE" != "ldiskfs" ] ||
                scrub_check_flags 4 recreated,inconsistent
 
        # run under dryrun mode
        scrub_start 5 --dryrun
        scrub_check_status 6 completed
-       if [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ]; then
+       if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
                scrub_check_flags 7 inconsistent
                repaired=2
        else
@@ -1232,7 +1233,7 @@ test_15() {
        # run under dryrun mode again
        scrub_start 10 --dryrun
        scrub_check_status 11 completed
-       if [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ]; then
+       if [ "$mds1_FSTYPE" != "ldiskfs" ]; then
                scrub_check_flags 12 inconsistent
        else
                scrub_check_flags 12 recreated,inconsistent
@@ -1273,6 +1274,114 @@ test_16() {
 }
 run_test 16 "Initial OI scrub can rebuild crashed index objects"
 
+test_17a() {
+       [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
+
+#define OBD_FAIL_OSD_OI_ENOSPC                         0x19d
+       do_facet mds1 $LCTL set_param fail_loc=0x8000019d
+       mkdir $DIR/$tdir && error "mkdir should fail"
+       stop mds1
+       local devname=$(mdsdevname 1)
+
+       stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT
+       FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n ||
+               error "e2fsck returned $?"
+}
+run_test 17a "ENOSPC on OI insert shouldn't leak inodes"
+
+test_17b() {
+       [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
+
+#define OBD_FAIL_OSD_DOTDOT_ENOSPC                     0x19e
+       do_facet mds1 $LCTL set_param fail_loc=0x8000019e
+       mkdir $DIR/$tdir && error "mkdir should fail"
+       stop mds1
+       local devname=$(mdsdevname 1)
+
+       stack_trap "start mds1 $devname $MDS_MOUNT_OPTS" EXIT
+       FSCK_MAX_ERR=0 run_e2fsck $(facet_active_host mds1) $devname -n ||
+               error "e2fsck returned $?"
+}
+run_test 17b "ENOSPC on .. insertion shouldn't leak inodes"
+
+test_18() {
+       local n
+       local fids=()
+       local opts=$(csa_add "$MOUNT_OPTS_SCRUB" -o resetoi)
+
+       scrub_prep 10
+       scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
+       mount_client $MOUNT || error "(2) Fail to start client!"
+       for n in $(seq $MDSCOUNT); do
+               fids+=($($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh))
+       done
+       cleanup_mount $MOUNT > /dev/null || error "(3) Fail to stop client!"
+       for n in $(seq $MDSCOUNT); do
+               stop mds$n > /dev/null || error "(4) Fail to stop MDS$n!"
+       done
+       scrub_start_mds 5 "$opts"
+       do_facet mds1 dmesg | grep "reset Object Index" ||
+               error "(6) reset log not found"
+       mount_client $MOUNT || error "(7) Fail to start client!"
+       scrub_check_data 7
+
+       local fid
+       local path
+       for n in $(seq $MDSCOUNT); do
+               path=$($LFS fid2path $DIR ${fids[$((n - 1))]})
+               [ "$path" == "$DIR/$tdir/mds$n/test-framework.sh" ] ||
+                       error "path mismatch $path != $DIR/$tdir/mds$n/test-framework.sh"
+               fid=$($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh)
+               [ "${fids[$((n - 1))]}" == "$fid" ] ||
+                       error "$DIR/$tdir/mds$n/test-framework.sh FID mismatch ${fids[$((n - 1))]} != $fid"
+       done
+}
+run_test 18 "test mount -o resetoi to recreate OI files"
+
+test_19() {
+       local rcmd="do_facet ost${ost}"
+
+       check_mount_and_prep
+       $LFS setstripe -c 1 -i 0 $DIR/$tdir
+       createmany -o $DIR/$tdir/f 64 || error "(0) Fail to create 32 files."
+
+       echo "stopall"
+       stopall > /dev/null
+
+       # create mulitple link file
+       mount_fstype ost1 || error "(1) Fail to mount ost1"
+       mntpt=$(facet_mntpt ost1)
+
+       local path=$mntpt/O/0/d2
+       local file=$(${rcmd} ls $path | awk '{print $0; exit}')
+
+       # create link to the first file
+       echo "link $path/1 to $path/$file"
+       ${rcmd} ln $path/$file $path/1
+       unmount_fstype ost1 || error "(2) Fail to umount ost1"
+
+       start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
+               error "(2) Fail to start ost1"
+
+       $START_SCRUB_ON_OST -r || error "(3) Fail to start OI scrub on OST!"
+
+       wait_update_facet ost1 "$LCTL get_param -n \
+               osd-*.$(facet_svc ost1).oi_scrub |
+               awk '/^status/ { print \\\$2 }'" "completed" 6 ||
+               error "(4) Expected '$expected' on ost1"
+
+       stop ost1
+       mount_fstype ost1 || error "(5) Fail to mount ost1"
+       links=$(do_facet ost1 "stat $path/$file" | awk '/Links:/ { print $6 }')
+       unmount_fstype ost1 || error "(6) Fail to umount ost1"
+
+       start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null ||
+               error "(7) Fail to start ost1"
+
+       (( links == 1)) || error "(8) object links $links != 1 after scrub"
+}
+run_test 19 "LFSCK can fix multiple linked files on OST"
+
 # restore MDS/OST size
 MDSSIZE=${SAVED_MDSSIZE}
 OSTSIZE=${SAVED_OSTSIZE}