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;
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);
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);
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;
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)
offset += rc2;
}
+ rc = offset;
out_free:
OBD_FREE_LARGE(buf, buf_len);
RETURN(rc);
struct dentry *dentry;
struct file *pcc_filp;
struct path path;
+ ssize_t ret;
int rc;
ENTRY;
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);
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);
}
}
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