From 6e7769fce4ce49c008759aeef1a0110142f64847 Mon Sep 17 00:00:00 2001 From: tappro Date: Thu, 20 Aug 2009 08:54:48 +0000 Subject: [PATCH] Branch HEAD b=189743 i=w.li i=nathan Update vbr tests from b1.8, add lctl version getting functionality --- lustre/include/lustre_lib.h | 2 + lustre/mdt/mdt_handler.c | 55 ++++ lustre/mdt/mdt_reint.c | 2 +- lustre/tests/replay-vbr.sh | 693 +++++++++++++++++++++++++++++++++++---- lustre/tests/runmultiop_bg_pause | 8 +- lustre/utils/lctl.c | 3 + lustre/utils/obd.c | 48 +++ lustre/utils/obdctl.h | 1 + 8 files changed, 755 insertions(+), 57 deletions(-) diff --git a/lustre/include/lustre_lib.h b/lustre/include/lustre_lib.h index d890d67..d5547ce 100644 --- a/lustre/include/lustre_lib.h +++ b/lustre/include/lustre_lib.h @@ -524,6 +524,8 @@ static inline void obd_ioctl_freedata(char *buf, int len) #define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) #define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) +#define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) + /* XXX _IOWR('f', 250, long) has been defined in * libcfs/include/libcfs/libcfs_private.h for debug, don't use it */ diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index e9ed811..41fe562 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -5490,6 +5490,50 @@ static int mdt_ioc_child(struct lu_env *env, struct mdt_device *mdt, RETURN(rc); } +static int mdt_ioc_version_get(struct mdt_thread_info *mti, void *karg) +{ + struct obd_ioctl_data *data = karg; + struct lu_fid *fid = (struct lu_fid *)data->ioc_inlbuf1; + __u64 version; + struct mdt_object *obj; + struct mdt_lock_handle *lh; + int rc; + ENTRY; + CDEBUG(D_IOCTL, "getting version for "DFID"\n", PFID(fid)); + if (!fid_is_sane(fid)) + RETURN(-EINVAL); + + lh = &mti->mti_lh[MDT_LH_PARENT]; + mdt_lock_reg_init(lh, LCK_CR); + + obj = mdt_object_find_lock(mti, fid, lh, MDS_INODELOCK_UPDATE); + if (IS_ERR(obj)) + RETURN(PTR_ERR(obj)); + + rc = mdt_object_exists(obj); + if (rc < 0) { + rc = -EREMOTE; + /** + * before calling version get the correct MDS should be + * fid, this is error to find remote object here + */ + CERROR("nonlocal object "DFID"\n", PFID(fid)); + } else if (rc == 0) { + rc = -ENOENT; + CDEBUG(D_IOCTL, "no such object: "DFID"\n", PFID(fid)); + } else { + version = mo_version_get(mti->mti_env, mdt_object_child(obj)); + if (version < 0) { + rc = (int)version; + } else { + *(__u64 *)data->ioc_inlbuf2 = version; + rc = 0; + } + } + mdt_object_unlock_put(mti, obj, lh, 1); + RETURN(rc); +} + /* ioctls on obd dev */ static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) @@ -5523,6 +5567,17 @@ static int mdt_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case OBD_IOC_CHANGELOG_CLEAR: rc = mdt_ioc_child(&env, mdt, cmd, len, karg); break; + case OBD_IOC_GET_OBJ_VERSION: { + struct mdt_thread_info *mti; + mti = lu_context_key_get(&env.le_ctx, &mdt_thread_key); + memset(mti, 0, sizeof *mti); + mti->mti_env = &env; + mti->mti_mdt = mdt; + mti->mti_exp = exp; + + rc = mdt_ioc_version_get(mti, karg); + break; + } default: CERROR("Not supported cmd = %d for device %s\n", cmd, obd->obd_name); diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index 3b005b1..38502ef 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -279,7 +279,7 @@ int mdt_attr_set(struct mdt_thread_info *info, struct mdt_object *mo, int flags) struct md_attr *ma = &info->mti_attr; struct mdt_lock_handle *lh; int som_update = 0; - int do_vbr = ma->ma_attr.la_valid & (LA_MODE|LA_UID|LA_GID); + int do_vbr = ma->ma_attr.la_valid & (LA_MODE|LA_UID|LA_GID|LA_FLAGS); int rc; ENTRY; diff --git a/lustre/tests/replay-vbr.sh b/lustre/tests/replay-vbr.sh index 75b3c85..1e166fa 100644 --- a/lustre/tests/replay-vbr.sh +++ b/lustre/tests/replay-vbr.sh @@ -16,14 +16,13 @@ init_test_env $@ . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh} +[ "$SLOW" = "no" ] && EXCEPT_SLOW="" + [ -n "$CLIENTS" ] || { skip "Need two or more clients" && exit 0; } [ $CLIENTCOUNT -ge 2 ] || \ { skip "Need two or more clients, have $CLIENTCOUNT" && exit 0; } -remote_mds_nodsh && skip "remote MDS with nodsh" && exit 0 - -[ "$SLOW" = "no" ] && EXCEPT_SLOW="" - +remote_mds_nodsh && skip "remote MDS with nodsh" && exit 0 [ ! "$NAME" = "ncli" ] && ALWAYS_EXCEPT="$ALWAYS_EXCEPT" [ "$NAME" = "ncli" ] && MOUNT_2="" MOUNT_2="" @@ -34,9 +33,561 @@ rm -rf $DIR/[df][0-9]* [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE +rmultiop_start() { + local client=$1 + local file=$2 + local cmds=$3 + + # We need to run do_node in bg, because pdsh does not exit + # if child process of run script exists. + # I.e. pdsh does not exit when runmultiop_bg_pause exited, + # because of multiop_bg_pause -> $MULTIOP_PROG & + # By the same reason we need sleep a bit after do_nodes starts + # to let runmultiop_bg_pause start muliop and + # update /tmp/multiop_bg.pid ; + # The rm /tmp/multiop_bg.pid guarantees here that + # we have the updated by runmultiop_bg_pause + # /tmp/multiop_bg.pid file + + local pid_file=$TMP/multiop_bg.pid.$$ + do_node $client "rm -f $pid_file && MULTIOP_PID_FILE=$pid_file LUSTRE= runmultiop_bg_pause $file $cmds" & + local pid=$! + sleep 3 + local multiop_pid + multiop_pid=$(do_node $client cat $pid_file) + [ -n "$multiop_pid" ] || error "$client : Can not get multiop_pid from $pid_file " + eval export $(client_var_name $client)_multiop_pid=$multiop_pid + eval export $(client_var_name $client)_do_node_pid=$pid + local var=$(client_var_name $client)_multiop_pid + echo client $client multiop_bg started multiop_pid=${!var} + return $? +} + +rmultiop_stop() { + local client=$1 + local multiop_pid=$(client_var_name $client)_multiop_pid + local do_node_pid=$(client_var_name $client)_do_node_pid + + echo "Stopping multiop_pid=${!multiop_pid} (kill ${!multiop_pid} on $client)" + do_node $client kill -USR1 ${!multiop_pid} + + wait ${!do_node_pid} +} + +get_version() { + local var=${SINGLEMDS}_svc + local client=$1 + local file=$2 + local fid + + fid=$(do_node $client $LFS path2fid $file) + do_facet $SINGLEMDS $LCTL --device ${!var} getobjversion $fid +} + +test_0a() { + local file=$DIR/$tfile + local pre + local post + + do_node $CLIENT1 mcreate $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 openfile -f O_RDWR $file + post=$(get_version $CLIENT1 $file) + if (($pre != $post)); then + error "version changed unexpectedly: pre $pre, post $post" + fi +} +run_test 0a "open and close do not change versions" + +test_0b() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR/$tdir + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -a $DIR/$tdir/$tfile; then + error "open succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0b "open (O_CREAT) checks version of parent" + +test_0c() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $DIR/$tdir/$tfile + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR/$tdir + do_node $CLIENT2 chmod 666 $DIR/$tdir/$tfile + rmultiop_start $CLIENT1 $DIR/$tdir/$tfile o_c + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT || error "$CLIENT1 evicted" + rmultiop_stop $CLIENT1 || error "close failed" + zconf_mount $CLIENT2 $MOUNT +} +run_test 0c "open (non O_CREAT) does not checks versions" + +test_0d() { + local pre + local post + + pre=$(get_version $CLIENT1 $DIR) + do_node $CLIENT1 mkfifo $DIR/$tfile + post=$(get_version $CLIENT1 $DIR) + if (($pre == $post)); then + error "version not changed: pre $pre, post $post" + fi +} +run_test 0d "create changes version of parent" + +test_0e() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR/$tdir + do_node $CLIENT1 mkfifo $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -a $DIR/$tdir/$tfile; then + error "create succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0e "create checks version of parent" + +test_0f() { + local pre + local post + + do_node $CLIENT1 mcreate $DIR/$tfile + pre=$(get_version $CLIENT1 $DIR) + do_node $CLIENT1 rm $DIR/$tfile + post=$(get_version $CLIENT1 $DIR) + if (($pre == $post)); then + error "version not changed: pre $pre, post $post" + fi +} +run_test 0f "unlink changes version of parent" + +test_0g() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + do_node $CLIENT1 mcreate $DIR/$tdir/$tfile + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR/$tdir + do_node $CLIENT1 rm $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if do_node $CLIENT1 $CHECKSTAT -a $DIR/$tdir/$tfile; then + error "unlink succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0g "unlink checks version of parent" + +test_0h() { + local file=$DIR/$tfile + local pre + local post + + do_node $CLIENT1 mcreate $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 chown $RUNAS_ID $file + post=$(get_version $CLIENT1 $file) + if (($pre == $post)); then + error "version not changed: pre $pre, post $post" + fi +} +run_test 0h "setattr of UID changes versions" + +test_0i() { + local file=$DIR/$tfile + local pre + local post + + do_node $CLIENT1 mcreate $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 chown :$RUNAS_ID $file + post=$(get_version $CLIENT1 $file) + if (($pre == $post)); then + error "version not changed: pre $pre, post $post" + fi +} +run_test 0i "setattr of GID changes versions" + +test_0j() { + local file=$DIR/$tfile + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mcreate $file + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chown :$RUNAS_ID $file + do_node $CLIENT1 chown $RUNAS_ID $file + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -u \\\#$UID $file; then + error "setattr of UID succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0j "setattr of UID checks versions" + +test_0k() { + local file=$DIR/$tfile + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mcreate $file + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chown $RUNAS_ID $file + do_node $CLIENT1 chown :$RUNAS_ID $file + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -g \\\#$UID $file; then + error "setattr of GID succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0k "setattr of GID checks versions" + +test_0l() { + local file=$DIR/$tfile + local pre + local post + + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 chmod 666 $file + post=$(get_version $CLIENT1 $file) + if (($pre == $post)); then + error "version not changed: pre $pre, post $post" + fi +} +run_test 0l "setattr of permission changes versions" + +test_0m() { + local file=$DIR/$tfile + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $file + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chown :$RUNAS_ID $file + do_node $CLIENT1 chmod 666 $file + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -p 0644 $file; then + error "setattr of permission succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0m "setattr of permission checks versions" + +test_0n() { + local file=$DIR/$tfile + local pre + local post + + do_node $CLIENT1 mcreate $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 chattr +i $file + post=$(get_version $CLIENT1 $file) + do_node $CLIENT1 chattr -i $file + if (($pre == $post)); then + error "version not changed: pre $pre, post $post" + fi +} +run_test 0n "setattr of flags changes versions" + +checkattr() { + local client=$1 + local attr=$2 + local file=$3 + local rc + + if ((${#attr} != 1)); then + error "checking multiple attributes not implemented yet" + fi + do_node $client lsattr $file | cut -d ' ' -f 1 | grep -q $attr +} + +test_0o() { + local file=$DIR/$tfile + local rc + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $file + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 666 $file + do_node $CLIENT1 chattr +i $file + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + checkattr $CLIENT1 i $file + rc=$? + do_node $CLIENT1 chattr -i $file + if [ $rc -eq 0 ]; then + error "setattr of flags succeeded unexpectedly" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0o "setattr of flags checks versions" + +test_0p() { + local file=$DIR/$tfile + local pre + local post + local ad_orig + local var=${SINGLEMDS}_svc + + ad_orig=$(do_facet $SINGLEMDS "$LCTL get_param mdd.${!var}.atime_diff") + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.atime_diff=0" + do_node $CLIENT1 mcreate $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 touch $file + post=$(get_version $CLIENT1 $file) + # + # We don't fail MDS in this test. atime_diff shall be + # restored to its original value. + # + do_facet $SINGLEMDS "$LCTL set_param $ad_orig" + if (($pre != $post)); then + error "version changed unexpectedly: pre $pre, post $post" + fi +} +run_test 0p "setattr of times does not change versions" + +test_0q() { + local file=$DIR/$tfile + local pre + local post + + do_node $CLIENT1 mcreate $file + pre=$(get_version $CLIENT1 $file) + do_node $CLIENT1 truncate $file 1 + post=$(get_version $CLIENT1 $file) + if (($pre != $post)); then + error "version changed unexpectedly: pre $pre, post $post" + fi +} +run_test 0q "setattr of size does not change versions" + +test_0r() { + local file=$DIR/$tfile + local mtime_pre + local mtime_post + local mtime + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.atime_diff=0" + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $file + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 666 $file + do_node $CLIENT1 truncate $file 1 + sleep 1 + mtime_pre=$(do_node $CLIENT1 stat --format=%Y $file) + do_node $CLIENT1 touch $file + mtime_post=$(do_node $CLIENT1 stat --format=%Y $file) + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT || error "$CLIENT1 evicted" + if (($mtime_pre >= $mtime_post)); then + error "time not changed: pre $mtime_pre, post $mtime_post" + fi + if ! do_node $CLIENT1 $CHECKSTAT -s 1 $file; then + error "setattr of size failed" + fi + mtime=$(do_node $CLIENT1 stat --format=%Y $file) + if (($mtime != $mtime_post)); then + error "setattr of times failed: expected $mtime_post, got $mtime" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0r "setattr of times and size does not check versions" + +test_0s() { + local pre + local post + local tp_pre + local tp_post + + do_node $CLIENT1 mcreate $DIR/$tfile + do_node $CLIENT1 mkdir -p $DIR/$tdir + pre=$(get_version $CLIENT1 $DIR/$tfile) + tp_pre=$(get_version $CLIENT1 $DIR/$tdir) + do_node $CLIENT1 link $DIR/$tfile $DIR/$tdir/$tfile + post=$(get_version $CLIENT1 $DIR/$tfile) + tp_post=$(get_version $CLIENT1 $DIR/$tdir) + if (($pre == $post)); then + error "version of source not changed: pre $pre, post $post" + fi + if (($tp_pre == $tp_post)); then + error "version of target parent not changed: pre $tp_pre, post $tp_post" + fi +} +run_test 0s "link changes versions of source and target parent" + +test_0t() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mcreate $DIR/$tfile + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR/$tdir + do_node $CLIENT1 link $DIR/$tfile $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -a $DIR/$tdir/$tfile; then + error "link should fail" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0t "link checks version of target parent" + +test_0u() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $DIR/$tfile + do_node $CLIENT1 mkdir -p $DIR/$tdir + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 666 $DIR/$tfile + do_node $CLIENT1 link $DIR/$tfile $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if ! do_node $CLIENT1 $CHECKSTAT -a $DIR/$tdir/$tfile; then + error "link should fail" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0u "link checks version of source" + +test_0v() { + local sp_pre + local tp_pre + local sp_post + local tp_post + + do_node $CLIENT1 mcreate $DIR/$tfile + do_node $CLIENT1 mkdir -p $DIR/$tdir + sp_pre=$(get_version $CLIENT1 $DIR) + tp_pre=$(get_version $CLIENT1 $DIR/$tdir) + do_node $CLIENT1 mv $DIR/$tfile $DIR/$tdir/$tfile + sp_post=$(get_version $CLIENT1 $DIR) + tp_post=$(get_version $CLIENT1 $DIR/$tdir) + if (($sp_pre == $sp_post)); then + error "version of source parent not changed: pre $sp_pre, post $sp_post" + fi + if (($tp_pre == $tp_post)); then + error "version of target parent not changed: pre $tp_pre, post $tp_post" + fi +} +run_test 0v "rename changes versions of source parent and target parent" + +test_0w() { + local pre + local post + + do_node $CLIENT1 mcreate $DIR/$tfile + pre=$(get_version $CLIENT1 $DIR) + do_node $CLIENT1 mv $DIR/$tfile $DIR/$tfile-new + post=$(get_version $CLIENT1 $DIR) + if (($pre == $post)); then + error "version of parent not changed: pre $pre, post $post" + fi +} +run_test 0w "rename within same dir changes version of parent" + +test_0x() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mcreate $DIR/$tfile + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR + do_node $CLIENT1 mv $DIR/$tfile $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if do_node $CLIENT1 $CHECKSTAT -a $DIR/$tfile; then + error "rename should fail" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0x "rename checks version of source parent" + +test_0y() { + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + do_node $CLIENT1 mcreate $DIR/$tfile + do_node $CLIENT1 mkdir -p -m 755 $DIR/$tdir + + replay_barrier $SINGLEMDS + do_node $CLIENT2 chmod 777 $DIR/$tdir + do_node $CLIENT1 mv $DIR/$tfile $DIR/$tdir/$tfile + zconf_umount $CLIENT2 $MOUNT + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1 not evicted" + if do_node $CLIENT1 $CHECKSTAT -a $DIR/$tfile; then + error "rename should fail" + fi + zconf_mount $CLIENT2 $MOUNT +} +run_test 0y "rename checks version of target parent" + [ "$CLIENTS" ] && zconf_umount_clients $CLIENTS $DIR -test_1() { +test_1a() { echo "mount client $CLIENT1,$CLIENT2..." zconf_mount_clients $CLIENT1 $DIR zconf_mount_clients $CLIENT2 $DIR @@ -62,9 +613,9 @@ test_1() { zconf_umount_clients $CLIENTS $DIR return 0 } -run_test 1 "lost client doesn't affect another during replay" +run_test 1a "client during replay doesn't affect another one" -test_2() { +test_2a() { zconf_mount_clients $CLIENT1 $DIR zconf_mount_clients $CLIENT2 $DIR @@ -91,7 +642,79 @@ test_2() { zconf_umount_clients $CLIENTS $DIR return 0 } -run_test 2 "lost data due to missed REMOTE client during replay" +run_test 2a "lost data due to missed REMOTE client during replay" + +# +# This test uses three Lustre clients on two hosts. +# +# Lustre Client 1: $CLIENT1:$MOUNT ($DIR) +# Lustre Client 2: $CLIENT2:$MOUNT2 ($DIR2) +# Lustre Client 3: $CLIENT2:$MOUNT1 ($DIR1) +# +test_2b() { + local pre + local post + local var=${SINGLEMDS}_svc + + do_facet $SINGLEMDS "$LCTL set_param mdd.${!var}.sync_permission=0" + zconf_mount $CLIENT1 $MOUNT + zconf_mount $CLIENT2 $MOUNT2 + zconf_mount $CLIENT2 $MOUNT1 + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $DIR/$tfile-a + do_node $CLIENT1 openfile -f O_RDWR:O_CREAT -m 0644 $DIR/$tfile-b + + # + # Save an MDT transaction number before recovery. + # + pre=$(get_version $CLIENT1 $DIR/$tfile-a) + + # + # Comments on the replay sequence state the expected result + # of each request. + # + # "R" Replayed. + # "U" Unable to replay. + # "J" Rejected. + # + replay_barrier $SINGLEMDS + do_node $CLIENT1 chmod 666 $DIR/$tfile-a # R + do_node $CLIENT2 chmod 666 $DIR1/$tfile-b # R + do_node $CLIENT2 chown :$RUNAS_ID $DIR2/$tfile-a # U + do_node $CLIENT1 chown $RUNAS_ID $DIR/$tfile-a # J + do_node $CLIENT2 truncate $DIR2/$tfile-b 1 # U + do_node $CLIENT2 chown :$RUNAS_ID $DIR1/$tfile-b # R + do_node $CLIENT1 chown $RUNAS_ID $DIR/$tfile-b # R + zconf_umount $CLIENT2 $MOUNT2 + facet_failover $SINGLEMDS + + do_node $CLIENT1 df $MOUNT && error "$CLIENT1:$MOUNT not evicted" + do_node $CLIENT2 df $MOUNT1 || error "$CLIENT2:$MOUNT1 evicted" + + # + # Check the MDT epoch. $post must be the first transaction + # number assigned after recovery. + # + do_node $CLIENT2 touch $DIR1/$tfile + post=$(get_version $CLIENT2 $DIR1/$tfile) + if (($(($pre >> 32)) == $((post >> 32)))); then + error "epoch not changed: pre $pre, post $post" + fi + if (($(($post & 0x00000000ffffffff)) != 1)); then + error "transno should restart from one: got $post" + fi + + do_node $CLIENT2 stat $DIR1/$tfile-a + do_node $CLIENT2 stat $DIR1/$tfile-b + + do_node $CLIENT2 $CHECKSTAT -p 0666 -u \\\#$UID -g \\\#$UID \ + $DIR1/$tfile-a || error "$DIR/$tfile-a: unexpected state" + do_node $CLIENT2 $CHECKSTAT -p 0666 -u \\\#$RUNAS_ID -g \\\#$RUNAS_ID \ + $DIR1/$tfile-b || error "$DIR/$tfile-b: unexpected state" + + zconf_umount $CLIENT2 $MOUNT1 + zconf_umount $CLIENT1 $MOUNT +} +run_test 2b "3 clients: some, none, and all reqs replayed" test_3a() { zconf_mount_clients $CLIENT1 $DIR @@ -412,46 +1035,6 @@ test_7a() { } run_test 7a "fail MDS, delayed recovery, fail MDS" -rmultiop_start() { - local client=$1 - local file=$2 - - # We need to run do_node in bg, because pdsh does not exit - # if child process of run script exists. - # I.e. pdsh does not exit when runmultiop_bg_pause exited, - # because of multiop_bg_pause -> $MULTIOP_PROG & - # By the same reason we need sleep a bit after do_nodes starts - # to let runmultiop_bg_pause start muliop and - # update /tmp/multiop_bg.pid ; - # The rm /tmp/multiop_bg.pid guarantees here that - # we have the updated by runmultiop_bg_pause - # /tmp/multiop_bg.pid file - - local pid_file=$TMP/multiop_bg.pid.$$ - do_node $client "rm -f $pid_file && MULTIOP_PID_FILE=$pid_file LUSTRE= runmultiop_bg_pause $file O_tSc" & - local pid=$! - sleep 3 - local multiop_pid - multiop_pid=$(do_node $client cat $pid_file) - [ -n "$multiop_pid" ] || error "$client : Can not get multiop_pid from $pid_file " - eval export $(client_var_name $client)_multiop_pid=$multiop_pid - eval export $(client_var_name $client)_do_node_pid=$pid - local var=$(client_var_name $client)_multiop_pid - echo client $client multiop_bg started multiop_pid=${!var} - return $? -} - -rmultiop_stop() { - local client=$1 - local multiop_pid=$(client_var_name $client)_multiop_pid - local do_node_pid=$(client_var_name $client)_do_node_pid - - echo "Stopping multiop_pid=${!multiop_pid} (kill ${!multiop_pid} on $client)" - do_node $client kill -USR1 ${!multiop_pid} - - wait ${!do_node_pid} || true -} - test_8a() { delayed_recovery_enabled || { skip "No delayed recovery support"; return 0; } @@ -461,7 +1044,7 @@ test_8a() { zconf_mount_clients $CLIENT1 $DIR zconf_mount_clients $CLIENT2 $DIR - rmultiop_start $CLIENT2 $DIR/$tfile || return 1 + rmultiop_start $CLIENT2 $DIR/$tfile O_tSc || return 1 do_node $CLIENT2 rm -f $DIR/$tfile replay_barrier $SINGLEMDS rmultiop_stop $CLIENT2 || return 2 @@ -488,7 +1071,7 @@ test_8b() { zconf_mount_clients $CLIENT1 $DIR zconf_mount_clients $CLIENT2 $DIR - rmultiop_start $CLIENT2 $DIR/$tfile || return 1 + rmultiop_start $CLIENT2 $DIR/$tfile O_tSc|| return 1 replay_barrier $SINGLEMDS do_node $CLIENT1 rm -f $DIR/$tfile @@ -515,7 +1098,7 @@ test_8c() { zconf_mount_clients $CLIENT1 $DIR zconf_mount_clients $CLIENT2 $DIR - rmultiop_start $CLIENT2 $DIR/$tfile || return 1 + rmultiop_start $CLIENT2 $DIR/$tfile O_tSc|| return 1 replay_barrier $SINGLEMDS do_node $CLIENT1 rm -f $DIR/$tfile rmultiop_stop $CLIENT2 || return 2 @@ -542,8 +1125,8 @@ test_8d() { zconf_mount_clients $CLIENT1 $DIR zconf_mount_clients $CLIENT2 $DIR - rmultiop_start $CLIENT1 $DIR/$tfile || return 1 - rmultiop_start $CLIENT2 $DIR/$tfile || return 2 + rmultiop_start $CLIENT1 $DIR/$tfile O_tSc|| return 1 + rmultiop_start $CLIENT2 $DIR/$tfile O_tSc|| return 2 replay_barrier $SINGLEMDS do_node $CLIENT1 rm -f $DIR/$tfile rmultiop_stop $CLIENT2 || return 3 @@ -671,8 +1254,8 @@ test_10 () { } run_test 10 "mds version recovery; $CLIENTCOUNT clients" +[ "$CLIENTS" ] && zconf_mount_clients $CLIENTS $DIR + equals_msg `basename $0`: test complete, cleaning up -#SLEEP=$((`date +%s` - $NOW)) -#[ $SLEEP -lt $TIMEOUT ] && sleep $SLEEP check_and_cleanup_lustre [ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG && grep -q FAIL $TESTSUITELOG && exit 1 || true diff --git a/lustre/tests/runmultiop_bg_pause b/lustre/tests/runmultiop_bg_pause index 823ebdd..640cc29 100644 --- a/lustre/tests/runmultiop_bg_pause +++ b/lustre/tests/runmultiop_bg_pause @@ -7,5 +7,11 @@ PTLDEBUG=${PTLDEBUG:--1} LUSTRE=${LUSTRE:-`dirname $0`/..} . $LUSTRE/tests/test-framework.sh +TMP=${TMP:-/tmp} +MULTIOP_PID_FILE=${MULTIOP_PID_FILE:-$TMP/multiop_bg.pid} +rm -f $MULTIOP_PID_FILE + multiop_bg_pause $* -exit $? +rc=$? +[ "$rc" = 0 ] && echo $! > $MULTIOP_PID_FILE +exit $rc diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index 0a586a4..3c78810 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -296,6 +296,9 @@ command_t cmdlist[] = { {"memhog", jt_ptl_memhog, 0, "memory pressure testing\n" "usage: memhog []"}, + {"getobjversion", jt_get_obj_version, 0, + "get the version of an object on servers\n" + "usage: getobjversion "}, {"==== obsolete (DANGEROUS) ====", jt_noop, 0, "obsolete (DANGEROUS)"}, /* some test scripts still use these */ diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 9fe5d4b..a5ba5a9 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -3134,6 +3134,54 @@ out: return rc; } +int jt_get_obj_version(int argc, char **argv) +{ + struct lu_fid fid; + struct obd_ioctl_data data; + __u64 version; + char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf, *fidstr; + int rc; + + if (argc != 2) + return CMD_HELP; + + fidstr = argv[1]; + while (*fidstr == '[') + fidstr++; + sscanf(fidstr, SFID, RFID(&fid)); + if (!fid_is_sane(&fid)) { + fprintf(stderr, "bad FID format [%s], should be "DFID"\n", + fidstr, (__u64)1, 2, 0); + return -EINVAL; + } + + memset(&data, 0, sizeof data); + data.ioc_dev = cur_device; + data.ioc_inlbuf1 = (char *) &fid; + data.ioc_inllen1 = sizeof fid; + data.ioc_inlbuf2 = (char *) &version; + data.ioc_inllen2 = sizeof version; + + memset(buf, 0, sizeof *buf); + rc = obd_ioctl_pack(&data, &buf, sizeof rawbuf); + if (rc) { + fprintf(stderr, "error: %s: packing ioctl arguments: %s\n", + jt_cmdname(argv[0]), strerror(-rc)); + return rc; + } + + rc = l2_ioctl(OBD_DEV_ID, OBD_IOC_GET_OBJ_VERSION, buf); + if (rc == -1) { + fprintf(stderr, "error: %s: ioctl: %s\n", + jt_cmdname(argv[0]), strerror(errno)); + return -errno; + } + + obd_ioctl_unpack(&data, buf, sizeof rawbuf); + printf("0x%llx\n", version); + return 0; +} + void llapi_ping_target(char *obd_type, char *obd_name, char *obd_uuid, void *args) { diff --git a/lustre/utils/obdctl.h b/lustre/utils/obdctl.h index dccd213..0c69b12 100644 --- a/lustre/utils/obdctl.h +++ b/lustre/utils/obdctl.h @@ -81,6 +81,7 @@ int jt_obd_recover(int argc, char **argv); int jt_obd_mdc_lookup(int argc, char **argv); int jt_get_version(int argc, char **argv); int jt_cfg_dump_log(int argc, char **argv); +int jt_get_obj_version(int argc, char **argv); int jt_llog_catlist(int argc, char **argv); int jt_llog_info(int argc, char **argv); -- 1.8.3.1