+ skip "Need MDS version at least 2.2.0"
+
+ changelog_register || error "changelog_register failed"
+ local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
+ changelog_users $SINGLEMDS | grep -q $cl_user ||
+ error "User '$cl_user' not found in changelog_users"
+
+ local longname1=$(str_repeat a 255)
+ local longname2=$(str_repeat b 255)
+
+ cd $DIR
+ echo "creating very long named file"
+ touch $longname1 || error "create of '$longname1' failed"
+ echo "renaming very long named file"
+ mv $longname1 $longname2
+
+ changelog_dump | grep RENME | tail -n 5
+ rm -f $longname2
+}
+run_test 160b "Verify that very long rename doesn't crash in changelog"
+
+test_160c() {
+ [ $PARALLEL == "yes" ] && skip "skip parallel run"
+ remote_mds_nodsh && skip "remote MDS with nodsh"
+
+ local rc=0
+ local server_version=$(lustre_version_code $SINGLEMDS)
+
+ [[ $server_version -gt $(version_code 2.5.57) ]] ||
+ [[ $server_version -gt $(version_code 2.5.1) &&
+ $server_version -lt $(version_code 2.5.50) ]] ||
+ skip "Need MDS version at least 2.5.58 or 2.5.2+"
+
+ # Registration step
+ changelog_register || error "changelog_register failed"
+
+ rm -rf $DIR/$tdir
+ mkdir -p $DIR/$tdir
+ $MCREATE $DIR/$tdir/foo_160c
+ changelog_chmask "-TRUNC"
+ $TRUNCATE $DIR/$tdir/foo_160c 200
+ changelog_chmask "+TRUNC"
+ $TRUNCATE $DIR/$tdir/foo_160c 199
+ changelog_dump | tail -n 5
+ local truncs=$(changelog_dump | tail -n 5 | grep -c TRUNC)
+ [ $truncs -eq 1 ] || error "TRUNC changelog mask count $truncs != 1"
+}
+run_test 160c "verify that changelog log catch the truncate event"
+
+test_160d() {
+ remote_mds_nodsh && skip "remote MDS with nodsh"
+ [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
+ [ $PARALLEL == "yes" ] && skip "skip parallel run"
+ [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.7.60) ]] ||
+ skip "Need MDS version at least 2.7.60"
+
+ # Registration step
+ changelog_register || error "changelog_register failed"
+
+ mkdir -p $DIR/$tdir/migrate_dir
+ changelog_clear 0 || error "changelog_clear failed"
+
+ $LFS migrate -m 1 $DIR/$tdir/migrate_dir || error "migrate fails"
+ changelog_dump | tail -n 5
+ local migrates=$(changelog_dump | grep -c "MIGRT")
+ [ $migrates -eq 1 ] || error "MIGRATE changelog count $migrates != 1"
+}
+run_test 160d "verify that changelog log catch the migrate event"
+
+test_160e() {
+ remote_mds_nodsh && skip "remote MDS with nodsh"
+
+ # Create a user
+ changelog_register || error "changelog_register failed"
+
+ # Delete a future user (expect fail)
+ local MDT0=$(facet_svc $SINGLEMDS)
+ do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister "cl77"
+ local rc=$?
+
+ if [ $rc -eq 0 ]; then
+ error "Deleted non-existant user cl77"
+ elif [ $rc -ne 2 ]; then
+ error "changelog_deregister failed with $rc, expect 2 (ENOENT)"
+ fi
+
+ # Clear to a bad index (1 billion should be safe)
+ $LFS changelog_clear $MDT0 "${CL_USERS[$SINGLEMDS]%% *}" 1000000000
+ rc=$?
+
+ if [ $rc -eq 0 ]; then
+ error "Successfully cleared to invalid CL index"
+ elif [ $rc -ne 22 ]; then
+ error "changelog_clear failed with $rc, expected 22 (EINVAL)"
+ fi
+}
+run_test 160e "changelog negative testing (should return errors)"
+
+test_160f() {
+ remote_mds_nodsh && skip "remote MDS with nodsh" && return
+ [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.10.56) ]] ||
+ { skip "Need MDS version at least 2.10.56"; return 0; }
+
+ local mdts=$(comma_list $(mdts_nodes))
+
+ # Create a user
+ changelog_register || error "first changelog_register failed"
+ changelog_register || error "second changelog_register failed"
+ local cl_users
+ declare -A cl_user1
+ declare -A cl_user2
+ local user_rec1
+ local user_rec2
+ local i
+
+ # generate some changelog records to accumulate on each MDT
+ test_mkdir -c $MDSCOUNT $DIR/$tdir || error "test_mkdir $tdir failed"
+ createmany -m $DIR/$tdir/$tfile $((MDSCOUNT * 2)) ||
+ error "create $DIR/$tdir/$tfile failed"
+
+ # check changelogs have been generated
+ local nbcl=$(changelog_dump | wc -l)
+ [[ $nbcl -eq 0 ]] && error "no changelogs found"
+
+ for param in "changelog_max_idle_time=10" \
+ "changelog_gc=1" \
+ "changelog_min_gc_interval=2" \
+ "changelog_min_free_cat_entries=3"; do
+ local MDT0=$(facet_svc $SINGLEMDS)
+ local var="${param%=*}"
+ local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
+
+ stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
+ do_nodes $mdts $LCTL set_param mdd.*.$param
+ done
+
+ # force cl_user2 to be idle (1st part)
+ sleep 9
+
+ # simulate changelog catalog almost full
+ #define OBD_FAIL_CAT_FREE_RECORDS 0x1313
+ do_nodes $mdts $LCTL set_param fail_loc=0x1313 fail_val=3
+
+ for i in $(seq $MDSCOUNT); do
+ cl_users=(${CL_USERS[mds$i]})
+ cl_user1[mds$i]="${cl_users[0]}"
+ cl_user2[mds$i]="${cl_users[1]}"
+
+ [ -n "${cl_user1[mds$i]}" ] ||
+ error "mds$i: no user registered"
+ [ -n "${cl_user2[mds$i]}" ] ||
+ error "mds$i: only ${cl_user2[mds$i]} is registered"
+
+ user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
+ [ -n "$user_rec1" ] ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ __changelog_clear mds$i ${cl_user1[mds$i]} +2
+ user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
+ [ -n "$user_rec2" ] ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
+ "$user_rec1 + 2 == $user_rec2"
+ [ $((user_rec1 + 2)) == $user_rec2 ] ||
+ error "mds$i: user ${cl_user1[mds$i]} index expected " \
+ "$user_rec1 + 2, but is $user_rec2"
+ user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
+ [ -n "$user_rec2" ] ||
+ error "mds$i: User ${cl_user2[mds$i]} not registered"
+ [ $user_rec1 == $user_rec2 ] ||
+ error "mds$i: user ${cl_user2[mds$i]} index expected " \
+ "$user_rec1, but is $user_rec2"
+ done
+
+ # force cl_user2 to be idle (2nd part) and to reach
+ # changelog_max_idle_time
+ sleep 2
+
+ # generate one more changelog to trigger fail_loc
+ createmany -m $DIR/$tdir/${tfile}bis $((MDSCOUNT * 2)) ||
+ error "create $DIR/$tdir/${tfile}bis failed"
+
+ # ensure gc thread is done
+ for i in $(mdts_nodes); do
+ wait_update $i \
+ "ps -e -o comm= | grep chlg_gc_thread" "" 20 ||
+ error "$i: GC-thread not done"
+ done
+
+ local first_rec
+ for i in $(seq $MDSCOUNT); do
+ # check cl_user1 still registered
+ changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ # check cl_user2 unregistered
+ changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
+ error "mds$i: User ${cl_user2[mds$i]} still registered"
+
+ # check changelogs are present and starting at $user_rec1 + 1
+ user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
+ [ -n "$user_rec1" ] ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ first_rec=$($LFS changelog $(facet_svc mds$i) |
+ awk '{ print $1; exit; }')
+
+ echo "mds$i: verifying first index $user_rec1 + 1 == $first_rec"
+ [ $((user_rec1 + 1)) == $first_rec ] ||
+ error "mds$i: first index should be $user_rec1 + 1, " \
+ "but is $first_rec"
+ done
+}
+run_test 160f "changelog garbage collect (timestamped users)"
+
+test_160g() {
+ remote_mds_nodsh && skip "remote MDS with nodsh"
+ [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.10.56) ]] ||
+ skip "Need MDS version at least 2.10.56"
+
+ local mdts=$(comma_list $(mdts_nodes))
+
+ #define OBD_FAIL_TIME_IN_CHLOG_USER 0x1314
+ do_nodes $mdts $LCTL set_param fail_loc=0x1314
+
+ # Create a user
+ changelog_register || error "first changelog_register failed"
+ changelog_register || error "second changelog_register failed"
+ local cl_users
+ declare -A cl_user1
+ declare -A cl_user2
+ local user_rec1
+ local user_rec2
+ local i
+
+ # generate some changelog records to accumulate on each MDT
+ test_mkdir -c $MDSCOUNT $DIR/$tdir || error "mkdir $tdir failed"
+ createmany -m $DIR/$tdir/$tfile $((MDSCOUNT * 2)) ||
+ error "create $DIR/$tdir/$tfile failed"
+
+ # check changelogs have been generated
+ local nbcl=$(changelog_dump | wc -l)
+ [[ $nbcl -eq 0 ]] && error "no changelogs found"
+
+ for param in "changelog_max_idle_indexes=$((nbcl / 2))" \
+ "changelog_gc=1" \
+ "changelog_min_gc_interval=2" \
+ "changelog_min_free_cat_entries=3"; do
+ local MDT0=$(facet_svc $SINGLEMDS)
+ local var="${param%=*}"
+ local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
+
+ stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
+ do_nodes $mdts $LCTL set_param mdd.*.$param ||
+ error "unable to set mdd.*.$param"
+ done
+
+ # simulate changelog catalog almost full
+ #define OBD_FAIL_CAT_FREE_RECORDS 0x1313
+ do_nodes $mdts $LCTL set_param fail_loc=0x1313 fail_val=3
+
+ for i in $(seq $MDSCOUNT); do
+ cl_users=(${CL_USERS[mds$i]})
+ cl_user1[mds$i]="${cl_users[0]}"
+ cl_user2[mds$i]="${cl_users[1]}"
+
+ [ -n "${cl_user1[mds$i]}" ] ||
+ error "mds$i: no user registered"
+ [ -n "${cl_user2[mds$i]}" ] ||
+ error "mds$i: only ${cl_user1[mds$i]} is registered"
+
+ user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
+ [ -n "$user_rec1" ] ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ __changelog_clear mds$i ${cl_user1[mds$i]} +2
+ user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
+ [ -n "$user_rec2" ] ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
+ "$user_rec1 + 2 == $user_rec2"
+ [ $((user_rec1 + 2)) == $user_rec2 ] ||
+ error "mds$i: user ${cl_user1[mds$i]} index expected " \
+ "$user_rec1 + 2, but is $user_rec2"
+ user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
+ [ -n "$user_rec2" ] ||
+ error "mds$i: User ${cl_user2[mds$i]} not registered"
+ [ $user_rec1 == $user_rec2 ] ||
+ error "mds$i: user ${cl_user2[mds$i]} index expected " \
+ "$user_rec1, but is $user_rec2"
+ done
+
+ # ensure we are past the previous changelog_min_gc_interval set above
+ sleep 2
+
+ # generate one more changelog to trigger fail_loc
+ createmany -m $DIR/$tdir/${tfile}bis $((MDSCOUNT * 2)) ||
+ error "create $DIR/$tdir/${tfile}bis failed"
+
+ # ensure gc thread is done
+ for i in $(mdts_nodes); do
+ wait_update $i \
+ "ps -e -o comm= | grep chlg_gc_thread" "" 20 ||
+ error "$i: GC-thread not done"
+ done
+
+ local first_rec
+ for i in $(seq $MDSCOUNT); do
+ # check cl_user1 still registered
+ changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ # check cl_user2 unregistered
+ changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
+ error "mds$i: User ${cl_user2[mds$i]} still registered"
+
+ # check changelogs are present and starting at $user_rec1 + 1
+ user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
+ [ -n "$user_rec1" ] ||
+ error "mds$i: User ${cl_user1[mds$i]} not registered"
+ first_rec=$($LFS changelog $(facet_svc mds$i) |
+ awk '{ print $1; exit; }')
+
+ echo "mds$i: verifying first index $user_rec1 + 1 == $first_rec"
+ [ $((user_rec1 + 1)) == $first_rec ] ||
+ error "mds$i: first index should be $user_rec1 + 1, " \
+ "but is $first_rec"
+ done
+}
+run_test 160g "changelog garbage collect (old users)"
+
+test_160h() {
+ remote_mds_nodsh && skip "remote MDS with nodsh" && return
+ [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.10.56) ]] ||
+ { skip "Need MDS version at least 2.10.56"; return 0; }
+
+ local mdts=$(comma_list $(mdts_nodes))
+
+ # Create a user
+ changelog_register || error "first changelog_register failed"
+ changelog_register || error "second changelog_register failed"
+ local cl_users
+ declare -A cl_user1
+ declare -A cl_user2
+ local user_rec1
+ local user_rec2
+ local i
+
+ # generate some changelog records to accumulate on each MDT
+ test_mkdir -c $MDSCOUNT $DIR/$tdir || error "test_mkdir $tdir failed"
+ createmany -m $DIR/$tdir/$tfile $((MDSCOUNT * 2)) ||
+ error "create $DIR/$tdir/$tfile failed"
+
+ # check changelogs have been generated
+ local nbcl=$(changelog_dump | wc -l)
+ [[ $nbcl -eq 0 ]] && error "no changelogs found"