diff options
author | Matthew Wilcox <matthew.r.wilcox@intel.com> | 2014-06-04 19:07:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 19:54:02 -0400 |
commit | 47a191fd38ebddb1bd1510ec2bc1085c578c8868 (patch) | |
tree | 5c65289e7195f4ecd445b2b55e8d44cfa7e7ea00 /fs/block_dev.c | |
parent | 57d998456ae8680ed446aa1993f45f4d8a9a5973 (diff) |
fs/block_dev.c: add bdev_read_page() and bdev_write_page()
A block device driver may choose to provide a rw_page operation. These
will be called when the filesystem is attempting to do page sized I/O to
page cache pages (ie not for direct I/O). This does preclude I/Os that
are larger than page size, so this may only be a performance gain for
some devices.
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Tested-by: Dheeraj Reddy <dheeraj.reddy@intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r-- | fs/block_dev.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 552a8d13bc32..83fba15cc394 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -363,6 +363,69 @@ int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync) | |||
363 | } | 363 | } |
364 | EXPORT_SYMBOL(blkdev_fsync); | 364 | EXPORT_SYMBOL(blkdev_fsync); |
365 | 365 | ||
366 | /** | ||
367 | * bdev_read_page() - Start reading a page from a block device | ||
368 | * @bdev: The device to read the page from | ||
369 | * @sector: The offset on the device to read the page to (need not be aligned) | ||
370 | * @page: The page to read | ||
371 | * | ||
372 | * On entry, the page should be locked. It will be unlocked when the page | ||
373 | * has been read. If the block driver implements rw_page synchronously, | ||
374 | * that will be true on exit from this function, but it need not be. | ||
375 | * | ||
376 | * Errors returned by this function are usually "soft", eg out of memory, or | ||
377 | * queue full; callers should try a different route to read this page rather | ||
378 | * than propagate an error back up the stack. | ||
379 | * | ||
380 | * Return: negative errno if an error occurs, 0 if submission was successful. | ||
381 | */ | ||
382 | int bdev_read_page(struct block_device *bdev, sector_t sector, | ||
383 | struct page *page) | ||
384 | { | ||
385 | const struct block_device_operations *ops = bdev->bd_disk->fops; | ||
386 | if (!ops->rw_page) | ||
387 | return -EOPNOTSUPP; | ||
388 | return ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ); | ||
389 | } | ||
390 | EXPORT_SYMBOL_GPL(bdev_read_page); | ||
391 | |||
392 | /** | ||
393 | * bdev_write_page() - Start writing a page to a block device | ||
394 | * @bdev: The device to write the page to | ||
395 | * @sector: The offset on the device to write the page to (need not be aligned) | ||
396 | * @page: The page to write | ||
397 | * @wbc: The writeback_control for the write | ||
398 | * | ||
399 | * On entry, the page should be locked and not currently under writeback. | ||
400 | * On exit, if the write started successfully, the page will be unlocked and | ||
401 | * under writeback. If the write failed already (eg the driver failed to | ||
402 | * queue the page to the device), the page will still be locked. If the | ||
403 | * caller is a ->writepage implementation, it will need to unlock the page. | ||
404 | * | ||
405 | * Errors returned by this function are usually "soft", eg out of memory, or | ||
406 | * queue full; callers should try a different route to write this page rather | ||
407 | * than propagate an error back up the stack. | ||
408 | * | ||
409 | * Return: negative errno if an error occurs, 0 if submission was successful. | ||
410 | */ | ||
411 | int bdev_write_page(struct block_device *bdev, sector_t sector, | ||
412 | struct page *page, struct writeback_control *wbc) | ||
413 | { | ||
414 | int result; | ||
415 | int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE; | ||
416 | const struct block_device_operations *ops = bdev->bd_disk->fops; | ||
417 | if (!ops->rw_page) | ||
418 | return -EOPNOTSUPP; | ||
419 | set_page_writeback(page); | ||
420 | result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw); | ||
421 | if (result) | ||
422 | end_page_writeback(page); | ||
423 | else | ||
424 | unlock_page(page); | ||
425 | return result; | ||
426 | } | ||
427 | EXPORT_SYMBOL_GPL(bdev_write_page); | ||
428 | |||
366 | /* | 429 | /* |
367 | * pseudo-fs | 430 | * pseudo-fs |
368 | */ | 431 | */ |