[PATCH] add AOP_TRUNCATED_PAGE, prepend AOP_ to WRITEPAGE_ACTIVATE
readpage(), prepare_write(), and commit_write() callers are updated to understand the special return code AOP_TRUNCATED_PAGE in the style of writepage() and WRITEPAGE_ACTIVATE. AOP_TRUNCATED_PAGE tells the caller that the callee has unlocked the page and that the operation should be tried again with a new page. OCFS2 uses this to detect and work around a lock inversion in its aop methods. There should be no change in behaviour for methods that don't return AOP_TRUNCATED_PAGE. WRITEPAGE_ACTIVATE is also prepended with AOP_ for consistency and they are made enums so that kerneldoc can be used to document their semantics. Signed-off-by: Zach Brown <zach.brown@oracle.com>
This commit is contained in:
@@ -213,7 +213,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
|
||||
struct address_space_operations *aops = mapping->a_ops;
|
||||
pgoff_t index;
|
||||
unsigned offset, bv_offs;
|
||||
int len, ret = 0;
|
||||
int len, ret;
|
||||
|
||||
down(&mapping->host->i_sem);
|
||||
index = pos >> PAGE_CACHE_SHIFT;
|
||||
@@ -232,9 +232,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
|
||||
page = grab_cache_page(mapping, index);
|
||||
if (unlikely(!page))
|
||||
goto fail;
|
||||
if (unlikely(aops->prepare_write(file, page, offset,
|
||||
offset + size)))
|
||||
ret = aops->prepare_write(file, page, offset,
|
||||
offset + size);
|
||||
if (unlikely(ret)) {
|
||||
if (ret == AOP_TRUNCATED_PAGE) {
|
||||
page_cache_release(page);
|
||||
continue;
|
||||
}
|
||||
goto unlock;
|
||||
}
|
||||
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
|
||||
bvec->bv_page, bv_offs, size, IV);
|
||||
if (unlikely(transfer_result)) {
|
||||
@@ -251,9 +257,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
}
|
||||
flush_dcache_page(page);
|
||||
if (unlikely(aops->commit_write(file, page, offset,
|
||||
offset + size)))
|
||||
ret = aops->commit_write(file, page, offset,
|
||||
offset + size);
|
||||
if (unlikely(ret)) {
|
||||
if (ret == AOP_TRUNCATED_PAGE) {
|
||||
page_cache_release(page);
|
||||
continue;
|
||||
}
|
||||
goto unlock;
|
||||
}
|
||||
if (unlikely(transfer_result))
|
||||
goto unlock;
|
||||
bv_offs += size;
|
||||
@@ -264,6 +276,7 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
up(&mapping->host->i_sem);
|
||||
return ret;
|
||||
|
||||
@@ -154,7 +154,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page,
|
||||
|
||||
/*
|
||||
* ->writepage to the the blockdev's mapping has to redirty the page so that the
|
||||
* VM doesn't go and steal it. We return WRITEPAGE_ACTIVATE so that the VM
|
||||
* VM doesn't go and steal it. We return AOP_WRITEPAGE_ACTIVATE so that the VM
|
||||
* won't try to (pointlessly) write the page again for a while.
|
||||
*
|
||||
* Really, these pages should not be on the LRU at all.
|
||||
@@ -165,7 +165,7 @@ static int ramdisk_writepage(struct page *page, struct writeback_control *wbc)
|
||||
make_page_uptodate(page);
|
||||
SetPageDirty(page);
|
||||
if (wbc->for_reclaim)
|
||||
return WRITEPAGE_ACTIVATE;
|
||||
return AOP_WRITEPAGE_ACTIVATE;
|
||||
unlock_page(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user