diff -ruN linux-2.4.21.orig/drivers/s390/block/dasd.c linux-2.4.21/drivers/s390/block/dasd.c --- linux-2.4.21.orig/drivers/s390/block/dasd.c 2003-07-21 23:46:01.000000000 -0500 +++ linux-2.4.21/drivers/s390/block/dasd.c 2003-07-23 03:06:06.000000000 -0500 @@ -577,15 +577,22 @@ if (strlen(buffer)) { if (!strcmp(buffer,"ro")) { /* handle 'ro' feature */ (*features) |= DASD_FEATURE_READONLY; - break; } - MESSAGE (KERN_WARNING, - "unsupported feature: %s, " - "ignoring setting", - buffer); + else if (!strcmp(buffer,"diag")) { /* handle 'diag' feature */ + (*features) |= DASD_FEATURE_USEDIAG; + } + + else { + MESSAGE (KERN_WARNING, + "unsupported feature: %s, " + "ignoring setting", + buffer); + } } } + if (temp[i] == ')') + i++; } *stra = temp+i; @@ -995,7 +1002,6 @@ dasd_features_from_devno (int devno) { dasd_range_t *temp; - int devindex = 0; unsigned long flags; struct list_head *l; @@ -1006,7 +1012,6 @@ spin_unlock_irqrestore (&range_lock, flags); return temp->features; } - devindex += temp->to - temp->from + 1; } spin_unlock_irqrestore (&range_lock, flags); return -ENODEV; @@ -1106,7 +1111,7 @@ * checks the list of disciplines for the first one able to access the device */ static inline dasd_discipline_t * -dasd_find_disc (dasd_device_t * device, dasd_discipline_t *discipline) +dasd_find_disc (dasd_device_t * device, dasd_discipline_t *discipline, int features) { dasd_discipline_t *t; struct list_head *l = discipline ? @@ -1114,8 +1119,9 @@ do { t = list_entry(l,dasd_discipline_t,list); - - if ( ( t->id_check == NULL || + if ( ( !( features & DASD_FEATURE_USEDIAG ) || + strncmp (t->name, "DIAG", 4) == 0 ) && + ( t->id_check == NULL || t->id_check (&device->devinfo) == 0 ) && ( t->check_characteristics == NULL || t->check_characteristics (device) == 0 ) ) @@ -3946,6 +3952,7 @@ struct list_head *l; major_info_t *major_info, *tmp; int i; + int features; dasd_device_t *device = *dptr; devfs_handle_t dir; char buffer[5]; @@ -3993,8 +4000,11 @@ if ( devno != device->devinfo.devno ) BUG(); + features = dasd_features_from_devno(device->devinfo.devno); + device->discipline = dasd_find_disc (device, - discipline); + discipline, + features); if ( device->discipline == NULL ) { rc = -ENODEV; goto out; @@ -4004,7 +4014,7 @@ dir = devfs_mk_dir (dasd_devfs_handle, buffer, device); device->major_info->gendisk.de_arr[MINOR(device->kdev) >> DASD_PARTN_BITS] = dir; - if (dasd_features_from_devno(device->devinfo.devno)&DASD_FEATURE_READONLY) { + if (features&DASD_FEATURE_READONLY) { devfs_perm &= ~(S_IWUSR); } device->devfs_entry = devfs_register (dir,"device",DEVFS_FL_DEFAULT, @@ -4527,6 +4537,7 @@ dasd_device_t *device; int devno = dasd_devno_from_devindex(index+i); int features; + char *featstr = ""; if ( devno == -ENODEV ) continue; @@ -4535,6 +4546,14 @@ if (features < DASD_FEATURE_DEFAULT) features = DASD_FEATURE_DEFAULT; + if ( (features & DASD_FEATURE_READONLY) && + (features & DASD_FEATURE_USEDIAG) ) + featstr = "(ru}"; + else if (features & DASD_FEATURE_READONLY) + featstr = "(ro)"; + else if (features & DASD_FEATURE_USEDIAG) + featstr = "(ud)"; + device = temp->dasd_device[i]; if (device) { @@ -4547,8 +4566,7 @@ temp->gendisk.major, i << DASD_PARTN_BITS, device->name, - (features & DASD_FEATURE_READONLY) ? - "(ro)" : " "); + featstr); switch (device->level) { case DASD_STATE_NEW: @@ -4618,8 +4636,7 @@ temp->gendisk.major, i << DASD_PARTN_BITS, buffer, - (features & DASD_FEATURE_READONLY) ? - "(ro)" : " "); + featstr); } if ( dasd_probeonly ) len += sprintf(info->data + len,"(probeonly)"); @@ -4686,7 +4703,10 @@ /* remove blanks after device range */ for (; isspace(*str); str++); - if (range->from < 0 || range->to < 0) { + /* Negative numbers in str/from/to indicate errors */ + if ((range->from < 0) || (range->to < 0) || + (range->from > 65535) || (range->to > 65535) || + (range->from > range->to)) { MESSAGE (KERN_WARNING, "/proc/dasd/devices: range parse error in '%s'", buffer); @@ -4709,21 +4729,19 @@ str = dasd_parse_range (buffer, &range); - /* Negative numbers in str/from/to indicate errors */ - if (IS_ERR (str) || (range.from < 0) || (range.to < 0) - || (range.from > 65535) || (range.to > 65535)) + if (IS_ERR (str)) return; - if (strncmp (str, "on", 2) == 0) { + if (strcmp (str, "on") == 0) { dasd_enable_ranges (&range, NULL, 0); - } else if (strncmp (str, "off", 3) == 0) { + } else if (strcmp (str, "off") == 0) { dasd_disable_ranges (&range, NULL, 0, 1); } else { MESSAGE (KERN_WARNING, "/proc/dasd/devices: " - "only 'on' and 'off' are alowed in 'set' " + "only 'on' and 'off' are allowed in 'set' " "command ('%s'/'%s')", buffer, str); @@ -4734,6 +4752,60 @@ } /* end dasd_proc_set */ /* + * Set / Unset the given feature after validateion + */ +static void +dasd_proc_feature (char *buffer, char *cmd, int feature) +{ + dasd_range_t *temp; + unsigned long flags; + struct list_head *l; + dasd_range_t range; + char *str; + int on; + + str = dasd_parse_range (buffer, + &range); + + if (IS_ERR (str)) + return; + + if (strcmp (str, "on") == 0) { + on = 1; + + } else if (strcmp (str, "off") == 0) { + on = 0; + + } else { + MESSAGE (KERN_WARNING, + "/proc/dasd/devices: " + "only 'on' and 'off' are allowed in '%s' " + "command ('%s')", + cmd, + str); + return; + } + + spin_lock_irqsave (&range_lock, flags); + list_for_each (l, &dasd_range_head.list) { + temp = list_entry (l, dasd_range_t, list); + if ( (range.from >= temp->from && range.from <= temp->to) || + (range.to >= temp->from && range.to <= temp->to) || + (temp->from >= range.from && temp->from <= range.to) || + (temp->to >= range.from && temp->to <= range.to) ) { + if (on) + temp->features |= feature; + else + temp->features &= ~feature; + } + } + spin_unlock_irqrestore (&range_lock, flags); + + return; + +} /* end dasd_proc_feature */ + +/* * Add the given devices */ static void @@ -4745,9 +4817,7 @@ str = dasd_parse_range (buffer, &range); - /* Negative numbers in str/from/to indicate errors */ - if (IS_ERR (str) || (range.from < 0) || (range.to < 0) - || (range.from > 65535) || (range.to > 65535)) + if (IS_ERR (str)) return; dasd_add_range (range.from, range.to, range.features); @@ -4926,6 +4996,14 @@ /* handle 'brk ' */ dasd_proc_brk (buffer); + } else if (strncmp (buffer, "readonly ", 9) == 0) { + /* handle 'readonly on/off' */ + dasd_proc_feature (&buffer[5], "readonly", DASD_FEATURE_READONLY); + + } else if (strncmp (buffer, "usediag ", 8) == 0) { + /* handle 'usediag on/off' */ + dasd_proc_feature (&buffer[4], "usediag", DASD_FEATURE_USEDIAG); + } else { MESSAGE (KERN_WARNING, "%s", "/proc/dasd/devices: only 'set' ,'add' and " diff -ruN linux-2.4.21.orig/include/asm-s390/dasd.h linux-2.4.21/include/asm-s390/dasd.h --- linux-2.4.21.orig/include/asm-s390/dasd.h 2003-07-21 23:45:46.000000000 -0500 +++ linux-2.4.21/include/asm-s390/dasd.h 2003-07-23 03:00:41.000000000 -0500 @@ -79,6 +79,7 @@ */ #define DASD_FEATURE_DEFAULT 0 #define DASD_FEATURE_READONLY 1 +#define DASD_FEATURE_USEDIAG 2 #define DASD_PARTN_BITS 2 diff -ruN linux-2.4.21.orig/include/asm-s390x/dasd.h linux-2.4.21/include/asm-s390x/dasd.h --- linux-2.4.21.orig/include/asm-s390x/dasd.h 2003-07-21 23:45:46.000000000 -0500 +++ linux-2.4.21/include/asm-s390x/dasd.h 2003-07-23 03:00:41.000000000 -0500 @@ -79,6 +79,7 @@ */ #define DASD_FEATURE_DEFAULT 0 #define DASD_FEATURE_READONLY 1 +#define DASD_FEATURE_USEDIAG 2 #define DASD_PARTN_BITS 2