diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 35 | 
1 files changed, 29 insertions, 6 deletions
| diff --git a/fs/block_dev.c b/fs/block_dev.c index 073bb57adab1..c25639e907bd 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -50,12 +50,21 @@ struct block_device *I_BDEV(struct inode *inode)  }  EXPORT_SYMBOL(I_BDEV); -static void bdev_write_inode(struct inode *inode) +static void bdev_write_inode(struct block_device *bdev)  { +	struct inode *inode = bdev->bd_inode; +	int ret; +  	spin_lock(&inode->i_lock);  	while (inode->i_state & I_DIRTY) {  		spin_unlock(&inode->i_lock); -		WARN_ON_ONCE(write_inode_now(inode, true)); +		ret = write_inode_now(inode, true); +		if (ret) { +			char name[BDEVNAME_SIZE]; +			pr_warn_ratelimited("VFS: Dirty inode writeback failed " +					    "for block device %s (err=%d).\n", +					    bdevname(bdev, name), ret); +		}  		spin_lock(&inode->i_lock);  	}  	spin_unlock(&inode->i_lock); @@ -381,9 +390,17 @@ int bdev_read_page(struct block_device *bdev, sector_t sector,  			struct page *page)  {  	const struct block_device_operations *ops = bdev->bd_disk->fops; +	int result = -EOPNOTSUPP; +  	if (!ops->rw_page || bdev_get_integrity(bdev)) -		return -EOPNOTSUPP; -	return ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ); +		return result; + +	result = blk_queue_enter(bdev->bd_queue, GFP_KERNEL); +	if (result) +		return result; +	result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ); +	blk_queue_exit(bdev->bd_queue); +	return result;  }  EXPORT_SYMBOL_GPL(bdev_read_page); @@ -412,14 +429,20 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,  	int result;  	int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE;  	const struct block_device_operations *ops = bdev->bd_disk->fops; +  	if (!ops->rw_page || bdev_get_integrity(bdev))  		return -EOPNOTSUPP; +	result = blk_queue_enter(bdev->bd_queue, GFP_KERNEL); +	if (result) +		return result; +  	set_page_writeback(page);  	result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw);  	if (result)  		end_page_writeback(page);  	else  		unlock_page(page); +	blk_queue_exit(bdev->bd_queue);  	return result;  }  EXPORT_SYMBOL_GPL(bdev_write_page); @@ -1075,7 +1098,7 @@ int revalidate_disk(struct gendisk *disk)  	if (disk->fops->revalidate_disk)  		ret = disk->fops->revalidate_disk(disk); - +	blk_integrity_revalidate(disk);  	bdev = bdget_disk(disk, 0);  	if (!bdev)  		return ret; @@ -1504,7 +1527,7 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)  		 * ->release can cause the queue to disappear, so flush all  		 * dirty data before.  		 */ -		bdev_write_inode(bdev->bd_inode); +		bdev_write_inode(bdev);  	}  	if (bdev->bd_contains == bdev) {  		if (disk->fops->release) | 
