diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-01-06 13:17:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-01-06 13:17:12 -0500 |
commit | 7b3d9545f9ac8b31528dd2d6d8ec8d19922917b8 (patch) | |
tree | e8af5ec41abf8ec3a678b5643de5580db417d16f /include/scsi | |
parent | 911833440b498e3e4fe2f12c1ae2bd44400c7004 (diff) |
Revert "scsi: revert "[SCSI] Get rid of scsi_cmnd->done""
This reverts commit ac40532ef0b8649e6f7f83859ea0de1c4ed08a19, which gets
us back the original cleanup of 6f5391c283d7fdcf24bf40786ea79061919d1e1d.
It turns out that the bug that was triggered by that commit was
apparently not actually triggered by that commit at all, and just the
testing conditions had changed enough to make it appear to be due to it.
The real problem seems to have been found by Peter Osterlund:
"pktcdvd sets it [block device size] when opening the /dev/pktcdvd
device, but when the drive is later opened as /dev/scd0, there is
nothing that sets it back. (Btw, 40944 is possible if the disk is a
CDRW that was formatted with "cdrwtool -m 10236".)
The problem is that pktcdvd opens the cd device in non-blocking mode
when pktsetup is run, and doesn't close it again until pktsetup -d is
run. The effect is that if you meanwhile open the cd device,
blkdev.c:do_open() doesn't call bd_set_size() because
bdev->bd_openers is non-zero."
In particular, to repeat the bug (regardless of whether commit
6f5391c283d7fdcf24bf40786ea79061919d1e1d is applied or not):
" 1. Start with an empty drive.
2. pktsetup 0 /dev/scd0
3. Insert a CD containing an isofs filesystem.
4. mount /dev/pktcdvd/0 /mnt/tmp
5. umount /mnt/tmp
6. Press the eject button.
7. Insert a DVD containing a non-writable filesystem.
8. mount /dev/scd0 /mnt/tmp
9. find /mnt/tmp -type f -print0 | xargs -0 sha1sum >/dev/null
10. If the DVD contains data beyond the physical size of a CD, you
get I/O errors in the terminal, and dmesg reports lots of
"attempt to access beyond end of device" errors."
which in turn is because the nested open after the media change won't
cause the size to be set properly (because the original open still holds
the block device, and we only do the bd_set_size() when we don't have
other people holding the device open).
The proper fix for that is probably to just do something like
bdev->bd_inode->i_size = (loff_t)get_capacity(disk)<<9;
in fs/block_dev.c:do_open() even for the cases where we're not the
original opener (but *not* call bd_set_size(), since that will also
change the block size of the device).
Cc: Peter Osterlund <petero2@telia.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/scsi')
-rw-r--r-- | include/scsi/scsi_cmnd.h | 2 | ||||
-rw-r--r-- | include/scsi/scsi_driver.h | 1 | ||||
-rw-r--r-- | include/scsi/sd.h | 13 |
3 files changed, 1 insertions, 15 deletions
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 7613c2989370..3f47e522a1ec 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h | |||
@@ -34,7 +34,6 @@ struct scsi_cmnd { | |||
34 | struct list_head list; /* scsi_cmnd participates in queue lists */ | 34 | struct list_head list; /* scsi_cmnd participates in queue lists */ |
35 | struct list_head eh_entry; /* entry for the host eh_cmd_q */ | 35 | struct list_head eh_entry; /* entry for the host eh_cmd_q */ |
36 | int eh_eflags; /* Used by error handlr */ | 36 | int eh_eflags; /* Used by error handlr */ |
37 | void (*done) (struct scsi_cmnd *); /* Mid-level done function */ | ||
38 | 37 | ||
39 | /* | 38 | /* |
40 | * A SCSI Command is assigned a nonzero serial_number before passed | 39 | * A SCSI Command is assigned a nonzero serial_number before passed |
@@ -122,7 +121,6 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); | |||
122 | extern void scsi_put_command(struct scsi_cmnd *); | 121 | extern void scsi_put_command(struct scsi_cmnd *); |
123 | extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, | 122 | extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, |
124 | struct device *); | 123 | struct device *); |
125 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); | ||
126 | extern void scsi_finish_command(struct scsi_cmnd *cmd); | 124 | extern void scsi_finish_command(struct scsi_cmnd *cmd); |
127 | extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); | 125 | extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); |
128 | 126 | ||
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 56a304709fde..1f5ca7f62116 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h | |||
@@ -15,6 +15,7 @@ struct scsi_driver { | |||
15 | struct device_driver gendrv; | 15 | struct device_driver gendrv; |
16 | 16 | ||
17 | void (*rescan)(struct device *); | 17 | void (*rescan)(struct device *); |
18 | int (*done)(struct scsi_cmnd *); | ||
18 | }; | 19 | }; |
19 | #define to_scsi_driver(drv) \ | 20 | #define to_scsi_driver(drv) \ |
20 | container_of((drv), struct scsi_driver, gendrv) | 21 | container_of((drv), struct scsi_driver, gendrv) |
diff --git a/include/scsi/sd.h b/include/scsi/sd.h index aa1e71613010..f7513313ef0d 100644 --- a/include/scsi/sd.h +++ b/include/scsi/sd.h | |||
@@ -47,19 +47,6 @@ struct scsi_disk { | |||
47 | }; | 47 | }; |
48 | #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) | 48 | #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) |
49 | 49 | ||
50 | static int sd_revalidate_disk(struct gendisk *disk); | ||
51 | static void sd_rw_intr(struct scsi_cmnd * SCpnt); | ||
52 | static int sd_probe(struct device *); | ||
53 | static int sd_remove(struct device *); | ||
54 | static void sd_shutdown(struct device *dev); | ||
55 | static int sd_suspend(struct device *dev, pm_message_t state); | ||
56 | static int sd_resume(struct device *dev); | ||
57 | static void sd_rescan(struct device *); | ||
58 | static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); | ||
59 | static void scsi_disk_release(struct class_device *cdev); | ||
60 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); | ||
61 | static void sd_print_result(struct scsi_disk *, int); | ||
62 | |||
63 | #define sd_printk(prefix, sdsk, fmt, a...) \ | 50 | #define sd_printk(prefix, sdsk, fmt, a...) \ |
64 | (sdsk)->disk ? \ | 51 | (sdsk)->disk ? \ |
65 | sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ | 52 | sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ |