Whamcloud - gitweb
LU-6449 mdt: correct status and ChangeLogs for dead objects 77/21077/13
authorBruno Faccini <bruno.faccini@intel.com>
Wed, 29 Jun 2016 17:06:21 +0000 (19:06 +0200)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 17 Dec 2016 05:40:38 +0000 (05:40 +0000)
This patch is an addon of first patch for LU-6449
(Gerrit change http://review.whamcloud.com/20991) which implements
the feature of broadcasting HSM remove requests, with no/0 archive_id
specified, to all currently registered archives.

hsm_cdt_request_completed() has been fixed to no longer only return
SUCCEED status for HSM requests on dead objects but effective status
and also to create associated ChangeLog records. This last change
has required to also change mdd/ChangeLog interface to allow to
specify a FID, and to use this way extensively.
Error case in retry-mode has also been fixed to allow layout-lock
to be released.

sanity-hsm/test_[220a,222[c,d],224a] have been added to check correct
behavior.

Signed-off-by: Bruno Faccini <bruno.faccini@intel.com>
Change-Id: I5885cc8feb2b3d50bfc691706401c7c19ba78f72
Reviewed-on: https://review.whamcloud.com/21077
Tested-by: Jenkins
Reviewed-by: Hongchao Zhang <hongchao.zhang@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/md_object.h
lustre/mdd/mdd_object.c
lustre/mdt/mdt_coordinator.c
lustre/tests/sanity-hsm.sh

index f3994bc..f8d695e 100644 (file)
@@ -195,9 +195,9 @@ struct md_object_operations {
 
         int (*moo_readlink)(const struct lu_env *env, struct md_object *obj,
                             struct lu_buf *buf);
-        int (*moo_changelog)(const struct lu_env *env,
-                             enum changelog_rec_type type, int flags,
-                             struct md_object *obj);
+       int (*moo_changelog)(const struct lu_env *env,
+                            enum changelog_rec_type type, int flags,
+                            struct md_device *m, const struct lu_fid *fid);
 
         int (*moo_open)(const struct lu_env *env,
                         struct md_object *obj, int flag);
@@ -355,11 +355,28 @@ static inline int mo_readlink(const struct lu_env *env,
 }
 
 static inline int mo_changelog(const struct lu_env *env,
-                               enum changelog_rec_type type,
-                               int flags, struct md_object *m)
+                              enum changelog_rec_type type,
+                              int flags, struct md_device *m,
+                              const struct lu_fid *fid)
 {
-        LASSERT(m->mo_ops->moo_changelog);
-        return m->mo_ops->moo_changelog(env, type, flags, m);
+       struct lu_fid rootfid;
+       struct md_object *root;
+       int rc;
+
+       rc = m->md_ops->mdo_root_get(env, m, &rootfid);
+       if (rc)
+               return rc;
+
+       root = md_object_find_slice(env, m, &rootfid);
+       if (IS_ERR(root))
+               RETURN(PTR_ERR(root));
+
+       LASSERT(root->mo_ops->moo_changelog);
+       rc = root->mo_ops->moo_changelog(env, type, flags, m, fid);
+
+       lu_object_put(env, &root->mo_lu);
+
+       return rc;
 }
 
 static inline int mo_attr_set(const struct lu_env *env,
index c3a6eb3..f0fe288 100644 (file)
@@ -633,42 +633,18 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
        RETURN(0);
 }
 
-/** Store a data change changelog record
- * If this fails, we must fail the whole transaction; we don't
- * want the change to commit without the log entry.
- * \param mdd_obj - mdd_object of change
- * \param handle - transaction handle
- */
-int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd,
-                            enum changelog_rec_type type, int flags,
-                            struct mdd_object *mdd_obj, struct thandle *handle)
+static int mdd_changelog_data_store_by_fid(const struct lu_env *env,
+                                   struct mdd_device *mdd,
+                                   enum changelog_rec_type type, int flags,
+                                   const struct lu_fid *fid,
+                                   struct thandle *handle)
 {
-       const struct lu_ucred           *uc = lu_ucred(env);
-       const struct lu_fid             *tfid;
+       const struct lu_ucred           *uc = lu_ucred(env);
        struct llog_changelog_rec       *rec;
        struct lu_buf                   *buf;
        int                              reclen;
        int                              rc;
 
-        /* Not recording */
-        if (!(mdd->mdd_cl.mc_flags & CLM_ON))
-                RETURN(0);
-        if ((mdd->mdd_cl.mc_mask & (1 << type)) == 0)
-                RETURN(0);
-
-        LASSERT(mdd_obj != NULL);
-        LASSERT(handle != NULL);
-
-       tfid = mdo2fid(mdd_obj);
-
-        if ((type >= CL_MTIME) && (type <= CL_ATIME) &&
-            cfs_time_before_64(mdd->mdd_cl.mc_starttime, mdd_obj->mod_cltime)) {
-                /* Don't need multiple updates in this log */
-                /* Don't check under lock - no big deal if we get an extra
-                   entry */
-                RETURN(0);
-        }
-
        flags = (flags & CLF_FLAGMASK) | CLF_VERSION;
        if (uc != NULL && uc->uc_jobid[0] != '\0')
                flags |= CLF_JOBID;
@@ -681,9 +657,8 @@ int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd,
 
        rec->cr.cr_flags = flags;
        rec->cr.cr_type = (__u32)type;
-       rec->cr.cr_tfid = *tfid;
+       rec->cr.cr_tfid = *fid;
        rec->cr.cr_namelen = 0;
-       mdd_obj->mod_cltime = cfs_time_current_64();
 
        if (flags & CLF_JOBID)
                mdd_changelog_rec_ext_jobid(&rec->cr, uc->uc_jobid);
@@ -693,15 +668,60 @@ int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd,
        RETURN(rc);
 }
 
+
+/** Store a data change changelog record
+ * If this fails, we must fail the whole transaction; we don't
+ * want the change to commit without the log entry.
+ * \param mdd_obj - mdd_object of change
+ * \param handle - transaction handle
+ */
+int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd,
+                            enum changelog_rec_type type, int flags,
+                            struct mdd_object *mdd_obj, struct thandle *handle)
+{
+       int                              rc;
+
+       /* Not recording */
+       if (!(mdd->mdd_cl.mc_flags & CLM_ON))
+               RETURN(0);
+       if ((mdd->mdd_cl.mc_mask & (1 << type)) == 0)
+               RETURN(0);
+
+       LASSERT(mdd_obj != NULL);
+       LASSERT(handle != NULL);
+
+       if ((type >= CL_MTIME) && (type <= CL_ATIME) &&
+           cfs_time_before_64(mdd->mdd_cl.mc_starttime, mdd_obj->mod_cltime)) {
+               /* Don't need multiple updates in this log */
+               /* Don't check under lock - no big deal if we get an extra
+                  entry */
+               RETURN(0);
+       }
+
+       rc = mdd_changelog_data_store_by_fid(env, mdd, type, flags,
+                                            mdo2fid(mdd_obj), handle);
+       if (rc == 0)
+               mdd_obj->mod_cltime = cfs_time_current_64();
+
+       RETURN(rc);
+}
+
 static int mdd_changelog(const struct lu_env *env, enum changelog_rec_type type,
-                        int flags, struct md_object *obj)
+                 int flags, struct md_device *m, const struct lu_fid *fid)
 {
        struct thandle *handle;
-       struct mdd_object *mdd_obj = md2mdd_obj(obj);
-       struct mdd_device *mdd = mdo2mdd(obj);
+       struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
        int rc;
        ENTRY;
 
+       /* Not recording */
+       if (!(mdd->mdd_cl.mc_flags & CLM_ON))
+               RETURN(0);
+       if (!(mdd->mdd_cl.mc_mask & (1 << type)))
+               RETURN(0);
+
+       LASSERT(fid != NULL);
+
        handle = mdd_trans_create(env, mdd);
        if (IS_ERR(handle))
                RETURN(PTR_ERR(handle));
@@ -714,8 +734,8 @@ static int mdd_changelog(const struct lu_env *env, enum changelog_rec_type type,
        if (rc)
                GOTO(stop, rc);
 
-       rc = mdd_changelog_data_store(env, mdd, type, flags, mdd_obj,
-                                     handle);
+       rc = mdd_changelog_data_store_by_fid(env, mdd, type, flags,
+                                                    fid, handle);
 
 stop:
        rc = mdd_trans_stop(env, mdd, rc, handle);
index c6253e8..0bf96dd 100644 (file)
@@ -1141,15 +1141,11 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
        /* default is to retry */
        *status = ARS_WAITING;
 
-       /* find object by FID */
+       /* find object by FID
+        * if error/removed continue anyway to get correct reporting done */
        obj = mdt_hsm_get_md_hsm(mti, &car->car_hai->hai_fid, &mh);
        /* we will update MD HSM only if needed */
        is_mh_changed = false;
-       if (IS_ERR(obj)) {
-               /* object removed */
-               *status = ARS_SUCCEED;
-               goto unlock;
-       }
 
        /* no need to change mh->mh_arch_id
         * mdt_hsm_get_md_hsm() got it from disk and it is still valid
@@ -1177,9 +1173,11 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                        *status = ARS_SUCCEED;
                        break;
                default:
+                       /* retry only if current policy or requested, and
+                        * object is not on error/removed */
                        *status = (cdt->cdt_policy & CDT_NORETRY_ACTION ||
-                                  !(pgs->hpk_flags & HP_FLAG_RETRY) ?
-                                  ARS_FAILED : ARS_WAITING);
+                                  !(pgs->hpk_flags & HP_FLAG_RETRY) ||
+                                  IS_ERR(obj)) ? ARS_FAILED : ARS_WAITING;
                        break;
                }
 
@@ -1278,16 +1276,13 @@ static int hsm_cdt_request_completed(struct mdt_thread_info *mti,
                                 mh.mh_flags & HS_DIRTY ? CLF_HSM_DIRTY : 0);
 
        /* unlock is done later, after layout lock management */
-       if (is_mh_changed)
+       if (is_mh_changed && !IS_ERR(obj))
                rc = mdt_hsm_attr_set(mti, obj, &mh);
 
-unlock:
        /* we give back layout lock only if restore was successful or
-        * if restore was canceled or if policy is to not retry
+        * if no retry will be attempted and if object is still alive,
         * in other cases we just unlock the object */
-       if (car->car_hai->hai_action == HSMA_RESTORE &&
-           (pgs->hpk_errval == 0 || pgs->hpk_errval == ECANCELED ||
-            cdt->cdt_policy & CDT_NORETRY_ACTION)) {
+       if (car->car_hai->hai_action == HSMA_RESTORE) {
                struct cdt_restore_handle       *crh;
 
                /* restore in data FID done, we swap the layouts
@@ -1325,11 +1320,12 @@ unlock:
        GOTO(out, rc);
 
 out:
-       if (obj != NULL && !IS_ERR(obj)) {
-               mo_changelog(env, CL_HSM, cl_flags,
-                            mdt_object_child(obj));
+       /* always add a ChangeLog record */
+       mo_changelog(env, CL_HSM, cl_flags, mdt->mdt_child,
+                    &car->car_hai->hai_fid);
+
+       if (!IS_ERR(obj))
                mdt_object_put(mti->mti_env, obj);
-       }
 
        RETURN(rc);
 }
index f1988cd..8577d25 100755 (executable)
@@ -377,6 +377,13 @@ copytool_suspend() {
        echo "Copytool is suspended on $agents"
 }
 
+copytool_continue() {
+       local agents=${1:-$(facet_active_host $SINGLEAGT)}
+
+       do_nodesv $agents "pkill -CONT -x $HSMTOOL_BASE" || return 0
+       echo "Copytool is continued on $agents"
+}
+
 copytool_remove_backend() {
        local fid=$1
        local be=$(do_facet $SINGLEAGT find $HSM_ARCHIVE -name $fid)
@@ -3981,6 +3988,40 @@ test_220() {
 }
 run_test 220 "Changelog for archive"
 
+test_220a() {
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+
+       local f=$DIR/$tdir/$tfile
+       local fid=$(copy_file /etc/passwd $f)
+
+       changelog_setup
+
+       # block copytool operations to allow for HSM request to be
+       # submitted and file be unlinked (CDT will find object removed)
+       copytool_suspend
+
+       $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+
+       rm -f $f
+
+       copytool_continue
+
+       wait_request_state $fid ARCHIVE FAILED
+
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
+       changelog_cleanup
+
+       # HE_ARCHIVE|ENOENT
+       local target=0x2
+       [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+
+       copytool_cleanup
+}
+run_test 220a "Changelog for failed archive"
+
 test_221() {
        # test needs a running copytool
        copytool_setup
@@ -4060,6 +4101,68 @@ test_222b() {
 }
 run_test 222b "Changelog for implicit restore"
 
+test_222c() {
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+       copy2archive /etc/passwd $tdir/$tfile
+
+       local f=$DIR/$tdir/$tfile
+       import_file $tdir/$tfile $f
+       local fid=$(path2fid $f)
+
+       changelog_setup
+
+       # block copytool operations to allow for HSM request to be
+       # submitted and file be unlinked (CDT will find object removed)
+       copytool_suspend
+
+       $LFS hsm_restore $f
+       rm -f $f
+
+       copytool_continue
+
+       wait_request_state $fid RESTORE FAILED
+
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
+
+       # HE_RESTORE|ENOENT
+       local target=0x82
+       [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+
+       cleanup
+}
+run_test 222c "Changelog for failed explicit restore"
+
+test_222d() {
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+       local f=$DIR/$tdir/$tfile
+       local fid=$(copy_file /etc/passwd $f)
+
+       changelog_setup
+       $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+       wait_request_state $fid ARCHIVE SUCCEED
+       $LFS hsm_release $f
+
+       copytool_remove_backend $fid
+       md5sum $f
+
+       wait_request_state $fid RESTORE FAILED
+
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -1)
+
+       # HE_RESTORE|ENOENT
+       local target=0x82
+       [[ $flags == $target ]] || error "Changelog flag is $flags not $target"
+
+       cleanup
+}
+run_test 222d "Changelog for failed implicit restore"
+
 test_223a() {
        # test needs a running copytool
        copytool_setup
@@ -4147,6 +4250,43 @@ test_224() {
 }
 run_test 224 "Changelog for remove"
 
+test_224a() {
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir
+
+       local f=$DIR/$tdir/$tfile
+       local fid=$(copy_file /etc/passwd $f)
+
+       changelog_setup
+       $LFS hsm_archive --archive $HSM_ARCHIVE_NUMBER $f
+       wait_request_state $fid ARCHIVE SUCCEED
+
+       copytool_remove_backend $fid
+
+       # block copytool operations to allow for HSM request to be
+       # submitted and file be unlinked (CDT will find object removed)
+       copytool_suspend
+
+       $LFS hsm_remove $f
+       rm -f $f
+
+       copytool_continue
+
+       wait_request_state $fid REMOVE FAILED
+
+       local flags=$(changelog_get_flags ${MDT[0]} HSM $fid | tail -n 1)
+
+       # HE_REMOVE|ENOENT
+       local target=0x202
+       [[ $flags == $target ]] ||
+               error "Changelog flag is $flags not $target"
+
+       cleanup
+}
+run_test 224a "Changelog for failed remove"
+
 test_225() {
        # test needs a running copytool
        copytool_setup