X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Ftests%2Fsanity-scrub.sh;h=80f78b76050887a882e33b422b9c61d63a647726;hp=aa32eb721f1a79ab5f6a2489218d739f38927933;hb=0c1ae1cb9c19f8a4f6c5a7ff6a1fd54807430795;hpb=7cecfcffae9737f929a2cbc8067e093a4f85c3ba diff --git a/lustre/tests/sanity-scrub.sh b/lustre/tests/sanity-scrub.sh index aa32eb7..80f78b7 100644 --- a/lustre/tests/sanity-scrub.sh +++ b/lustre/tests/sanity-scrub.sh @@ -7,683 +7,1389 @@ set -e ONLY=${ONLY:-"$*"} -ALWAYS_EXCEPT="$SANITY_SCRUB_EXCEPT" -[ "$SLOW" = "no" ] && EXCEPT_SLOW="" -# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT! -LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)} +LUSTRE=${LUSTRE:-$(dirname $0)/..} . $LUSTRE/tests/test-framework.sh init_test_env $@ -. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh} init_logging -[ "${MDSFSTYPE:-$FSTYPE}" != "ldiskfs" ] && - skip "test OI scrub only for ldiskfs" && exit 0 +ALWAYS_EXCEPT="$SANITY_SCRUB_EXCEPT" + +[ "$SLOW" = "no" ] && EXCEPT_SLOW="" +# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT! + +build_test_filter + require_dsh_mds || exit 0 +load_modules + +if ! check_versions; then + skip "It is NOT necessary to test scrub under interoperation mode" + exit 0 +fi + +cleanupall + SAVED_MDSSIZE=${MDSSIZE} SAVED_OSTSIZE=${OSTSIZE} +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 -MDSSIZE=100000 -OSTSIZE=100000 +# 400M MDT device can guarantee uninitialized groups during the OI scrub +[[ $MDSSIZE < 400000 || "$mds1_FSTYPE" == ldiskfs ]] && MDSSIZE=400000 +[[ $OSTSIZE < 400000 || "$ost1_FSTYPE" == ldiskfs ]] && OSTSIZE=400000 -check_and_setup_lustre -build_test_filter +# no need too many OSTs, to reduce the format/start/stop overhead +[ $OSTCOUNT -gt 4 ] && OSTCOUNT=4 + +# build up a clean test environment. +REFORMAT="yes" check_and_setup_lustre MDT_DEV="${FSNAME}-MDT0000" -MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/}) -START_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_start -M ${MDT_DEV}" +OST_DEV="${FSNAME}-OST0000" + +scrub_start() { + local error_id=$1 + local n + + # use "lfsck_start -A" when we no longer need testing interop + for n in $(seq $MDSCOUNT); do + do_facet mds$n $LCTL lfsck_start -M $(facet_svc mds$n) \ + -t scrub "$@" || + error "($error_id) Failed to start OI scrub on mds$n" + done +} + +scrub_stop() { + local error_id=$1 + local n + + # use "lfsck_stop -A" when we no longer need testing interop + for n in $(seq $MDSCOUNT); do + do_facet mds$n $LCTL lfsck_stop -M $(facet_svc mds$n) || + error "($error_id) Failed to stop OI scrub on mds$n" + done +} + +scrub_status() { + local n=$1 + + do_facet mds$n $LCTL get_param -n osd-*.$(facet_svc mds$n).oi_scrub +} + +START_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_start -M ${MDT_DEV} -t scrub" +START_SCRUB_ON_OST="do_facet ost1 $LCTL lfsck_start -M ${OST_DEV} -t scrub" STOP_SCRUB="do_facet $SINGLEMDS $LCTL lfsck_stop -M ${MDT_DEV}" SHOW_SCRUB="do_facet $SINGLEMDS \ - $LCTL get_param -n osd-ldiskfs.${MDT_DEV}.oi_scrub" -MOUNT_OPTS_SCRUB="-o user_xattr" -MOUNT_OPTS_NOSCRUB="-o user_xattr,noscrub" + $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="$MDS_MOUNT_OPTS -o user_xattr" +MOUNT_OPTS_NOSCRUB="$MDS_MOUNT_OPTS -o user_xattr,noscrub" scrub_prep() { local nfiles=$1 + local inject=$2 + local n + + check_mount_and_prep + + echo "preparing... $(date)" + for n in $(seq $MDSCOUNT); do + echo "creating $nfiles files on mds$n" + test_mkdir -i $((n - 1)) -c1 $DIR/$tdir/mds$n || + error "Failed to create directory mds$n" + cp $LUSTRE/tests/*.sh $DIR/$tdir/mds$n || + error "Failed to copy files to mds$n" + mkdir -p $DIR/$tdir/mds$n/d_$tfile || + error "mkdir failed on mds$n" + touch $DIR/$tdir/mds$n/d_$tfile/f1 > \ + /dev/null || error "create failed on mds$n" + dd if=/dev/zero of=$DIR/$tdir/mds$n/d_$tfile/f2 bs=1M count=1 || + error "write failed on mds$n" + if [[ $nfiles -gt 0 ]]; then + createmany -m $DIR/$tdir/mds$n/$tfile $nfiles > \ + /dev/null || error "createmany failed on mds$n" + fi + done + echo "prepared $(date)." - echo "formatall" - formatall > /dev/null - echo "setupall" - setupall > /dev/null + [ ! -z $inject ] && [ $inject -eq 2 ] && { + #define OBD_FAIL_OSD_NO_OI_ENTRY 0x198 + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0x198 + + for n in $(seq $MDSCOUNT); do + cp $LUSTRE/tests/runas $DIR/$tdir/mds$n || + error "Fail to copy runas to MDS$n" + done + + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0 + } - echo "preparing... ${nfiles} files will be created." - mkdir -p $DIR/$tdir - cp $LUSTRE/tests/*.sh $DIR/$tdir/ - [[ $nfiles -gt 0 ]] && { createmany -o $DIR/$tdir/$tfile $nfiles || - error "createmany failed"; } + [ ! -z $inject ] && [ $inject -eq 1 ] && + [ "$mds1_FSTYPE" = "zfs" ] && { + #define OBD_FAIL_OSD_FID_MAPPING 0x193 + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0x193 + + for n in $(seq $MDSCOUNT); do + chmod 0400 $DIR/$tdir/mds$n/test-framework.sh + chmod 0400 $DIR/$tdir/mds$n/sanity-scrub.sh + done + + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0 + } - echo "prepared." cleanup_mount $MOUNT > /dev/null || error "Fail to stop client!" - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "Fail to stop MDS!" + + # sync local transactions on every MDT + do_nodes $(comma_list $(mdts_nodes)) \ + "$LCTL set_param -n osd*.*MDT*.force_sync=1" + + # wait for a while to cancel update logs after transactions committed. + sleep 3 + + # sync again to guarantee all things done. + do_nodes $(comma_list $(mdts_nodes)) \ + "$LCTL set_param -n osd*.*MDT*.force_sync=1" + + for n in $(seq $MDSCOUNT); do + echo "stop mds$n" + stop mds$n > /dev/null || error "Fail to stop MDS$n!" + done + + [ ! -z $inject ] && [ "$mds1_FSTYPE" = "ldiskfs" ] && { + if [ $inject -eq 1 ]; then + for n in $(seq $MDSCOUNT); do + mds_backup_restore mds$n || + error "Backup/restore on mds$n failed" + done + elif [ $inject -eq 2 ]; then + scrub_remove_ois 1 + fi + } } -test_0() { - scrub_prep 0 - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(1) Fail to start MDS!" +scrub_start_mds() { + local error_id=$1 + local opts=$2 + local n - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(2) Expect 'init', but got '$STATUS'" + for n in $(seq $MDSCOUNT); do + start mds$n $(mdsdevname $n) $opts >/dev/null || + error "($error_id) Failed to start mds$n" + done +} - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(3) Expect empty flags, but got '$FLAGS'" +scrub_stop_mds() { + local error_id=$1 + local n - mount_client $MOUNT || error "(4) Fail to start client!" + for n in $(seq $MDSCOUNT); do + echo "stopping mds$n" + stop mds$n >/dev/null || + error "($error_id) Failed to stop mds$n" + done +} + +scrub_check_status() { + local error_id=$1 + local expected=$2 + local n + + for n in $(seq $MDSCOUNT); do + wait_update_facet mds$n "$LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub | + awk '/^status/ { print \\\$2 }'" "$expected" 6 || + error "($error_id) Expected '$expected' on mds$n" + done +} + +scrub_check_flags() { + local error_id=$1 + local expected=$2 + local actual + local n + + for n in $(seq $MDSCOUNT); do + actual=$(do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub | + awk '/^flags/ { print $2 }') + if [ "$actual" != "$expected" ]; then + error "($error_id) Expected '$expected' on mds$n, but" \ + "got '$actual'" + fi + done +} + +scrub_check_params() { + local error_id=$1 + local expected=$2 + local actual + local n + + for n in $(seq $MDSCOUNT); do + actual=$(do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub | + awk '/^param/ { print $2 }') + if [ "$actual" != "$expected" ]; then + error "($error_id) Expected '$expected' on mds$n, but" \ + "got '$actual'" + fi + done +} + +scrub_check_repaired() { + local error_id=$1 + local expected=$2 + local dryrun=$3 + local actual + local n + + for n in $(seq $MDSCOUNT); do + if [ $dryrun -eq 1 ]; then + actual=$(do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub | + awk '/^inconsistent:/ { print $2 }') + else + actual=$(do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub | + awk '/^updated:/ { print $2 }') + fi + + if [ $expected -eq 0 -a $actual -ne 0 ]; then + error "($error_id) Expected no repaired on mds$n, but" \ + "got '$actual'" + fi + + if [ $expected -ne 0 -a $actual -lt $expected ]; then + error "($error_id) Expected '$expected' on mds$n, but" \ + "got '$actual'" + fi + done +} + +scrub_check_data() { + local error_id=$1 + local n + + for n in $(seq $MDSCOUNT); do + diff -q $LUSTRE/tests/test-framework.sh \ + $DIR/$tdir/mds$n/test-framework.sh || + error "($error_id) File data check failed" + done +} + +scrub_check_data2() { + local filename=$1 + local error_id=$2 + local n + + for n in $(seq $MDSCOUNT); do + diff -q $LUSTRE/tests/$filename \ + $DIR/$tdir/mds$n/$filename || + error "($error_id) File data check failed" + done +} + +scrub_remove_ois() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && return + + local error_id=$1 + local index=$2 + local n + + for n in $(seq $MDSCOUNT); do + mds_remove_ois mds$n $index || + error "($error_id) Failed to remove OI .$index on mds$n" + done +} + +scrub_enable_auto() { + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param -n \ + osd-*.*.auto_scrub=1 +} + +full_scrub_ratio() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && return + + local ratio=$1 + + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param -n \ + osd-*.*.full_scrub_ratio=$ratio +} + +full_scrub_threshold_rate() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && return + + local rate=$1 - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(5) File diff failed unexpected!" + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param -n \ + osd-*.*.full_scrub_threshold_rate=$rate +} + +scrub_enable_index_backup() { + do_nodes $(comma_list $(all_server_nodes)) $LCTL set_param -n \ + osd-*.*.index_backup=1 +} + +scrub_disable_index_backup() { + do_nodes $(comma_list $(all_server_nodes)) $LCTL set_param -n \ + osd-*.*.index_backup=0 +} + +test_0() { + scrub_prep 0 + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 1 "$MOUNT_OPTS_SCRUB" + scrub_check_status 2 init + scrub_check_flags 3 "" + mount_client $MOUNT || error "(4) Fail to start client!" + scrub_check_data 5 } run_test 0 "Do not auto trigger OI scrub for non-backup/restore case" test_1a() { - scrub_prep 0 - mds_remove_ois || error "(1) Fail to remove/recreate!" + [ -n "$FILESET" ] && skip "Not functional for FILESET set" - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(2) Fail to start MDS!" + scrub_prep 0 + echo "start $SINGLEMDS without disabling OI scrub: $MOUNT_OPTS_SCRUB" + scrub_start_mds 1 "$MOUNT_OPTS_SCRUB" - sleep 3 - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(3) Expect 'completed', but got '$STATUS'" + local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') + [ -z "$FLAGS" ] || error "(3) Expect empty flags, but got '$FLAGS'" mount_client $MOUNT || error "(4) Fail to start client!" + #define OBD_FAIL_OSD_FID_MAPPING 0x193 + do_facet $SINGLEMDS $LCTL set_param fail_loc=0x193 + # update .lustre OI mapping + touch $MOUNT/.lustre + do_facet $SINGLEMDS $LCTL set_param fail_loc=0 + umount_client $MOUNT || error "(5) Fail to stop client!" + + echo "stop $SINGLEMDS" + stop $SINGLEMDS > /dev/null || error "(6) Fail to stop MDS!" - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(5) File diff failed unexpected!" + 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!" + + local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') + [ "$FLAGS" == "inconsistent" ] || + error "(9) Expect 'inconsistent', but got '$FLAGS'" } -run_test 1a "Trigger OI scrub when MDT mounts for OI files remove/recreate case" +run_test 1a "Auto trigger initial OI scrub when server mounts" test_1b() { + scrub_prep 0 2 + echo "start MDTs without disabling OI scrub" + scrub_start_mds 2 "$MOUNT_OPTS_SCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_status 3 completed + mount_client $MOUNT || error "(4) Fail to start client!" + scrub_check_data2 runas 5 + scrub_check_status 6 completed +} +run_test 1b "Trigger OI scrub when MDT mounts for OI files remove/recreate case" + +test_1c() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && + skip "ldiskfs special test" + local index # OI files to be removed: # idx 0: oi.16.0 - # idx 1: oi.16.1 # idx 2: oi.16.{2,4,8,16,32} # idx 3: oi.16.{3,9,27} - # idx 5: oi.16.{5,25} - # idx 7: oi.16.{7,49} - for index in 0 1 2 3 5 7; do + for index in 0 2 3; do scrub_prep 0 - mds_remove_ois ${index} || error "(1) Fail to remove/recreate!" + scrub_remove_ois 1 $index + echo "start MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_flags 3 recreated + scrub_start 4 + scrub_check_status 5 completed + scrub_check_flags 6 "" + done +} +run_test 1c "Auto detect kinds of OI file(s) removed/recreated cases" - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > \ - /dev/null || error "(2) Fail to start MDS!" +test_2() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && + skip "ldiskfs special test" - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "recreated" ] || - error "(3) Expect 'recreated', but got '$STATUS'" + scrub_prep 0 1 + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 2 "$MOUNT_OPTS_SCRUB" + scrub_check_status 3 completed + mount_client $MOUNT || error "(4) Fail to start client!" + scrub_check_data 5 +} +run_test 2 "Trigger OI scrub when MDT mounts for backup/restore case" - $START_SCRUB || error "(4) Fail to start OI scrub!" - sleep 3 - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(5) Expect 'completed', but got '$STATUS'" +# test_3 is obsolete, it will be covered by test_5. +test_3() { + formatall > /dev/null + setupall > /dev/null - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || - error "(6) Expect empty flags, but got '$FLAGS'" + scrub_prep 0 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_status 3 init + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent +} +#run_test 3 "Do not trigger OI scrub when MDT mounts if 'noscrub' specified" + +test_4a() { + scrub_prep 0 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent + mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 0 + scrub_check_data 6 + sleep 3 + + scrub_check_status 7 completed + scrub_check_flags 8 "" + + local -a updated0 + for n in $(seq $MDSCOUNT); do + updated0[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + done + + scrub_check_data2 sanity-scrub.sh 9 + sleep 3 + + local -a updated1 + for n in $(seq $MDSCOUNT); do + updated1[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + [ ${updated0[$n]} -eq ${updated1[$n]} ] || + error "(10) NOT auto trigger full scrub as expected" done } -run_test 1b "Auto detect kinds of OI file(s) removed/recreated cases" +run_test 4a "Auto trigger OI scrub if bad OI mapping was found (1)" -test_2() { - scrub_prep 0 - mds_backup_restore || error "(1) Fail to backup/restore!" +test_4b() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && + skip "ldiskfs special test" + + scrub_prep 5 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_flags 4 recreated,inconsistent + mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 10 + full_scrub_threshold_rate 10000 + scrub_check_data 6 + sleep 3 + + scrub_check_status 7 completed + scrub_check_flags 8 "" - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(2) Fail to start MDS!" + local -a updated0 + for n in $(seq $MDSCOUNT); do + updated0[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + echo "OI scrub on MDS$n status for the 1st time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub + done + + scrub_check_data2 sanity-scrub.sh 9 sleep 3 - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(3) Expect 'completed', but got '$STATUS'" - mount_client $MOUNT || error "(4) Fail to start client!" + scrub_check_status 10 completed + scrub_check_flags 11 "" - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(5) File diff failed unexpected!" -} -run_test 2 "Trigger OI scrub when MDT mounts for backup/restore case" + local -a updated1 + for n in $(seq $MDSCOUNT); do + updated1[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') -test_3() { - scrub_prep 0 - mds_backup_restore || error "(1) Fail to backup/restore!" + echo "OI scrub on MDS$n status for the 2nd time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + [ ${updated0[$n]} -lt ${updated1[$n]} ] || + error "(12) Auto trigger full scrub unexpectedly" + done - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + for n in $(seq $MDSCOUNT); do + ls -l $DIR/$tdir/mds$n/*.sh > /dev/null || + error "(13) fail to ls" + done + sleep 3 - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" - echo "stopall" - stopall > /dev/null -} -run_test 3 "Do not trigger OI scrub when MDT mounts if 'noscrub' specified" + scrub_check_status 14 completed + scrub_check_flags 15 "" -test_4() { - scrub_prep 0 - mds_backup_restore || error "(1) Fail to backup/restore!" + for n in $(seq $MDSCOUNT); do + updated0[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + echo "OI scrub on MDS$n status for the 3rd time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + [ ${updated0[$n]} -gt ${updated1[$n]} ] || + error "(16) Auto trigger full scrub unexpectedly" + done - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" + for n in $(seq $MDSCOUNT); do + ls -l $DIR/$tdir/mds$n/d_${tfile}/ || error "(17) fail to ls" + done + sleep 3 + + for n in $(seq $MDSCOUNT); do + updated1[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + [ ${updated0[$n]} -eq ${updated1[$n]} ] || { + echo "OI scrub on MDS$n status for the 4th time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub + error "(18) NOT auto trigger full scrub as expected" + } + done +} +run_test 4b "Auto trigger OI scrub if bad OI mapping was found (2)" + +test_4c() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && + skip "ldiskfs special test" + + scrub_prep 500 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_flags 4 recreated,inconsistent mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 2 + full_scrub_threshold_rate 20 + scrub_check_data 6 + sleep 3 - do_facet $SINGLEMDS \ - $LCTL set_param -n osd-ldiskfs.${MDT_DEV}.auto_scrub 1 - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(6) File diff failed unexpected!" + scrub_check_status 7 completed + scrub_check_flags 8 "" + local -a updated0 + for n in $(seq $MDSCOUNT); do + updated0[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + + echo "OI scrub on MDS$n status for the 1st time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub + done + + scrub_check_data2 sanity-scrub.sh 9 sleep 3 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(7) Expect 'completed', but got '$STATUS'" + + scrub_check_status 10 completed + scrub_check_flags 11 "" + + local -a updated1 + for n in $(seq $MDSCOUNT); do + updated1[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + + echo "OI scrub on MDS$n status for the 2nd time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub + + [ ${updated0[$n]} -lt ${updated1[$n]} ] || + error "(12) Auto trigger full scrub unexpectedly" + done + + for n in $(seq $MDSCOUNT); do + ls -l $DIR/$tdir/mds$n/*.sh > /dev/null || + error "(13) fail to ls" + done + sleep 3 + + scrub_check_status 14 completed + scrub_check_flags 15 "" + + for n in $(seq $MDSCOUNT); do + updated0[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + + echo "OI scrub on MDS$n status for the 3rd time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub + + [ ${updated0[$n]} -gt ${updated1[$n]} ] || + error "(16) Auto trigger full scrub unexpectedly" + done + + for n in $(seq $MDSCOUNT); do + ls -l $DIR/$tdir/mds$n/${tfile}1 || error "(17) fail to ls" + done + sleep 3 + + for n in $(seq $MDSCOUNT); do + updated1[$n]=$(scrub_status $n | + awk '/^prior_updated/ { print $2 }') + [ ${updated0[$n]} -eq ${updated1[$n]} ] || { + echo "OI scrub on MDS$n status for the 4th time:" + do_facet mds$n $LCTL get_param -n \ + osd-*.$(facet_svc mds$n).oi_scrub + + error "(18) NOT auto trigger full scrub as expected" + } + done } -run_test 4 "Trigger OI scrub automatically if inconsistent OI mapping was found" +run_test 4c "Auto trigger OI scrub if bad OI mapping was found (3)" -test_5() { - scrub_prep 1500 - mds_backup_restore || error "(1) Fail to backup/restore!" +test_4d() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && skip "ldiskfs only test" - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + check_mount_and_prep - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + #define OBD_FAIL_OSD_DUPLICATE_MAP 0x19b + do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x19b + for i in {1..100}; do + echo $i > $DIR/$tdir/f_$i || error "write f_$i failed" + done + do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0 - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" + for i in {101..200}; do + echo $i > $DIR/$tdir/f_$i || error "write f_$i failed" + done + for i in {1..200}; do + echo $i | cmp $DIR/$tdir/f_$i - || error "f_$i data corrupt" + done +} +run_test 4d "FID in LMA mismatch with object FID won't block create" + +test_5() { + formatall > /dev/null + setupall > /dev/null + + scrub_prep 100 1 + echo "starting MDTs with OI scrub disabled (1)" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_status 3 init + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 0 - do_facet $SINGLEMDS \ - $LCTL set_param -n osd-ldiskfs.${MDT_DEV}.auto_scrub 1 #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(6) File diff failed unexpected!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=3 fail_loc=0x190 + scrub_check_data 6 umount_client $MOUNT || error "(7) Fail to stop client!" - - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(8) Expect 'scanning', but got '$STATUS'" + scrub_check_status 8 scanning #define OBD_FAIL_OSD_SCRUB_CRASH 0x191 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80000191 + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x191 + sleep 4 - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(9) Fail to stop MDS!" + scrub_stop_mds 9 - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(10) Fail to start MDS!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "crashed" ] || - error "(11) Expect 'crashed', but got '$STATUS'" - - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(12) Fail to stop MDS!" + echo "starting MDTs with OI scrub disabled (2)" + scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB" + scrub_check_status 11 crashed + scrub_stop_mds 12 #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(13) Fail to start MDS!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=3 fail_loc=0x190 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(14) Expect 'scanning', but got '$STATUS'" + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 13 "$MOUNT_OPTS_SCRUB" + scrub_check_status 14 scanning #define OBD_FAIL_OSD_SCRUB_FATAL 0x192 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80000192 - sleep 4 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "failed" ] || - error "(15) Expect 'failed', but got '$STATUS'" + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x192 + scrub_check_status 15 failed mount_client $MOUNT || error "(16) Fail to start client!" - #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - stat $DIR/$tdir/${tfile}1000 || - error "(17) Fail to stat $DIR/$tdir/${tfile}1000!" + full_scrub_ratio 0 + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(18) Expect 'scanning', but got '$STATUS'" + local n + declare -a pids - do_facet $SINGLEMDS $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS $LCTL set_param fail_val=0 - sleep 5 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(19) Expect 'completed', but got '$STATUS'" + for n in $(seq $MDSCOUNT); do + stat $DIR/$tdir/mds$n/sanity-scrub.sh & + pids[$n]=$! + done + + for n in $(seq $MDSCOUNT); do + wait ${pids[$n]} || + error "(18) Fail to stat mds$n/sanity-scrub.sh" + done - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(20) Expect empty flags, but got '$FLAGS'" + scrub_check_status 19 completed + scrub_check_flags 20 "" } run_test 5 "OI scrub state machine" test_6() { - scrub_prep 1000 - mds_backup_restore || error "(1) Fail to backup/restore!" - - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" - - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" - - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" - + scrub_prep 100 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 0 - do_facet $SINGLEMDS \ - $LCTL set_param -n osd-ldiskfs.${MDT_DEV}.auto_scrub 1 #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(6) File diff failed unexpected!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=2 fail_loc=0x190 + + scrub_check_data 6 - sleep 8 + # Sleep 5 sec to guarantee at least one object processed by OI scrub + sleep 5 # Fail the OI scrub to guarantee there is at least one checkpoint #define OBD_FAIL_OSD_SCRUB_FATAL 0x192 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80000192 - sleep 4 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "failed" ] || - error "(7) Expect 'failed', but got '$STATUS'" + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x192 + + scrub_check_status 7 failed #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - # stat will re-trigger OI scrub - stat $DIR/$tdir/${tfile}800 || - error "(8) Fail to stat $DIR/$tdir/${tfile}800!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=3 fail_loc=0x190 + + local n + for n in $(seq $MDSCOUNT); do + # stat will re-trigger OI scrub + stat $DIR/$tdir/mds$n/sanity-scrub.sh || + error "(8) Failed to stat mds$n/sanity-scrub.sh" + done umount_client $MOUNT || error "(9) Fail to stop client!" - - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(10) Expect 'scanning', but got '$STATUS'" + scrub_check_status 10 scanning #define OBD_FAIL_OSD_SCRUB_CRASH 0x191 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80000191 + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x191 + sleep 4 - local POSITION0=$($SHOW_SCRUB | \ + local -a position0 + for n in $(seq $MDSCOUNT); do + position0[$n]=$(scrub_status $n | awk '/^last_checkpoint_position/ {print $2}') - POSITION0=$((POSITION0 + 1)) + position0[$n]=$((${position0[$n]} + 1)) + done - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(11) Fail to stop MDS!" + scrub_stop_mds 11 #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(12) Fail to start MDS!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=3 fail_loc=0x190 + + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 12 "$MOUNT_OPTS_SCRUB" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(13) Expect 'scanning', but got '$STATUS'" + scrub_check_status 13 scanning - local POSITION1=$($SHOW_SCRUB | \ + local -a position1 + for n in $(seq $MDSCOUNT); do + position1[$n]=$(scrub_status $n | awk '/^latest_start_position/ {print $2}') - [ $POSITION0 -eq $POSITION1 ] || - error "(14) Expect position: $POSITION0, but got $POSITION1" + if [ ${position0[$n]} -ne ${position1[$n]} ]; then + error "(14) Expected position ${position0[$n]}, but" \ + "got ${position1[$n]}" + fi + done - do_facet $SINGLEMDS $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS $LCTL set_param fail_val=0 - sleep 5 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(15) Expect 'completed', but got '$STATUS'" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(16) Expect empty flags, but got '$FLAGS'" + scrub_check_status 15 completed + scrub_check_flags 16 "" } run_test 6 "OI scrub resumes from last checkpoint" test_7() { - scrub_prep 500 - mds_backup_restore || error "(1) Fail to backup/restore!" + scrub_prep 500 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent + mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 0 - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=3 fail_loc=0x190 - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + scrub_check_data 6 - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" + local n + for n in $(seq $MDSCOUNT); do + stat $DIR/$tdir/mds$n/${tfile}300 || + error "(7) Failed to stat mds$n/${tfile}300!" + done - mount_client $MOUNT || error "(5) Fail to start client!" + scrub_check_status 8 scanning + if [ "$mds1_FSTYPE" != "ldiskfs" ]; then + scrub_check_flags 9 inconsistent,auto + else + scrub_check_flags 9 recreated,inconsistent,auto + fi + + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 + + scrub_check_status 10 completed + scrub_check_flags "" +} +run_test 7 "System is available during OI scrub scanning" + +test_8() { + scrub_prep 128 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent - do_facet $SINGLEMDS \ - $LCTL set_param -n osd-ldiskfs.${MDT_DEV}.auto_scrub 1 #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(6) File diff failed unexpected!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=1 fail_loc=0x190 - stat $DIR/$tdir/${tfile}300 || - error "(7) Fail to stat $DIR/$tdir/${tfile}300!" + scrub_start 5 + scrub_check_status 6 scanning + scrub_stop 7 + scrub_check_status 8 stopped + scrub_start 9 + scrub_check_status 10 scanning - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(8) Expect 'scanning', but got '$STATUS'" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent,auto" ] || - error "(9) Expect 'inconsistent,auto', but got '$FLAGS'" + scrub_check_status 11 completed + scrub_check_flags 12 "" +} +run_test 8 "Control OI scrub manually" - do_facet $SINGLEMDS $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS $LCTL set_param fail_val=0 - sleep 5 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(10) Expect 'completed', but got '$STATUS'" +test_9() { + # Skip scrub speed test for ZFS because of performance unstable + [ "$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." + fi + + scrub_prep 6000 1 + + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_flags 4 recreated,inconsistent + + local BASE_SPEED1=100 + local RUN_TIME1=10 + # OI scrub should run with full speed under inconsistent case + scrub_start 5 -s $BASE_SPEED1 + + 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 + + sleep $RUN_TIME1 + scrub_check_status 9 scanning + + # Do NOT ignore that there are 1024 pre-fetched items. And there + # may be time error, normally it should be less than 2 seconds. + # We allow another 20% schedule error. + local PRE_FETCHED=1024 + local TIME_DIFF=2 + # MAX_MARGIN = 1.2 = 12 / 10 + local MAX_SPEED=$(((PRE_FETCHED + BASE_SPEED1 * \ + (RUN_TIME1 + TIME_DIFF)) / RUN_TIME1 * 12 / 10)) + local n + for n in $(seq $MDSCOUNT); do + local SPEED=$(scrub_status $n | \ + awk '/^average_speed/ { print $2 }') + [ $SPEED -lt $MAX_SPEED ] || + error "(10) Got speed $SPEED, expected less than" \ + "$MAX_SPEED" + done + + # adjust speed limit + local BASE_SPEED2=300 + local RUN_TIME2=10 + for n in $(seq $MDSCOUNT); do + do_facet mds$n $LCTL set_param -n \ + mdd.$(facet_svc mds$n).lfsck_speed_limit $BASE_SPEED2 + done + sleep $RUN_TIME2 + + # 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) * (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) * (10 + MARGIN) / 10)) + for n in $(seq $MDSCOUNT); do + SPEED=$(scrub_status $n | awk '/^average_speed/ { print $2 }') + [ $SPEED -gt $MIN_SPEED ] || + error "(11) Got speed $SPEED, expected more than" \ + "$MIN_SPEED" + [ $SPEED -lt $MAX_SPEED ] || + error "(12) Got speed $SPEED, expected less than" \ + "$MAX_SPEED" + + do_facet mds$n $LCTL set_param -n \ + mdd.$(facet_svc mds$n).lfsck_speed_limit 0 + done - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(11) Expect empty flags, but got '$FLAGS'" + scrub_check_status 13 completed } -run_test 7 "System is available during OI scrub scanning" +run_test 9 "OI scrub speed control" -test_8() { - scrub_prep 0 - mds_backup_restore || error "(1) Fail to backup/restore!" +test_10a() { + scrub_prep 0 1 + echo "starting mds$n with OI scrub disabled (1)" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent + mount_client $MOUNT || error "(5) Fail to start client!" + scrub_enable_auto + full_scrub_ratio 0 - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=1 fail_loc=0x190 - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + scrub_check_data 6 + scrub_check_status 7 scanning + umount_client $MOUNT || error "(8) Fail to stop client!" + scrub_stop_mds 9 + echo "starting MDTs with OI scrub disabled (2)" + scrub_start_mds 10 "$MOUNT_OPTS_NOSCRUB" + scrub_check_status 11 paused + scrub_stop_mds 12 + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 13 "$MOUNT_OPTS_SCRUB" + scrub_check_status 14 scanning + + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 + + scrub_check_status 15 completed + scrub_check_flags 16 "" +} +run_test 10a "non-stopped OI scrub should auto restarts after MDS remount (1)" - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" +# test_10b is obsolete, it will be coverded by related sanity-lfsck tests. +test_10b() { + scrub_prep 0 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - $START_SCRUB || error "(5) Fail to start OI scrub!" + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_val=3 fail_loc=0x190 + + scrub_start 5 + scrub_check_status 6 scanning + scrub_stop_mds 7 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 8 "$MOUNT_OPTS_NOSCRUB" + scrub_check_status 9 paused + scrub_stop_mds 10 + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 11 "$MOUNT_OPTS_SCRUB" + scrub_check_status 12 scanning + + do_nodes $(comma_list $(mdts_nodes)) \ + $LCTL set_param fail_loc=0 fail_val=0 + + scrub_check_status 13 completed + scrub_check_flags 14 "" +} +#run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(6) Expect 'scanning', but got '$STATUS'" +test_11() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && + skip "ldiskfs special test" - $STOP_SCRUB || error "(7) Fail to stop OI scrub!" + local CREATED=100 + local n - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "stopped" ] || - error "(8) Expect 'stopped', but got '$STATUS'" + check_mount_and_prep - $START_SCRUB || error "(9) Fail to start OI scrub!" + for n in $(seq $MDSCOUNT); do + test_mkdir -i $((n - 1)) -c1 $DIR/$tdir/mds$n || + error "(1) Fail to mkdir $DIR/$tdir/mds$n" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(10) Expect 'scanning', but got '$STATUS'" + createmany -o $DIR/$tdir/mds$n/f $CREATED || + error "(2) Fail to create under $tdir/mds$n" + done - do_facet $SINGLEMDS $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS $LCTL set_param fail_val=0 - sleep 5 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(11) Expect 'completed', but got '$STATUS'" + # reset OI scrub start point by force + scrub_start 3 -r + scrub_check_status 4 completed + + declare -a checked0 + declare -a checked1 + + # OI scrub should skip the new created objects for the first accessing + # notice we're creating a new llog for every OST on every startup + # new features can make this even less stable, so we only check that + # the number of skipped files is more than the number or known created + local MINIMUM=$((CREATED + 1)) # files + directory + for n in $(seq $MDSCOUNT); do + local SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }') + [ $SKIPPED -lt $MINIMUM ] && + error "(5) Expect at least $MINIMUM objects" \ + "skipped on mds$n, but got $SKIPPED" + + checked0[$n]=$(scrub_status $n | awk '/^checked/ { print $2 }') + done + + # reset OI scrub start point by force + scrub_start 6 -r + scrub_check_status 7 completed + + # OI scrub should skip the new created object only once + for n in $(seq $MDSCOUNT); do + SKIPPED=$(scrub_status $n | awk '/^noscrub/ { print $2 }') + checked1[$n]=$(scrub_status $n | awk '/^checked/ { print $2 }') - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(12) Expect empty flags, but got '$FLAGS'" + [ ${checked0[$n]} -ne ${checked1[$n]} -o $SKIPPED -eq 0 ] || + error "(8) Expect 0 objects skipped on mds$n, but" \ + "got $SKIPPED" + done } -run_test 8 "Control OI scrub manually" +run_test 11 "OI scrub skips the new created objects only once" -test_9() { - scrub_prep 8000 - mds_backup_restore || error "(1) Fail to backup/restore!" +test_12() { + check_mount_and_prep + $LFS setstripe -c 1 -i 0 $DIR/$tdir - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + #define OBD_FAIL_OSD_COMPAT_INVALID_ENTRY 0x195 + do_facet ost1 $LCTL set_param fail_loc=0x195 + local count=$(precreated_ost_obj_count 0 0) - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + createmany -o $DIR/$tdir/f $((count + 32)) + umount_client $MOUNT || error "(1) Fail to stop client!" - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" + stop ost1 || error "(2) Fail to stop ost1" - # OI scrub should run with full speed under inconsistent case - $START_SCRUB -s 100 || error "(5) Fail to start OI scrub!" + #define OBD_FAIL_OST_NODESTROY 0x233 + do_facet ost1 $LCTL set_param fail_loc=0x233 - sleep 10 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(6) Expect 'completed', but got '$STATUS'" + start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB || + error "(3) Fail to start ost1" - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(7) Expect empty flags, but got '$FLAGS'" + mount_client $MOUNT || error "(4) Fail to start client!" - # OI scrub should run with limited speed under non-inconsistent case - $START_SCRUB -s 100 -r || error "(8) Fail to start OI scrub!" + ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail" - sleep 10 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(9) Expect 'scanning', but got '$STATUS'" + $START_SCRUB_ON_OST -r || error "(6) Fail to start OI scrub on OST!" - # Do NOT ignore that there are 1024 pre-fetched items. - # So the max speed may be (1024 + 100 * 10) / 10. - # And there may be time error, so the max speed may be more large. - local SPEED=$($SHOW_SCRUB | awk '/^average_speed/ { print $2 }') - [ $SPEED -gt 220 ] && - error "(10) Unexpected speed $SPEED, should not more than 220" + do_facet ost1 $LCTL set_param fail_loc=0 + wait_update_facet ost1 "$LCTL get_param -n \ + osd-*.$(facet_svc ost1).oi_scrub | + awk '/^status/ { print \\\$2 }'" "completed" 6 || + error "(7) Expected '$expected' on ost1" - # adjust speed limit - do_facet $SINGLEMDS \ - $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 300 - sleep 10 + ls -ail $DIR/$tdir > /dev/null || { + $SHOW_SCRUB_ON_OST + error "(8) ls should succeed" + } +} +run_test 12 "OI scrub can rebuild invalid /O entries" + +test_13() { + check_mount_and_prep + $LFS setstripe -c 1 -i 0 $DIR/$tdir - SPEED=$($SHOW_SCRUB | awk '/^average_speed/ { print $2 }') - [ $SPEED -lt 220 ] && - error "(11) Unexpected speed $SPEED, should not less than 220" + #define OBD_FAIL_OSD_COMPAT_NO_ENTRY 0x196 + do_facet ost1 $LCTL set_param fail_loc=0x196 + local count=$(precreated_ost_obj_count 0 0) - # (1024 + 100 * 10 + 300 * 10) / 20 - [ $SPEED -gt 270 ] && - error "(12) Unexpected speed $SPEED, should not more than 270" + createmany -o $DIR/$tdir/f $((count + 32)) + do_facet ost1 $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS \ - $LCTL set_param -n mdd.${MDT_DEV}.lfsck_speed_limit 0 - sleep 6 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(13) Expect 'completed', but got '$STATUS'" + umount_client $MOUNT || error "(1) Fail to stop client!" + + stop ost1 || error "(2) Fail to stop ost1" + + start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB || + error "(3) Fail to start ost1" + + mount_client $MOUNT || error "(4) Fail to start client!" + + ls -ail $DIR/$tdir > /dev/null 2>&1 && error "(5) ls should fail" + + $START_SCRUB_ON_OST -r || error "(6) 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 "(7) Expected '$expected' on ost1" + + ls -ail $DIR/$tdir > /dev/null || error "(8) ls should succeed" } -run_test 9 "OI scrub speed control" +run_test 13 "OI scrub can rebuild missed /O entries" -test_10a() { - scrub_prep 0 - mds_backup_restore || error "(1) Fail to backup/restore!" +test_14() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && + skip "ldiskfs special test" - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + check_mount_and_prep + $LFS setstripe -c 1 -i 0 $DIR/$tdir - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" + #define OBD_FAIL_OSD_COMPAT_NO_ENTRY 0x196 + do_facet ost1 $LCTL set_param fail_loc=0x196 + local count=$(precreated_ost_obj_count 0 0) - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" + createmany -o $DIR/$tdir/f $((count + 1000)) + do_facet ost1 $LCTL set_param fail_loc=0 - mount_client $MOUNT || error "(5) Fail to start client!" + umount_client $MOUNT || error "(1) Fail to stop client!" - do_facet $SINGLEMDS \ - $LCTL set_param -n osd-ldiskfs.${MDT_DEV}.auto_scrub 1 - #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 - diff -q $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh || - error "(6) File diff failed unexpected!" + stop ost1 || error "(2) Fail to stop ost1" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(7) Expect 'scanning', but got '$STATUS'" + echo "run e2fsck" + run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" || + error "(3) Fail to run e2fsck error" - umount_client $MOUNT || error "(8) Fail to stop client!" + start ost1 $(ostdevname 1) $OST_MOUNT_OPTS || + error "(4) Fail to start ost1" - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(9) Fail to stop MDS!" + mount_client $MOUNT || error "(5) Fail to start client!" - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(10) Fail to start MDS!" + local LF_REPAIRED=$($SHOW_SCRUB_ON_OST | + awk '/^lf_repa[ir]*ed/ { print $2 }') + [ $LF_REPAIRED -ge 1000 ] || + error "(6) Some entry under /lost+found should be repaired" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "paused" ] || - error "(11) Expect 'paused', but got '$STATUS'" + ls -ail $DIR/$tdir > /dev/null || error "(7) ls should succeed" - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(12) Fail to stop MDS!" + stopall - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(13) Fail to start MDS!" + echo "run e2fsck again after LFSCK" + run_e2fsck $(facet_host ost1) $(ostdevname 1) "-y" || + error "(8) Fail to run e2fsck error" +} +run_test 14 "OI scrub can repair OST objects under lost+found" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(14) Expect 'scanning', but got '$STATUS'" +test_15() { + local repaired - do_facet $SINGLEMDS $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS $LCTL set_param fail_val=0 - sleep 5 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(15) Expect 'completed', but got '$STATUS'" + formatall > /dev/null + setupall > /dev/null - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(16) Expect empty flags, but got '$FLAGS'" + scrub_prep 20 1 + echo "starting MDTs with OI scrub disabled" + scrub_start_mds 2 "$MOUNT_OPTS_NOSCRUB" + scrub_check_status 3 init + [ "$mds1_FSTYPE" != "ldiskfs" ] || + scrub_check_flags 4 recreated,inconsistent + + # run under dryrun mode + scrub_start 5 --dryrun + scrub_check_status 6 completed + if [ "$mds1_FSTYPE" != "ldiskfs" ]; then + scrub_check_flags 7 inconsistent + repaired=2 + else + scrub_check_flags 7 recreated,inconsistent + repaired=20 + fi + scrub_check_params 8 dryrun + scrub_check_repaired 9 $repaired 1 + + # run under dryrun mode again + scrub_start 10 --dryrun + scrub_check_status 11 completed + if [ "$mds1_FSTYPE" != "ldiskfs" ]; then + scrub_check_flags 12 inconsistent + else + scrub_check_flags 12 recreated,inconsistent + fi + scrub_check_params 13 dryrun + scrub_check_repaired 14 $repaired 1 + + # run under normal mode + scrub_start 15 + scrub_check_status 16 completed + scrub_check_flags 17 "" + scrub_check_params 18 "" + scrub_check_repaired 19 $repaired 0 + + # run under normal mode again + scrub_start 20 + scrub_check_status 21 completed + scrub_check_flags 22 "" + scrub_check_params 23 "" + scrub_check_repaired 24 0 0 } -run_test 10a "non-stopped OI scrub should auto restarts after MDS remount (1)" +run_test 15 "Dryrun mode OI scrub" -test_10b() { +test_16() { + check_mount_and_prep + scrub_enable_index_backup + + #define OBD_FAIL_OSD_INDEX_CRASH 0x199 + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0x199 scrub_prep 0 - mds_backup_restore || error "(1) Fail to backup/restore!" + do_nodes $(comma_list $(mdts_nodes)) $LCTL set_param fail_loc=0 - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(2) Fail to start MDS!" + echo "starting MDTs without disabling OI scrub" + scrub_start_mds 1 "$MOUNT_OPTS_SCRUB" + mount_client $MOUNT || error "(2) Fail to start client!" + scrub_check_data 3 + scrub_disable_index_backup +} +run_test 16 "Initial OI scrub can rebuild crashed index objects" - local STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "init" ] || - error "(3) Expect 'init', but got '$STATUS'" +test_17a() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test" - local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ "$FLAGS" == "inconsistent" ] || - error "(4) Expect 'inconsistent', but got '$FLAGS'" +#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) - #define OBD_FAIL_OSD_SCRUB_DELAY 0x190 - do_facet $SINGLEMDS $LCTL set_param fail_val=3 - do_facet $SINGLEMDS $LCTL set_param fail_loc=0x190 + 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" - $START_SCRUB || error "(5) Fail to start OI scrub!" +test_17b() { + [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(6) Expect 'scanning', but got '$STATUS'" +#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) - echo "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(7) Fail to stop MDS!" + 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" - echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || - error "(8) Fail to start MDS!" +test_19() { + local rcmd="do_facet ost${ost}" - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "paused" ] || - error "(9) Expect 'paused', but got '$STATUS'" + 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 "stop $SINGLEMDS" - stop $SINGLEMDS > /dev/null || error "(10) Fail to stop MDS!" + echo "stopall" + stopall > /dev/null - echo "start $SINGLEMDS without disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_SCRUB > /dev/null || - error "(11) Fail to start MDS!" + # create mulitple link file + mount_fstype ost1 || error "(1) Fail to mount ost1" + mntpt=$(facet_mntpt ost1) - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "scanning" ] || - error "(12) Expect 'scanning', but got '$STATUS'" + local path=$mntpt/O/0/d2 + local file=$(${rcmd} ls $path | awk '{print $0; exit}') - do_facet $SINGLEMDS $LCTL set_param fail_loc=0 - do_facet $SINGLEMDS $LCTL set_param fail_val=0 - sleep 5 - STATUS=$($SHOW_SCRUB | awk '/^status/ { print $2 }') - [ "$STATUS" == "completed" ] || - error "(13) Expect 'completed', but got '$STATUS'" + # 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" - FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') - [ -z "$FLAGS" ] || error "(14) Expect empty flags, but got '$FLAGS'" -} -run_test 10b "non-stopped OI scrub should auto restarts after MDS remount (2)" + start ost1 $(ostdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null || + error "(2) Fail to start ost1" -# restore the ${facet}_MKFS_OPTS variables -for facet in MGS MDS OST; do - opts=SAVED_${facet}_MKFS_OPTS - if [[ -n ${!opts} ]]; then - eval ${facet}_MKFS_OPTS=\"${!opts}\" - fi -done + $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} +OSTCOUNT=${SAVED_OSTCOUNT} # cleanup the system at last -formatall +REFORMAT="yes" cleanup_and_setup_lustre -complete $(basename $0) $SECONDS +complete $SECONDS +check_and_cleanup_lustre exit_status