Whamcloud - gitweb
Branch HEAD
authortappro <tappro>
Thu, 20 Aug 2009 08:54:48 +0000 (08:54 +0000)
committertappro <tappro>
Thu, 20 Aug 2009 08:54:48 +0000 (08:54 +0000)
b=189743
i=w.li
i=nathan

Update vbr tests from b1.8, add lctl version getting functionality

lustre/include/lustre_lib.h
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_reint.c
lustre/tests/replay-vbr.sh
lustre/tests/runmultiop_bg_pause
lustre/utils/lctl.c
lustre/utils/obd.c
lustre/utils/obdctl.h

index d890d67..d5547ce 100644 (file)
@@ -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
  */
index e9ed811..41fe562 100644 (file)
@@ -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);
index 3b005b1..38502ef 100644 (file)
@@ -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;
 
index 75b3c85..1e166fa 100644 (file)
@@ -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
index 823ebdd..640cc29 100644 (file)
@@ -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
index 0a586a4..3c78810 100644 (file)
@@ -296,6 +296,9 @@ command_t cmdlist[] = {
         {"memhog", jt_ptl_memhog, 0,
          "memory pressure testing\n"
          "usage: memhog <page count> [<gfp flags>]"},
+        {"getobjversion", jt_get_obj_version, 0,
+         "get the version of an object on servers\n"
+         "usage: getobjversion <fid>"},
 
         {"==== obsolete (DANGEROUS) ====", jt_noop, 0, "obsolete (DANGEROUS)"},
         /* some test scripts still use these */
index 9fe5d4b..a5ba5a9 100644 (file)
@@ -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)
 {
index dccd213..0c69b12 100644 (file)
@@ -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);