From f24acd4503270ed4c842c8fef0b71105285e0a06 Mon Sep 17 00:00:00 2001 From: Horst Hummel Date: Sun, 1 May 2005 08:58:59 -0700 Subject: [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: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 20 ++++++++++---- drivers/s390/block/dasd_devmap.c | 59 ++++++++++++++++++++++++++++------------ drivers/s390/block/dasd_genhd.c | 10 +++++-- drivers/s390/block/dasd_int.h | 7 +++-- drivers/s390/block/dasd_ioctl.c | 31 +++++++++++++-------- drivers/s390/block/dasd_proc.c | 8 ++++-- 6 files changed, 93 insertions(+), 42 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index b755bac6ccb..826fd238034 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.158 $ + * $Revision: 1.161 $ */ #include @@ -1131,13 +1131,17 @@ __dasd_process_blk_queue(struct dasd_device * device) request_queue_t *queue; struct request *req; struct dasd_ccw_req *cqr; - int nr_queued; + int nr_queued, feature_ro; queue = device->request_queue; /* No queue ? Then there is nothing to do. */ if (queue == NULL) 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 * queue only in two states. In state DASD_STATE_READY the @@ -1157,8 +1161,8 @@ __dasd_process_blk_queue(struct dasd_device * device) elv_next_request(queue) && nr_queued < DASD_CHANQ_MAX_SIZE) { 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, "Rejecting write request %p", req); @@ -1803,13 +1807,17 @@ dasd_generic_set_online (struct ccw_device *cdev, { 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); if (IS_ERR(device)) return PTR_ERR(device); - if (test_bit(DASD_FLAG_USE_DIAG, &device->flags)) { + if (feature_diag) { if (!dasd_diag_discipline_pointer) { printk (KERN_WARNING "dasd_generic couldn't online device %s " diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index ad1841a96c8..1aedc48e5f8 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -11,7 +11,7 @@ * functions may not be called from interrupt context. In particular * dasd_get_device is a no-no from interrupt context. * - * $Revision: 1.37 $ + * $Revision: 1.40 $ */ #include @@ -513,14 +513,6 @@ dasd_create_device(struct ccw_device *cdev) if (!devmap->device) { devmap->device = device; 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); device->cdev = cdev; rc = 0; @@ -651,14 +643,8 @@ dasd_ro_store(struct device *dev, const char *buf, size_t count) devmap->features |= DASD_FEATURE_READONLY; else devmap->features &= ~DASD_FEATURE_READONLY; - if (devmap->device) { - if (devmap->device->gdp) - 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); - } + if (devmap->device && devmap->device->gdp) + set_disk_ro(devmap->device->gdp, ro_flag); spin_unlock(&dasd_devmap_lock); return count; } @@ -739,6 +725,45 @@ static struct attribute_group dasd_attr_group = { .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 dasd_add_sysfs_files(struct ccw_device *cdev) { diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 1d52db406b2..96c49349701 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -9,7 +9,7 @@ * * gendisk related functions for the dasd driver. * - * $Revision: 1.48 $ + * $Revision: 1.50 $ */ #include @@ -31,12 +31,16 @@ int dasd_gendisk_alloc(struct dasd_device *device) { struct gendisk *gdp; - int len; + int len, feature_ro; /* Make sure the minor for this device exists. */ if (device->devindex >= DASD_PER_MAJOR) 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); if (!gdp) return -ENOMEM; @@ -71,7 +75,7 @@ dasd_gendisk_alloc(struct dasd_device *device) 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); gdp->private_data = device; gdp->queue = device->request_queue; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 4586e0ecc52..a9f38b23598 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.63 $ + * $Revision: 1.64 $ */ #ifndef DASD_INT_H @@ -329,8 +329,6 @@ struct dasd_device { #define DASD_STOPPED_DC_EIO 16 /* disconnected, return -EIO */ /* 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_OFFLINE 3 /* device is in offline processing */ @@ -501,6 +499,9 @@ void dasd_devmap_exit(void); struct dasd_device *dasd_create_device(struct ccw_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 *); void dasd_remove_sysfs_files(struct ccw_device *); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index f1892baa3b1..980c555aa53 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -7,6 +7,8 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * + * $Revision: 1.45 $ + * * i/o controls for the dasd driver. */ #include @@ -294,6 +296,7 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) { struct dasd_device *device; struct format_data_t fdata; + int feature_ro; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -304,7 +307,11 @@ dasd_ioctl_format(struct block_device *bdev, int no, long args) if (device == NULL) 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; if (copy_from_user(&fdata, (void __user *) args, sizeof (struct format_data_t))) @@ -377,7 +384,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) struct dasd_device *device; struct dasd_information2_t *dasd_info; unsigned long flags; - int rc; + int rc, feature_ro; struct ccw_device *cdev; device = bdev->bd_disk->private_data; @@ -387,6 +394,10 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) if (!device->discipline->fill_info) 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); if (dasd_info == NULL) return -ENOMEM; @@ -415,9 +426,8 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args) if ((device->state < DASD_STATE_READY) || (dasd_check_blocksize(device->bp_block))) dasd_info->format = DASD_FORMAT_NONE; - - dasd_info->features |= test_bit(DASD_FLAG_RO, &device->flags) ? - DASD_FEATURE_READONLY : DASD_FEATURE_DEFAULT; + + dasd_info->features |= feature_ro; if (device->discipline) memcpy(dasd_info->type, device->discipline->name, 4); @@ -460,7 +470,7 @@ static int dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) { struct dasd_device *device; - int intval; + int intval, rc; if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -472,12 +482,11 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) device = bdev->bd_disk->private_data; if (device == NULL) return -ENODEV; + set_disk_ro(bdev->bd_disk, intval); - if (intval) - set_bit(DASD_FLAG_RO, &device->flags); - else - clear_bit(DASD_FLAG_RO, &device->flags); - return 0; + rc = dasd_set_feature(device->cdev, DASD_FEATURE_READONLY, intval); + + return rc; } /* diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 353d41118c6..d7f19745911 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -9,7 +9,7 @@ * * /proc interface for the dasd driver. * - * $Revision: 1.30 $ + * $Revision: 1.31 $ */ #include @@ -54,6 +54,7 @@ dasd_devices_show(struct seq_file *m, void *v) { struct dasd_device *device; char *substr; + int feature; device = dasd_device_from_devindex((unsigned long) v - 1); if (IS_ERR(device)) @@ -77,7 +78,10 @@ dasd_devices_show(struct seq_file *m, void *v) else seq_printf(m, " is ????????"); /* 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); /* Print device status information. */ switch ((device != NULL) ? device->state : -1) { -- cgit v1.2.3-70-g09d2