Commit fc226000 authored by Stefan Roesch's avatar Stefan Roesch Committed by David Sterba

btrfs: make prepare_pages nowait compatible

Add nowait parameter to the prepare_pages function. In case nowait is
specified for an async buffered write request, do a nowait allocation or
return -EAGAIN.
Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarStefan Roesch <shr@fb.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 80f9d241
...@@ -1339,25 +1339,53 @@ static int prepare_uptodate_page(struct inode *inode, ...@@ -1339,25 +1339,53 @@ static int prepare_uptodate_page(struct inode *inode,
return 0; return 0;
} }
static unsigned int get_prepare_fgp_flags(bool nowait)
{
unsigned int fgp_flags = FGP_LOCK | FGP_ACCESSED | FGP_CREAT;
if (nowait)
fgp_flags |= FGP_NOWAIT;
return fgp_flags;
}
static gfp_t get_prepare_gfp_flags(struct inode *inode, bool nowait)
{
gfp_t gfp;
gfp = btrfs_alloc_write_mask(inode->i_mapping);
if (nowait) {
gfp &= ~__GFP_DIRECT_RECLAIM;
gfp |= GFP_NOWAIT;
}
return gfp;
}
/* /*
* this just gets pages into the page cache and locks them down. * this just gets pages into the page cache and locks them down.
*/ */
static noinline int prepare_pages(struct inode *inode, struct page **pages, static noinline int prepare_pages(struct inode *inode, struct page **pages,
size_t num_pages, loff_t pos, size_t num_pages, loff_t pos,
size_t write_bytes, bool force_uptodate) size_t write_bytes, bool force_uptodate,
bool nowait)
{ {
int i; int i;
unsigned long index = pos >> PAGE_SHIFT; unsigned long index = pos >> PAGE_SHIFT;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping); gfp_t mask = get_prepare_gfp_flags(inode, nowait);
unsigned int fgp_flags = get_prepare_fgp_flags(nowait);
int err = 0; int err = 0;
int faili; int faili;
for (i = 0; i < num_pages; i++) { for (i = 0; i < num_pages; i++) {
again: again:
pages[i] = find_or_create_page(inode->i_mapping, index + i, pages[i] = pagecache_get_page(inode->i_mapping, index + i,
mask | __GFP_WRITE); fgp_flags, mask | __GFP_WRITE);
if (!pages[i]) { if (!pages[i]) {
faili = i - 1; faili = i - 1;
if (nowait)
err = -EAGAIN;
else
err = -ENOMEM; err = -ENOMEM;
goto fail; goto fail;
} }
...@@ -1376,7 +1404,7 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages, ...@@ -1376,7 +1404,7 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
pos + write_bytes, false); pos + write_bytes, false);
if (err) { if (err) {
put_page(pages[i]); put_page(pages[i]);
if (err == -EAGAIN) { if (!nowait && err == -EAGAIN) {
err = 0; err = 0;
goto again; goto again;
} }
...@@ -1714,8 +1742,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb, ...@@ -1714,8 +1742,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
* contents of pages from loop to loop * contents of pages from loop to loop
*/ */
ret = prepare_pages(inode, pages, num_pages, ret = prepare_pages(inode, pages, num_pages,
pos, write_bytes, pos, write_bytes, force_page_uptodate, false);
force_page_uptodate);
if (ret) { if (ret) {
btrfs_delalloc_release_extents(BTRFS_I(inode), btrfs_delalloc_release_extents(BTRFS_I(inode),
reserve_bytes); reserve_bytes);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment