From 1cd2189806c82c31256c5ef9756d1dbf97784844 Mon Sep 17 00:00:00 2001 From: Giuseppe Di Natale Date: Thu, 1 Oct 2015 15:51:19 -0700 Subject: [PATCH] LU-7334 lprocfs: Refactored string to value helpers Refactored the string parsing helpers to correct inconsistent behavior and added handling for s64 overflow/underflow. Removed the old helper functions and refactored functions that called them. Signed-off-by: Giuseppe Di Natale Change-Id: I84f3b5d46d4e20bd09fe223589e1be96dc8f7468 Reviewed-on: http://review.whamcloud.com/16930 Reviewed-by: Christopher J. Morrone Tested-by: Jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/fid/lproc_fid.c | 31 ++- lustre/include/lprocfs_status.h | 15 +- lustre/include/lustre_lfsck.h | 2 +- lustre/ldlm/ldlm_resource.c | 7 +- lustre/lfsck/lfsck_lib.c | 2 +- lustre/llite/lproc_llite.c | 218 +++++++++--------- lustre/lod/lproc_lod.c | 110 +++++---- lustre/lov/lproc_lov.c | 115 ++++++---- lustre/mdc/lproc_mdc.c | 32 +-- lustre/mdd/mdd_lproc.c | 34 +-- lustre/mdt/mdt_coordinator.c | 6 +- lustre/mdt/mdt_lproc.c | 84 ++++--- lustre/obdclass/linux/linux-sysctl.c | 14 +- lustre/obdclass/lprocfs_jobstats.c | 7 +- lustre/obdclass/lprocfs_status.c | 392 +++++++++++++++++++++++--------- lustre/obdclass/lprocfs_status_server.c | 19 +- lustre/ofd/lproc_ofd.c | 116 +++++----- lustre/osc/lproc_osc.c | 172 ++++++++------ lustre/osd-ldiskfs/osd_lproc.c | 92 ++++---- lustre/osd-zfs/osd_lproc.c | 9 +- lustre/osp/lproc_osp.c | 85 +++---- lustre/ptlrpc/gss/lproc_gss.c | 18 +- lustre/ptlrpc/lproc_ptlrpc.c | 76 ++++--- lustre/quota/qsd_lib.c | 7 +- 24 files changed, 994 insertions(+), 669 deletions(-) diff --git a/lustre/fid/lproc_fid.c b/lustre/fid/lproc_fid.c index 00b2c7b..03a2098 100644 --- a/lustre/fid/lproc_fid.c +++ b/lustre/fid/lproc_fid.c @@ -166,19 +166,27 @@ lprocfs_server_fid_width_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct lu_server_seq *seq = ((struct seq_file *)file->private_data)->private; - int rc, val; + int rc; + __s64 val; ENTRY; LASSERT(seq != NULL); mutex_lock(&seq->lss_mutex); - rc = lprocfs_write_helper(buffer, count, &val); - if (rc != 0) { - CERROR("%s: invalid width.\n", seq->lss_name); + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) { + CERROR("%s: invalid FID sequence width: rc = %d\n", + seq->lss_name, rc); GOTO(out_unlock, count = rc); } + if (val < 0) { + CERROR("%s: invalid FID sequence width: rc = %d\n", + seq->lss_name, -ERANGE); + GOTO(out_unlock, count = -ERANGE); + } + seq->lss_width = val; CDEBUG(D_INFO, "%s: Width: "LPU64"\n", @@ -545,18 +553,18 @@ lprocfs_client_fid_width_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private; - __u64 max; - int rc, val; + __u64 max; + int rc; + __s64 val; ENTRY; LASSERT(seq != NULL); mutex_lock(&seq->lcs_mutex); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) { - mutex_unlock(&seq->lcs_mutex); - RETURN(rc); + GOTO(out_unlock, count = rc); } if (seq->lcs_type == LUSTRE_SEQ_DATA) @@ -569,9 +577,12 @@ lprocfs_client_fid_width_seq_write(struct file *file, const char __user *buffer, CDEBUG(D_INFO, "%s: Sequence size: "LPU64"\n", seq->lcs_name, seq->lcs_width); + } else { + GOTO(out_unlock, count = -ERANGE); } - mutex_unlock(&seq->lcs_mutex); +out_unlock: + mutex_unlock(&seq->lcs_mutex); RETURN(count); } diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 78e10f0..f103aae 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -707,19 +707,14 @@ extern int lprocfs_kbytesavail_seq_show(struct seq_file *m, void *data); extern int lprocfs_filestotal_seq_show(struct seq_file *m, void *data); extern int lprocfs_filesfree_seq_show(struct seq_file *m, void *data); -extern int lprocfs_write_helper(const char __user *buffer, unsigned long count, - int *val); -extern int lprocfs_write_frac_helper(const char __user *buffer, - unsigned long count, - int *val, int mult); extern int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult); extern int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult); -extern int lprocfs_write_u64_helper(const char __user *buffer, - unsigned long count, __u64 *val); -extern int lprocfs_write_frac_u64_helper(const char __user *buffer, - unsigned long count, - __u64 *val, int mult); +extern int lprocfs_str_to_s64(const char __user *buffer, unsigned long count, + __s64 *val); +extern int lprocfs_str_with_units_to_s64(const char __user *buffer, + unsigned long count, __s64 *val, + char defunit); char *lprocfs_find_named_value(const char *buffer, const char *name, size_t *count); void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value); diff --git a/lustre/include/lustre_lfsck.h b/lustre/include/lustre_lfsck.h index ee7d783..55ec284 100644 --- a/lustre/include/lustre_lfsck.h +++ b/lustre/include/lustre_lfsck.h @@ -78,7 +78,7 @@ int lfsck_query(const struct lu_env *env, struct dt_device *key, struct lfsck_query *que); int lfsck_get_speed(struct seq_file *m, struct dt_device *key); -int lfsck_set_speed(struct dt_device *key, int val); +int lfsck_set_speed(struct dt_device *key, __u32 val); int lfsck_get_windows(struct seq_file *m, struct dt_device *key); int lfsck_set_windows(struct dt_device *key, int val); diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index 1fe7c93..635d944 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -96,23 +96,24 @@ static ssize_t seq_watermark_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { + __s64 value; __u64 watermark; __u64 *data = ((struct seq_file *)file->private_data)->private; bool wm_low = (data == &ldlm_reclaim_threshold_mb) ? true : false; int rc; - rc = lprocfs_write_frac_u64_helper(buffer, count, &watermark, 1 << 20); + rc = lprocfs_str_with_units_to_s64(buffer, count, &value, 'M'); if (rc) { CERROR("Failed to set %s, rc = %d.\n", wm_low ? "lock_reclaim_threshold_mb" : "lock_limit_mb", rc); return rc; - } else if (watermark != 0 && watermark < (1 << 20)) { + } else if (value != 0 && value < (1 << 20)) { CERROR("%s should be greater than 1MB.\n", wm_low ? "lock_reclaim_threshold_mb" : "lock_limit_mb"); return -EINVAL; } - watermark >>= 20; + watermark = value >> 20; if (wm_low) { if (ldlm_lock_limit_mb != 0 && watermark > ldlm_lock_limit_mb) { diff --git a/lustre/lfsck/lfsck_lib.c b/lustre/lfsck/lfsck_lib.c index d485258..3ac83ac 100644 --- a/lustre/lfsck/lfsck_lib.c +++ b/lustre/lfsck/lfsck_lib.c @@ -2653,7 +2653,7 @@ int lfsck_get_speed(struct seq_file *m, struct dt_device *key) } EXPORT_SYMBOL(lfsck_get_speed); -int lfsck_set_speed(struct dt_device *key, int val) +int lfsck_set_speed(struct dt_device *key, __u32 val) { struct lu_env env; struct lfsck_instance *lfsck; diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c index 1767a00..dba3bac 100644 --- a/lustre/llite/lproc_llite.c +++ b/lustre/llite/lproc_llite.c @@ -220,9 +220,10 @@ static ssize_t ll_xattr_cache_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -272,26 +273,21 @@ ll_max_readahead_mb_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct super_block *sb = m->private; struct ll_sb_info *sbi = ll_s2sbi(sb); - __u64 val; - long pages_number; - int pages_shift; + __s64 pages_number; int rc; - pages_shift = 20 - PAGE_CACHE_SHIFT; - rc = lprocfs_write_frac_u64_helper(buffer, count, &val, - 1 << pages_shift); + rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M'); if (rc) return rc; - if (val > LONG_MAX) - return -ERANGE; - pages_number = (long)val; + pages_number >>= PAGE_CACHE_SHIFT; if (pages_number < 0 || pages_number > totalram_pages / 2) { /* 1/2 of RAM */ CERROR("%s: can't set max_readahead_mb=%lu > %luMB\n", - ll_get_fsname(sb, NULL, 0), pages_number >> pages_shift, - totalram_pages >> (pages_shift + 1)); + ll_get_fsname(sb, NULL, 0), + (unsigned long)pages_number >> (20 - PAGE_CACHE_SHIFT), + totalram_pages >> (20 - PAGE_CACHE_SHIFT + 1)); return -ERANGE; } @@ -325,19 +321,20 @@ ll_max_readahead_per_file_mb_seq_write(struct file *file, struct seq_file *m = file->private_data; struct super_block *sb = m->private; struct ll_sb_info *sbi = ll_s2sbi(sb); - int pages_shift, rc, pages_number; + int rc; + __s64 pages_number; - pages_shift = 20 - PAGE_CACHE_SHIFT; - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, - 1 << pages_shift); + rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M'); if (rc) return rc; + pages_number >>= PAGE_CACHE_SHIFT; + if (pages_number < 0 || pages_number > sbi->ll_ra_info.ra_max_pages) { - CERROR("%s: can't set max_readahead_per_file_mb=%u > " + CERROR("%s: can't set max_readahead_per_file_mb=%lu > " "max_read_ahead_mb=%lu\n", ll_get_fsname(sb, NULL, 0), - pages_number >> pages_shift, - sbi->ll_ra_info.ra_max_pages >> pages_shift); + (unsigned long)pages_number >> (20 - PAGE_CACHE_SHIFT), + sbi->ll_ra_info.ra_max_pages >> (20 - PAGE_CACHE_SHIFT)); return -ERANGE; } @@ -371,22 +368,24 @@ ll_max_read_ahead_whole_mb_seq_write(struct file *file, struct seq_file *m = file->private_data; struct super_block *sb = m->private; struct ll_sb_info *sbi = ll_s2sbi(sb); - int pages_shift, rc, pages_number; + int rc; + __s64 pages_number; - pages_shift = 20 - PAGE_CACHE_SHIFT; - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, - 1 << pages_shift); + rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M'); if (rc) return rc; + pages_number >>= PAGE_CACHE_SHIFT; + /* Cap this at the current max readahead window size, the readahead * algorithm does this anyway so it's pointless to set it larger. */ if (pages_number < 0 || pages_number > sbi->ll_ra_info.ra_max_pages_per_file) { - CERROR("%s: can't set max_read_ahead_whole_mb=%u > " + int pages_shift = 20 - PAGE_CACHE_SHIFT; + CERROR("%s: can't set max_read_ahead_whole_mb=%lu > " "max_read_ahead_per_file_mb=%lu\n", ll_get_fsname(sb, NULL, 0), - pages_number >> pages_shift, + (unsigned long)pages_number >> pages_shift, sbi->ll_ra_info.ra_max_pages_per_file >> pages_shift); return -ERANGE; } @@ -431,12 +430,10 @@ ll_max_cached_mb_seq_write(struct file *file, const char __user *buffer, struct ll_sb_info *sbi = ll_s2sbi(sb); struct cl_client_cache *cache = sbi->ll_cache; struct lu_env *env; - __u64 val; long diff = 0; long nrpages = 0; - long pages_number; __u16 refcheck; - int mult; + __s64 pages_number; long rc; char kernbuf[128]; ENTRY; @@ -448,16 +445,13 @@ ll_max_cached_mb_seq_write(struct file *file, const char __user *buffer, RETURN(-EFAULT); kernbuf[count] = 0; - mult = 1 << (20 - PAGE_CACHE_SHIFT); buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) - kernbuf; - rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult); + rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M'); if (rc) RETURN(rc); - if (val > LONG_MAX) - return -ERANGE; - pages_number = (long)val; + pages_number >>= PAGE_CACHE_SHIFT; if (pages_number < 0 || pages_number > totalram_pages) { CERROR("%s: can't set max cache more than %lu MB\n", @@ -550,26 +544,27 @@ static ssize_t ll_checksum_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; + int rc; + __s64 val; - if (!sbi->ll_dt_exp) - /* Not set up yet */ - return -EAGAIN; + if (!sbi->ll_dt_exp) + /* Not set up yet */ + return -EAGAIN; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; - if (val) - sbi->ll_flags |= LL_SBI_CHECKSUM; - else - sbi->ll_flags &= ~LL_SBI_CHECKSUM; - - rc = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), - KEY_CHECKSUM, sizeof(val), &val, NULL); - if (rc) - CWARN("Failed to set OSC checksum flags: %d\n", rc); + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val) + sbi->ll_flags |= LL_SBI_CHECKSUM; + else + sbi->ll_flags &= ~LL_SBI_CHECKSUM; - return count; + rc = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM), + KEY_CHECKSUM, sizeof(val), &val, NULL); + if (rc) + CWARN("Failed to set OSC checksum flags: %d\n", rc); + + return count; } LPROC_SEQ_FOPS(ll_checksum); @@ -592,18 +587,22 @@ static int ll_wr_track_id(const char __user *buffer, unsigned long count, void *data, enum stats_track_type type) { struct super_block *sb = data; - int rc, pid; + int rc; + __s64 pid; - rc = lprocfs_write_helper(buffer, count, &pid); - if (rc) - return rc; - ll_s2sbi(sb)->ll_stats_track_id = pid; - if (pid == 0) - ll_s2sbi(sb)->ll_stats_track_type = STATS_TRACK_ALL; - else - ll_s2sbi(sb)->ll_stats_track_type = type; - lprocfs_clear_stats(ll_s2sbi(sb)->ll_stats); - return count; + rc = lprocfs_str_to_s64(buffer, count, &pid); + if (rc) + return rc; + if (pid > INT_MAX || pid < 0) + return -ERANGE; + + ll_s2sbi(sb)->ll_stats_track_id = pid; + if (pid == 0) + ll_s2sbi(sb)->ll_stats_track_type = STATS_TRACK_ALL; + else + ll_s2sbi(sb)->ll_stats_track_type = type; + lprocfs_clear_stats(ll_s2sbi(sb)->ll_stats); + return count; } static int ll_track_pid_seq_show(struct seq_file *m, void *v) @@ -663,19 +662,20 @@ static ssize_t ll_statahead_max_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - if (val >= 0 && val <= LL_SA_RPC_MAX) - sbi->ll_sa_max = val; - else - CERROR("Bad statahead_max value %d. Valid values are in the " - "range [0, %d]\n", val, LL_SA_RPC_MAX); + if (val >= 0 && val <= LL_SA_RPC_MAX) + sbi->ll_sa_max = val; + else + CERROR("Bad statahead_max value "LPD64". Valid values are in " + "the range [0, %d]\n", val, LL_SA_RPC_MAX); - return count; + return count; } LPROC_SEQ_FOPS(ll_statahead_max); @@ -695,18 +695,19 @@ static ssize_t ll_statahead_agl_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - if (val) - sbi->ll_flags |= LL_SBI_AGL_ENABLED; - else - sbi->ll_flags &= ~LL_SBI_AGL_ENABLED; + if (val) + sbi->ll_flags |= LL_SBI_AGL_ENABLED; + else + sbi->ll_flags &= ~LL_SBI_AGL_ENABLED; - return count; + return count; } LPROC_SEQ_FOPS(ll_statahead_agl); @@ -741,18 +742,19 @@ static ssize_t ll_lazystatfs_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)m->private); - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - if (val) - sbi->ll_flags |= LL_SBI_LAZYSTATFS; - else - sbi->ll_flags &= ~LL_SBI_LAZYSTATFS; + if (val) + sbi->ll_flags |= LL_SBI_LAZYSTATFS; + else + sbi->ll_flags &= ~LL_SBI_LAZYSTATFS; - return count; + return count; } LPROC_SEQ_FOPS(ll_lazystatfs); @@ -818,18 +820,20 @@ static ssize_t ll_default_easize_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *unused) { - struct seq_file *seq = file->private_data; - struct super_block *sb = (struct super_block *)seq->private; - struct ll_sb_info *sbi = ll_s2sbi(sb); - int val; - int rc; + struct seq_file *seq = file->private_data; + struct super_block *sb = (struct super_block *)seq->private; + struct ll_sb_info *sbi = ll_s2sbi(sb); + __s64 val; + int rc; if (count == 0) return 0; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc < 0) + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; rc = ll_set_default_mdsize(sbi, val); if (rc) @@ -888,7 +892,8 @@ static ssize_t ll_unstable_stats_seq_write(struct file *file, struct seq_file *seq = file->private_data; struct ll_sb_info *sbi = ll_s2sbi((struct super_block *)seq->private); char kernbuf[128]; - int val, rc; + int rc; + __s64 val; if (count == 0) return 0; @@ -901,7 +906,7 @@ static ssize_t ll_unstable_stats_seq_write(struct file *file, buffer += lprocfs_find_named_value(kernbuf, "unstable_check:", &count) - kernbuf; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; @@ -1374,12 +1379,13 @@ static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file, struct ll_sb_info *sbi = seq->private; struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; int i; - int value = 1, rc = 0; + __s64 value = 1; + int rc = 0; if (len == 0) return -EINVAL; - rc = lprocfs_write_helper(buf, len, &value); + rc = lprocfs_str_to_s64(buf, len, &value); if (rc < 0 && len < 16) { char kernbuf[16]; @@ -1446,12 +1452,13 @@ static ssize_t ll_rw_extents_stats_seq_write(struct file *file, struct ll_sb_info *sbi = seq->private; struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info; int i; - int value = 1, rc = 0; + __s64 value = 1; + int rc = 0; if (len == 0) return -EINVAL; - rc = lprocfs_write_helper(buf, len, &value); + rc = lprocfs_str_to_s64(buf, len, &value); if (rc < 0 && len < 16) { char kernbuf[16]; @@ -1649,12 +1656,13 @@ static ssize_t ll_rw_offset_stats_seq_write(struct file *file, struct ll_sb_info *sbi = seq->private; struct ll_rw_process_info *process_info = sbi->ll_rw_process_info; struct ll_rw_process_info *offset_info = sbi->ll_rw_offset_info; - int value = 1, rc = 0; + __s64 value = 1; + int rc = 0; if (len == 0) return -EINVAL; - rc = lprocfs_write_helper(buf, len, &value); + rc = lprocfs_str_to_s64(buf, len, &value); if (rc < 0 && len < 16) { char kernbuf[16]; diff --git a/lustre/lod/lproc_lod.c b/lustre/lod/lproc_lod.c index 06e2314..389ac3f 100644 --- a/lustre/lod/lproc_lod.c +++ b/lustre/lod/lproc_lod.c @@ -87,20 +87,23 @@ static ssize_t lod_stripesize_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; struct lod_device *lod; - __u64 val; + __s64 val; int rc; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_u64_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0) + return -ERANGE; lod_fix_desc_stripe_size(&val); lod->lod_desc.ld_default_stripe_size = val; + return count; } LPROC_SEQ_FOPS(lod_stripesize); @@ -144,19 +147,22 @@ static ssize_t lod_stripeoffset_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; struct lod_device *lod; - __u64 val; + __s64 val; int rc; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_u64_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0) + return -ERANGE; lod->lod_desc.ld_default_stripe_offset = val; + return count; } LPROC_SEQ_FOPS(lod_stripeoffset); @@ -197,19 +203,25 @@ static ssize_t lod_stripetype_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; struct lod_device *lod; - int val, rc; + int rc; + __u32 pattern; + __s64 val; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0) + return -ERANGE; + + pattern = val; + lod_fix_desc_pattern(&pattern); + lod->lod_desc.ld_pattern = pattern; - lod_fix_desc_pattern(&val); - lod->lod_desc.ld_pattern = val; return count; } LPROC_SEQ_FOPS(lod_stripetype); @@ -251,19 +263,25 @@ static ssize_t lod_stripecount_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; struct lod_device *lod; - int val, rc; + int rc; + __s64 val; + __u32 stripe_count; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0) + return -ERANGE; + + stripe_count = val; + lod_fix_desc_stripe_count(&stripe_count); + lod->lod_desc.ld_default_stripe_count = stripe_count; - lod_fix_desc_stripe_count(&val); - lod->lod_desc.ld_default_stripe_count = val; return count; } LPROC_SEQ_FOPS(lod_stripecount); @@ -376,23 +394,25 @@ static ssize_t lod_qos_priofree_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; struct lod_device *lod; - int val, rc; + int rc; + __s64 val; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val > 100) + if (val < 0 || val > 100) return -EINVAL; lod->lod_qos.lq_prio_free = (val << 8) / 100; lod->lod_qos.lq_dirty = 1; lod->lod_qos.lq_reset = 1; + return count; } LPROC_SEQ_FOPS(lod_qos_priofree); @@ -439,15 +459,16 @@ static ssize_t lod_qos_thresholdrr_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; struct lod_device *lod; - int val, rc; + int rc; + __s64 val; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '%'); if (rc) return rc; @@ -456,6 +477,7 @@ lod_qos_thresholdrr_seq_write(struct file *file, const char __user *buffer, lod->lod_qos.lq_threshold_rr = (val << 8) / 100; lod->lod_qos.lq_dirty = 1; + return count; } LPROC_SEQ_FOPS(lod_qos_thresholdrr); @@ -496,20 +518,21 @@ static ssize_t lod_qos_maxage_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *dev = m->private; - struct lustre_cfg_bufs bufs; - struct lod_device *lod; - struct lu_device *next; - struct lustre_cfg *lcfg; - char str[32]; - unsigned int i; - int val, rc; + struct seq_file *m = file->private_data; + struct obd_device *dev = m->private; + struct lustre_cfg_bufs bufs; + struct lod_device *lod; + struct lu_device *next; + struct lustre_cfg *lcfg; + char str[32]; + unsigned int i; + int rc; + __s64 val; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -521,7 +544,7 @@ lod_qos_maxage_seq_write(struct file *file, const char __user *buffer, * propogate the value down to OSPs */ lustre_cfg_bufs_reset(&bufs, NULL); - sprintf(str, "%smaxage=%d", PARAM_OSP, val); + snprintf(str, 32, "%smaxage=%u", PARAM_OSP, (__u32)val); lustre_cfg_bufs_set_string(&bufs, 1, str); lcfg = lustre_cfg_new(LCFG_PARAM, &bufs); if (lcfg == NULL) @@ -698,23 +721,20 @@ static ssize_t lod_lmv_failout_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *dev = m->private; - struct lod_device *lod; - int val = 0; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *dev = m->private; + struct lod_device *lod; + __s64 val = 0; + int rc; LASSERT(dev != NULL); lod = lu2lod_dev(dev->obd_lu_dev); - rc = lprocfs_write_helper(buffer, count, &val); - if (rc != 0) + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) return rc; - if (val != 0) - lod->lod_lmv_failout = 1; - else - lod->lod_lmv_failout = 0; + lod->lod_lmv_failout = !!val; return count; } diff --git a/lustre/lov/lproc_lov.c b/lustre/lov/lproc_lov.c index 4732a35..ac3bb1a 100644 --- a/lustre/lov/lproc_lov.c +++ b/lustre/lov/lproc_lov.c @@ -60,19 +60,22 @@ static ssize_t lov_stripesize_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - struct lov_desc *desc; - __u64 val; - int rc; - - LASSERT(dev != NULL); - desc = &dev->u.lov.desc; - rc = lprocfs_write_u64_helper(buffer, count, &val); - if (rc) - return rc; - - lov_fix_desc_stripe_size(&val); - desc->ld_default_stripe_size = val; - return count; + struct lov_desc *desc; + __s64 val; + int rc; + + LASSERT(dev != NULL); + desc = &dev->u.lov.desc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0) + return -ERANGE; + + lov_fix_desc_stripe_size(&val); + desc->ld_default_stripe_size = val; + + return count; } LPROC_SEQ_FOPS(lov_stripesize); @@ -92,18 +95,21 @@ static ssize_t lov_stripeoffset_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - struct lov_desc *desc; - __u64 val; - int rc; - - LASSERT(dev != NULL); - desc = &dev->u.lov.desc; - rc = lprocfs_write_u64_helper(buffer, count, &val); - if (rc) - return rc; - - desc->ld_default_stripe_offset = val; - return count; + struct lov_desc *desc; + __s64 val; + int rc; + + LASSERT(dev != NULL); + desc = &dev->u.lov.desc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0) + return -ERANGE; + + desc->ld_default_stripe_offset = val; + + return count; } LPROC_SEQ_FOPS(lov_stripeoffset); @@ -123,18 +129,23 @@ static ssize_t lov_stripetype_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - struct lov_desc *desc; - int val, rc; - - LASSERT(dev != NULL); - desc = &dev->u.lov.desc; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; - - lov_fix_desc_pattern(&val); - desc->ld_pattern = val; - return count; + struct lov_desc *desc; + int pattern, rc; + __s64 val; + + LASSERT(dev != NULL); + desc = &dev->u.lov.desc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < INT_MIN || val > INT_MAX) + return -ERANGE; + + pattern = val; + lov_fix_desc_pattern(&pattern); + desc->ld_pattern = pattern; + + return count; } LPROC_SEQ_FOPS(lov_stripetype); @@ -155,18 +166,24 @@ static ssize_t lov_stripecount_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - struct lov_desc *desc; - int val, rc; - - LASSERT(dev != NULL); - desc = &dev->u.lov.desc; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; - - lov_fix_desc_stripe_count(&val); - desc->ld_default_stripe_count = val; - return count; + struct lov_desc *desc; + int rc; + __u32 stripe_count; + __s64 val; + + LASSERT(dev != NULL); + desc = &dev->u.lov.desc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0) + return -ERANGE; + + stripe_count = val; + lov_fix_desc_stripe_count(&stripe_count); + desc->ld_default_stripe_count = stripe_count; + + return count; } LPROC_SEQ_FOPS(lov_stripecount); diff --git a/lustre/mdc/lproc_mdc.c b/lustre/mdc/lproc_mdc.c index c8b0cd6..0312492 100644 --- a/lustre/mdc/lproc_mdc.c +++ b/lustre/mdc/lproc_mdc.c @@ -58,10 +58,11 @@ static ssize_t mdc_active_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev; - int val, rc; + int rc; + __s64 val; dev = ((struct seq_file *)file->private_data)->private; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; if (val < 0 || val > 1) @@ -71,7 +72,8 @@ static ssize_t mdc_active_seq_write(struct file *file, if (dev->u.cli.cl_import->imp_deactive == val) rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val); else - CDEBUG(D_CONFIG, "activate %d: ignoring repeat request\n", val); + CDEBUG(D_CONFIG, "activate "LPD64": ignoring repeat request\n", + val); return count; } @@ -94,15 +96,19 @@ static ssize_t mdc_max_rpcs_in_flight_seq_write(struct file *file, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc == 0) - rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val); + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - if (rc != 0) - count = rc; + if (val < 0 || val > UINT_MAX) + return -ERANGE; + + rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val); + if (rc) + return rc; return count; } @@ -127,18 +133,18 @@ static ssize_t mdc_max_mod_rpcs_in_flight_seq_write(struct file *file, { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc != 0) + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) return rc; if (val < 0 || val > USHRT_MAX) return -ERANGE; rc = obd_set_max_mod_rpcs_in_flight(&dev->u.cli, val); - if (rc != 0) + if (rc) count = rc; return count; diff --git a/lustre/mdd/mdd_lproc.c b/lustre/mdd/mdd_lproc.c index 1990ae1..099fc1a 100644 --- a/lustre/mdd/mdd_lproc.c +++ b/lustre/mdd/mdd_lproc.c @@ -244,15 +244,17 @@ mdd_sync_perm_seq_write(struct file *file, const char __user *buffer, { struct seq_file *m = file->private_data; struct mdd_device *mdd = m->private; - int val, rc; + int rc; + __s64 val; - LASSERT(mdd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + LASSERT(mdd != NULL); + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - mdd->mdd_sync_permission = !!val; - return count; + mdd->mdd_sync_permission = !!val; + + return count; } LPROC_SEQ_FOPS(mdd_sync_perm); @@ -270,13 +272,15 @@ mdd_lfsck_speed_limit_seq_write(struct file *file, const char __user *buffer, { struct seq_file *m = file->private_data; struct mdd_device *mdd = m->private; - __u32 val; + __s64 val; int rc; LASSERT(mdd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; rc = lfsck_set_speed(mdd->mdd_bottom, val); return rc != 0 ? rc : count; @@ -297,13 +301,17 @@ mdd_lfsck_async_windows_seq_write(struct file *file, const char __user *buffer, { struct seq_file *m = file->private_data; struct mdd_device *mdd = m->private; - __u32 val; + __s64 val; int rc; LASSERT(mdd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); - if (rc == 0) - rc = lfsck_set_windows(mdd->mdd_bottom, val); + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; + + rc = lfsck_set_windows(mdd->mdd_bottom, val); return rc != 0 ? rc : count; } diff --git a/lustre/mdt/mdt_coordinator.c b/lustre/mdt/mdt_coordinator.c index 346d5ae..970f6b8 100644 --- a/lustre/mdt/mdt_coordinator.c +++ b/lustre/mdt/mdt_coordinator.c @@ -1855,14 +1855,14 @@ mdt_hsm_##VAR##_seq_write(struct file *file, const char __user *buffer, \ struct seq_file *m = file->private_data; \ struct mdt_device *mdt = m->private; \ struct coordinator *cdt = &mdt->mdt_coordinator; \ - int val; \ + __s64 val; \ int rc; \ ENTRY; \ \ - rc = lprocfs_write_helper(buffer, count, &val); \ + rc = lprocfs_str_to_s64(buffer, count, &val); \ if (rc) \ RETURN(rc); \ - if (val > 0) { \ + if (val > 0 && val < INT_MAX) { \ cdt->VAR = val; \ RETURN(count); \ } \ diff --git a/lustre/mdt/mdt_lproc.c b/lustre/mdt/mdt_lproc.c index 612da16..4b288ed 100644 --- a/lustre/mdt/mdt_lproc.c +++ b/lustre/mdt/mdt_lproc.c @@ -228,13 +228,17 @@ mdt_identity_expire_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int rc, val; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; mdt->mdt_identity_cache->uc_entry_expire = val; + return count; } LPROC_SEQ_FOPS(mdt_identity_expire); @@ -256,13 +260,17 @@ mdt_identity_acquire_expire_seq_write(struct file *file, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int rc, val; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; mdt->mdt_identity_cache->uc_acquire_expire = val; + return count; } LPROC_SEQ_FOPS(mdt_identity_acquire_expire); @@ -332,11 +340,14 @@ lprocfs_identity_flush_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int rc, uid; + int rc; + __s64 uid; - rc = lprocfs_write_helper(buffer, count, &uid); + rc = lprocfs_str_to_s64(buffer, count, &uid); if (rc) return rc; + if (uid < INT_MIN || uid > INT_MAX) + return -ERANGE; mdt_flush_identity(mdt->mdt_identity_cache, uid); return count; @@ -492,9 +503,10 @@ mdt_evict_tgt_nids_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int val, rc; + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; mdt->mdt_opts.mo_evict_tgt_nids = !!val; @@ -519,22 +531,24 @@ mdt_sec_level_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE) - return -EINVAL; + if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE) + return -EINVAL; - if (val == LUSTRE_SEC_SPECIFY) { - CWARN("security level %d will be supported in future.\n", - LUSTRE_SEC_SPECIFY); - return -EINVAL; - } + if (val == LUSTRE_SEC_SPECIFY) { + CWARN("security level %d will be supported in future.\n", + LUSTRE_SEC_SPECIFY); + return -EINVAL; + } mdt->mdt_lut.lut_sec_level = val; + return count; } LPROC_SEQ_FOPS(mdt_sec_level); @@ -555,11 +569,15 @@ mdt_cos_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < INT_MIN || val > INT_MAX) + return -ERANGE; + mdt_enable_cos(mdt, val); return count; } @@ -640,14 +658,14 @@ mdt_enable_remote_dir_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - __u32 val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val > 1) + if (val > 1 || val < 0) return -ERANGE; mdt->mdt_enable_remote_dir = val; @@ -673,10 +691,10 @@ mdt_enable_remote_dir_gid_seq_write(struct file *file, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - __u32 val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -730,13 +748,16 @@ mdt_async_commit_count_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev); - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < INT_MIN || val > INT_MAX) + return -ERANGE; + atomic_set(&mdt->mdt_async_commit_count, val); return count; @@ -768,13 +789,16 @@ mdt_sync_count_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct lu_target *tgt = obd->u.obt.obt_lut; - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < INT_MIN || val > INT_MAX) + return -ERANGE; + atomic_set(&tgt->lut_sync_count, val); return count; diff --git a/lustre/obdclass/linux/linux-sysctl.c b/lustre/obdclass/linux/linux-sysctl.c index 4133b78..0c19fa9 100644 --- a/lustre/obdclass/linux/linux-sysctl.c +++ b/lustre/obdclass/linux/linux-sysctl.c @@ -124,7 +124,7 @@ static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - __u64 val; + __s64 val; int rc = 0; if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) { @@ -132,13 +132,19 @@ proc_max_dirty_pages_in_mb(struct ctl_table *table, int write, return 0; } if (write) { - rc = lprocfs_write_frac_u64_helper(buffer, *lenp, &val, - 1 << (20 - PAGE_CACHE_SHIFT)); + rc = lprocfs_str_with_units_to_s64(buffer, *lenp, &val, 'M'); + if (rc) + return rc; + + if (val < 0) + return -ERANGE; + + val >>= PAGE_CACHE_SHIFT; /* Don't allow them to let dirty pages exceed 90% of system * memory and set a hard minimum of 4MB. */ if (val > ((totalram_pages / 10) * 9)) { - CERROR("Refusing to set max dirty pages to "LPU64", " + CERROR("Refusing to set max dirty pages to "LPD64", " "which is more than 90%% of available RAM; " "setting to %lu\n", val, ((totalram_pages / 10) * 9)); diff --git a/lustre/obdclass/lprocfs_jobstats.c b/lustre/obdclass/lprocfs_jobstats.c index af6cc5f..744c0e2 100644 --- a/lustre/obdclass/lprocfs_jobstats.c +++ b/lustre/obdclass/lprocfs_jobstats.c @@ -647,7 +647,8 @@ lprocfs_job_interval_seq_write(struct file *file, const char __user *buffer, { struct obd_device *obd; struct obd_job_stats *stats; - int val, rc; + int rc; + __s64 val; obd = ((struct seq_file *)file->private_data)->private; if (obd == NULL) @@ -655,9 +656,11 @@ lprocfs_job_interval_seq_write(struct file *file, const char __user *buffer, stats = &obd->u.obt.obt_jobstats; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0 || val > UINT_MAX) + return -ERANGE; stats->ojs_cleanup_interval = val; lprocfs_job_cleanup(stats, stats->ojs_cleanup_interval); diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 7cb7a4d..3091bf2 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -321,9 +321,10 @@ ssize_t lprocfs_uint_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { int *data = ((struct seq_file *)file->private_data)->private; - int val = 0, rc; + int rc; + __s64 val = 0; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; @@ -353,14 +354,14 @@ lprocfs_atomic_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { atomic_t *atm = ((struct seq_file *)file->private_data)->private; - int val = 0; + __s64 val = 0; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; - if (val <= 0) + if (val <= 0 || val > INT_MAX) return -ERANGE; atomic_set(atm, val); @@ -1517,56 +1518,6 @@ __s64 lprocfs_read_helper(struct lprocfs_counter *lc, } EXPORT_SYMBOL(lprocfs_read_helper); -int lprocfs_write_helper(const char __user *buffer, unsigned long count, - int *val) -{ - return lprocfs_write_frac_helper(buffer, count, val, 1); -} -EXPORT_SYMBOL(lprocfs_write_helper); - -int lprocfs_write_frac_helper(const char __user *buffer, unsigned long count, - int *val, int mult) -{ - char kernbuf[20], *end, *pbuf; - - if (count > (sizeof(kernbuf) - 1)) - return -EINVAL; - - if (copy_from_user(kernbuf, buffer, count)) - return -EFAULT; - - kernbuf[count] = '\0'; - pbuf = kernbuf; - if (*pbuf == '-') { - mult = -mult; - pbuf++; - } - - *val = (int)simple_strtoul(pbuf, &end, 10) * mult; - if (pbuf == end) - return -EINVAL; - - if (end != NULL && *end == '.') { - int temp_val, pow = 1; - int i; - - pbuf = end + 1; - if (strlen(pbuf) > 5) - pbuf[5] = '\0'; /*only allow 5bits fractional*/ - - temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult; - - if (pbuf < end) { - for (i = 0; i < (end - pbuf); i++) - pow *= 10; - - *val += temp_val / pow; - } - } - return 0; -} -EXPORT_SYMBOL(lprocfs_write_frac_helper); - int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult) { @@ -1646,77 +1597,298 @@ int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult) } EXPORT_SYMBOL(lprocfs_seq_read_frac_helper); -int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, - __u64 *val) +/* Obtains the conversion factor for the unit specified */ +static int get_mult(char unit, __u64 *mult) +{ + __u64 units = 1; + + switch (unit) { + /* peta, tera, giga, mega, and kilo */ + case 'p': + case 'P': + units <<= 10; + case 't': + case 'T': + units <<= 10; + case 'g': + case 'G': + units <<= 10; + case 'm': + case 'M': + units <<= 10; + case 'k': + case 'K': + units <<= 10; + break; + /* some tests expect % to be accepted */ + case '%': + units = 1; + break; + default: + return -EINVAL; + } + + *mult = units; + + return 0; +} + +/* + * Ensures the numeric string is valid. The function provides the final + * multiplier in the case a unit exists at the end of the string. It also + * locates the start of the whole and fractional parts (if any). This + * function modifies the string so kstrtoull can be used to parse both + * the whole and fraction portions. This function also figures out + * the base of the number. + */ +static int preprocess_numeric_str(char *buffer, __u64 *mult, __u64 def_mult, + bool allow_units, char **whole, char **frac, + unsigned int *base) { - return lprocfs_write_frac_u64_helper(buffer, count, val, 1); + bool hit_decimal = false; + bool hit_unit = false; + int rc = 0; + char *start; + *mult = def_mult; + *whole = NULL; + *frac = NULL; + *base = 10; + + /* a hex string if it starts with "0x" */ + if (buffer[0] == '0' && tolower(buffer[1]) == 'x') { + *base = 16; + buffer += 2; + } + + start = buffer; + + while (*buffer) { + /* any chars after our unit indicates a malformed string */ + if (hit_unit) + return -EINVAL; + + /* ensure we only hit one decimal */ + if (*buffer == '.') { + if (hit_decimal) + return -EINVAL; + + /* if past start, there's a whole part */ + if (start != buffer) + *whole = start; + + *buffer = '\0'; + start = buffer + 1; + hit_decimal = true; + } else if (!isdigit(*buffer) && + !(*base == 16 && isxdigit(*buffer))) { + if (allow_units) { + /* if we allow units, attempt to get mult */ + hit_unit = true; + rc = get_mult(*buffer, mult); + if (rc) + return rc; + + /* string stops here, but keep processing */ + *buffer = '\0'; + } else { + /* bad string */ + return -EINVAL; + } + } + + buffer++; + } + + if (hit_decimal) { + /* hit a decimal, make sure there's a fractional part */ + if (!*start) + return -EINVAL; + + *frac = start; + } else { + /* didn't hit a decimal, but may have a whole part */ + if (start != buffer && *start) + *whole = start; + } + + /* malformed string if we didn't get anything */ + if (!*frac && !*whole) + return -EINVAL; + + return 0; } -EXPORT_SYMBOL(lprocfs_write_u64_helper); -int lprocfs_write_frac_u64_helper(const char __user *buffer, - unsigned long count, - __u64 *val, int mult) +/* + * Parses a numeric string which can contain a whole and fraction portion + * into a __u64. Accepts a multiplier to apply to the value parsed. Also + * allows the string to have a unit at the end. The function handles + * wrapping of the final unsigned value. + */ +static int str_to_u64_parse(char *buffer, unsigned long count, + __u64 *val, __u64 def_mult, bool allow_units) { - char kernbuf[22], *end, *pbuf; - __u64 whole, frac = 0, units; - unsigned frac_d = 1; + __u64 whole = 0; + __u64 frac = 0; + unsigned int frac_d = 1; + __u64 wrap_indicator = ULLONG_MAX; + int rc = 0; + __u64 mult; + char *strwhole; + char *strfrac; + unsigned int base = 10; - if (count > (sizeof(kernbuf) - 1)) - return -EINVAL; + rc = preprocess_numeric_str(buffer, &mult, def_mult, allow_units, + &strwhole, &strfrac, &base); - if (copy_from_user(kernbuf, buffer, count)) - return -EFAULT; + if (rc) + return rc; - kernbuf[count] = '\0'; - pbuf = kernbuf; - if (*pbuf == '-') { - mult = -mult; - pbuf++; - } + if (mult == 0) { + *val = 0; + return 0; + } - whole = simple_strtoull(pbuf, &end, 10); - if (pbuf == end) - return -EINVAL; + /* the multiplier limits how large the value can be */ + wrap_indicator /= mult; - if (end != NULL && *end == '.') { - int i; - pbuf = end + 1; + if (strwhole) { + rc = kstrtoull(strwhole, base, &whole); + if (rc) + return rc; - /* need to limit frac_d to a __u32 */ - if (strlen(pbuf) > 10) - pbuf[10] = '\0'; + if (whole > wrap_indicator) + return -ERANGE; - frac = simple_strtoull(pbuf, &end, 10); - /* count decimal places */ - for (i = 0; i < (end - pbuf); i++) - frac_d *= 10; - } + whole *= mult; + } + + if (strfrac) { + if (strlen(strfrac) > 10) + strfrac[10] = '\0'; - units = 1; - if (end != NULL) { - switch (*end) { - case 'p': case 'P': - units <<= 10; - case 't': case 'T': - units <<= 10; - case 'g': case 'G': - units <<= 10; - case 'm': case 'M': - units <<= 10; - case 'k': case 'K': - units <<= 10; + rc = kstrtoull(strfrac, base, &frac); + if (rc) + return rc; + + /* determine power of fractional portion */ + while (*strfrac) { + frac_d *= base; + strfrac++; } + + /* fractional portion is too large to perform calculation */ + if (frac > wrap_indicator) + return -ERANGE; + + frac *= mult; + do_div(frac, frac_d); } - /* Specified units override the multiplier */ - if (units > 1) - mult = mult < 0 ? -units : units; - frac *= mult; - do_div(frac, frac_d); - *val = whole * mult + frac; - return 0; + /* check that the sum of whole and fraction fits in u64 */ + if (whole > (ULLONG_MAX - frac)) + return -ERANGE; + + *val = whole + frac; + + return 0; +} + +/* + * This function parses numeric/hex strings into __s64. It accepts a multiplier + * which will apply to the value parsed. It also can allow the string to + * have a unit as the last character. The function handles overflow/underflow + * of the signed integer. + */ +static int str_to_s64_internal(const char __user *buffer, unsigned long count, + __s64 *val, __u64 def_mult, bool allow_units) +{ + char kernbuf[22]; + __u64 tmp; + unsigned int offset = 0; + int signed sign = 1; + __u64 max = LLONG_MAX; + int rc = 0; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + + kernbuf[count] = '\0'; + + /* keep track of our sign */ + if (*kernbuf == '-') { + sign = -1; + offset++; + /* equivalent to max = -LLONG_MIN, avoids overflow */ + max++; + } + + rc = str_to_u64_parse(kernbuf + offset, count - offset, + &tmp, def_mult, allow_units); + if (rc) + return rc; + + /* check for overflow/underflow */ + if (max < tmp) + return -ERANGE; + + *val = (__s64)tmp * sign; + + return 0; +} + +/** + * Convert a user string into a signed 64 bit number. This function produces + * an error when the value parsed from the string underflows or + * overflows. This function accepts strings which contain digits and + * optionally a decimal or hex strings which are prefixed with "0x". + * + * \param[in] buffer string consisting of numbers and optionally a decimal + * \param[in] count buffer length + * \param[in] val if successful, the value represented by the string + * + * \retval 0 on success + * \retval negative number on error + */ +int lprocfs_str_to_s64(const char __user *buffer, unsigned long count, + __s64 *val) +{ + return str_to_s64_internal(buffer, count, val, 1, false); +} +EXPORT_SYMBOL(lprocfs_str_to_s64); + +/** + * 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 + * overflows. This function only accepts strings that contains digits, an + * optional decimal, and a char representing a unit at the end. If a unit is + * specified in the string, the multiplier provided by the caller is ignored. + * This function can also accept hexadecimal strings which are prefixed with + * "0x". + * + * \param[in] buffer string consisting of numbers, a decimal, and a unit + * \param[in] count buffer length + * \param[in] val if successful, the value represented by the string + * \param[in] defunit default unit if string doesn't contain one + * + * \retval 0 on success + * \retval negative number on error + */ +int lprocfs_str_with_units_to_s64(const char __user *buffer, + unsigned long count, __s64 *val, char defunit) +{ + __u64 mult; + int rc; + + rc = get_mult(defunit, &mult); + if (rc) + return rc; + + return str_to_s64_internal(buffer, count, val, mult, true); } -EXPORT_SYMBOL(lprocfs_write_frac_u64_helper); +EXPORT_SYMBOL(lprocfs_str_with_units_to_s64); static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len) { diff --git a/lustre/obdclass/lprocfs_status_server.c b/lustre/obdclass/lprocfs_status_server.c index 6bb6c27..d6ee00d 100644 --- a/lustre/obdclass/lprocfs_status_server.c +++ b/lustre/obdclass/lprocfs_status_server.c @@ -642,10 +642,11 @@ lprocfs_ir_factor_seq_write(struct file *file, const char __user *buffer, { struct seq_file *m = file->private_data; struct obd_device *obd = m->private; - int val, rc; + int rc; + __s64 val; LASSERT(obd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -674,12 +675,15 @@ lprocfs_recovery_time_soft_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct obd_device *obd = m->private; - int val, rc; + int rc; + __s64 val; LASSERT(obd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; obd->obd_recovery_timeout = val; return count; @@ -703,12 +707,15 @@ lprocfs_recovery_time_hard_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct obd_device *obd = m->private; - int val, rc; + int rc; + __s64 val; LASSERT(obd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; obd->obd_recovery_time_hard = val; return count; diff --git a/lustre/ofd/lproc_ofd.c b/lustre/ofd/lproc_ofd.c index 76de817..281289c 100644 --- a/lustre/ofd/lproc_ofd.c +++ b/lustre/ofd/lproc_ofd.c @@ -187,17 +187,17 @@ static ssize_t ofd_precreate_batch_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val < 1) + if (val < 1 || val > INT_MAX) return -EINVAL; spin_lock(&ofd->ofd_batch_lock); @@ -277,13 +277,13 @@ static ssize_t ofd_fmd_max_num_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -338,10 +338,10 @@ ofd_fmd_max_age_seq_write(struct file *file, const char __user *buffer, struct seq_file *m = file->private_data; struct obd_device *obd = m->private; struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -398,12 +398,13 @@ static ssize_t ofd_degraded_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val, rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -480,13 +481,13 @@ static ssize_t ofd_syncjournal_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -519,13 +520,13 @@ static ssize_t ofd_brw_size_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -592,12 +593,12 @@ static ssize_t ofd_sync_lock_cancel_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct lu_target *tgt = obd->u.obt.obt_lut; - char kernbuf[SYNC_STATES_MAXLEN]; - int val = -1; - int i; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct lu_target *tgt = obd->u.obt.obt_lut; + char kernbuf[SYNC_STATES_MAXLEN]; + __s64 val = -1; + int i; if (count == 0 || count >= sizeof(kernbuf)) return -EINVAL; @@ -618,11 +619,7 @@ ofd_sync_lock_cancel_seq_write(struct file *file, const char __user *buffer, /* Legacy numeric codes */ if (val == -1) { - int rc; - - /* Safe to use userspace buffer as lprocfs_write_helper will - * use copy from user for parsing */ - rc = lprocfs_write_helper(buffer, count, &val); + int rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; } @@ -682,13 +679,13 @@ ofd_grant_compat_disable_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - int val; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -788,16 +785,19 @@ static ssize_t ofd_lfsck_speed_limit_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - __u32 val; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; + if (val < 0) + return -ERANGE; + rc = lfsck_set_speed(ofd->ofd_osd, val); return rc != 0 ? rc : count; @@ -863,13 +863,13 @@ static ssize_t ofd_lfsck_verify_pfid_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); - __u32 val; - int rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct ofd_device *ofd = ofd_dev(obd->obd_lu_dev); + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; diff --git a/lustre/osc/lproc_osc.c b/lustre/osc/lproc_osc.c index 6930bc9..7cd40be 100644 --- a/lustre/osc/lproc_osc.c +++ b/lustre/osc/lproc_osc.c @@ -59,21 +59,23 @@ static ssize_t osc_active_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; - if (val < 0 || val > 1) - return -ERANGE; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0 || val > 1) + return -ERANGE; - /* opposite senses */ - if (dev->u.cli.cl_import->imp_deactive == val) - rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val); - else - CDEBUG(D_CONFIG, "activate %d: ignoring repeat request\n", val); + /* opposite senses */ + if (dev->u.cli.cl_import->imp_deactive == val) + rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val); + else + CDEBUG(D_CONFIG, "activate %d: ignoring repeat request\n", + (int)val); - return count; + return count; } LPROC_SEQ_FOPS(osc_active); @@ -93,20 +95,20 @@ static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; - struct client_obd *cli = &dev->u.cli; - int val, rc; + struct client_obd *cli = &dev->u.cli; + int rc; int adding, added, req_count; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; - - if (val < 1 || val > OSC_MAX_RIF_MAX) - return -ERANGE; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 1 || val > OSC_MAX_RIF_MAX) + return -ERANGE; - LPROCFS_CLIMP_CHECK(dev); + LPROCFS_CLIMP_CHECK(dev); - adding = val - cli->cl_max_rpcs_in_flight; + adding = (int)val - cli->cl_max_rpcs_in_flight; req_count = atomic_read(&osc_pool_req_count); if (adding > 0 && req_count < osc_reqpool_maxreqcount) { /* @@ -151,13 +153,15 @@ static ssize_t osc_max_dirty_mb_seq_write(struct file *file, { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; - int pages_number, mult, rc; + int rc; + __s64 pages_number; - mult = 1 << (20 - PAGE_CACHE_SHIFT); - rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult); + rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M'); if (rc) return rc; + pages_number >>= PAGE_CACHE_SHIFT; + if (pages_number <= 0 || pages_number >= OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_CACHE_SHIFT) || pages_number > totalram_pages / 4) /* 1/4 of RAM */ @@ -196,10 +200,8 @@ osc_cached_mb_seq_write(struct file *file, const char __user *buffer, { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; - __u64 val; - long pages_number; + __s64 pages_number; long rc; - int mult; char kernbuf[128]; if (count >= sizeof(kernbuf)) @@ -209,17 +211,13 @@ osc_cached_mb_seq_write(struct file *file, const char __user *buffer, return -EFAULT; kernbuf[count] = 0; - mult = 1 << (20 - PAGE_CACHE_SHIFT); buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) - kernbuf; - rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult); - + rc = lprocfs_str_with_units_to_s64(buffer, count, &pages_number, 'M'); if (rc) return rc; - if (val > LONG_MAX) - return -ERANGE; - pages_number = (long)val; + pages_number >>= PAGE_CACHE_SHIFT; if (pages_number < 0) return -ERANGE; @@ -268,18 +266,20 @@ static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - struct client_obd *cli = &obd->u.cli; - int rc; - __u64 val; + struct client_obd *cli = &obd->u.cli; + int rc; + __s64 val; - if (obd == NULL) - return 0; + if (obd == NULL) + return 0; - rc = lprocfs_write_u64_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0) + return -ERANGE; - /* this is only for shrinking grant */ + /* this is only for shrinking grant */ spin_lock(&cli->cl_loi_list_lock); if (val >= cli->cl_avail_grant) { spin_unlock(&cli->cl_loi_list_lock); @@ -288,13 +288,13 @@ static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, spin_unlock(&cli->cl_loi_list_lock); - LPROCFS_CLIMP_CHECK(obd); - if (cli->cl_import->imp_state == LUSTRE_IMP_FULL) - rc = osc_shrink_grant_to_target(cli, val); - LPROCFS_CLIMP_EXIT(obd); - if (rc) - return rc; - return count; + LPROCFS_CLIMP_CHECK(obd); + if (cli->cl_import->imp_state == LUSTRE_IMP_FULL) + rc = osc_shrink_grant_to_target(cli, val); + LPROCFS_CLIMP_EXIT(obd); + if (rc) + return rc; + return count; } LPROC_SEQ_FOPS(osc_cur_grant_bytes); @@ -338,21 +338,22 @@ static ssize_t osc_grant_shrink_interval_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - int val, rc; + int rc; + __s64 val; if (obd == NULL) return 0; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - if (val <= 0) - return -ERANGE; + if (val <= 0 || val > INT_MAX) + return -ERANGE; - obd->u.cli.cl_grant_shrink_interval = val; + obd->u.cli.cl_grant_shrink_interval = val; - return count; + return count; } LPROC_SEQ_FOPS(osc_grant_shrink_interval); @@ -372,18 +373,19 @@ static ssize_t osc_checksum_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - int val, rc; + int rc; + __s64 val; - if (obd == NULL) - return 0; + if (obd == NULL) + return 0; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; - obd->u.cli.cl_checksum = (val ? 1 : 0); + obd->u.cli.cl_checksum = !!val; - return count; + return count; } LPROC_SEQ_FOPS(osc_checksum); @@ -454,13 +456,14 @@ static ssize_t osc_resend_count_seq_write(struct file *file, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val < 0) + if (val < 0 || val > INT_MAX) return -EINVAL; atomic_set(&obd->u.cli.cl_resends, val); @@ -484,8 +487,18 @@ static ssize_t osc_contention_seconds_seq_write(struct file *file, { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct osc_device *od = obd2osc_dev(obd); + int rc; + __s64 val; - return lprocfs_write_helper(buffer, count, &od->od_contention_time) ?: count; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0 || val > INT_MAX) + return -ERANGE; + + od->od_contention_time = val; + + return count; } LPROC_SEQ_FOPS(osc_contention_seconds); @@ -504,9 +517,18 @@ static ssize_t osc_lockless_truncate_seq_write(struct file *file, { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct osc_device *od = obd2osc_dev(obd); + int rc; + __s64 val; - return lprocfs_write_helper(buffer, count, &od->od_lockless_truncate) ?: - count; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc) + return rc; + if (val < 0) + return -ERANGE; + + od->od_lockless_truncate = !!val; + + return count; } LPROC_SEQ_FOPS(osc_lockless_truncate); @@ -532,11 +554,13 @@ static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file, struct client_obd *cli = &dev->u.cli; struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data; int chunk_mask, rc; - __u64 val; + __s64 val; - rc = lprocfs_write_u64_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0) + return -ERANGE; /* if the max_pages is specified in bytes, convert to pages */ if (val >= ONE_MB_BRW_SIZE) diff --git a/lustre/osd-ldiskfs/osd_lproc.c b/lustre/osd-ldiskfs/osd_lproc.c index 4812342..7eb806d 100644 --- a/lustre/osd-ldiskfs/osd_lproc.c +++ b/lustre/osd-ldiskfs/osd_lproc.c @@ -277,16 +277,17 @@ static ssize_t ldiskfs_osd_cache_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *osd = osd_dt_dev(dt); - int val, rc; + int rc; + __s64 val; LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -311,16 +312,17 @@ static ssize_t ldiskfs_osd_wcache_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *osd = osd_dt_dev(dt); - int val, rc; + int rc; + __s64 val; LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -363,15 +365,16 @@ static ssize_t ldiskfs_osd_pdo_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - int pdo, rc; + int rc; + __s64 pdo; - rc = lprocfs_write_helper(buffer, count, &pdo); - if (rc != 0) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &pdo); + if (rc != 0) + return rc; - ldiskfs_pdo = !!pdo; + ldiskfs_pdo = !!pdo; - return count; + return count; } LPROC_SEQ_FOPS(ldiskfs_osd_pdo); @@ -391,16 +394,17 @@ static ssize_t ldiskfs_osd_auto_scrub_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *dev = osd_dt_dev(dt); - int val, rc; + int rc; + __s64 val; LASSERT(dev != NULL); if (unlikely(dev->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -425,16 +429,17 @@ static ssize_t ldiskfs_osd_full_scrub_ratio_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *dev = osd_dt_dev(dt); - int val, rc; + int rc; + __s64 val; LASSERT(dev != NULL); if (unlikely(dev->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; @@ -465,16 +470,17 @@ ldiskfs_osd_full_scrub_threshold_rate_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *dev = osd_dt_dev(dt); - int val, rc; + int rc; + __s64 val; LASSERT(dev != NULL); if (unlikely(dev->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; @@ -498,10 +504,10 @@ ldiskfs_osd_track_declares_assert_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - int track_declares_assert; - int rc; + __s64 track_declares_assert; + int rc; - rc = lprocfs_write_helper(buffer, count, &track_declares_assert); + rc = lprocfs_str_to_s64(buffer, count, &track_declares_assert); if (rc != 0) return rc; @@ -539,19 +545,21 @@ static ssize_t ldiskfs_osd_readcache_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *osd = osd_dt_dev(dt); - __u64 val; - int rc; + __s64 val; + int rc; LASSERT(osd != NULL); if (unlikely(osd->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_u64_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; + if (val < 0) + return -ERANGE; osd->od_readcache_max_filesize = val > OSD_MAX_CACHE_SIZE ? OSD_MAX_CACHE_SIZE : val; @@ -576,19 +584,19 @@ static ssize_t ldiskfs_osd_index_in_idif_seq_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - struct lu_env env; - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; - struct osd_device *dev = osd_dt_dev(dt); - struct lu_target *tgt; - int val; - int rc; + struct lu_env env; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; + struct osd_device *dev = osd_dt_dev(dt); + struct lu_target *tgt; + __s64 val; + int rc; LASSERT(dev != NULL); if (unlikely(dev->od_mnt == NULL)) return -EINPROGRESS; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc != 0) return rc; diff --git a/lustre/osd-zfs/osd_lproc.c b/lustre/osd-zfs/osd_lproc.c index d648298..0dfb483 100644 --- a/lustre/osd-zfs/osd_lproc.c +++ b/lustre/osd-zfs/osd_lproc.c @@ -264,14 +264,15 @@ static ssize_t zfs_osd_iused_est_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct dt_device *dt = m->private; + struct seq_file *m = file->private_data; + struct dt_device *dt = m->private; struct osd_device *osd = osd_dt_dev(dt); - int rc, val; + int rc; + __s64 val; LASSERT(osd != NULL); - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; diff --git a/lustre/osp/lproc_osp.c b/lustre/osp/lproc_osp.c index cf0ee83..6dc9287 100644 --- a/lustre/osp/lproc_osp.c +++ b/lustre/osp/lproc_osp.c @@ -73,11 +73,12 @@ static ssize_t osp_active_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; + struct seq_file *m = file->private_data; struct obd_device *dev = m->private; - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; if (val < 0 || val > 1) @@ -88,7 +89,7 @@ osp_active_seq_write(struct file *file, const char __user *buffer, if (dev->u.cli.cl_import->imp_deactive == val) rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val); else - CDEBUG(D_CONFIG, "activate %d: ignoring repeat request\n", + CDEBUG(D_CONFIG, "activate "LPD64": ignoring repeat request\n", val); LPROCFS_CLIMP_EXIT(dev); @@ -223,19 +224,20 @@ static ssize_t osp_max_rpcs_in_flight_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *dev = m->private; - struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); - int val, rc; + struct seq_file *m = file->private_data; + struct obd_device *dev = m->private; + struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); + int rc; + __s64 val; if (osp == NULL) return -EINVAL; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val < 1) + if (val < 1 || val > INT_MAX) return -ERANGE; osp->opd_syn_max_rpc_in_flight = val; @@ -277,19 +279,20 @@ static ssize_t osp_max_rpcs_in_prog_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *dev = m->private; - struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); - int val, rc; + struct seq_file *m = file->private_data; + struct obd_device *dev = m->private; + struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); + int rc; + __s64 val; if (osp == NULL) return -EINVAL; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val < 1) + if (val < 1 || val > INT_MAX) return -ERANGE; osp->opd_syn_max_rpc_in_progress = val; @@ -332,15 +335,16 @@ static ssize_t osp_create_count_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - int val, rc, i; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); + int rc, i; + __s64 val; if (osp == NULL || osp->opd_pre == NULL) return 0; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; @@ -401,19 +405,20 @@ static ssize_t osp_max_create_count_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); - int val, rc; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); + int rc; + __s64 val; if (osp == NULL || osp->opd_pre == NULL) return 0; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val < 0) + if (val < 0 || val > INT_MAX) return -ERANGE; if (val > OST_MAX_PRECREATE) return -ERANGE; @@ -567,19 +572,20 @@ static ssize_t osp_maxage_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *dev = m->private; - struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); - int val, rc; + struct seq_file *m = file->private_data; + struct obd_device *dev = m->private; + struct osp_device *osp = lu2osp_dev(dev->obd_lu_dev); + int rc; + __s64 val; if (osp == NULL) return -EINVAL; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc) return rc; - if (val < 1) + if (val < 1 || val > INT_MAX) return -ERANGE; osp->opd_statfs_maxage = val; @@ -696,15 +702,18 @@ osp_lfsck_max_rpcs_in_flight_seq_write(struct file *file, { struct seq_file *m = file->private_data; struct obd_device *dev = m->private; - int val; + __s64 val; int rc; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc == 0) - rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val); + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc == 0) { + if (val < 0) + return -ERANGE; - if (rc != 0) + rc = obd_set_max_rpcs_in_flight(&dev->u.cli, val); + } else { count = rc; + } return count; } diff --git a/lustre/ptlrpc/gss/lproc_gss.c b/lustre/ptlrpc/gss/lproc_gss.c index 4648695..17b92e2 100644 --- a/lustre/ptlrpc/gss/lproc_gss.c +++ b/lustre/ptlrpc/gss/lproc_gss.c @@ -163,17 +163,19 @@ static ssize_t gss_lk_proc_dl_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - int val, rc; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc < 0) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc < 0) + return rc; + + if (val < 0 || val > 4) + return -ERANGE; - if (val < 0 || val > 4) - return -ERANGE; + gss_lk_debug_level = val; - gss_lk_debug_level = val; - return count; + return count; } LPROC_SEQ_FOPS(gss_lk_proc_dl); diff --git a/lustre/ptlrpc/lproc_ptlrpc.c b/lustre/ptlrpc/lproc_ptlrpc.c index 1920fc7..adbd7e2 100644 --- a/lustre/ptlrpc/lproc_ptlrpc.c +++ b/lustre/ptlrpc/lproc_ptlrpc.c @@ -294,33 +294,34 @@ ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct ptlrpc_service *svc = m->private; - int bufpages; - int val; - int rc; + struct seq_file *m = file->private_data; + struct ptlrpc_service *svc = m->private; + int bufpages; + __s64 val; + int rc; - rc = lprocfs_write_helper(buffer, count, &val); - if (rc < 0) - return rc; + rc = lprocfs_str_to_s64(buffer, count, &val); + if (rc < 0) + return rc; - if (val < 0) - return -ERANGE; + if (val < 0 || val > INT_MAX) + return -ERANGE; - /* This sanity check is more of an insanity check; we can still - * hose a kernel by allowing the request history to grow too - * far. */ + /* This sanity check is more of an insanity check; we can still + * hose a kernel by allowing the request history to grow too + * far. */ bufpages = (svc->srv_buf_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (val > totalram_pages/(2 * bufpages)) - return -ERANGE; + return -ERANGE; spin_lock(&svc->srv_lock); if (val == 0) svc->srv_hist_nrqbds_cpt_max = 0; else - svc->srv_hist_nrqbds_cpt_max = max(1, (val / svc->srv_ncpts)); + svc->srv_hist_nrqbds_cpt_max = + max(1, ((int)val / svc->srv_ncpts)); spin_unlock(&svc->srv_lock); @@ -343,10 +344,10 @@ ptlrpc_lprocfs_threads_min_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct ptlrpc_service *svc = m->private; - int val; - int rc = lprocfs_write_helper(buffer, count, &val); + struct seq_file *m = file->private_data; + struct ptlrpc_service *svc = m->private; + __s64 val; + int rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; @@ -360,7 +361,7 @@ ptlrpc_lprocfs_threads_min_seq_write(struct file *file, return -ERANGE; } - svc->srv_nthrs_cpt_init = val / svc->srv_ncpts; + svc->srv_nthrs_cpt_init = (int)val / svc->srv_ncpts; spin_unlock(&svc->srv_lock); @@ -399,10 +400,10 @@ ptlrpc_lprocfs_threads_max_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct ptlrpc_service *svc = m->private; - int val; - int rc = lprocfs_write_helper(buffer, count, &val); + struct seq_file *m = file->private_data; + struct ptlrpc_service *svc = m->private; + __s64 val; + int rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; @@ -416,7 +417,7 @@ ptlrpc_lprocfs_threads_max_seq_write(struct file *file, return -ERANGE; } - svc->srv_nthrs_cpt_limit = val / svc->srv_ncpts; + svc->srv_nthrs_cpt_limit = (int)val / svc->srv_ncpts; spin_unlock(&svc->srv_lock); @@ -1061,16 +1062,16 @@ static ssize_t ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct ptlrpc_service *svc = m->private; - int rc; - int val; + struct seq_file *m = file->private_data; + struct ptlrpc_service *svc = m->private; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; - if (val < 0) + if (val < 0 || val > INT_MAX) return -ERANGE; spin_lock(&svc->srv_lock); @@ -1315,13 +1316,14 @@ ssize_t lprocfs_pinger_recov_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct seq_file *m = file->private_data; - struct obd_device *obd = m->private; - struct client_obd *cli = &obd->u.cli; - struct obd_import *imp = cli->cl_import; - int rc, val; + struct seq_file *m = file->private_data; + struct obd_device *obd = m->private; + struct client_obd *cli = &obd->u.cli; + struct obd_import *imp = cli->cl_import; + int rc; + __s64 val; - rc = lprocfs_write_helper(buffer, count, &val); + rc = lprocfs_str_to_s64(buffer, count, &val); if (rc < 0) return rc; diff --git a/lustre/quota/qsd_lib.c b/lustre/quota/qsd_lib.c index efd7840..1a4b5ad 100644 --- a/lustre/quota/qsd_lib.c +++ b/lustre/quota/qsd_lib.c @@ -194,13 +194,14 @@ qsd_timeout_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct qsd_instance *qsd = ((struct seq_file *)file->private_data)->private; - int timeout, rc; + int rc; + __s64 timeout; LASSERT(qsd != NULL); - rc = lprocfs_write_helper(buffer, count, &timeout); + rc = lprocfs_str_to_s64(buffer, count, &timeout); if (rc) return rc; - if (timeout < 0) + if (timeout < 0 || timeout > INT_MAX) return -EINVAL; qsd->qsd_timeout = timeout; -- 1.8.3.1