From: Qian Yingjin Date: Wed, 22 Aug 2018 13:19:48 +0000 (+0800) Subject: LU-10918 pcc: auto RO-PCC caching when O_RDONLY open files X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=refs%2Fchanges%2F46%2F38346%2F9;p=fs%2Flustre-release.git LU-10918 pcc: auto RO-PCC caching when O_RDONLY open files During the file open() operation, if the file is being opened with O_RDONLY flags, and the file matches the predefined rule, it will be prefetched and attached into RO-PCC automatically. Test-Parameters: clientcount=3 testlist=sanity-pcc,sanity-pcc,sanity-pcc Signed-off-by: Qian Yingjin Change-Id: Ib2c2ab51d67aed84eb7676c8df191faa33dfad39 --- diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 9b9c4b8..0ea98ab 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -1095,6 +1095,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, item.pm_projid = ll_i2info(dir)->lli_projid; item.pm_name = &dentry->d_name; dataset = pcc_dataset_match_get(&sbi->ll_pcc_super, + LU_PCC_READWRITE, &item); pca.pca_dataset = dataset; } diff --git a/lustre/llite/pcc.c b/lustre/llite/pcc.c index b7657d6..41769d7 100644 --- a/lustre/llite/pcc.c +++ b/lustre/llite/pcc.c @@ -701,18 +701,29 @@ pcc_cond_match(struct pcc_match_rule *rule, struct pcc_matcher *matcher) return 0; } +static inline bool +pcc_dataset_attach_allowed(struct pcc_dataset *dataset, enum lu_pcc_type type) +{ + if (type == LU_PCC_READWRITE && dataset->pccd_flags & PCC_DATASET_RWPCC) + return true; + + if (type == LU_PCC_READONLY && dataset->pccd_flags & PCC_DATASET_ROPCC) + return true; + + return false; +} + struct pcc_dataset* -pcc_dataset_match_get(struct pcc_super *super, struct pcc_matcher *matcher) +pcc_dataset_match_get(struct pcc_super *super, enum lu_pcc_type type, + struct pcc_matcher *matcher) { struct pcc_dataset *dataset; struct pcc_dataset *selected = NULL; down_read(&super->pccs_rw_sem); list_for_each_entry(dataset, &super->pccs_datasets, pccd_linkage) { - if (!(dataset->pccd_flags & PCC_DATASET_RWPCC)) - continue; - - if (pcc_cond_match(&dataset->pccd_rule, matcher)) { + if (pcc_dataset_attach_allowed(dataset, type) && + pcc_cond_match(&dataset->pccd_rule, matcher)) { atomic_inc(&dataset->pccd_refcount); selected = dataset; break; @@ -1092,15 +1103,20 @@ void pcc_file_init(struct pcc_file *pccf) pccf->pccf_type = LU_PCC_NONE; } -static inline bool pcc_auto_attach_enabled(enum pcc_dataset_flags flags, +static inline bool pcc_auto_attach_enabled(struct pcc_dataset *dataset, + enum lu_pcc_type type, enum pcc_io_type iot) { - if (iot == PIT_OPEN) - return flags & PCC_DATASET_OPEN_ATTACH; - if (iot == PIT_GETATTR) - return flags & PCC_DATASET_STAT_ATTACH; - else - return flags & PCC_DATASET_AUTO_ATTACH; + if (pcc_dataset_attach_allowed(dataset, type)) { + if (iot == PIT_OPEN) + return dataset->pccd_flags & PCC_DATASET_OPEN_ATTACH; + if (iot == PIT_GETATTR) + return dataset->pccd_flags & PCC_DATASET_STAT_ATTACH; + else + return dataset->pccd_flags & PCC_DATASET_AUTO_ATTACH; + } + + return false; } static const char pcc_xattr_layout[] = XATTR_USER_PREFIX "PCC.layout"; @@ -1303,7 +1319,7 @@ static int pcc_try_datasets_attach(struct inode *inode, enum pcc_io_type iot, down_read(&super->pccs_rw_sem); list_for_each_entry_safe(dataset, tmp, &super->pccs_datasets, pccd_linkage) { - if (!pcc_auto_attach_enabled(dataset->pccd_flags, iot)) + if (!pcc_auto_attach_enabled(dataset, type, iot)) break; rc = pcc_try_dataset_attach(inode, gen, type, dataset, cached); @@ -1355,6 +1371,54 @@ static int pcc_try_datasets_attach(struct inode *inode, enum pcc_io_type iot, RETURN(rc); } +static int pcc_readonly_ioctl_attach(struct file *file, + struct inode *inode, + __u32 roid); + +/* Call with pcci_mutex hold */ +static int pcc_try_readonly_open_attach(struct inode *inode, struct file *file, + bool *cached) +{ + struct dentry *dentry = file->f_path.dentry; + struct pcc_dataset *dataset; + struct pcc_matcher item; + struct pcc_inode *pcci; + int rc = 0; + + ENTRY; + + if (!((file->f_flags & O_ACCMODE) == O_RDONLY)) + RETURN(0); + + item.pm_uid = from_kuid(&init_user_ns, current_uid()); + item.pm_gid = from_kgid(&init_user_ns, current_gid()); + item.pm_projid = ll_i2info(inode)->lli_projid; + item.pm_name = &dentry->d_name; + dataset = pcc_dataset_match_get(&ll_i2sbi(inode)->ll_pcc_super, + LU_PCC_READONLY, &item); + if (dataset == NULL) + RETURN(0); + + if ((dataset->pccd_flags & PCC_DATASET_PCC_ALL) == PCC_DATASET_ROPCC) { + pcc_inode_unlock(inode); + rc = pcc_readonly_ioctl_attach(file, inode, dataset->pccd_roid); + pcc_inode_lock(inode); + pcci = ll_i2pcci(inode); + if (pcci && pcc_inode_has_layout(pcci)) + *cached = true; + if (rc) { + CDEBUG(D_CACHE, + "Failed to try PCC-RO attach "DFID", rc = %d\n", + PFID(&ll_i2info(inode)->lli_fid), rc); + /* ignore the error during auto PCC-RO attach. */ + rc = 0; + } + } + + pcc_dataset_put(dataset); + RETURN(rc); +} + /* * TODO: For RW-PCC, it is desirable to store HSM info as a layout (LU-10606). * Thus the client can get archive ID from the layout directly. When try to @@ -1480,6 +1544,9 @@ int pcc_file_open(struct inode *inode, struct file *file) if (pcc_may_auto_attach(inode, PIT_OPEN)) rc = pcc_try_auto_attach(inode, &cached, PIT_OPEN); + if (rc == 0 && !cached) + rc = pcc_try_readonly_open_attach(inode, file, &cached); + if (rc < 0 || !cached) GOTO(out_unlock, rc); @@ -2455,6 +2522,15 @@ static ssize_t pcc_copy_data(struct file *src, struct file *dst) ENTRY; +#ifdef FMODE_CAN_READ + /* It needs to add FMODE_CAN_READ flags here, otherwise the check + * in kernel_read() during open() for auto PCC-RO attach will fail. + */ + if ((src->f_mode & FMODE_READ) && + likely(src->f_op->read || src->f_op->write_iter)) + src->f_mode |= FMODE_CAN_READ; +#endif + OBD_ALLOC_LARGE(buf, buf_len); if (buf == NULL) RETURN(-ENOMEM); @@ -2607,7 +2683,6 @@ out_unlock: } out_dataset_put: pcc_dataset_put(dataset); - RETURN(rc); } @@ -2730,9 +2805,16 @@ repeat: RETURN(rc); } +static void pcc_readonly_attach_fini(struct inode *inode) +{ + pcc_inode_lock(inode); + ll_i2info(inode)->lli_pcc_state &= ~PCC_STATE_FL_ATTACHING; + pcc_inode_unlock(inode); +} + static int pcc_readonly_ioctl_attach(struct file *file, struct inode *inode, - struct lu_pcc_attach *attach) + __u32 roid) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct pcc_super *super = ll_i2pccs(inode); @@ -2757,12 +2839,12 @@ static int pcc_readonly_ioctl_attach(struct file *file, rc = pcc_layout_rdonly_set(inode, &gen); if (rc) - RETURN(rc); + GOTO(out_fini, rc); dataset = pcc_dataset_get(&ll_s2sbi(inode->i_sb)->ll_pcc_super, - LU_PCC_READONLY, attach->pcca_id); + LU_PCC_READONLY, roid); if (dataset == NULL) - RETURN(-ENOENT); + GOTO(out_fini, rc = -ENOENT); rc = pcc_attach_data_archive(file, inode, dataset, &dentry); if (rc) @@ -2812,6 +2894,8 @@ out_put_unlock: mutex_unlock(&lli->lli_layout_mutex); out_dataset_put: pcc_dataset_put(dataset); +out_fini: + pcc_readonly_attach_fini(inode); RETURN(rc); } @@ -2829,7 +2913,8 @@ int pcc_ioctl_attach(struct file *file, rc = -ENOTSUPP; break; case LU_PCC_READONLY: - rc = pcc_readonly_ioctl_attach(file, inode, attach); + rc = pcc_readonly_ioctl_attach(file, inode, + attach->pcca_id); break; default: rc = -EINVAL; diff --git a/lustre/llite/pcc.h b/lustre/llite/pcc.h index 2fe6be5..c5a1ca8 100644 --- a/lustre/llite/pcc.h +++ b/lustre/llite/pcc.h @@ -261,6 +261,7 @@ 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, + enum lu_pcc_type type, struct pcc_matcher *matcher); void pcc_dataset_put(struct pcc_dataset *dataset); void pcc_inode_free(struct inode *inode); diff --git a/lustre/tests/sanity-pcc.sh b/lustre/tests/sanity-pcc.sh index a39076f..1515e05 100644 --- a/lustre/tests/sanity-pcc.sh +++ b/lustre/tests/sanity-pcc.sh @@ -2424,6 +2424,45 @@ test_28() { } run_test 28 "RW-PCC attach should fail when the file has cluster-wide openers" +test_29() { + local project_id=100 + local agt_facet=$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 + + ! 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 $SINGLEAGT \ + "projid={$project_id}\ rwid=$HSM_ARCHIVE_NUMBER\ ropcc=1" + $LCTL pcc list $MOUNT + + do_facet $SINGLEAGT mkdir -p $DIR/$tdir || + error "mkdir $DIR/$tdir failed" + do_facet $SINGLEAGT "echo -n ro_uptodate > $file" || + error "failed to write $file" + check_lpcc_state $file "none" + $LFS project -sp $project_id $file || + error "failed to set project for $file" + $LFS project -d $file + check_lpcc_state $file "readonly" + check_file_data $SINGLEAGT $file "ro_uptodate" + + echo -n Update_ro_data > $file2 + check_lpcc_state $file "readonly" + check_file_data $SINGLEAGT $file "Update_ro_data" + + do_facet $SINGLEAGT $LFS pcc detach $file || + error "failed to detach $file" +} +run_test 29 "Auto readonly caching on RO-PCC backend for O_RDONLY open" + complete $SECONDS check_and_cleanup_lustre exit_status