FS-Cache fixes
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAVB/u8ROxKuMESys7AQJGxA/9Ep4IwIAclMYcVQtk4zzvz+A9jVw0pu+X aItU70GcGoxehGlOxyqKXp/dg3CZ7ZPcxmQqzl7nzCZY28or5z/Nu6Y/YII+V0NB f6vgHPhfGO7CSSdwlSzFY/6DdU/EXhjA3X4suowRPIO3B/2ydLxDe3sahIWY/AhM 4h3ioDR+A4ZZvU8fmw62l9Iae46mkk7KT8Am/2bUJQpENu4caVEtNtyJ2IsiPtZ8 pddgvPL/f+piz4Ufdmc/XH4KB8kiLwU+7t3xfoZnSzYz9Vzcq4sQVvSxqNSaYzSC REEnELuLEweIh57PP67giZGPE6MA50kISH/soc43yl/oWj9i3cqkNb2JW+nxpvfS pIHfgRmzqUPe9MrmVUtle9c1HhjAyts3y27JB4onpLghN96JgIcTWJ1vZxnxbXzp ADVCgc3z8nhttLQMU+NsfD4fHUvj+bxULW1bSPdB5DfSrkpqmQJZBRexeFZWGyA9 p1p9Yaty2Sdq/RPmtIfMPA3cu1D9LG4wkvGPmmEAjnIlKebRBjriKDmCdwf9okWA m+fAbuBnTjc+R0ERE6Lh5OI72hbwcgyAyDx5RdWkXVIPMBuBK67nR6nJK7vPW4x0 qK0B5Pk2iwobKQMicVSxI+GImeeiQLi798KHJwN4uFBy74rIISWilIsylBrxlxK8 s2hdI83XJJI= =ojl4 -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
e2519c2c85
4 changed files with 24 additions and 11 deletions
|
@ -779,7 +779,8 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
|||
!subdir->d_inode->i_op->lookup ||
|
||||
!subdir->d_inode->i_op->mkdir ||
|
||||
!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->unlink)
|
||||
goto check_error;
|
||||
|
|
|
@ -151,7 +151,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
|
|||
struct cachefiles_one_read *monitor;
|
||||
struct cachefiles_object *object;
|
||||
struct fscache_retrieval *op;
|
||||
struct pagevec pagevec;
|
||||
int error, max;
|
||||
|
||||
op = container_of(_op, struct fscache_retrieval, op);
|
||||
|
@ -160,8 +159,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
|
|||
|
||||
_enter("{ino=%lu}", object->backer->d_inode->i_ino);
|
||||
|
||||
pagevec_init(&pagevec, 0);
|
||||
|
||||
max = 8;
|
||||
spin_lock_irq(&object->work_lock);
|
||||
|
||||
|
@ -396,7 +393,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
|
|||
{
|
||||
struct cachefiles_object *object;
|
||||
struct cachefiles_cache *cache;
|
||||
struct pagevec pagevec;
|
||||
struct inode *inode;
|
||||
sector_t block0, block;
|
||||
unsigned shift;
|
||||
|
@ -427,8 +423,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
|
|||
op->op.flags |= FSCACHE_OP_ASYNC;
|
||||
op->op.processor = cachefiles_read_copier;
|
||||
|
||||
pagevec_init(&pagevec, 0);
|
||||
|
||||
/* we assume the absence or presence of the first block is a good
|
||||
* enough indication for the page as a whole
|
||||
* - 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
|
|||
submit_op_failed:
|
||||
clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
|
||||
spin_unlock(&cookie->lock);
|
||||
fscache_unuse_cookie(object);
|
||||
kfree(op);
|
||||
_leave(" [EIO]");
|
||||
return transit_to(KILL_OBJECT);
|
||||
|
|
|
@ -43,6 +43,19 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa
|
|||
}
|
||||
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
|
||||
* - we're allowed to sleep if __GFP_WAIT is flagged
|
||||
|
@ -115,7 +128,10 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie,
|
|||
}
|
||||
|
||||
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;
|
||||
goto try_again;
|
||||
}
|
||||
|
@ -182,7 +198,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
|
|||
{
|
||||
struct fscache_operation *op;
|
||||
struct fscache_object *object;
|
||||
bool wake_cookie;
|
||||
bool wake_cookie = false;
|
||||
|
||||
_enter("%p", cookie);
|
||||
|
||||
|
@ -212,15 +228,16 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
|
|||
|
||||
__fscache_use_cookie(cookie);
|
||||
if (fscache_submit_exclusive_op(object, op) < 0)
|
||||
goto nobufs;
|
||||
goto nobufs_dec;
|
||||
spin_unlock(&cookie->lock);
|
||||
fscache_stat(&fscache_n_attr_changed_ok);
|
||||
fscache_put_operation(op);
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
nobufs:
|
||||
nobufs_dec:
|
||||
wake_cookie = __fscache_unuse_cookie(cookie);
|
||||
nobufs:
|
||||
spin_unlock(&cookie->lock);
|
||||
kfree(op);
|
||||
if (wake_cookie)
|
||||
|
|
Loading…
Reference in a new issue