linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] fix kernel oops, when IDE-Device (CF-Card) is removed while mounted.
@ 2005-09-06 18:54 Thomas Kleffel
  2005-09-12 14:43 ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Kleffel @ 2005-09-06 18:54 UTC (permalink / raw)
  To: B.Zolnierkiewicz; +Cc: linux-kernel, linux-ide

Hello,

when I physically remove a CF-Card while it is still mounted and 
accessed, the result is a kernel oops. I traced the problem down to the 
following situation:

1) Physical device is removed and the corresponding ide_trive_t gets 
deleted, reference to the contained *queue is given back and queue gets 
deleted.

2) struct block_device still exists, because the device is still 
mounted, and points to a struct gendisk, which contains the - now 
invalid - pointer to the queue that was destructed earlier.

3) As soon as a request is sent to the block device, the queue pointer 
is used and the kernel oopses.

To fix this matter, I've made the following changes:

1a) When a queue is attached to a struct gendisk by ide_disk_probe(), 
its reference counter shall be incremented by a blk_get_queue()-call.

1b) When a disk is released by disk_release(), its queue's reference 
count shall be decremented by calling blk_cleanup_queue().

2a) When a physical drive is released by drive_release_dev(), the 
corresponding queue is marked dead, so that no further calls to the 
physical device's queue-handler are made.

2b) When a request is submitted to a dead queue using 
generic_make_request(), the request shall be failed immedaiately with 
-ENXIO which causes the caller to recive a "Bus error". This is the same 
beaviour as when a USB-Storage device gets pulled while in use.


diff -uprN -X b/Documentation/dontdiff a/drivers/block/genhd.c 
b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	2005-08-08 15:30:13.000000000 +0200
+++ b/drivers/block/genhd.c	2005-09-05 02:07:46.000000000 +0200
@@ -415,6 +415,9 @@ static struct attribute * default_attrs[
  static void disk_release(struct kobject * kobj)
  {
  	struct gendisk *disk = to_disk(kobj);
+	
+	blk_cleanup_queue(disk->queue);
+	
  	kfree(disk->random);
  	kfree(disk->part);
  	free_disk_stats(disk);
diff -uprN -X b/Documentation/dontdiff a/drivers/block/ll_rw_blk.c 
b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2005-08-13 15:54:15.000000000 +0200
+++ b/drivers/block/ll_rw_blk.c	2005-09-05 02:08:35.000000000 +0200
@@ -2877,15 +2877,26 @@ end_io:
  		}

  		if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) {
-			printk("bio too big device %s (%u > %u)\n",
+			printk(KERN_ERR
+				"generic_make_request: "
+				"bio too big device %s (%u > %u)\n",
  				bdevname(bio->bi_bdev, b),
  				bio_sectors(bio),
  				q->max_hw_sectors);
  			goto end_io;
  		}

-		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-			goto end_io;
+		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+			printk(KERN_ERR
+				"generic_make_request: access to "
+				"dead device %s (%Lu)\n",
+				bdevname(bio->bi_bdev, b),
+				(long long) bio->bi_sector);
+			bio_endio(bio, bio->bi_size, -ENXIO);
+			break;
+		}

  		block_wait_queue_running(q);

diff -uprN -X b/Documentation/dontdiff a/drivers/ide/ide-disk.c 
b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	2005-08-24 17:58:02.000000000 +0200
+++ b/drivers/ide/ide-disk.c	2005-09-05 02:10:30.000000000 +0200
@@ -1224,6 +1221,9 @@ static int ide_disk_probe(struct device
  	if (!g)
  		goto out_free_idkp;

+	if(0 != blk_get_queue(drive->queue))
+		goto out_free_idkp;
+
  	ide_init_disk(g, drive);

  	ide_register_subdriver(drive, &idedisk_driver);
diff -uprN -X b/Documentation/dontdiff a/drivers/ide/ide-probe.c 
b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	2005-08-24 17:58:02.000000000 +0200
+++ b/drivers/ide/ide-probe.c	2005-09-05 02:10:59.000000000 +0200
@@ -1321,6 +1321,13 @@ static void drive_release_dev (struct de
  		drive->id = NULL;
  	}
  	drive->present = 0;
+
+	/* Set the queue dead, so it won't call us anymore */
+	set_bit(QUEUE_FLAG_DEAD, &drive->queue->queue_flags);
+
+	/* remove pointer to ide drive as it will be gone, soon */
+	drive->queue->queuedata = NULL;
+
  	/* Messed up locking ... */
  	spin_unlock_irq(&ide_lock);
  	blk_cleanup_queue(drive->queue);


Signed-off-by: Thomas Kleffel <tk@maintech.de>

Best regards,
Thomas

^ permalink raw reply	[flat|nested] 5+ messages in thread
* Re: [PATCH] fix kernel oops, when IDE-Device (CF-Card) is removed while mounted.
@ 2005-09-14  7:02 Chuck Ebbert
  0 siblings, 0 replies; 5+ messages in thread
From: Chuck Ebbert @ 2005-09-14  7:02 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz; +Cc: Thomas Kleffel, linux-ide, linux-kernel

In-Reply-To: <58cb370e050913013677fec525@mail.gmail.com>

On Tue, 13 Sep 2005 at 10:36:42 +0200, Bartlomiej Zolnierkiewicz wrote:

> >  From your responses I read that the correct solution would be to keep
> > the old pysical device as long as the ide layer still has references to
> > it and to fail all requests in the meantime.
> > 
> > Is that correct?
> 
> Yes, we should just fail all the requests if the device is not present.
> [ What do you mean by the old physical device, old 'ide_drive_t *'? ]

 Jens Axboe posted this patch for the same problem on 2 Aug:

===========================================================================
=====
That's not quite true, q is not invalid after this call. It will only be
invalid when it is freed (which doesn't happen from here but rather from
the blk_cleanup_queue() call when the reference count drops to 0).

This is still not perfect, but a lot better. Does it work for you?

--- linux-2.6.12/drivers/ide/ide-disk.c~        2005-08-02
12:48:16.000000000 +0200
+++ linux-2.6.12/drivers/ide/ide-disk.c 2005-08-02 12:48:32.000000000 +0200
@@ -1054,6 +1054,7 @@
        drive->driver_data = NULL;
        drive->devfs_name[0] = '\0';
        g->private_data = NULL;
+       g->disk = NULL;
        put_disk(g);
        kfree(idkp);
 }
__
Chuck

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-09-14  7:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-06 18:54 [PATCH] fix kernel oops, when IDE-Device (CF-Card) is removed while mounted Thomas Kleffel
2005-09-12 14:43 ` Bartlomiej Zolnierkiewicz
2005-09-12 18:09   ` Thomas Kleffel
2005-09-13  8:36     ` Bartlomiej Zolnierkiewicz
  -- strict thread matches above, loose matches on Subject: below --
2005-09-14  7:02 Chuck Ebbert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).