diff options
-rw-r--r-- | drivers/block/floppy.c | 36 | ||||
-rw-r--r-- | include/uapi/linux/fd.h | 3 |
2 files changed, 29 insertions, 10 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 6b29c4422828..2023043ce7c0 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -3691,9 +3691,12 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) | |||
3691 | if (!(mode & FMODE_NDELAY)) { | 3691 | if (!(mode & FMODE_NDELAY)) { |
3692 | if (mode & (FMODE_READ|FMODE_WRITE)) { | 3692 | if (mode & (FMODE_READ|FMODE_WRITE)) { |
3693 | UDRS->last_checked = 0; | 3693 | UDRS->last_checked = 0; |
3694 | clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); | ||
3694 | check_disk_change(bdev); | 3695 | check_disk_change(bdev); |
3695 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) | 3696 | if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) |
3696 | goto out; | 3697 | goto out; |
3698 | if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) | ||
3699 | goto out; | ||
3697 | } | 3700 | } |
3698 | res = -EROFS; | 3701 | res = -EROFS; |
3699 | if ((mode & FMODE_WRITE) && | 3702 | if ((mode & FMODE_WRITE) && |
@@ -3746,17 +3749,29 @@ static unsigned int floppy_check_events(struct gendisk *disk, | |||
3746 | * a disk in the drive, and whether that disk is writable. | 3749 | * a disk in the drive, and whether that disk is writable. |
3747 | */ | 3750 | */ |
3748 | 3751 | ||
3749 | static void floppy_rb0_complete(struct bio *bio, int err) | 3752 | struct rb0_cbdata { |
3753 | int drive; | ||
3754 | struct completion complete; | ||
3755 | }; | ||
3756 | |||
3757 | static void floppy_rb0_cb(struct bio *bio, int err) | ||
3750 | { | 3758 | { |
3751 | complete((struct completion *)bio->bi_private); | 3759 | struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private; |
3760 | int drive = cbdata->drive; | ||
3761 | |||
3762 | if (err) { | ||
3763 | pr_info("floppy: error %d while reading block 0", err); | ||
3764 | set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); | ||
3765 | } | ||
3766 | complete(&cbdata->complete); | ||
3752 | } | 3767 | } |
3753 | 3768 | ||
3754 | static int __floppy_read_block_0(struct block_device *bdev) | 3769 | static int __floppy_read_block_0(struct block_device *bdev, int drive) |
3755 | { | 3770 | { |
3756 | struct bio bio; | 3771 | struct bio bio; |
3757 | struct bio_vec bio_vec; | 3772 | struct bio_vec bio_vec; |
3758 | struct completion complete; | ||
3759 | struct page *page; | 3773 | struct page *page; |
3774 | struct rb0_cbdata cbdata; | ||
3760 | size_t size; | 3775 | size_t size; |
3761 | 3776 | ||
3762 | page = alloc_page(GFP_NOIO); | 3777 | page = alloc_page(GFP_NOIO); |
@@ -3769,6 +3784,8 @@ static int __floppy_read_block_0(struct block_device *bdev) | |||
3769 | if (!size) | 3784 | if (!size) |
3770 | size = 1024; | 3785 | size = 1024; |
3771 | 3786 | ||
3787 | cbdata.drive = drive; | ||
3788 | |||
3772 | bio_init(&bio); | 3789 | bio_init(&bio); |
3773 | bio.bi_io_vec = &bio_vec; | 3790 | bio.bi_io_vec = &bio_vec; |
3774 | bio_vec.bv_page = page; | 3791 | bio_vec.bv_page = page; |
@@ -3779,13 +3796,14 @@ static int __floppy_read_block_0(struct block_device *bdev) | |||
3779 | bio.bi_bdev = bdev; | 3796 | bio.bi_bdev = bdev; |
3780 | bio.bi_iter.bi_sector = 0; | 3797 | bio.bi_iter.bi_sector = 0; |
3781 | bio.bi_flags = (1 << BIO_QUIET); | 3798 | bio.bi_flags = (1 << BIO_QUIET); |
3782 | init_completion(&complete); | 3799 | bio.bi_private = &cbdata; |
3783 | bio.bi_private = &complete; | 3800 | bio.bi_end_io = floppy_rb0_cb; |
3784 | bio.bi_end_io = floppy_rb0_complete; | ||
3785 | 3801 | ||
3786 | submit_bio(READ, &bio); | 3802 | submit_bio(READ, &bio); |
3787 | process_fd_request(); | 3803 | process_fd_request(); |
3788 | wait_for_completion(&complete); | 3804 | |
3805 | init_completion(&cbdata.complete); | ||
3806 | wait_for_completion(&cbdata.complete); | ||
3789 | 3807 | ||
3790 | __free_page(page); | 3808 | __free_page(page); |
3791 | 3809 | ||
@@ -3827,7 +3845,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
3827 | UDRS->generation++; | 3845 | UDRS->generation++; |
3828 | if (drive_no_geom(drive)) { | 3846 | if (drive_no_geom(drive)) { |
3829 | /* auto-sensing */ | 3847 | /* auto-sensing */ |
3830 | res = __floppy_read_block_0(opened_bdev[drive]); | 3848 | res = __floppy_read_block_0(opened_bdev[drive], drive); |
3831 | } else { | 3849 | } else { |
3832 | if (cf) | 3850 | if (cf) |
3833 | poll_drive(false, FD_RAW_NEED_DISK); | 3851 | poll_drive(false, FD_RAW_NEED_DISK); |
diff --git a/include/uapi/linux/fd.h b/include/uapi/linux/fd.h index f1f3dd5981b2..84c517cbce90 100644 --- a/include/uapi/linux/fd.h +++ b/include/uapi/linux/fd.h | |||
@@ -185,7 +185,8 @@ enum { | |||
185 | * to clear media change status */ | 185 | * to clear media change status */ |
186 | FD_UNUSED_BIT, | 186 | FD_UNUSED_BIT, |
187 | FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */ | 187 | FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */ |
188 | FD_DISK_WRITABLE_BIT /* disk is writable */ | 188 | FD_DISK_WRITABLE_BIT, /* disk is writable */ |
189 | FD_OPEN_SHOULD_FAIL_BIT | ||
189 | }; | 190 | }; |
190 | 191 | ||
191 | #define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params) | 192 | #define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params) |