diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:22:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:22:42 -0400 |
commit | 2f9e825d3e0e2b407ae8f082de5c00afcf7378fb (patch) | |
tree | f8b3ee40674ce4acd5508a0a0bf52a30904caf6c /drivers/scsi/sd.c | |
parent | 7ae0dea900b027cd90e8a3e14deca9a19e17638b (diff) | |
parent | de75d60d5ea235e6e09f4962ab22541ce0fe176a (diff) |
Merge branch 'for-2.6.36' of git://git.kernel.dk/linux-2.6-block
* 'for-2.6.36' of git://git.kernel.dk/linux-2.6-block: (149 commits)
block: make sure that REQ_* types are seen even with CONFIG_BLOCK=n
xen-blkfront: fix missing out label
blkdev: fix blkdev_issue_zeroout return value
block: update request stacking methods to support discards
block: fix missing export of blk_types.h
writeback: fix bad _bh spinlock nesting
drbd: revert "delay probes", feature is being re-implemented differently
drbd: Initialize all members of sync_conf to their defaults [Bugz 315]
drbd: Disable delay probes for the upcomming release
writeback: cleanup bdi_register
writeback: add new tracepoints
writeback: remove unnecessary init_timer call
writeback: optimize periodic bdi thread wakeups
writeback: prevent unnecessary bdi threads wakeups
writeback: move bdi threads exiting logic to the forker thread
writeback: restructure bdi forker loop a little
writeback: move last_active to bdi
writeback: do not remove bdi from bdi_list
writeback: simplify bdi code a little
writeback: do not lose wake-ups in bdi threads
...
Fixed up pretty trivial conflicts in drivers/block/virtio_blk.c and
drivers/scsi/scsi_error.c as per Jens.
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cc8a1d1d915a..8e2e893db9e7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/blkdev.h> | 46 | #include <linux/blkdev.h> |
47 | #include <linux/blkpg.h> | 47 | #include <linux/blkpg.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/smp_lock.h> | ||
49 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
50 | #include <linux/string_helpers.h> | 51 | #include <linux/string_helpers.h> |
51 | #include <linux/async.h> | 52 | #include <linux/async.h> |
@@ -411,54 +412,85 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) | |||
411 | } | 412 | } |
412 | 413 | ||
413 | /** | 414 | /** |
414 | * sd_prepare_discard - unmap blocks on thinly provisioned device | 415 | * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device |
416 | * @sdp: scsi device to operate one | ||
415 | * @rq: Request to prepare | 417 | * @rq: Request to prepare |
416 | * | 418 | * |
417 | * Will issue either UNMAP or WRITE SAME(16) depending on preference | 419 | * Will issue either UNMAP or WRITE SAME(16) depending on preference |
418 | * indicated by target device. | 420 | * indicated by target device. |
419 | **/ | 421 | **/ |
420 | static int sd_prepare_discard(struct request *rq) | 422 | static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) |
421 | { | 423 | { |
422 | struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); | 424 | struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); |
423 | struct bio *bio = rq->bio; | 425 | struct bio *bio = rq->bio; |
424 | sector_t sector = bio->bi_sector; | 426 | sector_t sector = bio->bi_sector; |
425 | unsigned int num = bio_sectors(bio); | 427 | unsigned int nr_sectors = bio_sectors(bio); |
428 | unsigned int len; | ||
429 | int ret; | ||
430 | struct page *page; | ||
426 | 431 | ||
427 | if (sdkp->device->sector_size == 4096) { | 432 | if (sdkp->device->sector_size == 4096) { |
428 | sector >>= 3; | 433 | sector >>= 3; |
429 | num >>= 3; | 434 | nr_sectors >>= 3; |
430 | } | 435 | } |
431 | 436 | ||
432 | rq->cmd_type = REQ_TYPE_BLOCK_PC; | ||
433 | rq->timeout = SD_TIMEOUT; | 437 | rq->timeout = SD_TIMEOUT; |
434 | 438 | ||
435 | memset(rq->cmd, 0, rq->cmd_len); | 439 | memset(rq->cmd, 0, rq->cmd_len); |
436 | 440 | ||
441 | page = alloc_page(GFP_ATOMIC | __GFP_ZERO); | ||
442 | if (!page) | ||
443 | return BLKPREP_DEFER; | ||
444 | |||
437 | if (sdkp->unmap) { | 445 | if (sdkp->unmap) { |
438 | char *buf = kmap_atomic(bio_page(bio), KM_USER0); | 446 | char *buf = page_address(page); |
439 | 447 | ||
448 | rq->cmd_len = 10; | ||
440 | rq->cmd[0] = UNMAP; | 449 | rq->cmd[0] = UNMAP; |
441 | rq->cmd[8] = 24; | 450 | rq->cmd[8] = 24; |
442 | rq->cmd_len = 10; | ||
443 | |||
444 | /* Ensure that data length matches payload */ | ||
445 | rq->__data_len = bio->bi_size = bio->bi_io_vec->bv_len = 24; | ||
446 | 451 | ||
447 | put_unaligned_be16(6 + 16, &buf[0]); | 452 | put_unaligned_be16(6 + 16, &buf[0]); |
448 | put_unaligned_be16(16, &buf[2]); | 453 | put_unaligned_be16(16, &buf[2]); |
449 | put_unaligned_be64(sector, &buf[8]); | 454 | put_unaligned_be64(sector, &buf[8]); |
450 | put_unaligned_be32(num, &buf[16]); | 455 | put_unaligned_be32(nr_sectors, &buf[16]); |
451 | 456 | ||
452 | kunmap_atomic(buf, KM_USER0); | 457 | len = 24; |
453 | } else { | 458 | } else { |
459 | rq->cmd_len = 16; | ||
454 | rq->cmd[0] = WRITE_SAME_16; | 460 | rq->cmd[0] = WRITE_SAME_16; |
455 | rq->cmd[1] = 0x8; /* UNMAP */ | 461 | rq->cmd[1] = 0x8; /* UNMAP */ |
456 | put_unaligned_be64(sector, &rq->cmd[2]); | 462 | put_unaligned_be64(sector, &rq->cmd[2]); |
457 | put_unaligned_be32(num, &rq->cmd[10]); | 463 | put_unaligned_be32(nr_sectors, &rq->cmd[10]); |
458 | rq->cmd_len = 16; | 464 | |
465 | len = sdkp->device->sector_size; | ||
459 | } | 466 | } |
460 | 467 | ||
461 | return BLKPREP_OK; | 468 | blk_add_request_payload(rq, page, len); |
469 | ret = scsi_setup_blk_pc_cmnd(sdp, rq); | ||
470 | rq->buffer = page_address(page); | ||
471 | if (ret != BLKPREP_OK) { | ||
472 | __free_page(page); | ||
473 | rq->buffer = NULL; | ||
474 | } | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) | ||
479 | { | ||
480 | rq->timeout = SD_TIMEOUT; | ||
481 | rq->retries = SD_MAX_RETRIES; | ||
482 | rq->cmd[0] = SYNCHRONIZE_CACHE; | ||
483 | rq->cmd_len = 10; | ||
484 | |||
485 | return scsi_setup_blk_pc_cmnd(sdp, rq); | ||
486 | } | ||
487 | |||
488 | static void sd_unprep_fn(struct request_queue *q, struct request *rq) | ||
489 | { | ||
490 | if (rq->cmd_flags & REQ_DISCARD) { | ||
491 | free_page((unsigned long)rq->buffer); | ||
492 | rq->buffer = NULL; | ||
493 | } | ||
462 | } | 494 | } |
463 | 495 | ||
464 | /** | 496 | /** |
@@ -485,10 +517,13 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
485 | * Discard request come in as REQ_TYPE_FS but we turn them into | 517 | * Discard request come in as REQ_TYPE_FS but we turn them into |
486 | * block PC requests to make life easier. | 518 | * block PC requests to make life easier. |
487 | */ | 519 | */ |
488 | if (blk_discard_rq(rq)) | 520 | if (rq->cmd_flags & REQ_DISCARD) { |
489 | ret = sd_prepare_discard(rq); | 521 | ret = scsi_setup_discard_cmnd(sdp, rq); |
490 | 522 | goto out; | |
491 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { | 523 | } else if (rq->cmd_flags & REQ_FLUSH) { |
524 | ret = scsi_setup_flush_cmnd(sdp, rq); | ||
525 | goto out; | ||
526 | } else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { | ||
492 | ret = scsi_setup_blk_pc_cmnd(sdp, rq); | 527 | ret = scsi_setup_blk_pc_cmnd(sdp, rq); |
493 | goto out; | 528 | goto out; |
494 | } else if (rq->cmd_type != REQ_TYPE_FS) { | 529 | } else if (rq->cmd_type != REQ_TYPE_FS) { |
@@ -636,7 +671,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
636 | SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; | 671 | SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; |
637 | SCpnt->cmnd[7] = 0x18; | 672 | SCpnt->cmnd[7] = 0x18; |
638 | SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; | 673 | SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; |
639 | SCpnt->cmnd[10] = protect | (blk_fua_rq(rq) ? 0x8 : 0); | 674 | SCpnt->cmnd[10] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); |
640 | 675 | ||
641 | /* LBA */ | 676 | /* LBA */ |
642 | SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; | 677 | SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; |
@@ -661,7 +696,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
661 | SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; | 696 | SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; |
662 | } else if (block > 0xffffffff) { | 697 | } else if (block > 0xffffffff) { |
663 | SCpnt->cmnd[0] += READ_16 - READ_6; | 698 | SCpnt->cmnd[0] += READ_16 - READ_6; |
664 | SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); | 699 | SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); |
665 | SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; | 700 | SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; |
666 | SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; | 701 | SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; |
667 | SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; | 702 | SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; |
@@ -682,7 +717,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
682 | this_count = 0xffff; | 717 | this_count = 0xffff; |
683 | 718 | ||
684 | SCpnt->cmnd[0] += READ_10 - READ_6; | 719 | SCpnt->cmnd[0] += READ_10 - READ_6; |
685 | SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); | 720 | SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); |
686 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; | 721 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; |
687 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; | 722 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; |
688 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; | 723 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; |
@@ -691,7 +726,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
691 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; | 726 | SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; |
692 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; | 727 | SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; |
693 | } else { | 728 | } else { |
694 | if (unlikely(blk_fua_rq(rq))) { | 729 | if (unlikely(rq->cmd_flags & REQ_FUA)) { |
695 | /* | 730 | /* |
696 | * This happens only if this drive failed | 731 | * This happens only if this drive failed |
697 | * 10byte rw command with ILLEGAL_REQUEST | 732 | * 10byte rw command with ILLEGAL_REQUEST |
@@ -745,6 +780,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
745 | * or from within the kernel (e.g. as a result of a mount(1) ). | 780 | * or from within the kernel (e.g. as a result of a mount(1) ). |
746 | * In the latter case @inode and @filp carry an abridged amount | 781 | * In the latter case @inode and @filp carry an abridged amount |
747 | * of information as noted above. | 782 | * of information as noted above. |
783 | * | ||
784 | * Locking: called with bdev->bd_mutex held. | ||
748 | **/ | 785 | **/ |
749 | static int sd_open(struct block_device *bdev, fmode_t mode) | 786 | static int sd_open(struct block_device *bdev, fmode_t mode) |
750 | { | 787 | { |
@@ -799,7 +836,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode) | |||
799 | if (!scsi_device_online(sdev)) | 836 | if (!scsi_device_online(sdev)) |
800 | goto error_out; | 837 | goto error_out; |
801 | 838 | ||
802 | if (!sdkp->openers++ && sdev->removable) { | 839 | if ((atomic_inc_return(&sdkp->openers) == 1) && sdev->removable) { |
803 | if (scsi_block_when_processing_errors(sdev)) | 840 | if (scsi_block_when_processing_errors(sdev)) |
804 | scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); | 841 | scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); |
805 | } | 842 | } |
@@ -823,6 +860,8 @@ error_autopm: | |||
823 | * | 860 | * |
824 | * Note: may block (uninterruptible) if error recovery is underway | 861 | * Note: may block (uninterruptible) if error recovery is underway |
825 | * on this disk. | 862 | * on this disk. |
863 | * | ||
864 | * Locking: called with bdev->bd_mutex held. | ||
826 | **/ | 865 | **/ |
827 | static int sd_release(struct gendisk *disk, fmode_t mode) | 866 | static int sd_release(struct gendisk *disk, fmode_t mode) |
828 | { | 867 | { |
@@ -831,7 +870,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) | |||
831 | 870 | ||
832 | SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); | 871 | SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); |
833 | 872 | ||
834 | if (!--sdkp->openers && sdev->removable) { | 873 | if (atomic_dec_return(&sdkp->openers) && sdev->removable) { |
835 | if (scsi_block_when_processing_errors(sdev)) | 874 | if (scsi_block_when_processing_errors(sdev)) |
836 | scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); | 875 | scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); |
837 | } | 876 | } |
@@ -904,7 +943,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, | |||
904 | error = scsi_nonblockable_ioctl(sdp, cmd, p, | 943 | error = scsi_nonblockable_ioctl(sdp, cmd, p, |
905 | (mode & FMODE_NDELAY) != 0); | 944 | (mode & FMODE_NDELAY) != 0); |
906 | if (!scsi_block_when_processing_errors(sdp) || !error) | 945 | if (!scsi_block_when_processing_errors(sdp) || !error) |
907 | return error; | 946 | goto out; |
908 | 947 | ||
909 | /* | 948 | /* |
910 | * Send SCSI addressing ioctls directly to mid level, send other | 949 | * Send SCSI addressing ioctls directly to mid level, send other |
@@ -914,13 +953,17 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, | |||
914 | switch (cmd) { | 953 | switch (cmd) { |
915 | case SCSI_IOCTL_GET_IDLUN: | 954 | case SCSI_IOCTL_GET_IDLUN: |
916 | case SCSI_IOCTL_GET_BUS_NUMBER: | 955 | case SCSI_IOCTL_GET_BUS_NUMBER: |
917 | return scsi_ioctl(sdp, cmd, p); | 956 | error = scsi_ioctl(sdp, cmd, p); |
957 | break; | ||
918 | default: | 958 | default: |
919 | error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); | 959 | error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); |
920 | if (error != -ENOTTY) | 960 | if (error != -ENOTTY) |
921 | return error; | 961 | break; |
962 | error = scsi_ioctl(sdp, cmd, p); | ||
963 | break; | ||
922 | } | 964 | } |
923 | return scsi_ioctl(sdp, cmd, p); | 965 | out: |
966 | return error; | ||
924 | } | 967 | } |
925 | 968 | ||
926 | static void set_media_not_present(struct scsi_disk *sdkp) | 969 | static void set_media_not_present(struct scsi_disk *sdkp) |
@@ -1045,15 +1088,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
1045 | return 0; | 1088 | return 0; |
1046 | } | 1089 | } |
1047 | 1090 | ||
1048 | static void sd_prepare_flush(struct request_queue *q, struct request *rq) | ||
1049 | { | ||
1050 | rq->cmd_type = REQ_TYPE_BLOCK_PC; | ||
1051 | rq->timeout = SD_TIMEOUT; | ||
1052 | rq->retries = SD_MAX_RETRIES; | ||
1053 | rq->cmd[0] = SYNCHRONIZE_CACHE; | ||
1054 | rq->cmd_len = 10; | ||
1055 | } | ||
1056 | |||
1057 | static void sd_rescan(struct device *dev) | 1091 | static void sd_rescan(struct device *dev) |
1058 | { | 1092 | { |
1059 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 1093 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); |
@@ -1103,7 +1137,7 @@ static const struct block_device_operations sd_fops = { | |||
1103 | .owner = THIS_MODULE, | 1137 | .owner = THIS_MODULE, |
1104 | .open = sd_open, | 1138 | .open = sd_open, |
1105 | .release = sd_release, | 1139 | .release = sd_release, |
1106 | .locked_ioctl = sd_ioctl, | 1140 | .ioctl = sd_ioctl, |
1107 | .getgeo = sd_getgeo, | 1141 | .getgeo = sd_getgeo, |
1108 | #ifdef CONFIG_COMPAT | 1142 | #ifdef CONFIG_COMPAT |
1109 | .compat_ioctl = sd_compat_ioctl, | 1143 | .compat_ioctl = sd_compat_ioctl, |
@@ -1120,7 +1154,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) | |||
1120 | u64 bad_lba; | 1154 | u64 bad_lba; |
1121 | int info_valid; | 1155 | int info_valid; |
1122 | 1156 | ||
1123 | if (!blk_fs_request(scmd->request)) | 1157 | if (scmd->request->cmd_type != REQ_TYPE_FS) |
1124 | return 0; | 1158 | return 0; |
1125 | 1159 | ||
1126 | info_valid = scsi_get_sense_info_fld(scmd->sense_buffer, | 1160 | info_valid = scsi_get_sense_info_fld(scmd->sense_buffer, |
@@ -1171,6 +1205,12 @@ static int sd_done(struct scsi_cmnd *SCpnt) | |||
1171 | int sense_valid = 0; | 1205 | int sense_valid = 0; |
1172 | int sense_deferred = 0; | 1206 | int sense_deferred = 0; |
1173 | 1207 | ||
1208 | if (SCpnt->request->cmd_flags & REQ_DISCARD) { | ||
1209 | if (!result) | ||
1210 | scsi_set_resid(SCpnt, 0); | ||
1211 | return good_bytes; | ||
1212 | } | ||
1213 | |||
1174 | if (result) { | 1214 | if (result) { |
1175 | sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); | 1215 | sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); |
1176 | if (sense_valid) | 1216 | if (sense_valid) |
@@ -2121,7 +2161,7 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
2121 | else | 2161 | else |
2122 | ordered = QUEUE_ORDERED_DRAIN; | 2162 | ordered = QUEUE_ORDERED_DRAIN; |
2123 | 2163 | ||
2124 | blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush); | 2164 | blk_queue_ordered(sdkp->disk->queue, ordered); |
2125 | 2165 | ||
2126 | set_capacity(disk, sdkp->capacity); | 2166 | set_capacity(disk, sdkp->capacity); |
2127 | kfree(buffer); | 2167 | kfree(buffer); |
@@ -2234,6 +2274,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
2234 | sd_revalidate_disk(gd); | 2274 | sd_revalidate_disk(gd); |
2235 | 2275 | ||
2236 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); | 2276 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); |
2277 | blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn); | ||
2237 | 2278 | ||
2238 | gd->driverfs_dev = &sdp->sdev_gendev; | 2279 | gd->driverfs_dev = &sdp->sdev_gendev; |
2239 | gd->flags = GENHD_FL_EXT_DEVT; | 2280 | gd->flags = GENHD_FL_EXT_DEVT; |
@@ -2313,7 +2354,7 @@ static int sd_probe(struct device *dev) | |||
2313 | sdkp->driver = &sd_template; | 2354 | sdkp->driver = &sd_template; |
2314 | sdkp->disk = gd; | 2355 | sdkp->disk = gd; |
2315 | sdkp->index = index; | 2356 | sdkp->index = index; |
2316 | sdkp->openers = 0; | 2357 | atomic_set(&sdkp->openers, 0); |
2317 | sdkp->previous_state = 1; | 2358 | sdkp->previous_state = 1; |
2318 | 2359 | ||
2319 | if (!sdp->request_queue->rq_timeout) { | 2360 | if (!sdp->request_queue->rq_timeout) { |
@@ -2372,6 +2413,7 @@ static int sd_remove(struct device *dev) | |||
2372 | 2413 | ||
2373 | async_synchronize_full(); | 2414 | async_synchronize_full(); |
2374 | blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); | 2415 | blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); |
2416 | blk_queue_unprep_rq(sdkp->device->request_queue, NULL); | ||
2375 | device_del(&sdkp->dev); | 2417 | device_del(&sdkp->dev); |
2376 | del_gendisk(sdkp->disk); | 2418 | del_gendisk(sdkp->disk); |
2377 | sd_shutdown(dev); | 2419 | sd_shutdown(dev); |