From: Patrick Farrell Date: Fri, 21 Jun 2019 16:44:14 +0000 (-0400) Subject: LU-12455 osd: Correct readcache_max_filesize proc X-Git-Tag: 2.12.58~42 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=7aee262d513d607c0051f000a0c13e864408abfc;p=fs%2Flustre-release.git LU-12455 osd: Correct readcache_max_filesize proc Readcache max file size is displayed as unsigned, but parsed as signed. This causes confusion when users try to set it back to the default, which is 2^64-1 (or -1), and they can't use 2^64-1. Easy enough to add an unsigned parser and use it instead. Signed-off-by: Patrick Farrell Change-Id: I15f5677c61f4f12a8448a665c5d52a8c94d062f3 Reviewed-on: https://review.whamcloud.com/35266 Reviewed-by: Andreas Dilger Reviewed-by: Ann Koehler Tested-by: jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index f878c00..98a2b1a 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -618,6 +618,10 @@ extern int lprocfs_str_with_units_to_s64(const char __user *buffer, unsigned long count, __s64 *val, char defunit); +extern int lprocfs_str_with_units_to_u64(const char __user *buffer, + unsigned long count, __u64 *val, + char defunit); + char *lprocfs_strnstr(const char *s1, const char *s2, size_t len); char *lprocfs_find_named_value(const char *buffer, const char *name, size_t *count); diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 2035fb7..12ade8a 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -2024,6 +2024,29 @@ static int str_to_s64_internal(const char __user *buffer, unsigned long count, return 0; } +/* identical to s64 version, but does not handle overflow */ +static int str_to_u64_internal(const char __user *buffer, unsigned long count, + __u64 *val, __u64 def_mult, bool allow_units) +{ + char kernbuf[22]; + unsigned int offset = 0; + int rc = 0; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + + kernbuf[count] = '\0'; + + rc = str_to_u64_parse(kernbuf + offset, count - offset, + val, def_mult, allow_units); + if (rc) + return rc; + + return 0; +} /** * Convert a user string into a signed 64 bit number. This function produces * an error when the value parsed from the string times multiplier underflows or @@ -2057,6 +2080,23 @@ int lprocfs_str_with_units_to_s64(const char __user *buffer, } EXPORT_SYMBOL(lprocfs_str_with_units_to_s64); +/* identical to s64 version above, but does not handle overflow */ +int lprocfs_str_with_units_to_u64(const char __user *buffer, + unsigned long count, __u64 *val, char defunit) +{ + __u64 mult = 1; + int rc; + + if (defunit != '1') { + rc = get_mult(defunit, &mult); + if (rc) + return rc; + } + + return str_to_u64_internal(buffer, count, val, mult, true); +} +EXPORT_SYMBOL(lprocfs_str_with_units_to_u64); + char *lprocfs_strnstr(const char *s1, const char *s2, size_t len) { size_t l2; diff --git a/lustre/osd-ldiskfs/osd_lproc.c b/lustre/osd-ldiskfs/osd_lproc.c index 02cf972..cba3a82 100644 --- a/lustre/osd-ldiskfs/osd_lproc.c +++ b/lustre/osd-ldiskfs/osd_lproc.c @@ -561,18 +561,16 @@ ldiskfs_osd_readcache_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct dt_device *dt = m->private; struct osd_device *osd = osd_dt_dev(dt); - s64 val; + u64 val; int rc; LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1'); + rc = lprocfs_str_with_units_to_u64(buffer, count, &val, '1'); if (rc) return rc; - if (val < 0) - return -ERANGE; osd->od_readcache_max_filesize = val > OSD_MAX_CACHE_SIZE ? OSD_MAX_CACHE_SIZE : val; diff --git a/lustre/osd-zfs/osd_lproc.c b/lustre/osd-zfs/osd_lproc.c index e84ed46..a1becc1 100644 --- a/lustre/osd-zfs/osd_lproc.c +++ b/lustre/osd-zfs/osd_lproc.c @@ -387,18 +387,16 @@ zfs_osd_readcache_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct dt_device *dt = m->private; struct osd_device *osd = osd_dt_dev(dt); - s64 val; + u64 val; int rc; LASSERT(osd != NULL); if (unlikely(osd->od_os == NULL)) return -EINPROGRESS; - rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1'); + rc = lprocfs_str_with_units_to_u64(buffer, count, &val, '1'); if (rc) return rc; - if (val < 0) - return -ERANGE; osd->od_readcache_max_filesize = val > OSD_MAX_CACHE_SIZE ? OSD_MAX_CACHE_SIZE : val;