Whamcloud - gitweb
LU-6214 llite: tar restore fails for HSM released files. 60/16060/13
authorAditya Pandit <panditadityashreesh@yahoo.com>
Mon, 31 Aug 2015 10:32:00 +0000 (16:02 +0530)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 22 Sep 2015 23:23:12 +0000 (23:23 +0000)
If you create a file, archive and release it, it keeps only a
link and all information in xattr. If you tar the file
with --xattr you will store the same striping information and link
information in the tar. If you delete the file, the file and archive
state does not make sense. Now if you restore the file using tar
with xattr having the RELEASED flag turned on, then it is not correct
because this is a new file. Hence ignoring the HSM xattr and masking
out the "RELEASED" flag for the files, which are not archived.
Added testcase for the same.

Change-Id: I0ca8636bf508211d63ba796c3b756c9cb4b42d48
Signed-off-by: Aditya Pandit <panditadityashreesh@yahoo.com>
Reviewed-on: http://review.whamcloud.com/16060
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: frank zago <fzago@cray.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lustre/lustre_user.h
lustre/llite/xattr.c
lustre/tests/sanity-hsm.sh

index 4571b53..4f27ec3 100644 (file)
@@ -1048,6 +1048,7 @@ struct ioc_data_version {
  * See HSM_FLAGS below.
  */
 enum hsm_states {
  * See HSM_FLAGS below.
  */
 enum hsm_states {
+       HS_NONE         = 0x00000000,
        HS_EXISTS       = 0x00000001,
        HS_DIRTY        = 0x00000002,
        HS_RELEASED     = 0x00000004,
        HS_EXISTS       = 0x00000001,
        HS_DIRTY        = 0x00000002,
        HS_RELEASED     = 0x00000004,
index 8a365b4..89bda2a 100644 (file)
@@ -144,9 +144,12 @@ int ll_setxattr_common(struct inode *inode, const char *name,
                return -EPERM;
 
         /* b10667: ignore lustre special xattr for now */
                return -EPERM;
 
         /* b10667: ignore lustre special xattr for now */
-        if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
-            (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
-                RETURN(0);
+       if (strcmp(name, XATTR_NAME_HSM) == 0 ||
+               (xattr_type == XATTR_TRUSTED_T &&
+               strcmp(name, XATTR_NAME_LOV) == 0) ||
+               (xattr_type == XATTR_LUSTRE_T &&
+                strcmp(name, "lustre.lov") == 0))
+               RETURN(0);
 
         /* b15587: ignore security.capability xattr for now */
         if ((xattr_type == XATTR_SECURITY_T &&
 
         /* b15587: ignore security.capability xattr for now */
         if ((xattr_type == XATTR_SECURITY_T &&
@@ -225,6 +228,37 @@ int ll_setxattr_common(struct inode *inode, const char *name,
         RETURN(0);
 }
 
         RETURN(0);
 }
 
+static int get_hsm_state(struct inode *inode, __u32 *hus_states)
+{
+       struct md_op_data *op_data;
+       struct hsm_user_state *hus;
+       int rc;
+
+       OBD_ALLOC_PTR(hus);
+       if (hus == NULL)
+               return -ENOMEM;
+
+       op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
+                                    LUSTRE_OPC_ANY, hus);
+       if (!IS_ERR(op_data)) {
+               rc = obd_iocontrol(LL_IOC_HSM_STATE_GET, ll_i2mdexp(inode),
+                                  sizeof(*op_data), op_data, NULL);
+               if (rc == 0)
+                       *hus_states = hus->hus_states;
+               else
+                       CDEBUG(D_VFSTRACE, "obd_iocontrol failed. rc = %d\n",
+                              rc);
+
+               ll_finish_md_op_data(op_data);
+       } else {
+               rc = PTR_ERR(op_data);
+               CDEBUG(D_VFSTRACE, "Could not prepare the opdata. rc = %d\n",
+                      rc);
+       }
+       OBD_FREE_PTR(hus);
+       return rc;
+}
+
 int ll_setxattr(struct dentry *dentry, const char *name,
                 const void *value, size_t size, int flags)
 {
 int ll_setxattr(struct dentry *dentry, const char *name,
                 const void *value, size_t size, int flags)
 {
@@ -238,20 +272,40 @@ int ll_setxattr(struct dentry *dentry, const char *name,
 
         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
 
 
         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
 
-        if ((strncmp(name, XATTR_TRUSTED_PREFIX,
-                     sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
-             strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
-            (strncmp(name, XATTR_LUSTRE_PREFIX,
-                     sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
-             strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
+       if ((strncmp(name, XATTR_TRUSTED_PREFIX,
+                    sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
+            strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
+           (strncmp(name, XATTR_LUSTRE_PREFIX,
+                    sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
+            strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
                struct lov_user_md *lump = (struct lov_user_md *)value;
                struct lov_user_md *lump = (struct lov_user_md *)value;
-               int                 rc = 0;
-
-                /* Attributes that are saved via getxattr will always have
-                 * the stripe_offset as 0.  Instead, the MDS should be
-                 * allowed to pick the starting OST index.   b=17846 */
-                if (lump != NULL && lump->lmm_stripe_offset == 0)
-                        lump->lmm_stripe_offset = -1;
+               int rc = 0;
+
+               /* Attributes that are saved via getxattr will always have
+                * the stripe_offset as 0.  Instead, the MDS should be
+                * allowed to pick the starting OST index.   b=17846 */
+               if (lump != NULL && lump->lmm_stripe_offset == 0)
+                       lump->lmm_stripe_offset = -1;
+               /* Avoid anyone directly setting the RELEASED flag. */
+               if (lump != NULL &&
+                       (lump->lmm_pattern & LOV_PATTERN_F_RELEASED)) {
+                       /* Only if we have a released flag check if the file
+                       * was indeed archived. */
+                       __u32 state = HS_NONE;
+                       rc = get_hsm_state(inode, &state);
+                       if (rc != 0)
+                               RETURN(rc);
+                       if (!(state & HS_ARCHIVED)) {
+                               CDEBUG(D_VFSTRACE,
+                                       "hus_states state = %x, pattern = %x\n",
+                                       state, lump->lmm_pattern);
+                               /* Here the state is: real file is not
+                                * archived but user is requesting to set
+                                * the RELEASED flag so we mask off the
+                                * released flag from the request */
+                               lump->lmm_pattern ^= LOV_PATTERN_F_RELEASED;
+                       }
+               }
 
                if (lump != NULL && S_ISREG(inode->i_mode)) {
                        struct file     f;
 
                if (lump != NULL && S_ISREG(inode->i_mode)) {
                        struct file     f;
index d7eab96..172170d 100755 (executable)
@@ -2094,7 +2094,9 @@ test_24e() {
        $LFS hsm_archive $f || error "cannot archive $f"
        wait_request_state $fid ARCHIVE SUCCEED
        $LFS hsm_release $f || error "cannot release $f"
        $LFS hsm_archive $f || error "cannot archive $f"
        wait_request_state $fid ARCHIVE SUCCEED
        $LFS hsm_release $f || error "cannot release $f"
-       sleep 5
+       while ! $LFS hsm_state $f | grep released; do
+               sleep 1
+       done
 
        tar -cf $TMP/$tfile.tar $DIR/$tdir || error "cannot tar $DIR/$tdir"
 
 
        tar -cf $TMP/$tfile.tar $DIR/$tdir || error "cannot tar $DIR/$tdir"
 
@@ -2102,6 +2104,33 @@ test_24e() {
 }
 run_test 24e "tar succeeds on HSM released files" # LU-6213
 
 }
 run_test 24e "tar succeeds on HSM released files" # LU-6213
 
+test_24f() {
+
+       # test needs a running copytool
+       copytool_setup
+
+       mkdir -p $DIR/$tdir/d1
+       local f=$DIR/$tdir/$tfile
+       local fid=$(copy_file /etc/hosts $f)
+       sum0=$(md5sum $f)
+       echo $sum0
+       $LFS hsm_archive -a $HSM_ARCHIVE_NUMBER $f ||
+               error "hsm_archive failed"
+       wait_request_state $fid ARCHIVE SUCCEED
+       $LFS hsm_release $f || error "cannot release $f"
+       tar --xattrs -cvf $f.tar -C $DIR/$tdir $tfile
+       rm -f $f
+       sync
+       tar --xattrs -xvf $f.tar -C $DIR/$tdir ||
+               error "Can not recover the tar contents"
+       sum1=$(md5sum $f)
+       echo "Sum0 = $sum0, sum1 = $sum1"
+       [ "$sum0" == "$sum1" ] || error "md5sum mismatch for '$tfile'"
+
+       copytool_cleanup
+}
+run_test 24f "root can archive, release, and restore tar files"
+
 test_25a() {
        # test needs a running copytool
        copytool_setup
 test_25a() {
        # test needs a running copytool
        copytool_setup