[ENBD] md5sum switch
Peter T. Breuer
ptb at it.uc3m.es
Sun Jan 11 11:06:25 MST 2004
You might try the following patch. It
1) makes -ve md5 threshold values mean "never".
2) allows control of them per device via /proc/sys/dev/enbd/devices/*
There is a "md5sum" parameter (0/1) in each device subdir, but it still
only reflects the current state of the device, and will be changed by
time to time by the device itself. Nevertheless, if you change the
current state and the on/off thresholds, that is enough to achieve
whatever permanent state you want.
If you can tell me a name for it, I could make a parameter that has the
effect you want - namely when 0 it turns off md5summing forever,
whatever the state of the thresholds and the devices wishes, and when 1
it hands control to the device.
You know, I suppose that is three states: off, auto, on. Hmm.
Peter
diff -ubr nbd-2.4.31/kernel/linux/drivers/block/enbd.c nbd-2.4.32/kernel/linux/drivers/block/enbd.c
--- nbd-2.4.31/kernel/linux/drivers/block/enbd.c Sun Dec 7 00:57:36 2003
+++ nbd-2.4.32/kernel/linux/drivers/block/enbd.c Sun Jan 11 01:46:49 2004
@@ -1447,7 +1473,8 @@
atomic_add (req_blks, &lo->wrequests_5to); // 10
atomic_add (req_blks, &lo->wrequests_5wo);
atomic_inc (&lo->wrequests_5co);
- if (atomic_read (&lo->wrequests_5co) > md5_off_threshold) {
+ if (lo->md5_off_threshold >= 0 &&
+ atomic_read (&lo->wrequests_5co) > lo->md5_off_threshold) {
atomic_set (&lo->wrequests_5co, 0);
// turn off md5summing as it's not successful
atomic_clear_mask (ENBD_MD5SUM, &lo->flags);
@@ -1460,7 +1487,8 @@
atomic_add (req_blks, &lo->wrequests_5to); // 01
atomic_add (req_blks, &lo->wrequests_5eo);
atomic_inc (&lo->wrequests_5co);
- if (atomic_read (&lo->wrequests_5co) > md5_off_threshold) {
+ if (lo->md5_off_threshold >= 0 &&
+ atomic_read (&lo->wrequests_5co) > lo->md5_off_threshold) {
atomic_set (&lo->wrequests_5co, 0);
// turn off md5summing as it's errored
atomic_clear_mask (ENBD_MD5SUM, &lo->flags);
@@ -1472,7 +1500,8 @@
case 0:
// PTB nobody asked for a md5 and nobdy gave one back
atomic_inc (&lo->wrequests_5no);
- if (atomic_read (&lo->wrequests_5no) > md5_on_threshold) {
+ if (lo->md5_on_threshold >= 0 &&
+ atomic_read (&lo->wrequests_5no) > lo->md5_on_threshold) {
atomic_set (&lo->wrequests_5no, 0);
// turn on md5summing every so often
atomic_set_mask (ENBD_MD5SUM, &lo->flags);
@@ -4943,11 +4991,19 @@
case ENBD_SET_MD5SUM: /* PTB - change to do/plead md5summing */
ENBD_DEBUG (3, "ENBD_SET_MD5SUM %ld\n", arg);
- if (arg) {
+ if (arg & 1) {
+ // PTB switch on md5sum and possibly raise off_threshold
atomic_set_mask (ENBD_MD5SUM, &lo->flags);
+ if (arg != 1) {
+ lo->md5_off_threshold = (long)arg >> 1;
+ }
}
else {
+ // PTB switch off md5sum and possibly raise on_threshold
atomic_clear_mask (ENBD_MD5SUM, &lo->flags);
+ if (arg != 0) {
+ lo->md5_on_threshold = (long)arg >> 1;
+ }
}
err = 0;
ENBD_DEBUG (3, "exited OK\n");
@@ -6793,9 +6933,92 @@
+static int
+enbd_proc_dobit (ctl_table * table, int write, struct file *filp,
+ void *buffer, size_t * lenp)
+{
+ size_t len;
+ char *p, c;
+
+ if (!table->data || !table->maxlen || !*lenp ||
+ (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ if (write) {
+
+ short clear = 0, set = 0;
+
+ len = 0;
+ p = buffer;
+
+ // read from buffer until *lenp or end of entry
+ while (len < *lenp) {
+ if (get_user (c, p++))
+ return -EFAULT;
+ if (c == 0 || c == '\n')
+ break;
+ if (c == '0') {
+ if (set) {
+ set = 0;
+ break;
+ }
+ clear = 1;
+ break;
+ }
+ if (c == '1') {
+ clear = 0;
+ set = 1;
+ break;
+ }
+ if (c != ' ' && c != '\t' && c != '\r') {
+ clear = set = 0;
+ break;
+ }
+ len++;
+ }
+
+ if (!set && !clear) {
+ return -EINVAL;
+ }
+ if (set)
+ atomic_set_mask((unsigned long)table->extra1, (atomic_t *)table->data);
+ if (clear)
+ atomic_clear_mask((unsigned long)table->extra1, (atomic_t *)table->data);
+ filp->f_pos += *lenp;
+
+ } else {
+
+ // reading
+ len = 1;
+ if (len > *lenp)
+ len = *lenp;
+ if (len)
+ if (copy_to_user (buffer, (atomic_read((atomic_t *)table->data) & (unsigned long)table->extra1) ? "1" : "0", len))
+ return -EFAULT;
+ if (len < *lenp) {
+ if (put_user ('\n', ((char *) buffer) + len))
+ return -EFAULT;
+ len++;
+ }
+ *lenp = len;
+ filp->f_pos += len;
+ }
+ return 0;
+}
+
+
// PTB - and now to play with the sysctl interface ...
static struct ctl_table_header *enbd_table_header;
// the above was set by the register call of the root table
+
+static ctl_table enbd_systable [MAX_NBD+1] = {
+ {1, "a", NULL, 0, 0555, NULL, NULL, },
+ {2, "b", NULL, 0, 0555, NULL, NULL, },
+ {0},
+};
+
static ctl_table enbd_table[] = {
{1, "rahead",
&rahead, sizeof (int), 0644, NULL, &proc_dointvec},
@@ -6816,6 +7039,8 @@
&md5_on_threshold, sizeof (int), 0644, NULL, &proc_dointvec},
{9, "md5_off_threshold",
&md5_off_threshold, sizeof (int), 0644, NULL, &proc_dointvec},
+ {10, "devices",
+ NULL, 0, 0555, enbd_systable, NULL, },
{0}
};
static ctl_table enbd_dir_table[] = {
@@ -6842,7 +7067,10 @@
}
static void
enbd_destroy(struct enbd_device *lo) {
- int j;
+ int i, j;
+ i = lo->nbd; // offset in nbd_dev
+ enbd_systable[i] = (ctl_table) {0};
+
for (j = ENBD_MAXCONN - 1; j >= 0; j--) { /* PTB */
struct enbd_slot *slot;
write_lock(&lo->meta_lock);
@@ -6894,6 +7126,8 @@
lo->sectors = 0xfffffffe; /* PTB sectors */
lo->req_timeo = ENBD_REQ_TIMEO; /* PTB default pulse intvl */
lo->max_sectors = buf_sectors;
+ lo->md5_off_threshold = md5_off_threshold;
+ lo->md5_on_threshold = md5_on_threshold;
lo->acct = acct_create();
@@ -6933,6 +7167,39 @@
if (atomic_read(&atomic_merge_requests)) {
atomic_set(&lo->merge_requests,atomic_read(&atomic_merge_requests));
}
+
+ lo->systable[0] = (ctl_table) {9, "md5_off_threshold",
+ &lo->md5_off_threshold, sizeof (int), 0644,
+ NULL, &proc_dointvec, },
+ lo->systable[1] = (ctl_table) {8, "md5_on_threshold",
+ &lo->md5_on_threshold, sizeof (int), 0644,
+ NULL, &proc_dointvec, },
+ lo->systable[2] = (ctl_table) {5, "md5sum",
+ &lo->flags, 1, 0644,
+ NULL, &enbd_proc_dobit, NULL, NULL, (void *)ENBD_MD5SUM, },
+ lo->systable[3] = (ctl_table) {4, "merge_requests",
+ &lo->merge_requests, sizeof (int), 0644,
+ NULL, &proc_dointvec, },
+ lo->systable[4] = (ctl_table) {3, "sync",
+ &lo->flags, sizeof (int), 0644,
+ NULL, &enbd_proc_dobit, NULL, NULL, (void *)ENBD_SYNC},
+ lo->systable[5] = (ctl_table) {2, "show_errs",
+ &lo->flags, sizeof (int), 0644,
+ NULL, &enbd_proc_dobit, NULL, NULL, (void *)ENBD_SHOW_ERRS},
+ lo->systable[6] = (ctl_table) {1, "bufferwr",
+ &lo->flags, sizeof (int), 0644,
+ NULL, &enbd_proc_dobit, NULL, NULL, (void *)ENBD_BUFFERWR},
+ lo->systable[ENBD_SYSCTL_MAX - 1] = (ctl_table) {0};
+
+ enbd_systable[i] = (ctl_table){i+1, lo->devnam,
+ NULL, 0, 0555,
+ lo->systable, NULL, };
+
+ ENBD_INFO("made /proc/sys/dev/enbd/devices %s, inode %d\n",
+ lo->devnam, i+1);
+ unregister_sysctl_table (enbd_table_header);
+ enbd_table_header = register_sysctl_table (enbd_root_table, 1);
+
return 0;
}
@@ -6984,6 +7251,16 @@
}
#endif /* CONFIG_DEVFS_FS */
+static void
+enbd_sysctl_init(void) {
+ int i;
+ for (i = 0; i < MAX_NBD; i++) {
+ enbd_systable[i] = (ctl_table){i+1, NULL, NULL, 0, 0555, NULL, NULL};
+ }
+ enbd_systable[MAX_NBD] = (ctl_table){0};
+ enbd_table_header = register_sysctl_table (enbd_root_table, 1);
+}
+
int __init
enbd_init (void)
{
@@ -7093,7 +7370,9 @@
#endif /* CONFIG_DEVFS_FS */
// PTB - sysctl interface
- enbd_table_header = register_sysctl_table (enbd_root_table, 1);
+ enbd_sysctl_init();
+
+
spin_lock_init(&md_access_lock);
diff -ubr nbd-2.4.31/kernel/linux/include/linux/enbd.h nbd-2.4.32/kernel/linux/include/linux/enbd.h
--- nbd-2.4.31/kernel/linux/include/linux/enbd.h Sun Sep 28 10:01:08 2003
+++ nbd-2.4.32/kernel/linux/include/linux/enbd.h Sun Jan 11 01:41:42 2004
@@ -76,6 +78,7 @@
#define ENBD_CMDMASK 0x03 /* PTB mask pertaining to CMDBITS */
//#define ENBD_MAXGROUP 2 /* PTB number of client groups per device */
+ #define ENBD_SYSCTL_MAX 8 /* number of sysctl entries */
#ifdef __KERNEL__
@@ -274,6 +277,9 @@
atomic_t merge_requests; /* PTB local req blks limit - 1 */
atomic_t md_count; /* PTB count of raids we are in */
unsigned long reenable_time; /* PTB time to delayed reenable */
+ int md5_off_threshold; /* PTB autolimits on md5 */
+ int md5_on_threshold; /* PTB autolimits on md5 */
+ ctl_table systable[ENBD_SYSCTL_MAX];
};
/* COMPATIBILITY */
More information about the ENBD
mailing list