@@ -366,7 +366,7 @@ static int brd_rw_page(struct block_device *bdev, sector_t sector,
struct brd_device *brd = bdev->bd_disk->private_data;
int err = brd_do_bvec(brd, page, PAGE_CACHE_SIZE, 0, rw, sector);
page_endio(page, rw & WRITE, err);
- return err;
+ return 0;
}
#ifdef CONFIG_BLK_DEV_RAM_DAX
@@ -386,11 +386,12 @@ int bdev_read_page(struct block_device *bdev, sector_t sector,
struct page *page)
{
const struct block_device_operations *ops = bdev->bd_disk->fops;
- if (!ops->rw_page)
+ VM_BUG_ON_PAGE(!PageLocked(page), page);
+ if (!ops->rw_page || bdev_get_integrity(bdev))
return -EOPNOTSUPP;
return ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
}
-EXPORT_SYMBOL_GPL(bdev_read_page);
+EXPORT_UNUSED_SYMBOL_GPL(bdev_read_page);
/**
* bdev_write_page() - Start writing a page to a block device
@@ -400,14 +401,13 @@ EXPORT_SYMBOL_GPL(bdev_read_page);
* @wbc: The writeback_control for the write
*
* On entry, the page should be locked and not currently under writeback.
- * On exit, if the write started successfully, the page will be unlocked and
- * under writeback. If the write failed already (eg the driver failed to
- * queue the page to the device), the page will still be locked. If the
- * caller is a ->writepage implementation, it will need to unlock the page.
+ * On exit, the page will still be locked, and shall be under writeback if
+ * the I/O is in progress.
*
- * Errors returned by this function are usually "soft", eg out of memory, or
- * queue full; callers should try a different route to write this page rather
- * than propagate an error back up the stack.
+ * Errors returned by this function indicate that something went wrong with
+ * the submission. Callers should try a different route to write this page
+ * rather than propagate an error back up the stack. If the device has an
+ * error, that will be indicated by setting PageError.
*
* Return: negative errno if an error occurs, 0 if submission was successful.
*/
@@ -417,17 +417,16 @@ 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)
+ VM_BUG_ON_PAGE(!PageLocked(page) || PageWriteback(page), page);
+ if (!ops->rw_page || bdev_get_integrity(bdev))
return -EOPNOTSUPP;
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);
return result;
}
-EXPORT_SYMBOL_GPL(bdev_write_page);
+EXPORT_UNUSED_SYMBOL_GPL(bdev_write_page);
/**
* bdev_direct_access() - Get the address for directly-accessibly memory
@@ -3211,15 +3211,13 @@ failed:
return 0;
}
-int try_to_free_buffers(struct page *page)
+int __try_to_free_buffers(struct page *page)
{
struct address_space * const mapping = page->mapping;
struct buffer_head *buffers_to_free = NULL;
- int ret = 0;
+ int ret;
BUG_ON(!PageLocked(page));
- if (PageWriteback(page))
- return 0;
if (mapping == NULL) { /* can this still happen? */
ret = drop_buffers(page, &buffers_to_free);
@@ -3258,6 +3256,14 @@ out:
}
return ret;
}
+
+int try_to_free_buffers(struct page *page)
+{
+ BUG_ON(!PageLocked(page));
+ if (PageWriteback(page))
+ return 0;
+ return __try_to_free_buffers(page);
+}
EXPORT_SYMBOL(try_to_free_buffers);
/*
@@ -456,7 +456,7 @@ static void clean_buffers(struct page *page, unsigned first_unmapped)
* disk before we reach the platter.
*/
if (buffer_heads_over_limit && PageUptodate(page))
- try_to_free_buffers(page);
+ __try_to_free_buffers(page);
}
static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
@@ -599,6 +599,7 @@ alloc_new:
if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9),
page, wbc)) {
clean_buffers(page, first_unmapped);
+ unlock_page(page);
goto out;
}
}
@@ -154,6 +154,7 @@ void touch_buffer(struct buffer_head *bh);
void set_bh_page(struct buffer_head *bh,
struct page *page, unsigned long offset);
int try_to_free_buffers(struct page *);
+int __try_to_free_buffers(struct page *);
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
int retry);
void create_empty_buffers(struct page *, unsigned long,
@@ -311,6 +311,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc);
if (!ret) {
+ unlock_page(page);
count_vm_event(PSWPOUT);
return 0;
}