• Linus Torvalds's avatar
    Revert "scsi: revert "[SCSI] Get rid of scsi_cmnd->done"" · 7b3d9545
    Linus Torvalds authored
    This reverts commit ac40532e, which gets
    us back the original cleanup of 6f5391c2.
    
    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
    6f5391c2 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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    7b3d9545
scsi_priv.h 4.65 KB