Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 168840
b: refs/heads/master
c: fee096d
h: refs/heads/master
v: v3
  • Loading branch information
David Howells committed Nov 19, 2009
1 parent 3c097bc commit 3b1c472
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d0e27b7808dc667f3015be0b6888f6d680e222c8
refs/heads/master: fee096deb4f33897937b974cb2c5168bab7935be
1 change: 1 addition & 0 deletions trunk/Documentation/filesystems/caching/fscache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ proc files.
neg=N Number of negative lookups made
pos=N Number of positive lookups made
crt=N Number of objects created by lookup
tmo=N Number of lookups timed out and requeued
Updates n=N Number of update cookie requests seen
nul=N Number of upd reqs given a NULL parent
run=N Number of upd reqs granted CPU time
Expand Down
6 changes: 4 additions & 2 deletions trunk/fs/cachefiles/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ static struct fscache_object *cachefiles_alloc_object(

/*
* attempt to look up the nominated node in this cache
* - return -ETIMEDOUT to be scheduled again
*/
static void cachefiles_lookup_object(struct fscache_object *_object)
static int cachefiles_lookup_object(struct fscache_object *_object)
{
struct cachefiles_lookup_data *lookup_data;
struct cachefiles_object *parent, *object;
Expand Down Expand Up @@ -145,13 +146,14 @@ static void cachefiles_lookup_object(struct fscache_object *_object)
object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
cachefiles_attr_changed(&object->fscache);

if (ret < 0) {
if (ret < 0 && ret != -ETIMEDOUT) {
printk(KERN_WARNING "CacheFiles: Lookup failed error %d\n",
ret);
fscache_object_lookup_error(&object->fscache);
}

_leave(" [%d]", ret);
return ret;
}

/*
Expand Down
87 changes: 68 additions & 19 deletions trunk/fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@
#include <linux/security.h>
#include "internal.h"

static int cachefiles_wait_bit(void *flags)
{
schedule();
return 0;
}

#define CACHEFILES_KEYBUF_SIZE 512

/*
Expand Down Expand Up @@ -100,8 +94,8 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object,
/*
* record the fact that an object is now active
*/
static void cachefiles_mark_object_active(struct cachefiles_cache *cache,
struct cachefiles_object *object)
static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
struct cachefiles_object *object)
{
struct cachefiles_object *xobject;
struct rb_node **_p, *_parent = NULL;
Expand Down Expand Up @@ -139,8 +133,8 @@ static void cachefiles_mark_object_active(struct cachefiles_cache *cache,
rb_insert_color(&object->active_node, &cache->active_nodes);

write_unlock(&cache->active_lock);
_leave("");
return;
_leave(" = 0");
return 0;

/* an old object from a previous incarnation is hogging the slot - we
* need to wait for it to be destroyed */
Expand All @@ -155,13 +149,64 @@ static void cachefiles_mark_object_active(struct cachefiles_cache *cache,
atomic_inc(&xobject->usage);
write_unlock(&cache->active_lock);

_debug(">>> wait");
wait_on_bit(&xobject->flags, CACHEFILES_OBJECT_ACTIVE,
cachefiles_wait_bit, TASK_UNINTERRUPTIBLE);
_debug("<<< waited");
if (test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
wait_queue_head_t *wq;

signed long timeout = 60 * HZ;
wait_queue_t wait;
bool requeue;

/* if the object we're waiting for is queued for processing,
* then just put ourselves on the queue behind it */
if (slow_work_is_queued(&xobject->fscache.work)) {
_debug("queue OBJ%x behind OBJ%x immediately",
object->fscache.debug_id,
xobject->fscache.debug_id);
goto requeue;
}

/* otherwise we sleep until either the object we're waiting for
* is done, or the slow-work facility wants the thread back to
* do other work */
wq = bit_waitqueue(&xobject->flags, CACHEFILES_OBJECT_ACTIVE);
init_wait(&wait);
requeue = false;
do {
prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
if (!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags))
break;
requeue = slow_work_sleep_till_thread_needed(
&object->fscache.work, &timeout);
} while (timeout > 0 && !requeue);
finish_wait(wq, &wait);

if (requeue &&
test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
_debug("queue OBJ%x behind OBJ%x after wait",
object->fscache.debug_id,
xobject->fscache.debug_id);
goto requeue;
}

if (timeout <= 0) {
printk(KERN_ERR "\n");
printk(KERN_ERR "CacheFiles: Error: Overlong"
" wait for old active object to go away\n");
cachefiles_printk_object(object, xobject);
goto requeue;
}
}

ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));

cache->cache.ops->put_object(&xobject->fscache);
goto try_again;

requeue:
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
cache->cache.ops->put_object(&xobject->fscache);
_leave(" = -ETIMEDOUT");
return -ETIMEDOUT;
}

/*
Expand Down Expand Up @@ -466,12 +511,15 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
}

/* note that we're now using this object */
cachefiles_mark_object_active(cache, object);
ret = cachefiles_mark_object_active(cache, object);

mutex_unlock(&dir->d_inode->i_mutex);
dput(dir);
dir = NULL;

if (ret == -ETIMEDOUT)
goto mark_active_timed_out;

_debug("=== OBTAINED_OBJECT ===");

if (object->new) {
Expand Down Expand Up @@ -515,14 +563,18 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
cachefiles_io_error(cache, "Create/mkdir failed");
goto error;

mark_active_timed_out:
_debug("mark active timed out");
goto release_dentry;

check_error:
_debug("check error %d", ret);
write_lock(&cache->active_lock);
rb_erase(&object->active_node, &cache->active_nodes);
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE);
write_unlock(&cache->active_lock);

release_dentry:
dput(object->dentry);
object->dentry = NULL;
goto error_out;
Expand All @@ -543,9 +595,6 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
error_out2:
dput(dir);
error_out:
if (ret == -ENOSPC)
ret = -ENOBUFS;

_leave(" = error %d", -ret);
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/fscache/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ extern atomic_t fscache_n_object_no_alloc;
extern atomic_t fscache_n_object_lookups;
extern atomic_t fscache_n_object_lookups_negative;
extern atomic_t fscache_n_object_lookups_positive;
extern atomic_t fscache_n_object_lookups_timed_out;
extern atomic_t fscache_n_object_created;
extern atomic_t fscache_n_object_avail;
extern atomic_t fscache_n_object_dead;
Expand Down
10 changes: 9 additions & 1 deletion trunk/fs/fscache/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ static void fscache_lookup_object(struct fscache_object *object)
{
struct fscache_cookie *cookie = object->cookie;
struct fscache_object *parent;
int ret;

_enter("");

Expand All @@ -493,12 +494,19 @@ static void fscache_lookup_object(struct fscache_object *object)

fscache_stat(&fscache_n_object_lookups);
fscache_stat(&fscache_n_cop_lookup_object);
object->cache->ops->lookup_object(object);
ret = object->cache->ops->lookup_object(object);
fscache_stat_d(&fscache_n_cop_lookup_object);

if (test_bit(FSCACHE_OBJECT_EV_ERROR, &object->events))
set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);

if (ret == -ETIMEDOUT) {
/* probably stuck behind another object, so move this one to
* the back of the queue */
fscache_stat(&fscache_n_object_lookups_timed_out);
set_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events);
}

_leave("");
}

Expand Down
4 changes: 3 additions & 1 deletion trunk/fs/fscache/stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ atomic_t fscache_n_object_no_alloc;
atomic_t fscache_n_object_lookups;
atomic_t fscache_n_object_lookups_negative;
atomic_t fscache_n_object_lookups_positive;
atomic_t fscache_n_object_lookups_timed_out;
atomic_t fscache_n_object_created;
atomic_t fscache_n_object_avail;
atomic_t fscache_n_object_dead;
Expand Down Expand Up @@ -160,10 +161,11 @@ static int fscache_stats_show(struct seq_file *m, void *v)
atomic_read(&fscache_n_acquires_nobufs),
atomic_read(&fscache_n_acquires_oom));

seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u\n",
seq_printf(m, "Lookups: n=%u neg=%u pos=%u crt=%u tmo=%u\n",
atomic_read(&fscache_n_object_lookups),
atomic_read(&fscache_n_object_lookups_negative),
atomic_read(&fscache_n_object_lookups_positive),
atomic_read(&fscache_n_object_lookups_timed_out),
atomic_read(&fscache_n_object_created));

seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
Expand Down
6 changes: 4 additions & 2 deletions trunk/include/linux/fscache-cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,10 @@ struct fscache_cache_ops {
struct fscache_object *(*alloc_object)(struct fscache_cache *cache,
struct fscache_cookie *cookie);

/* look up the object for a cookie */
void (*lookup_object)(struct fscache_object *object);
/* look up the object for a cookie
* - return -ETIMEDOUT to be requeued
*/
int (*lookup_object)(struct fscache_object *object);

/* finished looking up */
void (*lookup_complete)(struct fscache_object *object);
Expand Down

0 comments on commit 3b1c472

Please sign in to comment.