Whamcloud - gitweb
LU-10918 pcc: auto RO-PCC caching when O_RDONLY open files 46/38346/9
authorQian Yingjin <qian@ddn.com>
Wed, 22 Aug 2018 13:19:48 +0000 (21:19 +0800)
committerQian Yingjin <qian@ddn.com>
Wed, 26 Aug 2020 02:20:09 +0000 (10:20 +0800)
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 <qian@ddn.com>
Change-Id: Ib2c2ab51d67aed84eb7676c8df191faa33dfad39

lustre/llite/namei.c
lustre/llite/pcc.c
lustre/llite/pcc.h
lustre/tests/sanity-pcc.sh

index 9b9c4b8..0ea98ab 100644 (file)
@@ -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;
                }
index b7657d6..41769d7 100644 (file)
@@ -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;
index 2fe6be5..c5a1ca8 100644 (file)
@@ -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);
index a39076f..1515e05 100644 (file)
@@ -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