Whamcloud - gitweb
LU-10499 pcc: add pcc_mode parameter for permission check 22/54422/4
authorQian Yingjin <qian@ddn.com>
Wed, 1 Sep 2021 13:45:47 +0000 (21:45 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 8 Aug 2024 00:15:16 +0000 (00:15 +0000)
This patch introduced a "llite.*.pcc_mode" parameter for PCC.
By this parameter, administrator can determine what file access
permissions should be allowed to bring files into PCC device for
caching.
This paramter is set with 0 by default.
Add sanity-pcc test_46 to verify it.

In this patch, it also ignores the EEXIST error when found that the
file had already attached into PCC during the manual attach.

EX-bug-id: EX-3741
Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I1e006e4f723c1c177ae84c64ad32c6049a57110f
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54422
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/lproc_llite.c
lustre/llite/pcc.c
lustre/llite/pcc.h
lustre/tests/sanity-pcc.sh

index 9492ffd..342132d 100644 (file)
@@ -2867,7 +2867,7 @@ out_state_free:
                if (!S_ISREG(inode2->i_mode))
                        GOTO(out_iput, rc = -EINVAL);
 
-               if (!inode_owner_or_capable(&nop_mnt_idmap, inode2))
+               if (!pcc_inode_permission(inode2))
                        GOTO(out_iput, rc = -EPERM);
 
                rc = pcc_ioctl_detach(inode2, &detach->pccd_flags);
index 617955e..a79b561 100644 (file)
@@ -4866,7 +4866,7 @@ out_ladvise:
                if (!S_ISREG(inode->i_mode))
                        RETURN(-EINVAL);
 
-               if (!inode_owner_or_capable(&nop_mnt_idmap, inode))
+               if (!pcc_inode_permission(inode))
                        RETURN(-EPERM);
 
                OBD_ALLOC_PTR(attach);
@@ -4896,7 +4896,7 @@ out_pcc:
                if (!S_ISREG(inode->i_mode))
                        GOTO(out_detach_free, rc = -EINVAL);
 
-               if (!inode_owner_or_capable(&nop_mnt_idmap, inode))
+               if (!pcc_inode_permission(inode))
                        GOTO(out_detach_free, rc = -EPERM);
 
                rc = pcc_ioctl_detach(inode, &detach->pccd_flags);
index 373ad0c..586a9c8 100644 (file)
@@ -673,6 +673,38 @@ static ssize_t pcc_async_affinity_store(struct kobject *kobj,
 }
 LUSTRE_RW_ATTR(pcc_async_affinity);
 
+static ssize_t pcc_mode_show(struct kobject *kobj, struct attribute *attr,
+                             char *buffer)
+{
+       struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
+                                             ll_kset.kobj);
+       struct pcc_super *super = &sbi->ll_pcc_super;
+
+       return sprintf(buffer, "0%o\n", super->pccs_mode);
+
+}
+
+static ssize_t pcc_mode_store(struct kobject *kobj, struct attribute *attr,
+                              const char *buffer, size_t count)
+{
+       struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
+                                             ll_kset.kobj);
+       struct pcc_super *super = &sbi->ll_pcc_super;
+       __u32 mode;
+       int rc;
+
+       rc = kstrtouint(buffer, 8, &mode);
+       if (rc)
+               return rc;
+
+       if (mode & ~S_IRWXUGO)
+               return -EINVAL;
+
+       super->pccs_mode = mode;
+       return count;
+}
+LUSTRE_RW_ATTR(pcc_mode);
+
 static ssize_t checksums_show(struct kobject *kobj, struct attribute *attr,
                              char *buf)
 {
@@ -2306,6 +2338,7 @@ static struct attribute *llite_attrs[] = {
        &lustre_attr_filename_enc_use_old_base64.attr,
 #endif
        &lustre_attr_pcc_async_threshold.attr,
+       &lustre_attr_pcc_mode.attr,
        &lustre_attr_pcc_async_affinity.attr,
        NULL,
 };
index 10c221f..1f112a7 100644 (file)
@@ -130,6 +130,7 @@ int pcc_super_init(struct pcc_super *super)
        INIT_LIST_HEAD(&super->pccs_datasets);
        super->pccs_generation = 1;
        super->pccs_async_threshold = PCC_DEFAULT_ASYNC_THRESHOLD;
+       super->pccs_mode = S_IRUSR;
 
        return 0;
 }
@@ -2299,6 +2300,16 @@ static void pcc_io_fini(struct inode *inode, enum pcc_io_type iot,
                wake_up_all(&pcci->pcci_waitq);
 }
 
+bool pcc_inode_permission(struct inode *inode)
+{
+       umode_t mask = inode->i_mode & ll_i2pccs(inode)->pccs_mode;
+
+       return (mask & (S_IRUSR | S_IXUSR) &&
+               inode_owner_or_capable(&nop_mnt_idmap, inode)) ||
+              (mask & (S_IRGRP | S_IXGRP) && in_group_p(inode->i_gid)) ||
+              (mask & (S_IROTH | S_IXOTH));
+}
+
 int pcc_file_open(struct inode *inode, struct file *file)
 {
        struct pcc_inode *pcci;
@@ -2330,7 +2341,7 @@ 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)
+               if (rc == 0 && !cached && pcc_inode_permission(inode))
                        rc = pcc_try_readonly_open_attach(inode, file, &cached);
 
                if (rc < 0)
@@ -3993,6 +4004,9 @@ static int pcc_readonly_attach_sync(struct file *file,
                CDEBUG(D_CACHE,
                       "PCC-RO caching for "DFID" not allowed, rc = %d\n",
                       PFID(ll_inode2fid(inode)), rc);
+               /* Ignore EEXIST error if the file has already attached. */
+               if (rc == -EEXIST)
+                       rc = 0;
                RETURN(rc);
        }
 
index d0247ac..fb3045e 100644 (file)
@@ -171,6 +171,7 @@ struct pcc_super {
        /* Size threshold for asynchrous PCC-RO attach in background. */
        __u64                    pccs_async_threshold;
        bool                     pccs_async_affinity;
+       umode_t                  pccs_mode;
 };
 
 struct pcc_inode {
@@ -286,6 +287,7 @@ int pcc_ioctl_detach(struct inode *inode, __u32 *flags);
 int pcc_ioctl_state(struct file *file, struct inode *inode,
                    struct lu_pcc_state *state);
 void pcc_file_init(struct pcc_file *pccf);
+bool pcc_inode_permission(struct inode *inode);
 int pcc_file_open(struct inode *inode, struct file *file);
 void pcc_file_release(struct inode *inode, struct file *file);
 ssize_t pcc_file_read_iter(struct kiocb *iocb, struct iov_iter *iter,
index 32ad858..f2c53c3 100755 (executable)
@@ -3340,6 +3340,9 @@ test_42() {
        local hsm_root="$mntpt/$tdir"
        local file=$DIR/$tfile
 
+       $LCTL get_param -n mdc.*.connect_flags | grep -q pcc_ro ||
+               skip "Server does not support PCC-RO"
+
        setup_loopdev $SINGLEAGT $loopfile $mntpt 60
        do_facet $SINGLEAGT mkdir $hsm_root || error "mkdir $hsm_root failed"
        setup_pcc_mapping $SINGLEAGT \
@@ -3355,6 +3358,32 @@ test_42() {
 }
 run_test 42 "PCC attach without attach ID specified"
 
+test_43() {
+       local loopfile="$TMP/$tfile"
+       local mntpt="/mnt/pcc.$tdir"
+       local hsm_root="$mntpt/$tdir"
+       local file=$DIR/$tfile
+
+       $LCTL get_param -n mdc.*.connect_flags | grep -q pcc_ro ||
+               skip "Server does not support PCC-RO"
+
+       setup_loopdev $SINGLEAGT $loopfile $mntpt 60
+       do_facet $SINGLEAGT mkdir $hsm_root || error "mkdir $hsm_root failed"
+       setup_pcc_mapping $SINGLEAGT \
+               "size\<{100M}\ roid=$HSM_ARCHIVE_NUMBER\ ropcc=1"
+       do_facet $SINGLEAGT $LCTL pcc list $MOUNT
+
+       echo "attach_root_user_data" > $file || error "echo $file failed"
+
+       do_facet $SINGLEAGT $LFS pcc state $file
+       # Attach by non-root user should fail.
+       do_facet $SINGLEAGT $RUNAS $LFS pcc attach -r $file &&
+               error "PCC attach -r $file should fail for non-root user"
+       do_facet $SINGLEAGT $RUNAS $LFS pcc state $file
+       check_lpcc_state $file "none"
+}
+run_test 43 "Auto attach at open() should add capacity owner check"
+
 test_44() {
        local loopfile="$TMP/$tfile"
        local mntpt="/mnt/pcc.$tdir"
@@ -3516,6 +3545,73 @@ test_45() {
 }
 run_test 45 "Concurrent read access from two mount points"
 
+test_46() {
+       local loopfile="$TMP/$tfile"
+       local mntpt="/mnt/pcc.$tdir"
+       local hsm_root="$mntpt/$tdir"
+       local file=$DIR/$tfile
+       local fsuuid=$($LFS getname $MOUNT | awk '{print $1}')
+
+       $LCTL get_param -n mdc.*.connect_flags | grep -q pcc_ro ||
+               skip "Server does not support PCC-RO"
+
+       setup_loopdev client $loopfile $mntpt 60
+       mkdir $hsm_root || error "mkdir $hsm_root failed"
+       setup_pcc_mapping client \
+               "projid={0}\ roid=$HSM_ARCHIVE_NUMBER\ ropcc=1\ mmap_conv=0"
+       $LCTL pcc list $MOUNT
+
+       local mode=$($LCTL get_param -n llite.$fsuuid.pcc_mode)
+       $RUNAS id
+
+       echo "Mode: $mode"
+       echo "QQQQQ" > $file || error "write $file failed"
+       chmod 664 $file || error "chomd $file failed"
+
+       $LCTL set_param llite.$fsuuid.pcc_mode="0" ||
+               error "Set PCC mode failed"
+       stack_trap "$LCTL set_param llite.$fsuuid.pcc_mode=$mode" EXIT
+       $RUNAS $LFS pcc attach -r $file &&
+               error "User should not attach $file"
+       $RUNAS cat $file || error "cat $file failed"
+       check_lpcc_state $file "none" client
+
+       $LCTL set_param llite.$fsuuid.pcc_mode="0400" ||
+               error "Set PCC mode failed"
+       stack_trap "$LCTL set_param llite.$fsuuid.pcc_mode=$mode" EXIT
+       $RUNAS $LFS pcc attach -r $file &&
+               error "User should not attach $file"
+       $RUNAS cat $file || error "cat $file failed"
+       check_lpcc_state $file "none" client
+
+       $LCTL set_param llite.$fsuuid.pcc_mode="0004" ||
+               error "Set PCC mode failed"
+       $RUNAS cat $file || error "cat $file failed"
+       $LFS pcc state $file
+       check_lpcc_state $file "readonly" client
+       $RUNAS $LFS pcc detach $file || error "Detach $file failed"
+
+       $RUNAS stat $file || error "stat $file failed"
+       $LFS pcc attach -r $file || error "failed to attach $file"
+       check_lpcc_state $file "readonly" client
+       $RUNAS $LFS pcc detach $file || error "failed to detach $file"
+
+       $LCTL set_param llite.$fsuuid.pcc_mode="0040" ||
+               error "Set PCC mode failed"
+       chmod 660 $file || error "chmod $file failed"
+       $RUNAS cat $file || error "cat $file failed"
+       $LFS pcc state $file
+       check_lpcc_state $file "readonly" client
+       $RUNAS $LFS pcc detach $file || error "failed to detach $file"
+
+       $RUNAS $LFS pcc attach -r $file || error "attach $file failed"
+       stat $file || error "stat $file failed"
+       $LFS pcc state $file
+       check_lpcc_state $file "readonly" client
+       $RUNAS $LFS pcc detach $file || error "Detach $file failed"
+}
+run_test 46 "Verify PCC mode setting works correctly"
+
 test_96() {
        local loopfile="$TMP/$tfile"
        local mntpt="/mnt/pcc.$tdir"