Message ID | 52a41497534bdaa301adc57d61ea3632ab65f2c6.1603884513.git.anand.jain@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | readmirror feature (read_policy sysfs and in-memory only approach) | expand |
On Wed, Oct 28, 2020 at 09:14:47PM +0800, Anand Jain wrote: > +static ssize_t btrfs_read_policy_store(struct kobject *kobj, > + struct kobj_attribute *a, > + const char *buf, size_t len) > +{ > + int i; > + struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); > + > + for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { > + if (btrfs_strmatch(buf, btrfs_read_policy_name[i])) { Does sysfs guarantee that the buf is nul terminated string or that it contains a null at all? Because if not, the skip_space step of strmatch could run out of the buffer.
On 30/10/20 12:45 am, David Sterba wrote: > On Wed, Oct 28, 2020 at 09:14:47PM +0800, Anand Jain wrote: >> +static ssize_t btrfs_read_policy_store(struct kobject *kobj, >> + struct kobj_attribute *a, >> + const char *buf, size_t len) >> +{ >> + int i; >> + struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); >> + >> + for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { >> + if (btrfs_strmatch(buf, btrfs_read_policy_name[i])) { > > Does sysfs guarantee that the buf is nul terminated string or that it > contains a null at all? Because if not, the skip_space step of strmatch > could run out of the buffer. > It does [ 173.555507] ? btrfs_read_policy_store+0x3e/0x12d [btrfs] [ 173.555541] ? kobj_attr_store+0x16/0x30 [ 173.555562] ? sysfs_kf_write+0x54/0x80 [ 173.555582] ? kernfs_fop_write+0xfa/0x290 [ 173.555611] ? vfs_write+0xee/0x2f0 [ 173.555641] ? ksys_write+0x80/0x170 [ 173.555671] ? __x64_sys_write+0x1e/0x30 [ 173.555692] ? do_syscall_64+0x4b/0x80 [ 173.555708] ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { :: buf[len] = '\0'; /* guarantee string termination */ Thanks, Anand
On Fri, Oct 30, 2020 at 03:30:10AM +0800, Anand Jain wrote: > > > On 30/10/20 12:45 am, David Sterba wrote: > > On Wed, Oct 28, 2020 at 09:14:47PM +0800, Anand Jain wrote: > >> +static ssize_t btrfs_read_policy_store(struct kobject *kobj, > >> + struct kobj_attribute *a, > >> + const char *buf, size_t len) > >> +{ > >> + int i; > >> + struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); > >> + > >> + for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { > >> + if (btrfs_strmatch(buf, btrfs_read_policy_name[i])) { > > > > Does sysfs guarantee that the buf is nul terminated string or that it > > contains a null at all? Because if not, the skip_space step of strmatch > > could run out of the buffer. > > > > It does > > [ 173.555507] ? btrfs_read_policy_store+0x3e/0x12d [btrfs] > [ 173.555541] ? kobj_attr_store+0x16/0x30 > [ 173.555562] ? sysfs_kf_write+0x54/0x80 > [ 173.555582] ? kernfs_fop_write+0xfa/0x290 > [ 173.555611] ? vfs_write+0xee/0x2f0 > [ 173.555641] ? ksys_write+0x80/0x170 > [ 173.555671] ? __x64_sys_write+0x1e/0x30 > [ 173.555692] ? do_syscall_64+0x4b/0x80 > [ 173.555708] ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 > > > static ssize_t kernfs_fop_write(struct file *file, const char __user > *user_buf, > size_t count, loff_t *ppos) > { > :: > buf[len] = '\0'; /* guarantee string termination */ Ok thanks.
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 5955379d3d9e..4dbf90ff088a 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -906,6 +906,54 @@ static bool btrfs_strmatch(const char *given, const char *golden) return false; } +static const char * const btrfs_read_policy_name[] = { "pid" }; + +static ssize_t btrfs_read_policy_show(struct kobject *kobj, + struct kobj_attribute *a, char *buf) +{ + int i; + ssize_t ret = 0; + struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); + + for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { + if (fs_devices->read_policy == i) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s[%s]", + (ret == 0 ? "" : " "), + btrfs_read_policy_name[i]); + else + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", + (ret == 0 ? "" : " "), + btrfs_read_policy_name[i]); + } + + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); + + return ret; +} + +static ssize_t btrfs_read_policy_store(struct kobject *kobj, + struct kobj_attribute *a, + const char *buf, size_t len) +{ + int i; + struct btrfs_fs_devices *fs_devices = to_fs_devs(kobj); + + for (i = 0; i < BTRFS_NR_READ_POLICY; i++) { + if (btrfs_strmatch(buf, btrfs_read_policy_name[i])) { + if (i != fs_devices->read_policy) { + fs_devices->read_policy = i; + btrfs_info(fs_devices->fs_info, + "read policy set to '%s'", + btrfs_read_policy_name[i]); + } + return len; + } + } + + return -EINVAL; +} +BTRFS_ATTR_RW(, read_policy, btrfs_read_policy_show, btrfs_read_policy_store); + static const struct attribute *btrfs_attrs[] = { BTRFS_ATTR_PTR(, label), BTRFS_ATTR_PTR(, nodesize), @@ -916,6 +964,7 @@ static const struct attribute *btrfs_attrs[] = { BTRFS_ATTR_PTR(, checksum), BTRFS_ATTR_PTR(, exclusive_operation), BTRFS_ATTR_PTR(, generation), + BTRFS_ATTR_PTR(, read_policy), NULL, };