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.
Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I1e006e4f723c1c177ae84c64ad32c6049a57110f
Reviewed-on: https://review.whamcloud.com/44804
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Yang Sheng <ys@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
if (!S_ISREG(inode2->i_mode))
GOTO(out_iput, rc = -EINVAL);
- if (!inode_owner_or_capable(inode2))
+ if (!pcc_inode_permission(inode2))
GOTO(out_iput, rc = -EPERM);
rc = pcc_ioctl_detach(inode2, &detach->pccd_flags);
if (!S_ISREG(inode->i_mode))
RETURN(-EINVAL);
- if (!inode_owner_or_capable(inode))
+ if (!pcc_inode_permission(inode))
RETURN(-EPERM);
if (IS_ENCRYPTED(inode))
if (!S_ISREG(inode->i_mode))
GOTO(out_detach_free, rc = -EINVAL);
- if (!inode_owner_or_capable(inode))
+ if (!pcc_inode_permission(inode))
GOTO(out_detach_free, rc = -EPERM);
rc = pcc_ioctl_detach(inode, &detach->pccd_flags);
}
LUSTRE_RW_ATTR(pcc_async_threshold);
+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)
{
&lustre_attr_heat_period_second.attr,
&lustre_attr_inode_cache.attr,
&lustre_attr_pcc_async_threshold.attr,
+ &lustre_attr_pcc_mode.attr,
&lustre_attr_opencache_threshold_count.attr,
&lustre_attr_opencache_threshold_ms.attr,
&lustre_attr_opencache_max_ms.attr,
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;
}
}
}
+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(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;
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)
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);
}
__u64 pccs_generation;
/* Size threshold for asynchrous PCC-RO attach in background. */
__u64 pccs_async_threshold;
+ umode_t pccs_mode;
};
struct pcc_inode {
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,
}
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
+
+ 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"
}
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}')
+
+ 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"