PCC_STATE_FL_ATTACHING = 0x02,
/* Allow to auto attach at open */
PCC_STATE_FL_OPEN_ATTACH = 0x04,
+ /* Allow to auto attach during I/O after layout lock revocation */
+ PCC_STATE_FL_IO_ATTACH = 0x08,
+ /* Allow to auto attach at stat */
+ PCC_STATE_FL_STAT_ATTACH = 0x10,
+ /* Allow to auto attach at the next open or layout refresh */
+ PCC_STATE_FL_AUTO_ATTACH = PCC_STATE_FL_OPEN_ATTACH |
+ PCC_STATE_FL_IO_ATTACH |
+ PCC_STATE_FL_STAT_ATTACH,
};
struct lu_pcc_state {
return rc;
}
-struct pcc_create_attach {
- struct pcc_dataset *pca_dataset;
- struct dentry *pca_dentry;
-};
-
static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
struct lookup_intent *it,
void **secctx, __u32 *secctxlen,
void *secctx = NULL;
__u32 secctxlen = 0;
struct ll_sb_info *sbi;
- struct pcc_create_attach pca = {NULL, NULL};
- struct pcc_dataset *dataset = NULL;
+ struct pcc_create_attach pca = { NULL, NULL };
int rc = 0;
ENTRY;
if (!filename_is_volatile(dentry->d_name.name,
dentry->d_name.len, NULL)) {
struct pcc_matcher item;
+ struct pcc_dataset *dataset;
item.pm_uid = from_kuid(&init_user_ns, current_uid());
item.pm_gid = from_kgid(&init_user_ns, current_gid());
dput(de);
goto out_release;
}
- if (dataset != NULL && dentry->d_inode) {
- rc = pcc_inode_create_fini(dataset,
- dentry->d_inode,
- pca.pca_dentry);
- if (rc) {
- if (de != NULL)
- dput(de);
- GOTO(out_release, rc);
- }
+
+ rc = pcc_inode_create_fini(dentry->d_inode, &pca);
+ if (rc) {
+ if (de != NULL)
+ dput(de);
+ GOTO(out_release, rc);
}
+
ll_set_created(opened, file);
+ } else {
+ /* Open the file with O_CREAT, but the file already
+ * existed on MDT. This may happend in the case that
+ * the LOOKUP ibits lock is revoked and the
+ * corresponding dentry cache is deleted.
+ * i.e. In the current Lustre, the truncate operation
+ * will revoke the LOOKUP ibits lock, and the file
+ * dentry cache will be invalidated. The following open
+ * with O_CREAT flag will call into ->atomic_open, the
+ * file was wrongly though as newly created file and
+ * try to auto cache the file. So after client knows it
+ * is not a DISP_OPEN_CREATE, it should cleanup the
+ * already created PCC copy.
+ */
+ pcc_create_attach_cleanup(dir->i_sb, &pca);
}
if (dentry->d_inode && it_disposition(it, DISP_OPEN_OPEN)) {
} else {
rc = finish_no_open(file, de);
}
+ } else {
+ pcc_create_attach_cleanup(dir->i_sb, &pca);
}
out_release:
- if (dataset != NULL)
- pcc_dataset_put(dataset);
ll_intent_release(it);
OBD_FREE(it, sizeof(*it));
if (id <= 0)
return -EINVAL;
cmd->u.pccc_add.pccc_roid = id;
+ } else if (strcmp(key, "auto_attach") == 0) {
+ rc = kstrtoul(val, 10, &id);
+ if (rc)
+ return rc;
+ if (id == 0)
+ cmd->u.pccc_add.pccc_flags &= ~PCC_DATASET_AUTO_ATTACH;
} else if (strcmp(key, "open_attach") == 0) {
rc = kstrtoul(val, 10, &id);
if (rc)
return rc;
- if (id > 0)
- cmd->u.pccc_add.pccc_flags |= PCC_DATASET_OPEN_ATTACH;
+ if (id == 0)
+ cmd->u.pccc_add.pccc_flags &= ~PCC_DATASET_OPEN_ATTACH;
+ } else if (strcmp(key, "io_attach") == 0) {
+ rc = kstrtoul(val, 10, &id);
+ if (rc)
+ return rc;
+ if (id == 0)
+ cmd->u.pccc_add.pccc_flags &= ~PCC_DATASET_IO_ATTACH;
+ } else if (strcmp(key, "stat_attach") == 0) {
+ rc = kstrtoul(val, 10, &id);
+ if (rc)
+ return rc;
+ if (id == 0)
+ cmd->u.pccc_add.pccc_flags &= ~PCC_DATASET_STAT_ATTACH;
} else if (strcmp(key, "rwpcc") == 0) {
rc = kstrtoul(val, 10, &id);
if (rc)
char *token;
int rc;
+ switch (cmd->pccc_cmd) {
+ case PCC_ADD_DATASET:
+ /* Enable auto attach by default */
+ cmd->u.pccc_add.pccc_flags |= PCC_DATASET_AUTO_ATTACH;
+ break;
+ case PCC_DEL_DATASET:
+ case PCC_CLEAR_ALL:
+ break;
+ default:
+ return -EINVAL;
+ }
+
val = buffer;
while (val != NULL && strlen(val) != 0) {
token = strsep(&val, " ");
{
pcci->pcci_lli = lli;
lli->lli_pcc_inode = pcci;
- lli->lli_pcc_state = PCC_STATE_FL_NONE;
atomic_set(&pcci->pcci_refcount, 0);
pcci->pcci_type = LU_PCC_NONE;
pcci->pcci_layout_gen = CL_LAYOUT_GEN_NONE;
pccf->pccf_type = LU_PCC_NONE;
}
-static inline bool pcc_open_attach_enabled(struct pcc_dataset *dataset)
+static inline bool pcc_auto_attach_enabled(struct pcc_dataset *dataset)
{
- return dataset->pccd_flags & PCC_DATASET_OPEN_ATTACH;
+ return dataset->pccd_flags & PCC_DATASET_AUTO_ATTACH;
}
static const char pcc_xattr_layout[] = XATTR_USER_PREFIX "PCC.layout";
ENTRY;
- if (!(lli->lli_pcc_state & PCC_STATE_FL_OPEN_ATTACH))
+ if (!(lli->lli_pcc_state & PCC_STATE_FL_AUTO_ATTACH))
RETURN(0);
#ifndef HAVE_VFS_SETXATTR
struct dentry *dentry,
enum lu_pcc_type type)
{
+ struct ll_inode_info *lli = pcci->pcci_lli;
+
pcci->pcci_path.mnt = mntget(dataset->pccd_path.mnt);
pcci->pcci_path.dentry = dentry;
LASSERT(atomic_read(&pcci->pcci_refcount) == 0);
pcci->pcci_type = type;
pcci->pcci_attr_valid = false;
- if (pcc_open_attach_enabled(dataset)) {
- struct ll_inode_info *lli = pcci->pcci_lli;
-
+ if (dataset->pccd_flags & PCC_DATASET_OPEN_ATTACH)
lli->lli_pcc_state |= PCC_STATE_FL_OPEN_ATTACH;
- }
+ if (dataset->pccd_flags & PCC_DATASET_IO_ATTACH)
+ lli->lli_pcc_state |= PCC_STATE_FL_IO_ATTACH;
+ if (dataset->pccd_flags & PCC_DATASET_STAT_ATTACH)
+ lli->lli_pcc_state |= PCC_STATE_FL_STAT_ATTACH;
}
static inline void pcc_layout_gen_set(struct pcc_inode *pcci,
down_read(&super->pccs_rw_sem);
list_for_each_entry_safe(dataset, tmp,
&super->pccs_datasets, pccd_linkage) {
- if (!pcc_open_attach_enabled(dataset))
+ if (!pcc_auto_attach_enabled(dataset))
continue;
rc = pcc_try_dataset_attach(inode, gen, type, dataset, cached);
if (rc < 0 || (!rc && *cached))
RETURN(rc);
}
-static int pcc_try_open_attach(struct inode *inode, bool *cached)
+static int pcc_try_auto_attach(struct inode *inode, bool *cached, bool is_open)
{
struct pcc_super *super = &ll_i2sbi(inode)->ll_pcc_super;
struct cl_layout clt = {
.cl_layout_gen = 0,
.cl_is_released = false,
};
+ struct ll_inode_info *lli = ll_i2info(inode);
+ __u32 gen;
int rc;
ENTRY;
* obtain valid layout lock from MDT (i.e. the file is being
* HSM restoring).
*/
- if (ll_layout_version_get(ll_i2info(inode)) == CL_LAYOUT_GEN_NONE)
- RETURN(0);
+ if (is_open) {
+ if (ll_layout_version_get(lli) == CL_LAYOUT_GEN_NONE)
+ RETURN(0);
+ } else {
+ rc = ll_layout_refresh(inode, &gen);
+ if (rc)
+ RETURN(rc);
+ }
rc = pcc_get_layout_info(inode, &clt);
if (rc)
RETURN(rc);
+ if (!is_open && gen != clt.cl_layout_gen) {
+ CDEBUG(D_CACHE, DFID" layout changed from %d to %d.\n",
+ PFID(ll_inode2fid(inode)), gen, clt.cl_layout_gen);
+ RETURN(-EINVAL);
+ }
+
if (clt.cl_is_released)
rc = pcc_try_datasets_attach(inode, clt.cl_layout_gen,
LU_PCC_READWRITE, cached);
GOTO(out_unlock, rc = 0);
if (!pcci || !pcc_inode_has_layout(pcci)) {
- rc = pcc_try_open_attach(inode, &cached);
+ if (lli->lli_pcc_state & PCC_STATE_FL_OPEN_ATTACH)
+ rc = pcc_try_auto_attach(inode, &cached, true);
+
if (rc < 0 || !cached)
GOTO(out_unlock, rc);
RETURN_EXIT;
}
-static void pcc_io_init(struct inode *inode, bool *cached)
+static void pcc_io_init(struct inode *inode, enum pcc_io_type iot, bool *cached)
{
+ struct ll_inode_info *lli = ll_i2info(inode);
struct pcc_inode *pcci;
pcc_inode_lock(inode);
*cached = true;
} else {
*cached = false;
+ if ((lli->lli_pcc_state & PCC_STATE_FL_IO_ATTACH &&
+ iot != PIT_GETATTR) ||
+ (iot == PIT_GETATTR &&
+ lli->lli_pcc_state & PCC_STATE_FL_STAT_ATTACH)) {
+ (void) pcc_try_auto_attach(inode, cached, false);
+ if (*cached) {
+ pcci = ll_i2pcci(inode);
+ LASSERT(atomic_read(&pcci->pcci_refcount) > 0);
+ atomic_inc(&pcci->pcci_active_ios);
+ }
+ }
}
pcc_inode_unlock(inode);
}
RETURN(0);
}
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_READ, cached);
if (!*cached)
RETURN(0);
RETURN(-EAGAIN);
}
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_WRITE, cached);
if (!*cached)
RETURN(0);
RETURN(0);
}
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_SETATTR, cached);
if (!*cached)
RETURN(0);
RETURN(0);
}
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_GETATTR, cached);
if (!*cached)
RETURN(0);
if (!file_inode(pcc_file)->i_fop->splice_read)
RETURN(-ENOTSUPP);
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_SPLICE_READ, cached);
if (!*cached)
RETURN(0);
RETURN(0);
}
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_FSYNC, cached);
if (!*cached)
RETURN(0);
CDEBUG(D_MMAP,
"%s: PCC backend fs not support ->page_mkwrite()\n",
ll_i2sbi(inode)->ll_fsname);
- pcc_ioctl_detach(inode, PCC_DETACH_OPT_NONE);
+ pcc_ioctl_detach(inode, PCC_DETACH_OPT_UNCACHE);
up_read(&mm->mmap_sem);
*cached = true;
RETURN(VM_FAULT_RETRY | VM_FAULT_NOPAGE);
/* Pause to allow for a race with concurrent detach */
OBD_FAIL_TIMEOUT(OBD_FAIL_LLITE_PCC_MKWRITE_PAUSE, cfs_fail_val);
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_PAGE_MKWRITE, cached);
if (!*cached) {
/* This happens when the file is detached from PCC after got
* the fault page via ->fault() on the inode of the PCC copy.
*/
if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_PCC_DETACH_MKWRITE)) {
pcc_io_fini(inode);
- pcc_ioctl_detach(inode, PCC_DETACH_OPT_NONE);
+ pcc_ioctl_detach(inode, PCC_DETACH_OPT_UNCACHE);
up_read(&mm->mmap_sem);
RETURN(VM_FAULT_RETRY | VM_FAULT_NOPAGE);
}
RETURN(0);
}
- pcc_io_init(inode, cached);
+ pcc_io_init(inode, PIT_FAULT, cached);
if (!*cached)
RETURN(0);
return rc;
}
-int pcc_inode_create_fini(struct pcc_dataset *dataset, struct inode *inode,
- struct dentry *pcc_dentry)
+int pcc_inode_create_fini(struct inode *inode, struct pcc_create_attach *pca)
{
+ struct dentry *pcc_dentry = pca->pca_dentry;
const struct cred *old_cred;
struct pcc_inode *pcci;
- int rc = 0;
+ int rc;
ENTRY;
+ if (!pca->pca_dataset)
+ RETURN(0);
+
+ if (!inode)
+ GOTO(out_dataset_put, rc = 0);
+
+ LASSERT(pcc_dentry);
+
old_cred = override_creds(pcc_super_cred(inode->i_sb));
pcc_inode_lock(inode);
LASSERT(ll_i2pcci(inode) == NULL);
GOTO(out_put, rc);
pcc_inode_init(pcci, ll_i2info(inode));
- pcc_inode_attach_init(dataset, pcci, pcc_dentry, LU_PCC_READWRITE);
+ pcc_inode_attach_init(pca->pca_dataset, pcci, pcc_dentry,
+ LU_PCC_READWRITE);
rc = pcc_layout_xattr_set(pcci, 0);
if (rc) {
out_unlock:
pcc_inode_unlock(inode);
revert_creds(old_cred);
+out_dataset_put:
+ pcc_dataset_put(pca->pca_dataset);
RETURN(rc);
}
+void pcc_create_attach_cleanup(struct super_block *sb,
+ struct pcc_create_attach *pca)
+{
+ if (!pca->pca_dataset)
+ return;
+
+ if (pca->pca_dentry) {
+ const struct cred *old_cred;
+ int rc;
+
+ old_cred = override_creds(pcc_super_cred(sb));
+ rc = ll_vfs_unlink(pca->pca_dentry->d_parent->d_inode,
+ pca->pca_dentry);
+ if (rc)
+ CWARN("failed to unlink PCC file %.*s, rc = %d\n",
+ pca->pca_dentry->d_name.len,
+ pca->pca_dentry->d_name.name, rc);
+ /* ignore the unlink failure */
+ revert_creds(old_cred);
+ dput(pca->pca_dentry);
+ }
+
+ pcc_dataset_put(pca->pca_dataset);
+}
+
static int pcc_filp_write(struct file *filp, const void *buf, ssize_t count,
loff_t *offset)
{
old_cred = override_creds(pcc_super_cred(inode->i_sb));
pcc_inode_lock(inode);
pcci = ll_i2pcci(inode);
- lli->lli_pcc_state &= ~PCC_STATE_FL_ATTACHING;
if (rc || lease_broken) {
if (attached && pcci)
pcc_inode_put(pcci);
if (rc)
GOTO(out_put, rc);
+ LASSERT(lli->lli_pcc_state & PCC_STATE_FL_ATTACHING);
rc = ll_layout_refresh(inode, &gen2);
if (!rc) {
if (gen2 == gen) {
pcc_inode_put(pcci);
}
out_unlock:
+ lli->lli_pcc_state &= ~PCC_STATE_FL_ATTACHING;
pcc_inode_unlock(inode);
revert_creds(old_cred);
RETURN(rc);
enum pcc_dataset_flags {
PCC_DATASET_NONE = 0x0,
- /* Try auto attach at open, disabled by default */
- PCC_DATASET_OPEN_ATTACH = 0x1,
+ /* Try auto attach at open, enabled by default */
+ PCC_DATASET_OPEN_ATTACH = 0x01,
+ /* Try auto attach during IO when layout refresh, enabled by default */
+ PCC_DATASET_IO_ATTACH = 0x02,
+ /* Try auto attach at stat */
+ PCC_DATASET_STAT_ATTACH = 0x04,
+ PCC_DATASET_AUTO_ATTACH = PCC_DATASET_OPEN_ATTACH |
+ PCC_DATASET_IO_ATTACH |
+ PCC_DATASET_STAT_ATTACH,
/* PCC backend is only used for RW-PCC */
- PCC_DATASET_RWPCC = 0x2,
+ PCC_DATASET_RWPCC = 0x08,
/* PCC backend is only used for RO-PCC */
- PCC_DATASET_ROPCC = 0x4,
+ PCC_DATASET_ROPCC = 0x10,
/* PCC backend provides caching services for both RW-PCC and RO-PCC */
PCC_DATASET_PCC_ALL = PCC_DATASET_RWPCC | PCC_DATASET_ROPCC,
};
enum lu_pcc_type pccf_type;
};
+enum pcc_io_type {
+ /* read system call */
+ PIT_READ = 1,
+ /* write system call */
+ PIT_WRITE,
+ /* truncate, utime system calls */
+ PIT_SETATTR,
+ /* stat system call */
+ PIT_GETATTR,
+ /* mmap write handling */
+ PIT_PAGE_MKWRITE,
+ /* page fault handling */
+ PIT_FAULT,
+ /* fsync system call handling */
+ PIT_FSYNC,
+ /* splice_read system call */
+ PIT_SPLICE_READ
+};
+
enum pcc_cmd_type {
PCC_ADD_DATASET = 0,
PCC_DEL_DATASET,
} u;
};
+struct pcc_create_attach {
+ struct pcc_dataset *pca_dataset;
+ struct dentry *pca_dentry;
+};
+
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,
bool *cached);
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);
+int pcc_inode_create_fini(struct inode *inode, struct pcc_create_attach *pca);
+void pcc_create_attach_cleanup(struct super_block *sb,
+ struct pcc_create_attach *pca);
struct pcc_dataset *pcc_dataset_match_get(struct pcc_super *super,
struct pcc_matcher *matcher);
void pcc_dataset_put(struct pcc_dataset *dataset);
void pcc_inode_free(struct inode *inode);
void pcc_layout_invalidate(struct inode *inode);
-
#endif /* LLITE_PCC_H */
do_facet $facet $LCTL pcc add $MOUNT $hsm_root -p $param
}
+setup_loopdev() {
+ local facet=$1
+ local file=$2
+ local mntpt=$3
+ local size=${4:-50}
+
+ do_facet $facet mkdir -p $mntpt || error "mkdir -p $hsm_root failed"
+ stack_trap "do_facet $facet rm -rf $mntpt" EXIT
+ do_facet $facet dd if=/dev/zero of=$file bs=1M count=$size
+ stack_trap "do_facet $facet rm -f $file" EXIT
+ do_facet $facet mkfs.ext4 $file ||
+ error "mkfs.ext4 $file failed"
+ do_facet $facet file $file
+ do_facet $facet mount -t ext4 -o loop,usrquota,grpquota $file $mntpt ||
+ error "mount -o loop,usrquota,grpquota $file $mntpt failed"
+ stack_trap "do_facet $facet $UMOUNT $mntpt" EXIT
+}
+
lpcc_rw_test() {
local restore="$1"
local project="$2"
local project_id=100
local agt_facet=$SINGLEAGT
- local hsm_root=$(hsm_root)
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
local file=$DIR/$tdir/$tfile
local -a state
local -a lpcc_path
$project && enable_project_quota
do_facet $SINGLEAGT rm -rf $hsm_root
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
is_project_quota_supported || project=false
local -a lpcc_path
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
$LCTL pcc list $MOUNT
mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
chmod 777 $DIR/$tdir || error "chmod 777 $DIR/$tdir failed"
test_1f() {
local project_id=100
local agt_facet=$SINGLEAGT
- local hsm_root=$(hsm_root)
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
local file=$DIR/$tdir/$tfile
! is_project_quota_supported &&
skip "project quota is not supported"
enable_project_quota
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ open_attach=0\ stat_attach=0"
+
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 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 ||
+ do_facet $SINGLEAGT $RUNAS dd if=/dev/zero of=$file bs=256 count=1 ||
error "failed to dd write from $file"
check_lpcc_state $file "readwrite"
do_facet $SINGLEAGT $RUNAS $LFS pcc detach $file ||
error "failed to detach file $file"
- check_lpcc_state $file "none"
wait_request_state $(path2fid $file) REMOVE SUCCEED
+ check_lpcc_state $file "none"
}
run_test 1f "Test auto RW-PCC cache with non-root user"
test_1g() {
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
local file=$DIR/$tfile
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
test_2a() {
local project_id=100
local agt_facet=$SINGLEAGT
- local hsm_root=$(hsm_root)
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
local agt_host=$(facet_active_host $SINGLEAGT)
! is_project_quota_supported &&
skip "project quota is not supported" && return
enable_project_quota
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
file=$DIR/$tdir/multiop
# HSM released exists archived status
check_hsm_flags $file "0x0000000d"
+ do_facet $SINGLEAGT $LFS pcc detach $file ||
+ error "failed to detach $file"
rmultiop_stop $agt_host || error "close $file failed"
}
run_test 2a "Test multi open when creating"
#
test_2b() {
local agt_facet=$SINGLEAGT
- local hsm_root=$(hsm_root)
local agt_host=$(facet_active_host $SINGLEAGT)
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
needclients 2 || return 0
remote_client=$(get_remote_client)
enable_project_quota
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
file=$DIR/$tdir/multiop
test_2c() {
local agt_host=$(facet_active_host $SINGLEAGT)
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
local file=$DIR/$tdir/$tfile
local file2=$DIR2/$tdir/$tfile
enable_project_quota
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
mkdir -p $DIR/$tdir
local file=$DIR/$tdir/$tfile
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
dd if=/dev/zero of=$file bs=1024 count=1 ||
# Start all of the copytools and setup PCC
for n in $(seq $AGTCOUNT); do
copytool setup -f agt$n -a $n -m $MOUNT
- setup_pcc_mapping agt$n "projid={100}\ rwid=$n"
+ setup_pcc_mapping agt$n "projid={100}\ rwid=$n\ auto_attach=0"
done
mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
test_4() {
local project_id=100
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
! is_project_quota_supported &&
skip "project quota is not supported" && return
enable_project_quota
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
$LUSTRE/tests/mmap_sanity -d $DIR/$tdir -m $DIR2/$tdir -e 7 ||
error "mmap_sanity test failed"
sync; sleep 1; sync
+
+ rm -rf $DIR/$tdir || error "failed to remove $DIR/$tdir"
}
run_test 4 "Auto cache test for mmap"
test_5() {
local file=$DIR/$tfile
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
}
run_test 5 "Mmap & cat a RW-PCC cached file"
-setup_loopdev() {
- local facet=$1
- local file=$2
- local mntpt=$3
- local size=${4:-50}
-
- do_facet $facet mkdir -p $mntpt || error "mkdir -p $hsm_root failed"
- stack_trap "do_facet $facet rm -rf $mntpt" EXIT
- do_facet $facet dd if=/dev/zero of=$file bs=1M count=$size
- stack_trap "do_facet $facet rm -f $file" EXIT
- do_facet $facet mkfs.ext4 $file ||
- error "mkfs.ext4 $file failed"
- do_facet $facet file $file
- do_facet $facet mount -t ext4 -o loop,usrquota,grpquota $file $mntpt ||
- error "mount -o loop,usrquota,grpquota $file $mntpt failed"
- stack_trap "do_facet $facet $UMOUNT $mntpt" EXIT
-}
-
test_6() {
local loopfile="$TMP/$tfile"
local mntpt="/mnt/pcc.$tdir"
error "mmap write data mismatch: $content"
check_lpcc_state $file "readwrite"
- do_facet $SINGLEAGT $LFS pcc detach -k $file ||
+ do_facet $SINGLEAGT $LFS pcc detach $file ||
error "failed to detach file $file"
+ wait_request_state $(path2fid $file) REMOVE SUCCEED
content=$(do_facet $SINGLEAGT $MMAP_CAT $file)
[[ $content == "nmap_write_data" ]] ||
setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
echo "QQQQQ" > $file
do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
do_facet $SINGLEAGT $MULTIOP $file OSMWUc &
pid=$!
+ sleep 3
do_facet $SINGLEAGT $LFS pcc detach -k $file ||
error "failed to detach file $file"
run_test 7b "Test the race with concurrent mkwrite and detach"
test_8() {
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
local file=$DIR/$tfile
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping
local pid
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
echo -n race_rw_attach_hsmremove > $file
lpcc_path=$(lpcc_fid2path $hsm_root $file)
local myRUNAS="$3"
local file=$DIR/$tdir/$tfile
- setup_pcc_mapping $SINGLEAGT "$rule\ rwid=$HSM_ARCHIVE_NUMBER"
+ setup_pcc_mapping $SINGLEAGT \
+ "$rule\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
$LCTL pcc list $MOUNT
do_facet $SINGLEAGT mkdir -p $DIR/$tdir
error "failed to dd write from $file"
check_lpcc_state $file "readwrite"
- do_facet $SINGLEAGT $myRUNAS $LFS pcc detach -k $file ||
+ do_facet $SINGLEAGT $myRUNAS $LFS pcc detach $file ||
error "failed to detach file $file"
+ wait_request_state $(path2fid $file) REMOVE SUCCEED
check_lpcc_state $file "none"
+
+ cleanup_pcc_mapping
}
test_13a() {
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping $SINGLEAGT \
- "fname={*.h5\ suffix.*\ Mid*dle}\ rwid=$HSM_ARCHIVE_NUMBER"
+ "fname={*.h5\ suffix.*\ Mid*dle}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
$LCTL pcc list $MOUNT
do_facet $SINGLEAGT mkdir -p $DIR/$tdir
test_13c() {
local file
local myRUNAS
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
! is_project_quota_supported &&
echo "Skip project quota is not supported" && return 0
enable_project_quota
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
setup_pcc_mapping $SINGLEAGT \
"projid={100\ 200}\&fname={*.h5},uid={500}\&gid={1000}\ rwid=$HSM_ARCHIVE_NUMBER"
local file=$DIR/$tdir/$tfile
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ auto_attach=0"
mkdir -p $DIR/$tdir || error "mkdir -p $DIR/$tdir failed"
do_facet $SINGLEAGT "echo -n autodetach_data > $file"
setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping $SINGLEAGT \
- "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ open_attach=1"
+ setup_pcc_mapping
mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
chmod 777 $DIR/$tdir || error "chmod 777 $DIR/$tdir failed"
setup_loopdev $SINGLEAGT $loopfile $mntpt 50
copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
- setup_pcc_mapping $SINGLEAGT \
- "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ open_attach=1"
+ setup_pcc_mapping
do_facet $SINGLEAGT "echo -n detach_data > $file"
lpcc_path=$(lpcc_fid2path $hsm_root $file)
}
run_test 16 "Test detach with different options"
+test_17() {
+ 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
+
+ setup_loopdev $SINGLEAGT $loopfile $mntpt 50
+ copytool setup -m "$MOUNT" -a "$HSM_ARCHIVE_NUMBER"
+ setup_pcc_mapping $SINGLEAGT \
+ "projid={100}\ rwid=$HSM_ARCHIVE_NUMBER\ open_attach=0\ stat_attach=0"
+
+ do_facet $SINGLEAGT $LCTL pcc list $MOUNT
+
+ do_facet $SINGLEAGT "echo -n layout_refresh_data > $file"
+ do_facet $SINGLEAGT $LFS pcc attach -i $HSM_ARCHIVE_NUMBER $file ||
+ error "PCC attach $file failed"
+ check_lpcc_state $file "readwrite"
+
+ do_facet $SINGLEAGT $LFS pcc detach -k $file ||
+ error "PCC detach $file failed"
+ check_lpcc_state $file "none"
+
+ # Truncate should attach the file into PCC automatically
+ # as the PCC copy is still valid.
+ echo "Verify auto attach during IO for truncate"
+ do_facet $SINGLEAGT $TRUNCATE $file 4 || error "truncate $file failed"
+ check_lpcc_state $file "readwrite"
+
+ echo "Verify auto attach during IO for read/write"
+ rmultiop_start $agt_host $file O_r || error "open $file failed"
+ sleep 3
+
+ # Revoke the layout lock, the PCC-cached file will be
+ # detached automatically.
+ do_facet $SINGLEAGT $LCTL \
+ set_param ldlm.namespaces.*mdc*.lru_size=clear
+
+ check_lpcc_state $file "none"
+ rmultiop_stop $agt_host || error "close $file failed"
+ sleep 3
+ check_lpcc_state $file "readwrite"
+
+ do_facet $SINGLEAGT $LFS pcc detach -k $file ||
+ error "PCC detach $file failed"
+ check_lpcc_state $file "none"
+}
+run_test 17 "Test auto attach for layout refresh"
+
complete $SECONDS
check_and_cleanup_lustre
exit_status