From 7a810496c2ce970294af7ad5939d43490c1817d7 Mon Sep 17 00:00:00 2001 From: Qian Yingjin Date: Wed, 27 Nov 2019 23:28:24 +0800 Subject: [PATCH] LU-13023 pcc: Incorrect size after re-attach 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 Change-Id: I18f2c883454450bf5dc2f2b3600e2685d8f8f130 Reviewed-on: https://review.whamcloud.com/36884 Tested-by: jenkins Reviewed-by: Andreas Dilger Reviewed-by: Li Xi Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/pcc.c | 55 +++++++++++++++++++++------------- lustre/tests/sanity-pcc.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 20 deletions(-) diff --git a/lustre/llite/pcc.c b/lustre/llite/pcc.c index e6f9d8f..d8b582f 100644 --- a/lustre/llite/pcc.c +++ b/lustre/llite/pcc.c @@ -2135,8 +2135,12 @@ out: 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; @@ -2144,9 +2148,10 @@ int pcc_inode_store_ugpid(struct dentry *dentry, kuid_t uid, kgid_t gid) ENTRY; - attr.ia_valid = ATTR_UID | ATTR_GID; + attr.ia_valid = valid; attr.ia_uid = uid; attr.ia_gid = gid; + attr.ia_size = size; 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); - 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); @@ -2266,9 +2271,9 @@ static int pcc_filp_write(struct file *filp, const void *buf, ssize_t count, 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; @@ -2281,6 +2286,9 @@ static int pcc_copy_data(struct file *src, struct file *dst) 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) @@ -2295,6 +2303,7 @@ static int pcc_copy_data(struct file *src, struct file *dst) offset += rc2; } + rc = offset; 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; + ssize_t ret; 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); - if (rc) { - revert_creds(old_cred); + if (rc) GOTO(out_dataset_put, rc); - } 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 - 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); - revert_creds(old_cred); 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); - 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); @@ -2395,13 +2410,13 @@ out_fput: fput(pcc_filp); out_dentry: if (rc) { - old_cred = override_creds(pcc_super_cred(inode->i_sb)); (void) pcc_inode_remove(inode, dentry); - revert_creds(old_cred); dput(dentry); } out_dataset_put: pcc_dataset_put(dataset); + revert_creds(old_cred); + RETURN(rc); } diff --git a/lustre/tests/sanity-pcc.sh b/lustre/tests/sanity-pcc.sh index c563df0..fb49a39 100644 --- a/lustre/tests/sanity-pcc.sh +++ b/lustre/tests/sanity-pcc.sh @@ -1373,6 +1373,79 @@ test_17() { } 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 -- 1.8.3.1