summaryrefslogtreecommitdiffstats
path: root/fs/fscache
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fscache')
-rw-r--r--fs/fscache/object-list.c16
-rw-r--r--fs/fscache/object.c1
-rw-r--r--fs/fscache/page.c25
3 files changed, 24 insertions, 18 deletions
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
index b8179ca6bf9d..51dde817e1f2 100644
--- a/fs/fscache/object-list.c
+++ b/fs/fscache/object-list.c
@@ -380,26 +380,14 @@ no_config:
static int fscache_objlist_open(struct inode *inode, struct file *file)
{
struct fscache_objlist_data *data;
- struct seq_file *m;
- int ret;
- ret = seq_open(file, &fscache_objlist_ops);
- if (ret < 0)
- return ret;
-
- m = file->private_data;
-
- /* buffer for key extraction */
- data = kmalloc(sizeof(struct fscache_objlist_data), GFP_KERNEL);
- if (!data) {
- seq_release(inode, file);
+ data = __seq_open_private(file, &fscache_objlist_ops, sizeof(*data));
+ if (!data)
return -ENOMEM;
- }
/* get the configuration key */
fscache_objlist_config(data);
- m->private = data;
return 0;
}
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index d3b4539f1651..da032daf0e0d 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -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);
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 85332b9d19d1..de33b3fccca6 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -44,6 +44,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)
OpenPOWER on IntegriCloud