Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+14 −6
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	       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,


{
{
	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 "
+42 −17
Original line number Original line Diff line number Diff line
@@ -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)
	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)
		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 = {
	.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)
{
{
+7 −3
Original line number Original line Diff line number Diff line
@@ -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
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)


 	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;
+4 −3
Original line number Original line Diff line number Diff line
@@ -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 {
#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);
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 *);


+20 −11
Original line number Original line Diff line number Diff line
@@ -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)
{
{
	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)


	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)
	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)
	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;
@@ -416,8 +427,7 @@ dasd_ioctl_information(struct block_device *bdev, int no, long args)
	    (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
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)
	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;
}
}


/*
/*
Loading