if (rc)
GOTO(out_och_free, rc);
}
+
rc = pcc_file_open(inode, file);
if (rc)
GOTO(out_och_free, rc);
* from PCC cache automatically.
*/
result = pcc_file_write_iter(iocb, from, &cached);
- if (cached && result != -ENOSPC)
+ if (cached && result != -ENOSPC && result != -EDQUOT)
return result;
/* NB: we can't do direct IO for tiny writes because they use the page
unsigned long pages;
unsigned long lru_page_max;
struct sysinfo si;
+ int rc;
int i;
+
ENTRY;
OBD_ALLOC_PTR(sbi);
if (sbi == NULL)
- RETURN(NULL);
+ RETURN(ERR_PTR(-ENOMEM));
+
+ rc = pcc_super_init(&sbi->ll_pcc_super);
+ if (rc < 0)
+ GOTO(out_sbi, rc);
spin_lock_init(&sbi->ll_lock);
mutex_init(&sbi->ll_lco.lco_lock);
/* initialize ll_cache data */
sbi->ll_cache = cl_cache_init(lru_page_max);
- if (sbi->ll_cache == NULL) {
- OBD_FREE(sbi, sizeof(*sbi));
- RETURN(NULL);
- }
+ if (sbi->ll_cache == NULL)
+ GOTO(out_pcc, rc = -ENOMEM);
sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32,
SBI_DEFAULT_READAHEAD_MAX);
sbi->ll_squash.rsi_gid = 0;
INIT_LIST_HEAD(&sbi->ll_squash.rsi_nosquash_nids);
init_rwsem(&sbi->ll_squash.rsi_sem);
- pcc_super_init(&sbi->ll_pcc_super);
/* Per-filesystem file heat */
sbi->ll_heat_decay_weight = SBI_DEFAULT_HEAT_DECAY_WEIGHT;
sbi->ll_heat_period_second = SBI_DEFAULT_HEAT_PERIOD_SECOND;
RETURN(sbi);
+out_pcc:
+ pcc_super_fini(&sbi->ll_pcc_super);
+out_sbi:
+ OBD_FREE_PTR(sbi);
+ RETURN(ERR_PTR(rc));
}
static void ll_free_sbi(struct super_block *sb)
/* client additional sb info */
lsi->lsi_llsbi = sbi = ll_init_sbi();
- if (!sbi)
- GOTO(out_free_cfg, err = -ENOMEM);
+ if (IS_ERR(sbi))
+ GOTO(out_free_cfg, err = PTR_ERR(sbi));
err = ll_options(lsi->lsi_lmd->lmd_opts, sbi);
if (err)
int next, force = 1, rc = 0;
ENTRY;
- if (!sbi)
+ if (IS_ERR(sbi))
GOTO(out_no_sbi, 0);
/* Should replace instance_id with something better for ASLR */
if (rc)
GOTO(out, retval = ERR_PTR(rc));
- rc = pcc_inode_create(dataset, &op_data->op_fid2,
+ rc = pcc_inode_create(parent->i_sb, dataset, &op_data->op_fid2,
&pca->pca_dentry);
if (rc)
GOTO(out, retval = ERR_PTR(rc));
struct kmem_cache *pcc_inode_slab;
-void pcc_super_init(struct pcc_super *super)
+int pcc_super_init(struct pcc_super *super)
{
+ struct cred *cred;
+
+ super->pccs_cred = cred = prepare_creds();
+ if (!cred)
+ return -ENOMEM;
+
+ /* Never override disk quota limits or use reserved space */
+ cap_lower(cred->cap_effective, CAP_SYS_RESOURCE);
spin_lock_init(&super->pccs_lock);
INIT_LIST_HEAD(&super->pccs_datasets);
+
+ return 0;
}
/**
return 0;
}
-void pcc_super_fini(struct pcc_super *super)
+static void pcc_remove_datasets(struct pcc_super *super)
{
struct pcc_dataset *dataset, *tmp;
}
}
+void pcc_super_fini(struct pcc_super *super)
+{
+ pcc_remove_datasets(super);
+ put_cred(super->pccs_cred);
+}
static bool pathname_is_valid(const char *pathname)
{
rc = pcc_dataset_del(super, cmd->pccc_pathname);
break;
case PCC_CLEAR_ALL:
- pcc_super_fini(super);
+ pcc_remove_datasets(super);
break;
default:
rc = -EINVAL;
PFID(fid));
}
+static inline const struct cred *pcc_super_cred(struct super_block *sb)
+{
+ return ll_s2sbi(sb)->ll_pcc_super.pccs_cred;
+}
+
void pcc_file_init(struct pcc_file *pccf)
{
pccf->pccf_file = NULL;
dname = &path->dentry->d_name;
CDEBUG(D_CACHE, "opening pcc file '%.*s'\n", dname->len,
dname->name);
+
#ifdef HAVE_DENTRY_OPEN_USE_PATH
- pcc_file = dentry_open(path, file->f_flags, current_cred());
+ pcc_file = dentry_open(path, file->f_flags,
+ pcc_super_cred(inode->i_sb));
#else
- pcc_file = dentry_open(path->dentry, path->mnt,
- file->f_flags, current_cred());
+ pcc_file = dentry_open(path->dentry, path->mnt, file->f_flags,
+ pcc_super_cred(inode->i_sb));
#endif
if (IS_ERR_OR_NULL(pcc_file)) {
rc = pcc_file == NULL ? -EINVAL : PTR_ERR(pcc_file);
bool *cached)
{
int rc;
+ const struct cred *old_cred;
struct iattr attr2 = *attr;
struct dentry *pcc_dentry;
struct pcc_inode *pcci;
attr2.ia_valid = attr->ia_valid & (ATTR_SIZE | ATTR_ATIME |
ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET |
- ATTR_CTIME);
+ ATTR_CTIME | ATTR_UID | ATTR_GID);
pcci = ll_i2pcci(inode);
pcc_dentry = pcci->pcci_path.dentry;
inode_lock(pcc_dentry->d_inode);
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc = pcc_dentry->d_inode->i_op->setattr(pcc_dentry, &attr2);
+ revert_creds(old_cred);
inode_unlock(pcc_dentry->d_inode);
pcc_io_fini(inode);
int pcc_inode_getattr(struct inode *inode, bool *cached)
{
struct ll_inode_info *lli = ll_i2info(inode);
+ const struct cred *old_cred;
struct kstat stat;
s64 atime;
s64 mtime;
if (!*cached)
RETURN(0);
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc = ll_vfs_getattr(&ll_i2pcci(inode)->pcci_path, &stat);
+ revert_creds(old_cred);
if (rc)
GOTO(out, rc);
pcc_fid2dataset_path(path, MAX_PCC_DATABASE_PATH, fid);
- base = pcc_mkdir_p(dataset->pccd_path.dentry, path, 0700);
+ base = pcc_mkdir_p(dataset->pccd_path.dentry, path, 0);
if (IS_ERR(base)) {
rc = PTR_ERR(base);
GOTO(out, rc);
}
snprintf(path, MAX_PCC_DATABASE_PATH, DFID_NOBRACE, PFID(fid));
- child = pcc_create(base, path, 0600);
+ child = pcc_create(base, path, 0);
if (IS_ERR(child)) {
rc = PTR_ERR(child);
GOTO(out_base, rc);
return rc;
}
-int pcc_inode_create(struct pcc_dataset *dataset, struct lu_fid *fid,
- struct dentry **pcc_dentry)
+/* TODO: Set the project ID for PCC copy */
+int pcc_inode_store_ugpid(struct dentry *dentry, kuid_t uid, kgid_t gid)
+{
+ struct inode *inode = dentry->d_inode;
+ struct iattr attr;
+ int rc;
+
+ ENTRY;
+
+ attr.ia_valid = ATTR_UID | ATTR_GID;
+ attr.ia_uid = uid;
+ attr.ia_gid = gid;
+
+ inode_lock(inode);
+ rc = notify_change(dentry, &attr, NULL);
+ inode_unlock(inode);
+
+ RETURN(rc);
+}
+
+int pcc_inode_create(struct super_block *sb, struct pcc_dataset *dataset,
+ struct lu_fid *fid, struct dentry **pcc_dentry)
{
- return __pcc_inode_create(dataset, fid, pcc_dentry);
+ const struct cred *old_cred;
+ int rc;
+
+ old_cred = override_creds(pcc_super_cred(sb));
+ rc = __pcc_inode_create(dataset, fid, pcc_dentry);
+ revert_creds(old_cred);
+ return rc;
}
int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
struct dentry *pcc_dentry)
{
+ const struct cred *old_cred;
struct pcc_inode *pcci;
int rc = 0;
ENTRY;
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
pcc_inode_lock(inode);
LASSERT(ll_i2pcci(inode) == NULL);
OBD_SLAB_ALLOC_PTR_GFP(pcci, pcc_inode_slab, GFP_NOFS);
if (pcci == NULL)
GOTO(out_unlock, rc = -ENOMEM);
+ rc = pcc_inode_store_ugpid(pcc_dentry, old_cred->suid,
+ old_cred->sgid);
+ if (rc)
+ GOTO(out_unlock, rc);
+
pcc_inode_init(pcci, ll_i2info(inode));
pcc_inode_attach_init(dataset, pcci, pcc_dentry, LU_PCC_READWRITE);
/* Set the layout generation of newly created file with 0 */
}
pcc_inode_unlock(inode);
+ revert_creds(old_cred);
+ if (rc && pcci)
+ OBD_SLAB_FREE_PTR(pcci, pcc_inode_slab);
+
RETURN(rc);
}
struct pcc_dataset *dataset;
struct ll_inode_info *lli = ll_i2info(inode);
struct pcc_inode *pcci;
+ const struct cred *old_cred;
struct dentry *dentry;
struct file *pcc_filp;
struct path path;
if (dataset == NULL)
RETURN(-ENOENT);
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc = __pcc_inode_create(dataset, &lli->lli_fid, &dentry);
- if (rc)
+ if (rc) {
+ revert_creds(old_cred);
GOTO(out_dataset_put, rc);
+ }
path.mnt = dataset->pccd_path.mnt;
path.dentry = dentry;
#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);
+ if (rc)
+ GOTO(out_fput, rc);
+
rc = pcc_copy_data(file, pcc_filp);
if (rc)
GOTO(out_fput, rc);
if (rc) {
int rc2;
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
rc2 = ll_vfs_unlink(dentry->d_parent->d_inode, dentry);
+ revert_creds(old_cred);
if (rc2)
CWARN("failed to unlink PCC file, rc = %d\n", rc2);
bool attached)
{
struct ll_inode_info *lli = ll_i2info(inode);
+ const struct cred *old_cred;
struct pcc_inode *pcci;
__u32 gen2;
pcc_inode_lock(inode);
pcci = ll_i2pcci(inode);
lli->lli_pcc_state &= ~PCC_STATE_FL_ATTACHING;
- if ((rc || lease_broken)) {
+ if (rc || lease_broken) {
if (attached && pcci)
pcc_inode_put(pcci);
out_put:
if (rc) {
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
pcc_inode_remove(pcci);
+ revert_creds(old_cred);
pcc_inode_put(pcci);
}
out_unlock:
};
struct pcc_super {
- spinlock_t pccs_lock; /* Protect pccs_datasets */
- struct list_head pccs_datasets; /* List of datasets */
+ /* Protect pccs_datasets */
+ spinlock_t pccs_lock;
+ /* List of datasets */
+ struct list_head pccs_datasets;
+ /* creds of process who forced instantiation of super block */
+ const struct cred *pccs_cred;
};
struct pcc_inode {
} u;
};
-void pcc_super_init(struct pcc_super *super);
+int pcc_super_init(struct pcc_super *super);
void pcc_super_fini(struct pcc_super *super);
int pcc_cmd_handle(char *buffer, unsigned long count,
struct pcc_super *super);
int pcc_fault(struct vm_area_struct *mva, struct vm_fault *vmf, bool *cached);
int pcc_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
bool *cached);
-int pcc_inode_create(struct pcc_dataset *dataset, struct lu_fid *fid,
- struct dentry **pcc_dentry);
+int pcc_inode_create(struct super_block *sb, struct pcc_dataset *dataset,
+ struct lu_fid *fid, struct dentry **pcc_dentry);
int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
- struct dentry *pcc_dentry);
+ struct dentry *pcc_dentry);
struct pcc_dataset *pcc_dataset_get(struct pcc_super *super, __u32 projid,
__u32 archive_id);
void pcc_dataset_put(struct pcc_dataset *dataset);
local param="$2"
[ -z "$param" ] && param="$HSM_ARCHIVE_NUMBER\ 100"
- cleanup_pcc_mapping $facet
+ stack_trap "cleanup_pcc_mapping $facet" EXIT
do_facet $facet $LCTL pcc add $MOUNT $hsm_root -p $param
}
# HSM released exists archived status
check_hsm_flags $file "0x0000000d"
check_file_data $SINGLEAGT $file "attach_detach"
-
- cleanup_pcc_mapping
}
test_1a() {
}
run_test 1d "Test Project ID with remote access"
+test_1e() {
+ local file=$DIR/$tdir/$tfile
+ local hsm_root=$(hsm_root)
+ local -a lpcc_path
+
+ copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
+ setup_pcc_mapping
+ mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ chmod 777 $DIR/$tdir || error "chmod 777 $DIR/$tdir failed"
+
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 ||
+ error "failed to dd write to $file"
+ do_facet $SINGLEAGT $RUNAS $LFS pcc attach -i $HSM_ARCHIVE_NUMBER \
+ $file || error "failed to attach file $file"
+ check_lpcc_state $file "readwrite"
+ do_facet $SINGLEAGT $RUNAS dd if=$file of=/dev/null bs=1024 count=1 ||
+ error "failed to dd read from $file"
+ do_facet $SINGLEAGT $RUNAS $TRUNCATE $file 256 ||
+ error "failed to truncate $file"
+ do_facet $SINGLEAGT $RUNAS $TRUNCATE $file 2048 ||
+ error "failed to truncate $file"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 ||
+ error "failed to dd write to $file"
+ check_lpcc_state $file "readwrite"
+
+ # non-root user is forbidden to access PCC file directly
+ lpcc_path=$(lpcc_fid2path $hsm_root $file)
+ do_facet $SINGLEAGT $RUNAS touch $lpcc_path &&
+ error "non-root user can touch access PCC file $lpcc_path"
+ do_facet $SINGLEAGT $RUNAS dd if=$lpcc_path of=/dev/null bs=1024 \
+ count=1 && error "non-root user can read PCC file $lpcc_path"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$lpcc_path bs=1024 \
+ count=1 && error "non-root user can write PCC file $lpcc_path"
+
+ local perm=$(do_facet $SINGLEAGT stat -c %a $lpcc_path)
+
+ [[ $perm == "0" ]] || error "PCC file permission ($perm) is not zero"
+
+ do_facet $SINGLEAGT $RUNAS $LFS pcc detach $file ||
+ error "failed to detach file $file"
+ check_lpcc_state $file "none"
+}
+run_test 1e "Test RW-PCC with non-root user"
+
+test_1f() {
+ local project_id=100
+ local agt_facet=$SINGLEAGT
+ local hsm_root=$(hsm_root)
+ local file=$DIR/$tdir/$tfile
+
+ ! is_project_quota_supported &&
+ skip "project quota is not supported"
+
+ enable_project_quota
+ copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
+ setup_pcc_mapping
+ do_facet $SINGLEAGT mkdir -p $DIR/$tdir
+ chmod 777 $DIR/$tdir || error "chmod 0777 $DIR/$tdir failed"
+ $LFS project -sp $project_id $DIR/$tdir ||
+ error "failed to set project for $DIR/$tdir"
+
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 ||
+ error "failed to dd write to $file"
+
+ check_lpcc_state $file "readwrite"
+ do_facet $SINGLEAGT $RUNAS dd if=$file of=/dev/null bs=1024 count=1 ||
+ error "failed to dd read from $file"
+ do_facet $SINGLEAGT $RUNAS $TRUNCATE $file 256 ||
+ error "failed to truncate $file"
+ do_facet $SINGLEAGT $RUNAS $TRUNCATE $file 2048 ||
+ error "failed to truncate $file"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 ||
+ error "failed to dd write from $file"
+ check_lpcc_state $file "readwrite"
+
+ # non-root user is forbidden to access PCC file directly
+ lpcc_path=$(lpcc_fid2path $hsm_root $file)
+ do_facet $SINGLEAGT $RUNAS touch $lpcc_path &&
+ error "non-root user can touch access PCC file $lpcc_path"
+ do_facet $SINGLEAGT $RUNAS dd if=$lpcc_path of=/dev/null bs=1024 \
+ count=1 && error "non-root user can read PCC file $lpcc_path"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$lpcc_path bs=1024 \
+ count=1 && error "non-root user can write PCC file $lpcc_path"
+
+ do_facet $SINGLEAGT $RUNAS $LFS pcc detach $file ||
+ error "failed to detach file $file"
+ check_lpcc_state $file "none"
+}
+run_test 1f "Test auto RW-PCC cache with non-root user"
+
+test_1g() {
+ local file=$DIR/$tfile
+
+ copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
+ setup_pcc_mapping
+
+ dd if=/dev/zero of=$file bs=1024 count=1 ||
+ error "failed to dd write to $file"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 &&
+ error "non-root user can dd write to $file"
+ do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
+ error "failed to attach file $file"
+ check_lpcc_state $file "readwrite"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 &&
+ error "non-root user can dd write to $file"
+ chmod 777 $file || error "chmod 777 $file failed"
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=1024 count=1 ||
+ error "non-root user cannot write $file with permission (777)"
+
+ do_facet $SINGLEAGT $RUNAS $LFS pcc detach $file &&
+ error "non-root user or non owner can detach $file"
+ chown $RUNAS_ID $file || error "chown $RUNAS_ID $file failed"
+ do_facet $SINGLEAGT $RUNAS $LFS pcc detach $file ||
+ error "failed to detach file $file"
+ check_lpcc_state $file "none"
+ do_facet $SINGLEAGT $RUNAS dd if=$file of=/dev/null bs=1024 count=1 ||
+ error "non-root user cannot read to $file with permisson (777)"
+}
+run_test 1g "General permission test for RW-PCC"
+
#
# When a process created a LPCC file and holding the open,
# another process on the same client should be able to open the file.
check_hsm_flags $file "0x0000000d"
rmultiop_stop $agt_host || error "close $file failed"
- cleanup_pcc_mapping
}
run_test 2a "Test multi open when creating"
"cat $file on remote client failed"
do_node $remote_client echo -n "multiopen_data" > $file \
|| error "write $file on remote client failed"
- cleanup_pcc_mapping
}
run_test 2b "Test multi remote open when creating"
cat $file2 || error "cat $file on mount $MOUNT2 failed"
echo -n "multiopen_data" > $file2 ||
error "write $file on mount $MOUNT2 failed"
-
- cleanup_pcc_mapping
}
run_test 2c "Test multi open on different mount points when creating"
do_facet $SINGLEAGT $LFS pcc detach $file ||
error "failed to detach file $file"
check_lpcc_state $file "none"
-
- cleanup_pcc_mapping
}
run_test 3a "Repeat attach/detach operations"
do_facet agt2 $LFS pcc detach $file ||
error "failed to detach file $file"
check_lpcc_state $file "none" agt2
-
- for n in $(seq $AGTCOUNT); do
- cleanup_pcc_mapping agt$n
- done
}
run_test 3b "Repeat attach/detach operations on multiple clients"
$LUSTRE/tests/mmap_sanity -d $DIR/$tdir -m $DIR2/$tdir -e 7 ||
error "mmap_sanity test failed"
sync; sleep 1; sync
-
- cleanup_pcc_mapping
}
run_test 4 "Auto cache test for mmap"
content=$($MMAP_CAT $file)
[[ $content == "attach_mmap_data" ]] ||
error "mmap cat data mismatch: $content"
-
- cleanup_pcc_mapping
}
run_test 5 "Mmap & cat a RW-PCC cached file"
content=$(do_facet $SINGLEAGT $MMAP_CAT $file)
[[ $content == "nmap_write_data" ]] ||
error "mmap write data mismatch: $content"
-
- cleanup_pcc_mapping
}
run_test 6 "Test mmap write on RW-PCC "
check_lpcc_state $file "none"
content=$(do_facet $SINGLEAGT $MMAP_CAT $file)
[[ $content == "RQQQQ" ]] || error "data mismatch: $content"
-
- cleanup_pcc_mapping
}
run_test 7a "Fake file detached between fault() and page_mkwrite() for RW-PCC"
check_lpcc_state $file "none"
content=$(do_facet $SINGLEAGT $MMAP_CAT $file)
[[ $content == "RQQQQ" ]] || error "data mismatch: $content"
-
- cleanup_pcc_mapping
}
run_test 7b "Test the race with concurrent mkwrite and detach"
# IO path. It will restore the HSM released file.
check_lpcc_state $file "none"
check_file_data $SINGLEAGT $file "ENOSPC_write"
-
- cleanup_pcc_mapping
}
run_test 8 "Test fake -ENOSPC tolerance for RW-PCC"
error "fail to dd write $file"
check_lpcc_state $file "none"
check_file_size $SINGLEAGT $file 62914560
-
- cleanup_pcc_mapping
}
run_test 9 "Test -ENOSPC tolerance on loop PCC device for RW-PCC"
-test_10() {
+test_usrgrp_quota() {
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
+ local ug=$1
+ local id=$RUNAS_ID
+
+ [[ $ug == "g" ]] && id=$RUNAS_GID
+
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
+ do_facet $SINGLEAGT quotacheck -c$ug $mntpt ||
+ error "quotacheck -c$ug $mntpt failed"
+ do_facet $SINGLEAGT quotaon -$ug $mntpt ||
+ error "quotaon -$ug $mntpt failed"
+ do_facet $SINGLEAGT setquota -$ug $id 0 20480 0 0 $mntpt ||
+ error "setquota -$ug $id on $mntpt failed"
+ do_facet $SINGLEAGT repquota -${ug}vs $mntpt
+
+ copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMVER" -h "$hsm_root"
+ setup_pcc_mapping
+ do_facet $SINGLEAGT $LCTL pcc list $MOUNT
+
+ mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+
+ local file1=$DIR/$tdir/${ug}quotaA
+ local file2=$DIR/$tdir/${ug}quotaB
+
+ dd if=/dev/zero of=$file1 bs=1M count=15 ||
+ error "dd write $file1 failed"
+ dd if=/dev/zero of=$file2 bs=1M count=15 ||
+ error "dd write $file2 failed"
+ chown $RUNAS_ID:$RUNAS_GID $file1 ||
+ error "chown $RUNAS_ID:$RUNAS_GID $file1 failed"
+ chown $RUNAS_ID:$RUNAS_GID $file2 ||
+ error "chown $RUNAS_ID:$RUNAS_GID $file2 failed"
+ do_facet $SINGLEAGT $RUNAS $LFS pcc attach -i $HSM_ARCHIVE_NUMBER \
+ $file1 || error "attach $file1 failed"
+ do_facet $SINGLEAGT $RUNAS $LFS pcc attach -i $HSM_ARCHIVE_NUMBER \
+ $file2 && error "attach $file2 should fail due to quota limit"
+ check_lpcc_state $file1 "readwrite"
+ check_lpcc_state $file2 "none"
+
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file1 bs=1M count=30 ||
+ error "dd write $file1 failed"
+ # -EDQUOT error should be tolerated via fallback to normal Lustre path.
+ check_lpcc_state $file1 "none"
+ do_facet $SINGLEAGT $LFS pcc detach $file1 ||
+ error "failed to detach file $file"
+ rm $file1 $file2
+}
+
+test_10a() {
+ test_usrgrp_quota "u"
+}
+run_test 10a "Test RW-PCC with user quota on loop PCC device"
+
+test_10b() {
+ test_usrgrp_quota "g"
+}
+run_test 10b "Test RW-PCC with group quota on loop PCC device"
+
+test_11() {
local file=$DIR/$tdir/$tfile
local hsm_root=$(hsm_root)
local file=$DIR/$tdir/$tfile
do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file &&
error "attach $file should fail as PCC path is a directory"
rm $file || error "rm $file failed"
-
- cleanup_pcc_mapping
}
-run_test 10 "Test attach fault injection with simulated PCC file path"
+run_test 11 "Test attach fault injection with simulated PCC file path"
-test_11() {
+test_12() {
local file=$DIR/$tfile
local pid
$LFS hsm_remove $file || error "hsm remove $file failed"
wait $pid && error "RW-PCC attach $file should fail"
- cleanup_pcc_mapping
+ return 0
}
-run_test 11 "RW-PCC attach races with concurrent HSM remove"
+run_test 12 "RW-PCC attach races with concurrent HSM remove"
complete $SECONDS
check_and_cleanup_lustre