Whamcloud - gitweb
LU-13023 pcc: Incorrect size after re-attach 84/36884/7
authorQian Yingjin <qian@ddn.com>
Wed, 27 Nov 2019 15:28:24 +0000 (23:28 +0800)
committerOleg Drokin <green@whamcloud.com>
Tue, 3 Dec 2019 18:59:28 +0000 (18:59 +0000)
The following test case will result in incorrect size for PCC copy:
- Attach a file with size of s1 (s2 > 0) into PCC;
- Detach this file with --keep option, and the data will retain
  on PCC;
- Truncate this file locally or on an remote client to a new size
  s2 (s2 < s1);
- Re-attach the file again. The size of PCC copy is still s1.

To solve this problem, it need to truncate the size of the PCC copy
to the same size of the Lustre copy which will be HSM released
later after finished the data copy (archive) phase.
This patch also adds the handle for the signal pending when the
attach process is killed by an administrator.

Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I18f2c883454450bf5dc2f2b3600e2685d8f8f130
Reviewed-on: https://review.whamcloud.com/36884
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/pcc.c
lustre/tests/sanity-pcc.sh

index e6f9d8f..d8b582f 100644 (file)
@@ -2135,8 +2135,12 @@ out:
        return rc;
 }
 
        return rc;
 }
 
-/* TODO: Set the project ID for PCC copy */
-int pcc_inode_store_ugpid(struct dentry *dentry, kuid_t uid, kgid_t gid)
+/*
+ * Reset uid, gid or size for the PCC copy masked by @valid.
+ * TODO: Set the project ID for PCC copy.
+ */
+int pcc_inode_reset_iattr(struct dentry *dentry, unsigned int valid,
+                         kuid_t uid, kgid_t gid, loff_t size)
 {
        struct inode *inode = dentry->d_inode;
        struct iattr attr;
 {
        struct inode *inode = dentry->d_inode;
        struct iattr attr;
@@ -2144,9 +2148,10 @@ int pcc_inode_store_ugpid(struct dentry *dentry, kuid_t uid, kgid_t gid)
 
        ENTRY;
 
 
        ENTRY;
 
-       attr.ia_valid = ATTR_UID | ATTR_GID;
+       attr.ia_valid = valid;
        attr.ia_uid = uid;
        attr.ia_gid = gid;
        attr.ia_uid = uid;
        attr.ia_gid = gid;
+       attr.ia_size = size;
 
        inode_lock(inode);
        rc = notify_change(dentry, &attr, NULL);
 
        inode_lock(inode);
        rc = notify_change(dentry, &attr, NULL);
@@ -2191,8 +2196,8 @@ int pcc_inode_create_fini(struct inode *inode, struct pcc_create_attach *pca)
        if (pcci == NULL)
                GOTO(out_put, rc = -ENOMEM);
 
        if (pcci == NULL)
                GOTO(out_put, rc = -ENOMEM);
 
-       rc = pcc_inode_store_ugpid(pcc_dentry, old_cred->suid,
-                                  old_cred->sgid);
+       rc = pcc_inode_reset_iattr(pcc_dentry, ATTR_UID | ATTR_GID,
+                                  old_cred->suid, old_cred->sgid, 0);
        if (rc)
                GOTO(out_put, rc);
 
        if (rc)
                GOTO(out_put, rc);
 
@@ -2266,9 +2271,9 @@ static int pcc_filp_write(struct file *filp, const void *buf, ssize_t count,
        return 0;
 }
 
        return 0;
 }
 
-static int pcc_copy_data(struct file *src, struct file *dst)
+static ssize_t pcc_copy_data(struct file *src, struct file *dst)
 {
 {
-       int rc = 0;
+       ssize_t rc = 0;
        ssize_t rc2;
        loff_t pos, offset = 0;
        size_t buf_len = 1048576;
        ssize_t rc2;
        loff_t pos, offset = 0;
        size_t buf_len = 1048576;
@@ -2281,6 +2286,9 @@ static int pcc_copy_data(struct file *src, struct file *dst)
                RETURN(-ENOMEM);
 
        while (1) {
                RETURN(-ENOMEM);
 
        while (1) {
+               if (signal_pending(current))
+                       GOTO(out_free, rc = -EINTR);
+
                pos = offset;
                rc2 = cfs_kernel_read(src, buf, buf_len, &pos);
                if (rc2 < 0)
                pos = offset;
                rc2 = cfs_kernel_read(src, buf, buf_len, &pos);
                if (rc2 < 0)
@@ -2295,6 +2303,7 @@ static int pcc_copy_data(struct file *src, struct file *dst)
                offset += rc2;
        }
 
                offset += rc2;
        }
 
+       rc = offset;
 out_free:
        OBD_FREE_LARGE(buf, buf_len);
        RETURN(rc);
 out_free:
        OBD_FREE_LARGE(buf, buf_len);
        RETURN(rc);
@@ -2332,6 +2341,7 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
        struct dentry *dentry;
        struct file *pcc_filp;
        struct path path;
        struct dentry *dentry;
        struct file *pcc_filp;
        struct path path;
+       ssize_t ret;
        int rc;
 
        ENTRY;
        int rc;
 
        ENTRY;
@@ -2347,33 +2357,38 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
 
        old_cred = override_creds(pcc_super_cred(inode->i_sb));
        rc = __pcc_inode_create(dataset, &lli->lli_fid, &dentry);
 
        old_cred = override_creds(pcc_super_cred(inode->i_sb));
        rc = __pcc_inode_create(dataset, &lli->lli_fid, &dentry);
-       if (rc) {
-               revert_creds(old_cred);
+       if (rc)
                GOTO(out_dataset_put, rc);
                GOTO(out_dataset_put, rc);
-       }
 
        path.mnt = dataset->pccd_path.mnt;
        path.dentry = dentry;
 #ifdef HAVE_DENTRY_OPEN_USE_PATH
 
        path.mnt = dataset->pccd_path.mnt;
        path.dentry = dentry;
 #ifdef HAVE_DENTRY_OPEN_USE_PATH
-       pcc_filp = dentry_open(&path, O_TRUNC | O_WRONLY | O_LARGEFILE,
-                              current_cred());
+       pcc_filp = dentry_open(&path, O_WRONLY | O_LARGEFILE, current_cred());
 #else
 #else
-       pcc_filp = dentry_open(path.dentry, path.mnt,
-                              O_TRUNC | O_WRONLY | O_LARGEFILE,
+       pcc_filp = dentry_open(path.dentry, path.mnt, O_WRONLY | O_LARGEFILE,
                               current_cred());
 #endif
        if (IS_ERR_OR_NULL(pcc_filp)) {
                rc = pcc_filp == NULL ? -EINVAL : PTR_ERR(pcc_filp);
                               current_cred());
 #endif
        if (IS_ERR_OR_NULL(pcc_filp)) {
                rc = pcc_filp == NULL ? -EINVAL : PTR_ERR(pcc_filp);
-               revert_creds(old_cred);
                GOTO(out_dentry, rc);
        }
 
                GOTO(out_dentry, rc);
        }
 
-       rc = pcc_inode_store_ugpid(dentry, old_cred->uid, old_cred->gid);
-       revert_creds(old_cred);
+       rc = pcc_inode_reset_iattr(dentry, ATTR_UID | ATTR_GID,
+                                  old_cred->uid, old_cred->gid, 0);
        if (rc)
                GOTO(out_fput, rc);
 
        if (rc)
                GOTO(out_fput, rc);
 
-       rc = pcc_copy_data(file, pcc_filp);
+       ret = pcc_copy_data(file, pcc_filp);
+       if (ret < 0)
+               GOTO(out_fput, rc = ret);
+
+       /*
+        * It must to truncate the PCC copy to the same size of the Lustre
+        * copy after copy data. Otherwise, it may get wrong file size after
+        * re-attach a file. See LU-13023 for details.
+        */
+       rc = pcc_inode_reset_iattr(dentry, ATTR_SIZE, KUIDT_INIT(0),
+                                  KGIDT_INIT(0), ret);
        if (rc)
                GOTO(out_fput, rc);
 
        if (rc)
                GOTO(out_fput, rc);
 
@@ -2395,13 +2410,13 @@ out_fput:
        fput(pcc_filp);
 out_dentry:
        if (rc) {
        fput(pcc_filp);
 out_dentry:
        if (rc) {
-               old_cred = override_creds(pcc_super_cred(inode->i_sb));
                (void) pcc_inode_remove(inode, dentry);
                (void) pcc_inode_remove(inode, dentry);
-               revert_creds(old_cred);
                dput(dentry);
        }
 out_dataset_put:
        pcc_dataset_put(dataset);
                dput(dentry);
        }
 out_dataset_put:
        pcc_dataset_put(dataset);
+       revert_creds(old_cred);
+
        RETURN(rc);
 }
 
        RETURN(rc);
 }
 
index c563df0..fb49a39 100644 (file)
@@ -1373,6 +1373,79 @@ test_17() {
 }
 run_test 17 "Test auto attach for layout refresh"
 
 }
 run_test 17 "Test auto attach for layout refresh"
 
+test_18() {
+       local agt_host=$(facet_active_host $SINGLEAGT)
+       local loopfile="$TMP/$tfile"
+       local mntpt="/mnt/pcc.$tdir"
+       local hsm_root="$mntpt/$tdir"
+       local file=$DIR/$tfile
+       local oldmd5
+       local newmd5
+
+       setup_loopdev $SINGLEAGT $loopfile $mntpt 50
+       copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
+       setup_pcc_mapping $SINGLEAGT \
+               "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER"
+
+       do_facet $SINGLEAGT $LCTL pcc list $MOUNT
+       do_facet $SINGLEAGT dd if=/dev/urandom of=$file bs=1M count=4 ||
+               error "failed to write $file"
+       do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
+               error "failed to attach $file"
+       do_facet $SINGLEAGT $LFS pcc state $file
+       check_lpcc_state $file "readwrite"
+       do_facet $SINGLEAGT $LFS pcc detach --keep $file ||
+               error "failed to detach $file"
+       do_facet $SINGLEAGT $LFS pcc state $file
+       $CHECKSTAT -s 4194304 $file
+       dd if=/dev/zero of=$DIR2/$tfile seek=1k bs=1k count=1 ||
+               error "failed to write $DIR2/$tfile"
+       oldmd5=$(md5sum $DIR2/$tfile | awk '{print $1}')
+       $CHECKSTAT -s 1049600 $DIR2/$tfile || error "$DIR2/$tfile size wrong"
+
+       local lpcc_path=$(lpcc_fid2path $hsm_root $file)
+
+       do_facet $SINGLEAGT $LFS pcc state $file
+       check_file_size $SINGLEAGT $lpcc_path 4194304
+       do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
+               error "failed to attach $file"
+       check_lpcc_sizes $SINGLEAGT $lpcc_path $file 1049600
+       newmd5=$(do_facet $SINGLEAGT md5sum $file | awk '{print $1}')
+       [ "$oldmd5" == "$newmd5" ] || error "md5sum differ: $oldmd5 $newmd5"
+       do_facet $SINGLEAGT $LFS pcc detach $file ||
+               error "failed to detach $file"
+}
+run_test 18 "Verify size correctness after re-attach the file"
+
+test_19() {
+       local agt_host=$(facet_active_host $SINGLEAGT)
+       local loopfile="$TMP/$tfile"
+       local mntpt="/mnt/pcc.$tdir"
+       local hsm_root="$mntpt/$tdir"
+       local file=$DIR/$tfile
+       local lpcc_path
+
+       setup_loopdev $SINGLEAGT $loopfile $mntpt 50
+       copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
+       setup_pcc_mapping $SINGLEAGT \
+               "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
+
+       do_facet $SINGLEAGT "echo -n QQQQQ > $file" || error "echo $file failed"
+       lpcc_path=$(lpcc_fid2path $hsm_root $file)
+       do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
+               error "Failed to attach $file"
+       check_lpcc_state $file "readwrite"
+       check_lpcc_sizes $SINGLEAGT $file $lpcc_path 5
+       do_facet $SINGLEAGT $LFS pcc detach --keep $file ||
+               error "Failed to detach $file"
+       do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
+               error "Failed to attach $file"
+       check_lpcc_sizes $SINGLEAGT $file $lpcc_path 5
+       do_facet $SINGLEAGT $LFS pcc detach --keep $file ||
+               error "Failed to detach $file"
+}
+run_test 19 "Verify the file re-attach works as expected"
+
 complete $SECONDS
 check_and_cleanup_lustre
 exit_status
 complete $SECONDS
 check_and_cleanup_lustre
 exit_status