Commit f24acd45 authored by Horst Hummel's avatar Horst Hummel Committed by Linus Torvalds

[PATCH] s390: dasd readonly attribute

The independent read-only flags in devmap, dasd_device and gendisk are not
kept in sync.  Use one bit per feature in the dasd driver and keep that bit in
sync with the gendisk bit.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e8f0641e
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
* *
* $Revision: 1.158 $ * $Revision: 1.161 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -1131,13 +1131,17 @@ __dasd_process_blk_queue(struct dasd_device * device) ...@@ -1131,13 +1131,17 @@ __dasd_process_blk_queue(struct dasd_device * device)
request_queue_t *queue; request_queue_t *queue;
struct request *req; struct request *req;
struct dasd_ccw_req *cqr; struct dasd_ccw_req *cqr;
int nr_queued; int nr_queued, feature_ro;
queue = device->request_queue; queue = device->request_queue;
/* No queue ? Then there is nothing to do. */ /* No queue ? Then there is nothing to do. */
if (queue == NULL) if (queue == NULL)
return; return;
feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
if (feature_ro < 0) /* no devmap */
return;
/* /*
* We requeue request from the block device queue to the ccw * We requeue request from the block device queue to the ccw
* queue only in two states. In state DASD_STATE_READY the * queue only in two states. In state DASD_STATE_READY the
...@@ -1157,8 +1161,8 @@ __dasd_process_blk_queue(struct dasd_device * device) ...@@ -1157,8 +1161,8 @@ __dasd_process_blk_queue(struct dasd_device * device)
elv_next_request(queue) && elv_next_request(queue) &&
nr_queued < DASD_CHANQ_MAX_SIZE) { nr_queued < DASD_CHANQ_MAX_SIZE) {
req = elv_next_request(queue); req = elv_next_request(queue);
if (test_bit(DASD_FLAG_RO, &device->flags) &&
rq_data_dir(req) == WRITE) { if (feature_ro && rq_data_dir(req) == WRITE) {
DBF_DEV_EVENT(DBF_ERR, device, DBF_DEV_EVENT(DBF_ERR, device,
"Rejecting write request %p", "Rejecting write request %p",
req); req);
...@@ -1803,13 +1807,17 @@ dasd_generic_set_online (struct ccw_device *cdev, ...@@ -1803,13 +1807,17 @@ dasd_generic_set_online (struct ccw_device *cdev,
{ {
struct dasd_device *device; struct dasd_device *device;
int rc; int feature_diag, rc;
feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
if (feature_diag < 0)
return feature_diag;
device = dasd_create_device(cdev); device = dasd_create_device(cdev);
if (IS_ERR(device)) if (IS_ERR(device))
return PTR_ERR(device); return PTR_ERR(device);
if (test_bit(DASD_FLAG_USE_DIAG, &device->flags)) { if (feature_diag) {
if (!dasd_diag_discipline_pointer) { if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING printk (KERN_WARNING
"dasd_generic couldn't online device %s " "dasd_generic couldn't online device %s "
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* functions may not be called from interrupt context. In particular * functions may not be called from interrupt context. In particular
* dasd_get_device is a no-no from interrupt context. * dasd_get_device is a no-no from interrupt context.
* *
* $Revision: 1.37 $ * $Revision: 1.40 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -513,14 +513,6 @@ dasd_create_device(struct ccw_device *cdev) ...@@ -513,14 +513,6 @@ dasd_create_device(struct ccw_device *cdev)
if (!devmap->device) { if (!devmap->device) {
devmap->device = device; devmap->device = device;
device->devindex = devmap->devindex; device->devindex = devmap->devindex;
if (devmap->features & DASD_FEATURE_READONLY)
set_bit(DASD_FLAG_RO, &device->flags);
else
clear_bit(DASD_FLAG_RO, &device->flags);
if (devmap->features & DASD_FEATURE_USEDIAG)
set_bit(DASD_FLAG_USE_DIAG, &device->flags);
else
clear_bit(DASD_FLAG_USE_DIAG, &device->flags);
get_device(&cdev->dev); get_device(&cdev->dev);
device->cdev = cdev; device->cdev = cdev;
rc = 0; rc = 0;
...@@ -651,14 +643,8 @@ dasd_ro_store(struct device *dev, const char *buf, size_t count) ...@@ -651,14 +643,8 @@ dasd_ro_store(struct device *dev, const char *buf, size_t count)
devmap->features |= DASD_FEATURE_READONLY; devmap->features |= DASD_FEATURE_READONLY;
else else
devmap->features &= ~DASD_FEATURE_READONLY; devmap->features &= ~DASD_FEATURE_READONLY;
if (devmap->device) { if (devmap->device && devmap->device->gdp)
if (devmap->device->gdp) set_disk_ro(devmap->device->gdp, ro_flag);
set_disk_ro(devmap->device->gdp, ro_flag);
if (ro_flag)
set_bit(DASD_FLAG_RO, &devmap->device->flags);
else
clear_bit(DASD_FLAG_RO, &devmap->device->flags);
}
spin_unlock(&dasd_devmap_lock); spin_unlock(&dasd_devmap_lock);
return count; return count;
} }
...@@ -739,6 +725,45 @@ static struct attribute_group dasd_attr_group = { ...@@ -739,6 +725,45 @@ static struct attribute_group dasd_attr_group = {
.attrs = dasd_attrs, .attrs = dasd_attrs,
}; };
/*
* Return value of the specified feature.
*/
int
dasd_get_feature(struct ccw_device *cdev, int feature)
{
struct dasd_devmap *devmap;
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
return (int) PTR_ERR(devmap);
return ((devmap->features & feature) != 0);
}
/*
* Set / reset given feature.
* Flag indicates wether to set (!=0) or the reset (=0) the feature.
*/
int
dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
{
struct dasd_devmap *devmap;
devmap = dasd_find_busid(cdev->dev.bus_id);
if (IS_ERR(devmap))
return (int) PTR_ERR(devmap);
spin_lock(&dasd_devmap_lock);
if (flag)
devmap->features |= feature;
else
devmap->features &= ~feature;
spin_unlock(&dasd_devmap_lock);
return 0;
}
int int
dasd_add_sysfs_files(struct ccw_device *cdev) dasd_add_sysfs_files(struct ccw_device *cdev)
{ {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* gendisk related functions for the dasd driver. * gendisk related functions for the dasd driver.
* *
* $Revision: 1.48 $ * $Revision: 1.50 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -31,12 +31,16 @@ int ...@@ -31,12 +31,16 @@ int
dasd_gendisk_alloc(struct dasd_device *device) dasd_gendisk_alloc(struct dasd_device *device)
{ {
struct gendisk *gdp; struct gendisk *gdp;
int len; int len, feature_ro;
/* Make sure the minor for this device exists. */ /* Make sure the minor for this device exists. */
if (device->devindex >= DASD_PER_MAJOR) if (device->devindex >= DASD_PER_MAJOR)
return -EBUSY; return -EBUSY;
feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
if (feature_ro < 0)
return feature_ro;
gdp = alloc_disk(1 << DASD_PARTN_BITS); gdp = alloc_disk(1 << DASD_PARTN_BITS);
if (!gdp) if (!gdp)
return -ENOMEM; return -ENOMEM;
...@@ -71,7 +75,7 @@ dasd_gendisk_alloc(struct dasd_device *device) ...@@ -71,7 +75,7 @@ dasd_gendisk_alloc(struct dasd_device *device)
sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id); sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id);
if (test_bit(DASD_FLAG_RO, &device->flags)) if (feature_ro)
set_disk_ro(gdp, 1); set_disk_ro(gdp, 1);
gdp->private_data = device; gdp->private_data = device;
gdp->queue = device->request_queue; gdp->queue = device->request_queue;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
* *
* $Revision: 1.63 $ * $Revision: 1.64 $
*/ */
#ifndef DASD_INT_H #ifndef DASD_INT_H
...@@ -329,8 +329,6 @@ struct dasd_device { ...@@ -329,8 +329,6 @@ struct dasd_device {
#define DASD_STOPPED_DC_EIO 16 /* disconnected, return -EIO */ #define DASD_STOPPED_DC_EIO 16 /* disconnected, return -EIO */
/* per device flags */ /* per device flags */
#define DASD_FLAG_RO 0 /* device is read-only */
#define DASD_FLAG_USE_DIAG 1 /* use diag disciplnie */
#define DASD_FLAG_DSC_ERROR 2 /* return -EIO when disconnected */ #define DASD_FLAG_DSC_ERROR 2 /* return -EIO when disconnected */
#define DASD_FLAG_OFFLINE 3 /* device is in offline processing */ #define DASD_FLAG_OFFLINE 3 /* device is in offline processing */
...@@ -501,6 +499,9 @@ void dasd_devmap_exit(void); ...@@ -501,6 +499,9 @@ void dasd_devmap_exit(void);
struct dasd_device *dasd_create_device(struct ccw_device *); struct dasd_device *dasd_create_device(struct ccw_device *);
void dasd_delete_device(struct dasd_device *); void dasd_delete_device(struct dasd_device *);
int dasd_get_feature(struct ccw_device *, int);
int dasd_set_feature(struct ccw_device *, int, int);
int dasd_add_sysfs_files(struct ccw_device *); int dasd_add_sysfs_files(struct ccw_device *);
void dasd_remove_sysfs_files(struct ccw_device *); void dasd_remove_sysfs_files(struct ccw_device *);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* Bugreports.to..: <Linux390@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
* *
* $Revision: 1.45 $
*
* i/o controls for the dasd driver. * i/o controls for the dasd driver.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -294,6 +296,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) ...@@ -294,6 +296,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
{ {
struct dasd_device *device; struct dasd_device *device;
struct format_data_t fdata; struct format_data_t fdata;
int feature_ro;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
...@@ -304,7 +307,11 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) ...@@ -304,7 +307,11 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args)
if (device == NULL) if (device == NULL)
return -ENODEV; return -ENODEV;
if (test_bit(DASD_FLAG_RO, &device->flags))
feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
if (feature_ro < 0)
return feature_ro;
if (feature_ro)
return -EROFS; return -EROFS;
if (copy_from_user(&fdata, (void __user *) args, if (copy_from_user(&fdata, (void __user *) args,
sizeof (struct format_data_t))) sizeof (struct format_data_t)))
...@@ -377,7 +384,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) ...@@ -377,7 +384,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
struct dasd_device *device; struct dasd_device *device;
struct dasd_information2_t *dasd_info; struct dasd_information2_t *dasd_info;
unsigned long flags; unsigned long flags;
int rc; int rc, feature_ro;
struct ccw_device *cdev; struct ccw_device *cdev;
device = bdev->bd_disk->private_data; device = bdev->bd_disk->private_data;
...@@ -387,6 +394,10 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) ...@@ -387,6 +394,10 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
if (!device->discipline->fill_info) if (!device->discipline->fill_info)
return -EINVAL; return -EINVAL;
feature_ro = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
if (feature_ro < 0)
return feature_ro;
dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); dasd_info = kmalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
if (dasd_info == NULL) if (dasd_info == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -415,9 +426,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) ...@@ -415,9 +426,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
if ((device->state < DASD_STATE_READY) || if ((device->state < DASD_STATE_READY) ||
(dasd_check_blocksize(device->bp_block))) (dasd_check_blocksize(device->bp_block)))
dasd_info->format = DASD_FORMAT_NONE; dasd_info->format = DASD_FORMAT_NONE;
dasd_info->features |= test_bit(DASD_FLAG_RO, &device->flags) ? dasd_info->features |= feature_ro;
DASD_FEATURE_READONLY : DASD_FEATURE_DEFAULT;
if (device->discipline) if (device->discipline)
memcpy(dasd_info->type, device->discipline->name, 4); memcpy(dasd_info->type, device->discipline->name, 4);
...@@ -460,7 +470,7 @@ static int ...@@ -460,7 +470,7 @@ static int
dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
{ {
struct dasd_device *device; struct dasd_device *device;
int intval; int intval, rc;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EACCES; return -EACCES;
...@@ -472,12 +482,11 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) ...@@ -472,12 +482,11 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
device = bdev->bd_disk->private_data; device = bdev->bd_disk->private_data;
if (device == NULL) if (device == NULL)
return -ENODEV; return -ENODEV;
set_disk_ro(bdev->bd_disk, intval); set_disk_ro(bdev->bd_disk, intval);
if (intval) rc = dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval);
set_bit(DASD_FLAG_RO, &device->flags);
else return rc;
clear_bit(DASD_FLAG_RO, &device->flags);
return 0;
} }
/* /*
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* /proc interface for the dasd driver. * /proc interface for the dasd driver.
* *
* $Revision: 1.30 $ * $Revision: 1.31 $
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -54,6 +54,7 @@ dasd_devices_show(struct seq_file *m, void *v) ...@@ -54,6 +54,7 @@ dasd_devices_show(struct seq_file *m, void *v)
{ {
struct dasd_device *device; struct dasd_device *device;
char *substr; char *substr;
int feature;
device = dasd_device_from_devindex((unsigned long) v - 1); device = dasd_device_from_devindex((unsigned long) v - 1);
if (IS_ERR(device)) if (IS_ERR(device))
...@@ -77,7 +78,10 @@ dasd_devices_show(struct seq_file *m, void *v) ...@@ -77,7 +78,10 @@ dasd_devices_show(struct seq_file *m, void *v)
else else
seq_printf(m, " is ????????"); seq_printf(m, " is ????????");
/* Print devices features. */ /* Print devices features. */
substr = test_bit(DASD_FLAG_RO, &device->flags) ? "(ro)" : " "; feature = dasd_get_feature(device->cdev, DASD_FEATURE_READONLY);
if (feature < 0)
return 0;
substr = feature ? "(ro)" : " ";
seq_printf(m, "%4s: ", substr); seq_printf(m, "%4s: ", substr);
/* Print device status information. */ /* Print device status information. */
switch ((device != NULL) ? device->state : -1) { switch ((device != NULL) ? device->state : -1) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment