sysctl for bdflush

Tom Dyas (tdyas@vger.rutgers.edu)
Fri, 23 Feb 96 1:32:06 EST


This little patch against 1.3.68 adds a sysctl entry for those
wonderful bdflush parameters. The patch does checking against the min
and max values and acts accordingly.

--- ./fs/buffer.c- Thu Feb 22 22:18:54 1996
+++ ./fs/buffer.c Thu Feb 22 23:25:12 1996
@@ -72,13 +72,16 @@
int nr_buffer_heads = 0;
extern int *blksize_size[];

-/* Here is the parameter block for the bdflush process. */
+/* Here is the parameter block for the bdflush process. If you add or
+ * remove any of the parameters, make sure to update kernel/sysctl.c.
+ */
+
static void wakeup_bdflush(int);

#define N_PARAM 9
#define LAV

-static union bdflush_param{
+union bdflush_param{
struct {
int nfract; /* Percentage of buffer cache dirty to
activate bdflush */
@@ -109,8 +112,8 @@


/* These are the min and max parameter values that we will allow to be assigned */
-static int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 100, 100, 1, 1};
-static int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 60000, 60000, 2047, 5};
+int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 100, 100, 1, 1};
+int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 60000, 60000, 2047, 5};

/*
* Rewrote the wait-routines to use the "new" wait-queue functionality,
--- ./kernel/sysctl.c- Thu Feb 22 22:23:23 1996
+++ ./kernel/sysctl.c Fri Feb 23 00:58:54 1996
@@ -3,6 +3,7 @@
*
* Begun 24 March 1995, Stephen Tweedie
* Added /proc support, Dec 1995
+ * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
*/

#include <linux/config.h>
@@ -81,6 +82,8 @@
static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
#endif

+extern int bdf_prm[], bdflush_min[], bdflush_max[];
+
static int do_securelevel_strategy (ctl_table *, int *, int, void *, size_t *,
void *, size_t, void **);

@@ -123,6 +126,9 @@
&kswapd_ctl, sizeof(kswapd_ctl), 0600, NULL, &proc_dointvec},
{VM_FREEPG, "freepages",
&min_free_pages, 3*sizeof(int), 0600, NULL, &proc_dointvec},
+ {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL,
+ &proc_dointvec_minmax, &sysctl_intvec, NULL,
+ &bdflush_min, &bdflush_max},
{0}
};

@@ -582,6 +588,88 @@
return 0;
}

+int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+ int *i, *min, *max, vleft, first=1, len, left, neg, val;
+ #define TMPBUFLEN 20
+ char buf[TMPBUFLEN], *p;
+
+ if (!table->data || !table->maxlen || !*lenp ||
+ (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ i = (int *) table->data;
+ min = (int *) table->extra1;
+ max = (int *) table->extra2;
+ vleft = table->maxlen / sizeof(int);
+ left = *lenp;
+
+ for (; left && vleft--; i++, first=0) {
+ if (write) {
+ while (left && isspace(get_user((char *) buffer)))
+ left--, ((char *) buffer)++;
+ if (!left)
+ break;
+ neg = 0;
+ len = left;
+ if (len > TMPBUFLEN-1)
+ len = TMPBUFLEN-1;
+ memcpy_fromfs(buf, buffer, len);
+ buf[len] = 0;
+ p = buf;
+ if (*p == '-' && left > 1) {
+ neg = 1;
+ left--, p++;
+ }
+ if (*p < '0' || *p > '9')
+ break;
+ val = simple_strtoul(p, &p, 0);
+ len = p-buf;
+ if ((len < left) && *p && !isspace(*p))
+ break;
+ if (neg)
+ val = -val;
+ buffer += len;
+ left -= len;
+
+ if (min && val < *min++)
+ continue;
+ if (max && val > *max++)
+ continue;
+ *i = val;
+ } else {
+ p = buf;
+ if (!first)
+ *p++ = '\t';
+ sprintf(p, "%d", *i);
+ len = strlen(buf);
+ if (len > left)
+ len = left;
+ memcpy_tofs(buffer, buf, len);
+ left -= len;
+ buffer += len;
+ }
+ }
+
+ if (!write && !first && left) {
+ put_user('\n', (char *) buffer);
+ left--, buffer++;
+ }
+ if (write) {
+ p = (char *) buffer;
+ while (left && isspace(get_user(p++)))
+ left--;
+ }
+ if (write && first)
+ return -EINVAL;
+ *lenp -= left;
+ filp->f_pos += *lenp;
+ return 0;
+}
+
#else /* CONFIG_PROC_FS */

int proc_dostring(ctl_table *table, int write, struct file *filp,
@@ -596,6 +684,12 @@
return -ENOSYS;
}

+int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+ return -ENOSYS;
+}
+
#endif /* CONFIG_PROC_FS */


@@ -631,6 +725,43 @@
if (len == table->maxlen)
len--;
((char *) table->data)[len] = 0;
+ }
+ return 0;
+}
+
+/*
+ * This function makes sure that all of the integers in the vector
+ * are between the minimum and maximum values given in the arrays
+ * table->extra1 and table->extra2, respectively.
+ */
+int sysctl_intvec(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen, void **context)
+{
+ int i, length, *vec, *min, *max;
+
+ if (newval && newlen) {
+ if (newlen % sizeof(int) != 0)
+ return -EINVAL;
+
+ if (!table->extra1 && !table->extra2)
+ return 0;
+
+ if (newlen > table->maxlen)
+ newlen = table->maxlen;
+ length = newlen / sizeof(int);
+
+ vec = (int *) newval;
+ min = (int *) table->extra1;
+ max = (int *) table->extra2;
+
+ for (i = 0; i < length; i++) {
+ int value = get_user(vec + i);
+ if (min && value < min[i])
+ return -EINVAL;
+ if (max && value > max[i])
+ return -EINVAL;
+ }
}
return 0;
}
--- ./include/linux/sysctl.h- Thu Feb 22 22:28:41 1996
+++ ./include/linux/sysctl.h Fri Feb 23 01:01:08 1996
@@ -60,7 +60,8 @@
#define VM_SWAPCTL 1 /* struct: Set vm swapping control */
#define VM_KSWAPD 2 /* struct: control background pagout */
#define VM_FREEPG 3 /* struct: Set free page thresholds */
-#define VM_MAXID 4
+#define VM_BDFLUSH 4 /* struct: Control buffer cache flushing */
+#define VM_MAXID 5

/* CTL_NET names: */

@@ -91,6 +92,8 @@
void *, size_t *);
extern int proc_dointvec(ctl_table *, int, struct file *,
void *, size_t *);
+extern int proc_dointvec_minmax(ctl_table *, int, struct file *,
+ void *, size_t *);

extern int do_sysctl (int *name, int nlen,
void *oldval, size_t *oldlenp,
@@ -102,6 +105,7 @@
void *newval, size_t newlen, void ** context);

extern ctl_handler sysctl_string;
+extern ctl_handler sysctl_intvec;

extern int do_string (
void *oldval, size_t *oldlenp, void *newval, size_t newlen,
@@ -163,6 +167,8 @@
proc_handler *proc_handler; /* Callback for text formatting */
ctl_handler *strategy; /* Callback function for all r/w */
struct proc_dir_entry *de; /* /proc control block */
+ void *extra1;
+ void *extra2;
};

/* struct ctl_table_header is used to maintain dynamic lists of