sysctl: Generate do_proc_douintvec with a type-generic macro

Generate the behavior in do_proc_douintvec{,_w,_r} functions with
do_proc_dotypevec(uint). The originals (do_proc_douintvec{,_w,_r})
where created in the same way as do_proc_dotypevec but for individual
values (no vectors). In this commit we use the existing macro
implementation to extend do_proc_douintvec to include vectors of values.

Signed-off-by: Joel Granados <joel.granados@kernel.org>
This commit is contained in:
Joel Granados
2026-07-08 13:12:30 +02:00
parent c27eb1e1c3
commit 8ff8fbfc6a
+1 -113
View File
@@ -651,119 +651,7 @@ out: \
do_proc_dotypevec(int)
do_proc_dotypevec(ulong)
static int do_proc_douintvec_w(const struct ctl_table *table, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *u_ptr,
unsigned int *k_ptr, int dir,
const struct ctl_table *table))
{
unsigned long lval;
int err = 0;
size_t left;
bool neg;
char *p = buffer;
left = *lenp;
if (proc_first_pos_non_zero_ignore(ppos, table))
goto bail_early;
if (left > PAGE_SIZE - 1)
left = PAGE_SIZE - 1;
proc_skip_spaces(&p, &left);
if (!left) {
err = -EINVAL;
goto out_free;
}
err = proc_get_long(&p, &left, &lval, &neg,
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
if (err || neg) {
err = -EINVAL;
goto out_free;
}
if (conv(&neg, &lval, (unsigned int *) table->data, 1, table)) {
err = -EINVAL;
goto out_free;
}
if (!err && left)
proc_skip_spaces(&p, &left);
out_free:
if (err)
return -EINVAL;
return 0;
bail_early:
*ppos += *lenp;
return err;
}
static int do_proc_douintvec_r(const struct ctl_table *table, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *u_ptr,
unsigned int *k_ptr, int dir,
const struct ctl_table *table))
{
unsigned long lval;
int err = 0;
size_t left;
bool negp;
left = *lenp;
if (conv(&negp, &lval, (unsigned int *) table->data, 0, table)) {
err = -EINVAL;
goto out;
}
proc_put_long(&buffer, &left, lval, false);
if (!left)
goto out;
proc_put_char(&buffer, &left, '\n');
out:
*lenp -= left;
*ppos += *lenp;
return err;
}
static int do_proc_douintvec(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, ulong *u_ptr, uint *k_ptr,
int dir, const struct ctl_table *table))
{
unsigned int vleft;
if (!table->data || !table->maxlen || !*lenp ||
(*ppos && SYSCTL_KERN_TO_USER(dir))) {
*lenp = 0;
return 0;
}
vleft = table->maxlen / sizeof(unsigned int);
/*
* Arrays are not supported, keep this simple. *Do not* add
* support for them.
*/
if (vleft != 1) {
*lenp = 0;
return -EINVAL;
}
if (SYSCTL_USER_TO_KERN(dir))
return do_proc_douintvec_w(table, buffer, lenp, ppos, conv);
return do_proc_douintvec_r(table, buffer, lenp, ppos, conv);
}
do_proc_dotypevec(uint)
/**
* proc_douintvec_conv - read a vector of unsigned ints with a custom converter