aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cachefiles
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cachefiles')
-rw-r--r--fs/cachefiles/interface.c6
-rw-r--r--fs/cachefiles/namei.c87
2 files changed, 72 insertions, 21 deletions
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}