mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	floppy: bail out in open() if drive is not responding to block0 read
In case reading of block 0 during open() fails, it is not the right thing to let open() succeed. Fix this by introducing FD_OPEN_SHOULD_FAIL_BIT flag, and setting it in case the bio callback encounters an error while trying to read block 0. As a bonus, this works around certain broken userspace (blkid), which is not able to properly handle read()s returning IO errors. Hence be nice to those, and bail out during open() already; if block 0 is not readable, read()s are not going to provide any meaningful data anyway. Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
		
							parent
							
								
									8586ea96b4
								
							
						
					
					
						commit
						7b7b68bba5
					
				
					 2 changed files with 29 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -3691,9 +3691,12 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
 | 
			
		|||
	if (!(mode & FMODE_NDELAY)) {
 | 
			
		||||
		if (mode & (FMODE_READ|FMODE_WRITE)) {
 | 
			
		||||
			UDRS->last_checked = 0;
 | 
			
		||||
			clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
 | 
			
		||||
			check_disk_change(bdev);
 | 
			
		||||
			if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
 | 
			
		||||
				goto out;
 | 
			
		||||
			if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
 | 
			
		||||
				goto out;
 | 
			
		||||
		}
 | 
			
		||||
		res = -EROFS;
 | 
			
		||||
		if ((mode & FMODE_WRITE) &&
 | 
			
		||||
| 
						 | 
				
			
			@ -3746,17 +3749,29 @@ static unsigned int floppy_check_events(struct gendisk *disk,
 | 
			
		|||
 * a disk in the drive, and whether that disk is writable.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static void floppy_rb0_complete(struct bio *bio, int err)
 | 
			
		||||
struct rb0_cbdata {
 | 
			
		||||
	int drive;
 | 
			
		||||
	struct completion complete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void floppy_rb0_cb(struct bio *bio, int err)
 | 
			
		||||
{
 | 
			
		||||
	complete((struct completion *)bio->bi_private);
 | 
			
		||||
	struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private;
 | 
			
		||||
	int drive = cbdata->drive;
 | 
			
		||||
 | 
			
		||||
	if (err) {
 | 
			
		||||
		pr_info("floppy: error %d while reading block 0", err);
 | 
			
		||||
		set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
 | 
			
		||||
	}
 | 
			
		||||
	complete(&cbdata->complete);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __floppy_read_block_0(struct block_device *bdev)
 | 
			
		||||
static int __floppy_read_block_0(struct block_device *bdev, int drive)
 | 
			
		||||
{
 | 
			
		||||
	struct bio bio;
 | 
			
		||||
	struct bio_vec bio_vec;
 | 
			
		||||
	struct completion complete;
 | 
			
		||||
	struct page *page;
 | 
			
		||||
	struct rb0_cbdata cbdata;
 | 
			
		||||
	size_t size;
 | 
			
		||||
 | 
			
		||||
	page = alloc_page(GFP_NOIO);
 | 
			
		||||
| 
						 | 
				
			
			@ -3769,6 +3784,8 @@ static int __floppy_read_block_0(struct block_device *bdev)
 | 
			
		|||
	if (!size)
 | 
			
		||||
		size = 1024;
 | 
			
		||||
 | 
			
		||||
	cbdata.drive = drive;
 | 
			
		||||
 | 
			
		||||
	bio_init(&bio);
 | 
			
		||||
	bio.bi_io_vec = &bio_vec;
 | 
			
		||||
	bio_vec.bv_page = page;
 | 
			
		||||
| 
						 | 
				
			
			@ -3779,13 +3796,14 @@ static int __floppy_read_block_0(struct block_device *bdev)
 | 
			
		|||
	bio.bi_bdev = bdev;
 | 
			
		||||
	bio.bi_iter.bi_sector = 0;
 | 
			
		||||
	bio.bi_flags = (1 << BIO_QUIET);
 | 
			
		||||
	init_completion(&complete);
 | 
			
		||||
	bio.bi_private = &complete;
 | 
			
		||||
	bio.bi_end_io = floppy_rb0_complete;
 | 
			
		||||
	bio.bi_private = &cbdata;
 | 
			
		||||
	bio.bi_end_io = floppy_rb0_cb;
 | 
			
		||||
 | 
			
		||||
	submit_bio(READ, &bio);
 | 
			
		||||
	process_fd_request();
 | 
			
		||||
	wait_for_completion(&complete);
 | 
			
		||||
 | 
			
		||||
	init_completion(&cbdata.complete);
 | 
			
		||||
	wait_for_completion(&cbdata.complete);
 | 
			
		||||
 | 
			
		||||
	__free_page(page);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3827,7 +3845,7 @@ static int floppy_revalidate(struct gendisk *disk)
 | 
			
		|||
			UDRS->generation++;
 | 
			
		||||
		if (drive_no_geom(drive)) {
 | 
			
		||||
			/* auto-sensing */
 | 
			
		||||
			res = __floppy_read_block_0(opened_bdev[drive]);
 | 
			
		||||
			res = __floppy_read_block_0(opened_bdev[drive], drive);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (cf)
 | 
			
		||||
				poll_drive(false, FD_RAW_NEED_DISK);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,7 +185,8 @@ enum {
 | 
			
		|||
				 * to clear media change status */
 | 
			
		||||
	FD_UNUSED_BIT,
 | 
			
		||||
	FD_DISK_CHANGED_BIT,	/* disk has been changed since last i/o */
 | 
			
		||||
	FD_DISK_WRITABLE_BIT	/* disk is writable */
 | 
			
		||||
	FD_DISK_WRITABLE_BIT,	/* disk is writable */
 | 
			
		||||
	FD_OPEN_SHOULD_FAIL_BIT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue