aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/caching/fscache.txt1
-rw-r--r--fs/cachefiles/interface.c6
-rw-r--r--fs/cachefiles/namei.c87
-rw-r--r--fs/fscache/internal.h1
-rw-r--r--fs/fscache/object.c10
-rw-r--r--fs/fscache/stats.c4
-rw-r--r--include/linux/fscache-cache.h6
7 files changed, 90 insertions, 25 deletions
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
index 3c23411956bb..a91e2e2095b0 100644
--- a/Documentation/filesystems/caching/fscache.txt
+++ b/Documentation/filesystems/caching/fscache.txt
@@ -235,6 +235,7 @@ proc files.
235 neg=N Number of negative lookups made 235 neg=N Number of negative lookups made
236 pos=N Number of positive lookups made 236 pos=N Number of positive lookups made
237 crt=N Number of objects created by lookup 237 crt=N Number of objects created by lookup
238 tmo=N Number of lookups timed out and requeued
238 Updates n=N Number of update cookie requests seen 239 Updates n=N Number of update cookie requests seen
239 nul=N Number of upd reqs given a NULL parent 240 nul=N Number of upd reqs given a NULL parent
240 run=N Number of upd reqs granted CPU time 241 run=N Number of upd reqs granted CPU time
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 8e67abf05985..9d3c426044ae 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -114,8 +114,9 @@ nomem_lookup_data:
114 114
115/* 115/*
116 * attempt to look up the nominated node in this cache 116 * attempt to look up the nominated node in this cache
117 * - return -ETIMEDOUT to be scheduled again
117 */ 118 */
118static void cachefiles_lookup_object(struct fscache_object *_object) 119static int cachefiles_lookup_object(struct fscache_object *_object)
119{ 120{
120 struct cachefiles_lookup_data *lookup_data; 121 struct cachefiles_lookup_data *lookup_data;
121 struct cachefiles_object *parent, *object; 122 struct cachefiles_object *parent, *object;
@@ -145,13 +146,14 @@ static void cachefiles_lookup_object(struct fscache_object *_object)
145 object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) 146 object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
146 cachefiles_attr_changed(&object->fscache); 147 cachefiles_attr_changed(&object->fscache);
147 148
148 if (ret < 0) { 149 if (ret < 0 && ret != -ETIMEDOUT) {
149 printk(KERN_WARNING "CacheFiles: Lookup failed error %d\n", 150 printk(KERN_WARNING "CacheFiles: Lookup failed error %d\n",
150 ret); 151 ret);
151 fscache_object_lookup_error(&object->fscache); 152 fscache_object_lookup_error(&object->fscache);
152 } 153 }
153 154
154 _leave(" [%d]", ret); 155 _leave(" [%d]", ret);
156 return ret;
155} 157}
156 158
157/* 159/*
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 00a0cda8f47a..14ac4806e291 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -21,12 +21,6 @@
21#include <linux/security.h> 21#include <linux/security.h>
22#include "internal.h" 22#include "internal.h"
23 23
24static int cachefiles_wait_bit(void *flags)
25{
26 schedule();
27 return 0;
28}
29
30#define CACHEFILES_KEYBUF_SIZE 512 24#define CACHEFILES_KEYBUF_SIZE 512
31 25
32/* 26/*
@@ -100,8 +94,8 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object,
100/* 94/*
101 * record the fact that an object is now active 95 * record the fact that an object is now active
102 */ 96 */
103static void cachefiles_mark_object_active(struct cachefiles_cache *cache, 97static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
104 struct cachefiles_object *object) 98 struct cachefiles_object *object)
105{ 99{
106 struct cachefiles_object *xobject; 100 struct cachefiles_object *xobject;
107 struct rb_node **_p, *_parent = NULL; 101 struct rb_node **_p, *_parent = NULL;
@@ -139,8 +133,8 @@ try_again:
139 rb_insert_color(&object->active_node, &cache->active_nodes); 133 rb_insert_color(&object->active_node, &cache->active_nodes);
140 134
141 write_unlock(&cache->active_lock); 135 write_unlock(&cache->active_lock);
142 _leave(""); 136 _leave(" = 0");
143 return; 137 return 0;
144 138
145 /* an old object from a previous incarnation is hogging the slot - we 139 /* an old object from a previous incarnation is hogging the slot - we
146 * need to wait for it to be destroyed */ 140 * need to wait for it to be destroyed */
@@ -155,13 +149,64 @@ wait_for_old_object:
155 atomic_inc(&xobject->usage); 149 atomic_inc(&xobject->usage);
156 write_unlock(&cache->active_lock); 150 write_unlock(&cache->active_lock);
157 151
158 _debug(">>> wait"); 152 if (test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
159 wait_on_bit(&xobject->flags, CACHEFILES_OBJECT_ACTIVE, 153 wait_queue_head_t *wq;
160 cachefiles_wait_bit, TASK_UNINTERRUPTIBLE); 154
161 _debug("<<< waited"); 155 signed long timeout = 60 * HZ;
156 wait_queue_t wait;
157 bool requeue;
158
159 /* if the object we're waiting for is queued for processing,
160 * then just put ourselves on the queue behind it */
161 if (slow_work_is_queued(&xobject->fscache.work)) {
162 _debug("queue OBJ%x behind OBJ%x immediately",
163 object->fscache.debug_id,
164 xobject->fscache.debug_id);
165 goto requeue;
166 }
167
168 /* otherwise we sleep until either the object we're waiting for
169 * is done, or the slow-work facility wants the thread back to
170 * do other work */
171 wq = bit_waitqueue(&xobject->flags, CACHEFILES_OBJECT_ACTIVE);
172 init_wait(&wait);
173 requeue = false;
174 do {
175 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
176 if (!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags))
177 break;
178 requeue = slow_work_sleep_till_thread_needed(
179 &object->fscache.work, &timeout);
180 } while (timeout > 0 && !requeue);
181 finish_wait(wq, &wait);
182
183 if (requeue &&
184 test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
185 _debug("queue OBJ%x behind OBJ%x after wait",
186 object->fscache.debug_id,
187 xobject->fscache.debug_id);
188 goto requeue;
189 }
190
191 if (timeout <= 0) {
192 printk(KERN_ERR "\n");
193 printk(KERN_ERR "CacheFiles: Error: Overlong"
194 " wait for old active object to go away\n");
195 cachefiles_printk_object(object, xobject);
196 goto requeue;
197 }
198 }
199
200 ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
162 201
163 cache->cache.ops->put_object(&xobject->fscache); 202 cache->cache.ops->put_object(&xobject->fscache);
164 goto try_again; 203 goto try_again;
204
205requeue:
206 clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
207 cache->cache.ops->put_object(&xobject->fscache);
208 _leave(" = -ETIMEDOUT");
209 return -ETIMEDOUT;
165} 210}
166 211
167/* 212/*
@@ -466,12 +511,15 @@ lookup_again:
466 } 511 }
467 512
468 /* note that we're now using this object */ 513 /* note that we're now using this object */
469 cachefiles_mark_object_active(cache, object); 514 ret = cachefiles_mark_object_active(cache, object);
470 515
471 mutex_unlock(&dir->d_inode->i_mutex); 516 mutex_unlock(&dir->d_inode->i_mutex);
472 dput(dir); 517 dput(dir);
473 dir = NULL; 518 dir = NULL;
474 519
520 if (ret == -ETIMEDOUT)
521 goto mark_active_timed_out;
522
475 _debug("=== OBTAINED_OBJECT ==="); 523 _debug("=== OBTAINED_OBJECT ===");
476 524
477 if (object->new) { 525 if (object->new) {
@@ -515,6 +563,10 @@ create_error:
515 cachefiles_io_error(cache, "Create/mkdir failed"); 563 cachefiles_io_error(cache, "Create/mkdir failed");
516 goto error; 564 goto error;
517 565
566mark_active_timed_out:
567 _debug("mark active timed out");
568 goto release_dentry;
569
518check_error: 570check_error:
519 _debug("check error %d", ret); 571 _debug("check error %d", ret);
520 write_lock(&cache->active_lock); 572 write_lock(&cache->active_lock);
@@ -522,7 +574,7 @@ check_error:
522 clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); 574 clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
523 wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); 575 wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
524 write_unlock(&cache->active_lock); 576 write_unlock(&cache->active_lock);
525 577release_dentry:
526 dput(object->dentry); 578 dput(object->dentry);
527 object->dentry = NULL; 579 object->dentry = NULL;
528 goto error_out; 580 goto error_out;
@@ -543,9 +595,6 @@ error:
543error_out2: 595error_out2:
544 dput(dir); 596 dput(dir);
545error_out: 597error_out:
546 if (ret == -ENOSPC)
547 ret = -ENOBUFS;
548
549 _leave(" = error %d", -ret); 598 _leave(" = error %d", -ret);
550 return ret; 599 return ret;
551} 600}
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index 5b49a373689b..0ca2566e038c 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -215,6 +215,7 @@ extern atomic_t fscache_n_object_no_alloc;
215extern atomic_t fscache_n_object_lookups; 215extern atomic_t fscache_n_object_lookups;
216extern atomic_t fscache_n_object_lookups_negative; 216extern atomic_t fscache_n_object_lookups_negative;
217extern atomic_t fscache_n_object_lookups_positive; 217extern atomic_t fscache_n_object_lookups_positive;
218extern atomic_t fscache_n_object_lookups_timed_out;
218extern atomic_t fscache_n_object_created; 219extern atomic_t fscache_n_object_created;
219extern atomic_t fscache_n_object_avail; 220extern atomic_t fscache_n_object_avail;
220extern atomic_t fscache_n_object_dead; 221extern atomic_t fscache_n_object_dead;
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index f3f952cf887e..e513ac599c8e 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -468,6 +468,7 @@ static void fscache_lookup_object(struct fscache_object *object)
468{ 468{
469 struct fscache_cookie *cookie = object->cookie; 469 struct fscache_cookie *cookie = object->cookie;
470 struct fscache_object *parent; 470 struct fscache_object *parent;
471 int ret;
471 472
472 _enter(""); 473 _enter("");
473 474
@@ -493,12 +494,19 @@ static void fscache_lookup_object(struct fscache_object *object)
493 494
494 fscache_stat(&fscache_n_object_lookups); 495 fscache_stat(&fscache_n_object_lookups);
495 fscache_stat(&fscache_n_cop_lookup_object); 496 fscache_stat(&fscache_n_cop_lookup_object);
496 object->cache->ops->lookup_object(object); 497 ret = object->cache->ops->lookup_object(object);
497 fscache_stat_d(&fscache_n_cop_lookup_object); 498 fscache_stat_d(&fscache_n_cop_lookup_object);
498 499
499 if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events)) 500 if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events))
500 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags); 501 set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
501 502
503 if (ret == -ETIMEDOUT) {
504 /* probably stuck behind another object, so move this one to
505 * the back of the queue */
506 fscache_stat(&fscache_n_object_lookups_timed_out);
507 set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
508 }
509
502 _leave(""); 510 _leave("");
503} 511}
504 512
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c
index 05f77caf4a2d..46435f3aae68 100644
--- a/fs/fscache/stats.c
+++ b/fs/fscache/stats.c
@@ -98,6 +98,7 @@ atomic_t fscache_n_object_no_alloc;
98atomic_t fscache_n_object_lookups; 98atomic_t fscache_n_object_lookups;
99atomic_t fscache_n_object_lookups_negative; 99atomic_t fscache_n_object_lookups_negative;
100atomic_t fscache_n_object_lookups_positive; 100atomic_t fscache_n_object_lookups_positive;
101atomic_t fscache_n_object_lookups_timed_out;
101atomic_t fscache_n_object_created; 102atomic_t fscache_n_object_created;
102atomic_t fscache_n_object_avail; 103atomic_t fscache_n_object_avail;
103atomic_t fscache_n_object_dead; 104atomic_t fscache_n_object_dead;
@@ -160,10 +161,11 @@ static int fscache_stats_show(struct seq_file *m, void *v)
160 atomic_read(&fscache_n_acquires_nobufs), 161 atomic_read(&fscache_n_acquires_nobufs),
161 atomic_read(&fscache_n_acquires_oom)); 162 atomic_read(&fscache_n_acquires_oom));
162 163
163 seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n", 164 seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u tmo=%u\n",
164 atomic_read(&fscache_n_object_lookups), 165 atomic_read(&fscache_n_object_lookups),
165 atomic_read(&fscache_n_object_lookups_negative), 166 atomic_read(&fscache_n_object_lookups_negative),
166 atomic_read(&fscache_n_object_lookups_positive), 167 atomic_read(&fscache_n_object_lookups_positive),
168 atomic_read(&fscache_n_object_lookups_timed_out),
167 atomic_read(&fscache_n_object_created)); 169 atomic_read(&fscache_n_object_created));
168 170
169 seq_printf(m, "Updates: n=%u nul=%u run=%u\n", 171 seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 5db50002f3b5..7be0c6fbe880 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -234,8 +234,10 @@ struct fscache_cache_ops {
234 struct fscache_object *(*alloc_object)(struct fscache_cache *cache, 234 struct fscache_object *(*alloc_object)(struct fscache_cache *cache,
235 struct fscache_cookie *cookie); 235 struct fscache_cookie *cookie);
236 236
237 /* look up the object for a cookie */ 237 /* look up the object for a cookie
238 void (*lookup_object)(struct fscache_object *object); 238 * - return -ETIMEDOUT to be requeued
239 */
240 int (*lookup_object)(struct fscache_object *object);
239 241
240 /* finished looking up */ 242 /* finished looking up */
241 void (*lookup_complete)(struct fscache_object *object); 243 void (*lookup_complete)(struct fscache_object *object);