mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] s390 update (8/9): dasd driver reference counting.
@ 2003-03-26 15:14 Martin Schwidefsky
  0 siblings, 0 replies; only message in thread
From: Martin Schwidefsky @ 2003-03-26 15:14 UTC (permalink / raw)
  To: linux-kernel, torvalds

* Improve reference counting.
* Remove devno from struct dasd_device.
* Remove unnecessary bdget/bdput calls.

diffstat:
 dasd.c        |  148 +++++++++++++++------------------------------
 dasd_devmap.c |  188 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 dasd_diag.c   |   10 +--
 dasd_genhd.c  |    9 --
 dasd_int.h    |   51 +++++++--------
 dasd_ioctl.c  |    2 
 dasd_proc.c   |   11 +--
 7 files changed, 244 insertions(+), 175 deletions(-)

diff -urN linux-2.5.66/drivers/s390/block/dasd.c linux-2.5.66-s390/drivers/s390/block/dasd.c
--- linux-2.5.66/drivers/s390/block/dasd.c	Wed Mar 26 15:45:19 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd.c	Wed Mar 26 15:45:19 2003
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.81 $
+ * $Revision: 1.82 $
  *
  * History of changes (starts July 2000)
  * 11/09/00 complete redesign after code review
@@ -101,7 +101,7 @@
  * Allocate memory for a new device structure.
  */
 dasd_device_t *
-dasd_alloc_device(dasd_devmap_t *devmap)
+dasd_alloc_device(unsigned int devindex)
 {
 	dasd_device_t *device;
 	struct gendisk *gdp;
@@ -111,8 +111,6 @@
 		return ERR_PTR(-ENOMEM);
 	memset(device, 0, sizeof (dasd_device_t));
 
-	device->devno = devmap->devno;
-
 	/* Get two pages for normal block device operations. */
 	device->ccw_mem = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 1);
 	if (device->ccw_mem == NULL) {
@@ -128,7 +126,7 @@
 	}
 
 	/* Allocate gendisk structure for device. */
-	gdp = dasd_gendisk_alloc(devmap->devindex);
+	gdp = dasd_gendisk_alloc(devindex);
 	if (IS_ERR(gdp)) {
 		free_page((unsigned long) device->erp_mem);
 		free_pages((unsigned long) device->ccw_mem, 1);
@@ -147,7 +145,7 @@
 		     (unsigned long) device);
 	INIT_LIST_HEAD(&device->ccw_queue);
 	init_timer(&device->timer);
-	INIT_WORK(&device->kick_work, do_kick_device, (void *) (addr_t) device->devno);
+	INIT_WORK(&device->kick_work, do_kick_device, device);
 	device->state = DASD_STATE_NEW;
 	device->target = DASD_STATE_NEW;
 
@@ -174,22 +172,19 @@
 static inline int
 dasd_state_new_to_known(dasd_device_t *device)
 {
-	dasd_devmap_t *devmap;
 	umode_t devfs_perm;
-	int major, minor;
+	kdev_t kdev;
 	char buf[20];
 
-	/* Increase reference count of bdev. */
-	if (bdget(MKDEV(device->gdp->major, device->gdp->first_minor)) == NULL)
+	kdev = dasd_get_kdev(device);
+	if (kdev_none(kdev))
 		return -ENODEV;
 
-	devmap = dasd_devmap_from_devno(device->devno);
-	if (devmap == NULL)
-		return -ENODEV;
-	major = dasd_gendisk_index_major(devmap->devindex);
-	if (major < 0)
-		return -ENODEV;
-	minor = devmap->devindex % DASD_PER_MAJOR;
+	/*
+	 * As long as the device is not in state DASD_STATE_NEW we want to 
+	 * keep the reference count > 0.
+	 */
+	dasd_get_device(device);
 
 #ifdef CONFIG_DEVFS_FS
 	/* Add a proc directory and the dasd device entry to devfs. */
@@ -201,9 +196,11 @@
 	else
 		devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR;
 
-	snprintf(buf, sizeof(buf), "dasd/%04x/device", device->devno);
+	snprintf(buf, sizeof(buf), "dasd/%04x/device",
+		 _ccw_device_get_device_number(device->cdev));
 	device->devfs_entry = devfs_register(NULL, buf, 0,
-					     major, minor << DASD_PARTN_BITS,
+					     major(kdev),
+					     minor(kdev) << DASD_PARTN_BITS,
 					     devfs_perm,
 					     &dasd_device_operations, NULL);
 	device->state = DASD_STATE_KNOWN;
@@ -216,8 +213,6 @@
 static inline void
 dasd_state_known_to_new(dasd_device_t * device)
 {
-	struct block_device *bdev;
-
 	/* Remove device entry and devfs directory. */
 	devfs_unregister(device->devfs_entry);
 	devfs_unregister(device->gdp->de);
@@ -226,10 +221,8 @@
 	device->discipline = NULL;
 	device->state = DASD_STATE_NEW;
 
-	/* Decrease reference count of bdev. */
-	bdev = bdget(MKDEV(device->gdp->major, device->gdp->first_minor));
-	bdput(bdev);
-	bdput(bdev);
+	/* Give up reference we took in dasd_state_new_to_known. */
+	dasd_put_device(device);
 }
 
 /*
@@ -429,7 +422,8 @@
         if (rc && rc != -EAGAIN) {
 		if (rc != -ENODEV)
 			MESSAGE (KERN_INFO, "giving up on dasd device with "
-				 "devno %04x", device->devno);
+				 "devno %04x",
+				 _ccw_device_get_device_number(device->cdev));
                 device->target = device->state;
         }
 
@@ -446,26 +440,18 @@
 static void
 do_kick_device(void *data)
 {
-	int devno;
-	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 
-	devno = (long) data;
-	devmap = dasd_devmap_from_devno(devno);
-	device = (devmap != NULL) ?
-		dasd_get_device(devmap) : ERR_PTR(-ENODEV);
-	if (IS_ERR(device))
-		return;
-	atomic_dec(&device->ref_count);
+	device = (dasd_device_t *) data;
 	dasd_change_state(device);
 	dasd_schedule_bh(device);
-	dasd_put_device(devmap);
+	dasd_put_device(device);
 }
 
 void
 dasd_kick_device(dasd_device_t *device)
 {
-	atomic_inc(&device->ref_count);
+	dasd_get_device(device);
 	/* queue call to dasd_kick_device to the kernel event daemon. */
 	schedule_work(&device->kick_work);
 }
@@ -647,7 +633,7 @@
 	}
 	strncpy((char *) &cqr->magic, magic, 4);
 	ASCEBC((char *) &cqr->magic, 4);
-	atomic_inc(&device->ref_count);
+	dasd_get_device(device);
 	return cqr;
 }
 
@@ -694,7 +680,7 @@
 	}
 	strncpy((char *) &cqr->magic, magic, 4);
 	ASCEBC((char *) &cqr->magic, 4);
-	atomic_inc(&device->ref_count);
+	dasd_get_device(device);
 	return cqr;
 }
 
@@ -724,7 +710,7 @@
 	if (cqr->data != NULL)
 		kfree(cqr->data);
 	kfree(cqr);
-	atomic_dec(&device->ref_count);
+	dasd_put_device(device);
 }
 
 void
@@ -739,7 +725,7 @@
 	spin_lock_irqsave(&device->mem_lock, flags);
 	dasd_free_chunk(&device->ccw_chunks, cqr);
 	spin_unlock_irqrestore(&device->mem_lock, flags);
-	atomic_dec(&device->ref_count);
+	dasd_put_device(device);
 }
 
 /*
@@ -937,19 +923,14 @@
 		struct work_struct work;
 		dasd_device_t *device;
 	} *p;
-	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 	dasd_ccw_req_t *cqr;
-	int devno;
 
 	p = data;
 	device = p->device;
 	DBF_EVENT(DBF_NOTICE, "State change Interrupt for bus_id %s",
 		  device->cdev->dev.bus_id);
 
-	// FIXME: get rid of devmap.
-	devno = _ccw_device_get_device_number(device->cdev);
-	devmap = dasd_devmap_from_devno(devno);
 	spin_lock_irq(get_ccwdev_lock(device->cdev));
 	/* re-activate first request in queue */
 	if (!list_empty(&device->ccw_queue)) {
@@ -966,7 +947,7 @@
 	}
 	spin_unlock_irq(get_ccwdev_lock(device->cdev));
 	dasd_schedule_bh(device);
-	dasd_put_device(devmap);
+	dasd_put_device(device);
 	kfree(p);
 }
 
@@ -1014,8 +995,7 @@
 		return;
 	INIT_WORK(&p->work, (void *) do_state_change_pending, p);
 	p->device = device;
-	atomic_inc(&device->ref_count);
-	/* queue call to do_state_change_pending to the kernel event daemon. */
+	dasd_get_device(device);
 	schedule_work(&p->work);
 }
 
@@ -1143,7 +1123,6 @@
 		BUG();
 	add_disk_randomness(req->rq_disk);
 	end_that_request_last(req);
-	return;
 }
 
 /*
@@ -1226,7 +1205,6 @@
 __dasd_process_blk_queue(dasd_device_t * device)
 {
 	request_queue_t *queue;
-	struct list_head *l;
 	struct request *req;
 	dasd_ccw_req_t *cqr;
 	int nr_queued;
@@ -1248,11 +1226,9 @@
 		return;
 	nr_queued = 0;
 	/* Now we try to fetch requests from the request queue */
-	list_for_each(l, &device->ccw_queue) {
-		cqr = list_entry(l, dasd_ccw_req_t, list);
+	list_for_each_entry(cqr, &device->ccw_queue, list)
 		if (cqr->status == DASD_CQR_QUEUED)
 			nr_queued++;
-	}
 	while (!blk_queue_plugged(queue) &&
 	       !blk_queue_empty(queue) &&
 		nr_queued < DASD_CHANQ_MAX_SIZE) {
@@ -1260,7 +1236,8 @@
 		if (device->ro_flag && rq_data_dir(req) == WRITE) {
 			DBF_EVENT(DBF_ERR,
 				  "(%04x) Rejecting write request %p",
-				  device->devno, req);
+				  _ccw_device_get_device_number(device->cdev),
+				  req);
 			blkdev_dequeue_request(req);
 			dasd_end_request(req, 0);
 			continue;
@@ -1271,7 +1248,8 @@
 				break;	/* terminate request queue loop */
 			DBF_EVENT(DBF_ERR,
 				  "(%04x) CCW creation failed on request %p",
-				  device->devno, req);
+				  _ccw_device_get_device_number(device->cdev),
+				  req);
 			blkdev_dequeue_request(req);
 			dasd_end_request(req, 0);
 			continue;
@@ -1408,8 +1386,7 @@
 	__dasd_start_head(device);
 	spin_unlock(get_ccwdev_lock(device->cdev));
 	spin_unlock_irq(&device->request_queue_lock);
-	/* FIXME: what if ref_count == 0 && state == DASD_STATE_NEW ?? */
-	atomic_dec(&device->ref_count);
+	dasd_put_device(device);
 }
 
 /*
@@ -1421,7 +1398,7 @@
 	/* Protect against rescheduling. */
 	if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled))
 		return;
-	atomic_inc(&device->ref_count);
+	dasd_get_device(device);
 	tasklet_hi_schedule(&device->tasklet);
 }
 
@@ -1803,8 +1780,8 @@
 	return 0;
 }
 
-struct
-block_device_operations dasd_device_operations = {
+struct block_device_operations
+dasd_device_operations = {
 	.owner		= THIS_MODULE,
 	.open		= dasd_open,
 	.release	= dasd_release,
@@ -1885,30 +1862,12 @@
 			 dasd_discipline_t *discipline)
 
 {
-	int devno;
-	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 	int rc;
 
-	if (cdev->dev.driver_data != NULL) /* already enabled */
-		return 0;
-
-	devno = _ccw_device_get_device_number(cdev);
-	rc = dasd_add_range(devno, devno, DASD_FEATURE_DEFAULT);
-	if (rc)
-		return rc;
-
-	if (!(devmap = dasd_devmap_from_devno (devno)))
-		return 0; /* device is still disabled -> ignore it */
-
-	if (IS_ERR(device = dasd_get_device(devmap))) {
-		printk (KERN_WARNING "dasd_generic could not get %s\n",
-				cdev->dev.bus_id);
+	device = dasd_create_device(cdev);
+	if (IS_ERR(device))
 		return PTR_ERR(device);
-	}
-
-	device->gdp->driverfs_dev = &cdev->dev;
-	device->cdev = cdev;
 
 	if (device->use_diag_flag)
 		device->discipline = dasd_diag_discipline_pointer;
@@ -1929,7 +1888,7 @@
 	if (rc) {
 		printk (KERN_WARNING "dasd_generic found a bad device %s\n", 
 			cdev->dev.bus_id);
-		dasd_put_device(devmap);
+		dasd_delete_device(device);
 		return rc;
 	}
 
@@ -1940,16 +1899,17 @@
 			cdev->dev.bus_id);
 		rc = -ENODEV;
 		dasd_set_target_state(device, DASD_STATE_NEW);
+		dasd_delete_device(device);
 	} else {
 		pr_debug("dasd_generic device %s found\n",
 				cdev->dev.bus_id);
 		cdev->dev.driver_data = device;
 	}
 
-	dasd_put_device(devmap);
 	/* FIXME: we have to wait for the root device but we don't want
 	 * to wait for each single device but for all at once. */
 	wait_event(dasd_init_waitq, _wait_for_device(device));
+
 	return rc;
 }
 
@@ -1957,21 +1917,16 @@
 dasd_generic_set_offline (struct ccw_device *cdev)
 {
 	dasd_device_t *device;
-	dasd_devmap_t *devmap;
-	int devno;
 
-	devno = _ccw_device_get_device_number(cdev);
 	device = cdev->dev.driver_data;
-	devmap = dasd_devmap_from_devno(devno);
-	if (device == NULL || devmap == NULL)
-		return -ENODEV;
-
-	device = dasd_get_device(devmap);
-	if (IS_ERR(device))
-		return PTR_ERR(device);
-
+	if (atomic_read(&device->open_count) > 0) {
+		printk (KERN_WARNING "Can't offline dasd device with open"
+			" count = %i.\n",
+			atomic_read(&device->open_count));
+		return -EBUSY;
+	}
 	dasd_set_target_state(device, DASD_STATE_NEW);
-	dasd_put_device(devmap);
+	dasd_delete_device(device);
 	
 	return 0;
 }
@@ -1999,8 +1954,7 @@
 			continue;
 		cdev = to_ccwdev(dev);
 		devno = _ccw_device_get_device_number(cdev);
-		if (dasd_autodetect ||
-		    dasd_devmap_from_devno(devno) != 0)
+		if (dasd_autodetect || dasd_devno_in_range(devno) == 0)
 			ccw_device_set_online(cdev);
 		put_device(dev);
 	}
diff -urN linux-2.5.66/drivers/s390/block/dasd_devmap.c linux-2.5.66-s390/drivers/s390/block/dasd_devmap.c
--- linux-2.5.66/drivers/s390/block/dasd_devmap.c	Mon Mar 24 23:00:40 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd_devmap.c	Wed Mar 26 15:45:19 2003
@@ -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.11 $
+ * $Revision: 1.12 $
  *
  * History of changes 
  * 05/04/02 split from dasd.c, code restructuring.
@@ -31,6 +31,25 @@
 #include "dasd_int.h"
 
 /*
+ * dasd_devmap_t is used to store the features and the relation
+ * between device number and device index. To find a dasd_devmap_t
+ * that corresponds to a device number of a device index each
+ * dasd_devmap_t is added to two linked lists, one to search by
+ * the device number and one to search by the device index. As
+ * soon as big minor numbers are available the device index list
+ * can be removed since the device number will then be identical
+ * to the device index.
+ */
+typedef struct {
+	struct list_head devindex_list;
+	struct list_head devno_list;
+        unsigned int devindex;
+        unsigned short devno;
+        unsigned short features;
+	dasd_device_t *device;
+} dasd_devmap_t;
+
+/*
  * Parameter parsing functions for dasd= parameter. The syntax is:
  *   <devno>		: (0x)?[0-9a-fA-F]+
  *   <feature>		: ro
@@ -279,6 +298,29 @@
 }
 
 /*
+ * Check if devno has been added to the list of dasd ranges.
+ */
+int
+dasd_devno_in_range(int devno)
+{
+	struct list_head *l;
+	int ret;
+		
+	ret = -ENOENT;
+	spin_lock(&dasd_devmap_lock);
+	/* Find devmap for device with device number devno */
+	list_for_each(l, &dasd_devno_hashlists[devno&255]) {
+		if (list_entry(l, dasd_devmap_t, devno_list)->devno == devno) {
+			/* Found the device. */
+			ret = 0;
+			break;
+		}
+	}
+	spin_unlock(&dasd_devmap_lock);
+	return ret;
+}
+
+/*
  * Forget all about the device numbers added so far.
  * This may only be called at module unload or system shutdown.
  */
@@ -307,7 +349,7 @@
  * Find the devmap structure from a devno. Can be removed as soon
  * as big minors are available.
  */
-dasd_devmap_t *
+static dasd_devmap_t *
 dasd_devmap_from_devno(int devno)
 {
 	struct list_head *l;
@@ -332,7 +374,7 @@
  * Find the devmap for a device by its device index. Can be removed
  * as soon as big minors are available.
  */
-dasd_devmap_t *
+static dasd_devmap_t *
 dasd_devmap_from_devindex(int devindex)
 {
 	struct list_head *l;
@@ -353,60 +395,140 @@
 	return devmap;
 }
 
-/*
- * Find the device structure for device number devno. If it does not
- * exists yet, allocate it. Increase the reference counter in the device
- * structure and return a pointer to it.
- */
 dasd_device_t *
-dasd_get_device(dasd_devmap_t *devmap)
+dasd_device_from_devindex(int devindex)
 {
+	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 
+	devmap = dasd_devmap_from_devindex(devindex);
 	spin_lock(&dasd_devmap_lock);
 	device = devmap->device;
-	if (device != NULL)
-		atomic_inc(&device->ref_count);
+	if (device)
+		dasd_get_device(device);
+	else
+		device = ERR_PTR(-ENODEV);
 	spin_unlock(&dasd_devmap_lock);
-	if (device != NULL)
-		return device;
+	return device;
+}
 
-	device = dasd_alloc_device(devmap);
+/*
+ * Return kdev for a dasd device.
+ */
+kdev_t
+dasd_get_kdev(dasd_device_t *device)
+{
+	dasd_devmap_t *devmap;
+	int major, minor;
+	int devno;
+
+	devno = _ccw_device_get_device_number(device->cdev);
+	devmap = dasd_devmap_from_devno(devno);
+	if (devmap == NULL)
+		return NODEV;
+	major = dasd_gendisk_index_major(devmap->devindex);
+	if (major < 0)
+		return NODEV;
+	minor = devmap->devindex % DASD_PER_MAJOR;
+	return mk_kdev(major, minor);
+}
+
+/*
+ * Create a dasd device structure for cdev.
+ */
+dasd_device_t *
+dasd_create_device(struct ccw_device *cdev)
+{
+	dasd_devmap_t *devmap;
+	dasd_device_t *device;
+	int devno;
+	int rc;
+
+	devno = _ccw_device_get_device_number(cdev);
+	rc = dasd_add_range(devno, devno, DASD_FEATURE_DEFAULT);
+	if (rc)
+		return ERR_PTR(rc);
+
+	if (!(devmap = dasd_devmap_from_devno (devno)))
+		return ERR_PTR(-ENODEV);
+
+	device = dasd_alloc_device(devmap->devindex);
 	if (IS_ERR(device))
 		return device;
+	atomic_set(&device->ref_count, 1);
+	device->ro_flag = (devmap->features & DASD_FEATURE_READONLY) ? 1 : 0;
+	device->use_diag_flag = 1;
 
-	spin_lock(&dasd_devmap_lock);
-	if (devmap->device != NULL) {
+	spin_lock_irq(get_ccwdev_lock(cdev));
+	if (cdev->dev.driver_data == NULL) {
+		get_device(&cdev->dev);
+		cdev->dev.driver_data = device;
+		device->gdp->driverfs_dev = &cdev->dev;
+		device->cdev = cdev;
+		rc = 0;
+	} else
 		/* Someone else was faster. */
+		rc = -EBUSY;
+	spin_unlock_irq(get_ccwdev_lock(cdev));
+	if (rc) {
 		dasd_free_device(device);
-		device = devmap->device;
-	} else
-		devmap->device = device;
-	atomic_inc(&device->ref_count);
-	device->ro_flag = (devmap->features & DASD_FEATURE_READONLY) ? 1 : 0;
-	device->use_diag_flag = 1;
+		return ERR_PTR(rc);
+	}
+	/* Device created successfully. Make it known via devmap. */
+	spin_lock(&dasd_devmap_lock);
+	devmap->device = device;
 	spin_unlock(&dasd_devmap_lock);
+
 	return device;
 }
 
 /*
- * Decrease the reference counter of a devices structure. If the
- * reference counter reaches zero and the device status is
- * DASD_STATE_NEW the device structure is freed. 
+ * Wait queue for dasd_delete_device waits.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
+
+/*
+ * Remove a dasd device structure.
  */
 void
-dasd_put_device(dasd_devmap_t *devmap)
+dasd_delete_device(dasd_device_t *device)
 {
-	dasd_device_t *device;
+	struct ccw_device *cdev;
+	dasd_devmap_t *devmap;
+	int devno;
 
+	/* First remove device pointer from devmap. */
+	devno = _ccw_device_get_device_number(device->cdev);
+	devmap = dasd_devmap_from_devno (devno);
 	spin_lock(&dasd_devmap_lock);
-	device = devmap->device;
-	if (atomic_dec_return(&device->ref_count) == 0 &&
-	    device->state == DASD_STATE_NEW) {
-		devmap->device = NULL;
-		dasd_free_device(device);
-	}
+	devmap->device = NULL;
 	spin_unlock(&dasd_devmap_lock);
+
+	/* Wait for reference counter to drop to zero. */
+	atomic_dec(&device->ref_count);
+	wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
+
+	/* Disconnect dasd_device structure from ccw_device structure. */
+	cdev = device->cdev;
+	device->cdev = NULL;
+	device->gdp->driverfs_dev = NULL;
+	cdev->dev.driver_data = NULL;
+
+	/* Put ccw_device structure. */
+	put_device(&cdev->dev);
+
+	/* Now the device structure can be freed. */
+	dasd_free_device(device);
+}
+
+/*
+ * Reference counter dropped to zero. Wake up waiter
+ * in dasd_delete_device.
+ */
+void
+dasd_put_device_wake(dasd_device_t *device)
+{
+	wake_up(&dasd_delete_wq);
 }
 
 int
diff -urN linux-2.5.66/drivers/s390/block/dasd_diag.c linux-2.5.66-s390/drivers/s390/block/dasd_diag.c
--- linux-2.5.66/drivers/s390/block/dasd_diag.c	Mon Mar 24 22:59:54 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd_diag.c	Wed Mar 26 15:45:19 2003
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.27 $
+ * $Revision: 1.28 $
  *
  * History of changes
  * 07/13/00 Added fixup sections for diagnoses ans saved some registers
@@ -96,7 +96,7 @@
 	iib = &private->iib;
 	memset(iib, 0, sizeof (diag_init_io_t));
 
-	iib->dev_nr = device->devno;
+	iib->dev_nr = _ccw_device_get_device_number(device->cdev);
 	iib->block_size = blocksize;
 	iib->offset = offset;
 	iib->start_block = 0;
@@ -117,7 +117,7 @@
 	private = (dasd_diag_private_t *) device->private;
 	iib = &private->iib;
 	memset(iib, 0, sizeof (diag_init_io_t));
-	iib->dev_nr = device->devno;
+	iib->dev_nr = _ccw_device_get_device_number(device->cdev);
 	rc = dia250(iib, TERM_BIO);
 	return rc & 3;
 }
@@ -134,7 +134,7 @@
 	private = (dasd_diag_private_t *) device->private;
 	dreq = (dasd_diag_req_t *) cqr->data;
 
-	private->iob.dev_nr = device->devno;
+	private->iob.dev_nr = _ccw_device_get_device_number(device->cdev);
 	private->iob.key = 0;
 	private->iob.flags = 2;	/* do asynchronous io */
 	private->iob.block_count = dreq->block_count;
@@ -252,7 +252,7 @@
 	}
 	/* Read Device Characteristics */
 	rdc_data = (void *) &(private->rdc_data);
-	rdc_data->dev_nr = device->devno;
+	rdc_data->dev_nr = _ccw_device_get_device_number(device->cdev);
 	rdc_data->rdc_len = sizeof (dasd_diag_characteristics_t);
 
 	rc = diag210((struct diag210 *) rdc_data);
diff -urN linux-2.5.66/drivers/s390/block/dasd_genhd.c linux-2.5.66-s390/drivers/s390/block/dasd_genhd.c
--- linux-2.5.66/drivers/s390/block/dasd_genhd.c	Wed Mar 26 15:45:19 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd_genhd.c	Wed Mar 26 15:45:19 2003
@@ -108,7 +108,6 @@
 struct gendisk *
 dasd_gendisk_alloc(int devindex)
 {
-	struct list_head *l;
 	struct major_info *mi;
 	struct gendisk *gdp;
 	int index, len, rc;
@@ -118,8 +117,7 @@
 	while (1) {
 		spin_lock(&dasd_major_lock);
 		index = devindex;
-		list_for_each(l, &dasd_major_info) {
-			mi = list_entry(l, struct major_info, list);
+		list_for_each_entry(mi, &dasd_major_info, list) {
 			if (index < DASD_PER_MAJOR)
 				break;
 			index -= DASD_PER_MAJOR;
@@ -192,14 +190,12 @@
  */
 int dasd_gendisk_index_major(int devindex)
 {
-	struct list_head *l;
 	struct major_info *mi;
 	int rc;
 
 	spin_lock(&dasd_major_lock);
 	rc = -ENODEV;
-	list_for_each(l, &dasd_major_info) {
-		mi = list_entry(l, struct major_info, list);
+	list_for_each_entry(mi, &dasd_major_info, list) {
 		if (devindex < DASD_PER_MAJOR) {
 			rc = mi->major;
 			break;
@@ -232,6 +228,7 @@
 dasd_destroy_partitions(dasd_device_t * device)
 {
 	del_gendisk(device->gdp);
+	put_disk(device->gdp);
 }
 
 int
diff -urN linux-2.5.66/drivers/s390/block/dasd_int.h linux-2.5.66-s390/drivers/s390/block/dasd_int.h
--- linux-2.5.66/drivers/s390/block/dasd_int.h	Wed Mar 26 15:45:19 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd_int.h	Wed Mar 26 15:45:19 2003
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.37 $
+ * $Revision: 1.38 $
  *
  * History of changes (starts July 2000)
  * 02/01/01 added dynamic registration of ioctls
@@ -297,10 +297,6 @@
 	struct list_head ccw_chunks;
 	struct list_head erp_chunks;
 
-	/* Common i/o stuff. */
-	/* FIXME: remove the next */
-	int devno;
-
 	atomic_t tasklet_scheduled;
         struct tasklet_struct tasklet;
 	struct work_struct kick_work;
@@ -315,24 +311,23 @@
 #endif
 } dasd_device_t;
 
+void dasd_put_device_wake(dasd_device_t *);
+
 /*
- * dasd_devmap_t is used to store the features and the relation
- * between device number and device index. To find a dasd_devmap_t
- * that corresponds to a device number of a device index each
- * dasd_devmap_t is added to two linked lists, one to search by
- * the device number and one to search by the device index. As
- * soon as big minor numbers are available the device index list
- * can be removed since the device number will then be identical
- * to the device index.
+ * Reference count inliners
  */
-typedef struct {
-	struct list_head devindex_list;
-	struct list_head devno_list;
-        unsigned int devindex;
-        unsigned short devno;
-        unsigned short features;
-        dasd_device_t *device;
-} dasd_devmap_t;
+static inline void
+dasd_get_device(dasd_device_t *device)
+{
+	atomic_inc(&device->ref_count);
+}
+
+static inline void
+dasd_put_device(dasd_device_t *device)
+{
+	if (atomic_dec_return(&device->ref_count) == 0)
+		dasd_put_device_wake(device);
+}
 
 /*
  * The static memory in ccw_mem and erp_mem is managed by a sorted
@@ -444,8 +439,9 @@
 	return set_normalized_cda(ccw, cda);
 }
 
-dasd_device_t *dasd_alloc_device(dasd_devmap_t *);
+dasd_device_t *dasd_alloc_device(unsigned int devindex);
 void dasd_free_device(dasd_device_t *);
+
 void dasd_enable_device(dasd_device_t *);
 void dasd_set_target_state(dasd_device_t *, int);
 void dasd_kick_device(dasd_device_t *);
@@ -476,13 +472,16 @@
 
 int dasd_devmap_init(void);
 void dasd_devmap_exit(void);
-dasd_devmap_t *dasd_devmap_from_devno(int);
-dasd_devmap_t *dasd_devmap_from_devindex(int);
-dasd_device_t *dasd_get_device(dasd_devmap_t *);
-void dasd_put_device(dasd_devmap_t *);
+
+dasd_device_t *dasd_create_device(struct ccw_device *);
+void dasd_delete_device(dasd_device_t *);
+
+kdev_t dasd_get_kdev(dasd_device_t *);
+dasd_device_t *dasd_device_from_devindex(int);
 
 int dasd_parse(void);
 int dasd_add_range(int, int, int);
+int dasd_devno_in_range(int);
 
 /* externals in dasd_gendisk.c */
 int  dasd_gendisk_init(void);
diff -urN linux-2.5.66/drivers/s390/block/dasd_ioctl.c linux-2.5.66-s390/drivers/s390/block/dasd_ioctl.c
--- linux-2.5.66/drivers/s390/block/dasd_ioctl.c	Mon Mar 24 23:00:48 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd_ioctl.c	Wed Mar 26 15:45:19 2003
@@ -333,7 +333,7 @@
 
 	cdev = device->cdev;
 
-	dasd_info->devno = device->devno;
+	dasd_info->devno = _ccw_device_get_device_number(device->cdev);
 	dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev);
 	dasd_info->cu_type = cdev->id.cu_type;
 	dasd_info->cu_model = cdev->id.cu_model;
diff -urN linux-2.5.66/drivers/s390/block/dasd_proc.c linux-2.5.66-s390/drivers/s390/block/dasd_proc.c
--- linux-2.5.66/drivers/s390/block/dasd_proc.c	Mon Mar 24 23:00:09 2003
+++ linux-2.5.66-s390/drivers/s390/block/dasd_proc.c	Wed Mar 26 15:45:19 2003
@@ -9,7 +9,7 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.17 $
+ * $Revision: 1.18 $
  *
  * History of changes
  * 05/04/02 split from dasd.c, code restructuring.
@@ -56,17 +56,14 @@
 static int
 dasd_devices_show(struct seq_file *m, void *v)
 {
-	dasd_devmap_t *devmap;
 	dasd_device_t *device;
 	char *substr;
 
-	devmap = dasd_devmap_from_devindex((unsigned long) v - 1);
-	device = (devmap != NULL) ?
-		dasd_get_device(devmap) : ERR_PTR(-ENODEV);
+	device = dasd_device_from_devindex((unsigned long) v - 1);
 	if (IS_ERR(device))
 		return 0;
 	/* Print device number. */
-	seq_printf(m, "%04x", devmap->devno);
+	seq_printf(m, "%04x", _ccw_device_get_device_number(device->cdev));
 	/* Print discipline string. */
 	if (device != NULL && device->discipline != NULL)
 		seq_printf(m, "(%s)", device->discipline->name);
@@ -113,7 +110,7 @@
 		seq_printf(m, "no stat");
 		break;
 	}
-	dasd_put_device(devmap);
+	dasd_put_device(device);
 	if (dasd_probeonly)
 		seq_printf(m, "(probeonly)");
 	seq_printf(m, "\n");


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-03-26 15:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-26 15:14 [PATCH] s390 update (8/9): dasd driver reference counting Martin Schwidefsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®