From 72d9be33f333a084747ac59e73e700dc5bdbc358 Mon Sep 17 00:00:00 2001 From: Qian Yingjin Date: Wed, 1 Sep 2021 21:45:47 +0800 Subject: [PATCH] LU-10499 pcc: add pcc_mode parameter for permission check 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 Change-Id: I1e006e4f723c1c177ae84c64ad32c6049a57110f Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54422 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/llite/dir.c | 2 +- lustre/llite/file.c | 4 +- lustre/llite/lproc_llite.c | 33 ++++++++++++++++ lustre/llite/pcc.c | 16 +++++++- lustre/llite/pcc.h | 2 + lustre/tests/sanity-pcc.sh | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 4 deletions(-) diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 9492ffd..342132d 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -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); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 617955e..a79b561 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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); diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c index 373ad0c..586a9c8 100644 --- a/lustre/llite/lproc_llite.c +++ b/lustre/llite/lproc_llite.c @@ -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, }; diff --git a/lustre/llite/pcc.c b/lustre/llite/pcc.c index 10c221f..1f112a7 100644 --- a/lustre/llite/pcc.c +++ b/lustre/llite/pcc.c @@ -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); } diff --git a/lustre/llite/pcc.h b/lustre/llite/pcc.h index d0247ac..fb3045e 100644 --- a/lustre/llite/pcc.h +++ b/lustre/llite/pcc.h @@ -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, diff --git a/lustre/tests/sanity-pcc.sh b/lustre/tests/sanity-pcc.sh index 32ad858..f2c53c3 100755 --- a/lustre/tests/sanity-pcc.sh +++ b/lustre/tests/sanity-pcc.sh @@ -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" -- 1.8.3.1