Commit e2519c2c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fscache-fixes-20140917' of...

Merge tag 'fscache-fixes-20140917' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

Pull fs-cache fixes from David Howells:

 - Put a timeout in releasepage() to deal with a recursive hang between
   the memory allocator, writeback, ext4 and fscache under memory
   pressure.

 - Fix a pair of refcount bugs in the fscache error handling.

 - Remove a couple of unused pagevecs.

 - The cachefiles requirement that the base directory support rename
   should permit rename2 as an alternative - otherwise certain
   filesystems cannot now be used as backing stores (such as ext4).

* tag 'fscache-fixes-20140917' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
  CacheFiles: Handle rename2
  cachefiles: remove two unused pagevecs.
  FS-Cache: refcount becomes corrupt under vma pressure.
  FS-Cache: Reduce cookie ref count if submit fails.
  FS-Cache: Timeout for releasepage()
parents b0e2a55c e2cf1f1c
...@@ -779,7 +779,8 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, ...@@ -779,7 +779,8 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
!subdir->d_inode->i_op->lookup || !subdir->d_inode->i_op->lookup ||
!subdir->d_inode->i_op->mkdir || !subdir->d_inode->i_op->mkdir ||
!subdir->d_inode->i_op->create || !subdir->d_inode->i_op->create ||
!subdir->d_inode->i_op->rename || (!subdir->d_inode->i_op->rename &&
!subdir->d_inode->i_op->rename2) ||
!subdir->d_inode->i_op->rmdir || !subdir->d_inode->i_op->rmdir ||
!subdir->d_inode->i_op->unlink) !subdir->d_inode->i_op->unlink)
goto check_error; goto check_error;
......
...@@ -151,7 +151,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op) ...@@ -151,7 +151,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
struct cachefiles_one_read *monitor; struct cachefiles_one_read *monitor;
struct cachefiles_object *object; struct cachefiles_object *object;
struct fscache_retrieval *op; struct fscache_retrieval *op;
struct pagevec pagevec;
int error, max; int error, max;
op = container_of(_op, struct fscache_retrieval, op); op = container_of(_op, struct fscache_retrieval, op);
...@@ -160,8 +159,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op) ...@@ -160,8 +159,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
_enter("{ino=%lu}", object->backer->d_inode->i_ino); _enter("{ino=%lu}", object->backer->d_inode->i_ino);
pagevec_init(&pagevec, 0);
max = 8; max = 8;
spin_lock_irq(&object->work_lock); spin_lock_irq(&object->work_lock);
...@@ -396,7 +393,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, ...@@ -396,7 +393,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
{ {
struct cachefiles_object *object; struct cachefiles_object *object;
struct cachefiles_cache *cache; struct cachefiles_cache *cache;
struct pagevec pagevec;
struct inode *inode; struct inode *inode;
sector_t block0, block; sector_t block0, block;
unsigned shift; unsigned shift;
...@@ -427,8 +423,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, ...@@ -427,8 +423,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
op->op.flags |= FSCACHE_OP_ASYNC; op->op.flags |= FSCACHE_OP_ASYNC;
op->op.processor = cachefiles_read_copier; op->op.processor = cachefiles_read_copier;
pagevec_init(&pagevec, 0);
/* we assume the absence or presence of the first block is a good /* we assume the absence or presence of the first block is a good
* enough indication for the page as a whole * enough indication for the page as a whole
* - TODO: don't use bmap() for this as it is _not_ actually good * - TODO: don't use bmap() for this as it is _not_ actually good
......
...@@ -982,6 +982,7 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj ...@@ -982,6 +982,7 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj
submit_op_failed: submit_op_failed:
clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags); clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
spin_unlock(&cookie->lock); spin_unlock(&cookie->lock);
fscache_unuse_cookie(object);
kfree(op); kfree(op);
_leave(" [EIO]"); _leave(" [EIO]");
return transit_to(KILL_OBJECT); return transit_to(KILL_OBJECT);
......
...@@ -43,6 +43,19 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa ...@@ -43,6 +43,19 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa
} }
EXPORT_SYMBOL(__fscache_wait_on_page_write); EXPORT_SYMBOL(__fscache_wait_on_page_write);
/*
* wait for a page to finish being written to the cache. Put a timeout here
* since we might be called recursively via parent fs.
*/
static
bool release_page_wait_timeout(struct fscache_cookie *cookie, struct page *page)
{
wait_queue_head_t *wq = bit_waitqueue(&cookie->flags, 0);
return wait_event_timeout(*wq, !__fscache_check_page_write(cookie, page),
HZ);
}
/* /*
* decide whether a page can be released, possibly by cancelling a store to it * decide whether a page can be released, possibly by cancelling a store to it
* - we're allowed to sleep if __GFP_WAIT is flagged * - we're allowed to sleep if __GFP_WAIT is flagged
...@@ -115,7 +128,10 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie, ...@@ -115,7 +128,10 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
} }
fscache_stat(&fscache_n_store_vmscan_wait); fscache_stat(&fscache_n_store_vmscan_wait);
__fscache_wait_on_page_write(cookie, page); if (!release_page_wait_timeout(cookie, page))
_debug("fscache writeout timeout page: %p{%lx}",
page, page->index);
gfp &= ~__GFP_WAIT; gfp &= ~__GFP_WAIT;
goto try_again; goto try_again;
} }
...@@ -182,7 +198,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) ...@@ -182,7 +198,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
{ {
struct fscache_operation *op; struct fscache_operation *op;
struct fscache_object *object; struct fscache_object *object;
bool wake_cookie; bool wake_cookie = false;
_enter("%p", cookie); _enter("%p", cookie);
...@@ -212,15 +228,16 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) ...@@ -212,15 +228,16 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
__fscache_use_cookie(cookie); __fscache_use_cookie(cookie);
if (fscache_submit_exclusive_op(object, op) < 0) if (fscache_submit_exclusive_op(object, op) < 0)
goto nobufs; goto nobufs_dec;
spin_unlock(&cookie->lock); spin_unlock(&cookie->lock);
fscache_stat(&fscache_n_attr_changed_ok); fscache_stat(&fscache_n_attr_changed_ok);
fscache_put_operation(op); fscache_put_operation(op);
_leave(" = 0"); _leave(" = 0");
return 0; return 0;
nobufs: nobufs_dec:
wake_cookie = __fscache_unuse_cookie(cookie); wake_cookie = __fscache_unuse_cookie(cookie);
nobufs:
spin_unlock(&cookie->lock); spin_unlock(&cookie->lock);
kfree(op); kfree(op);
if (wake_cookie) if (wake_cookie)
......
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