Merge tag 'fscache-fixes-20140917' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 23 Sep 2014 00:52:16 +0000 (17:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 23 Sep 2014 00:52:16 +0000 (17:52 -0700)
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()

fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/fscache/object.c
fs/fscache/page.c

index 5bf2b41e66d392d0b013a140648c1768bc62b5fd..83e9c94ca2cf6f90c1bce59c7205d974092606b9 100644 (file)
@@ -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;
index 4b1fb5ca65b8058c4713e92dda3b1772cdeb6cfe..25e745b8eb1b5fe127be7fb20998444432ca9263 100644 (file)
@@ -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
index d3b4539f16515451cdd691fd853927d00fa3f8a8..da032daf0e0d7562f40e5a050685829af68869ac 100644 (file)
@@ -982,6 +982,7 @@ nomem:
 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);
index 85332b9d19d1613322168bc8a1c9ab6f3263e183..de33b3fccca650da99ee850597d5aef437b3a6fe 100644 (file)
@@ -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 @@ page_busy:
        }
 
        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)