Skip to content

Commit

Permalink
Merge branch 'fscache-fixes' into for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Al Viro committed Jun 23, 2015
2 parents a6de82c + 4a47132 commit 8ea3a7c
Show file tree
Hide file tree
Showing 11 changed files with 378 additions and 184 deletions.
23 changes: 23 additions & 0 deletions Documentation/filesystems/caching/backend-api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,29 @@ FS-Cache provides some utilities that a cache backend may make use of:
as possible.


(*) Indicate that a stale object was found and discarded:

void fscache_object_retrying_stale(struct fscache_object *object);

This is called to indicate that the lookup procedure found an object in
the cache that the netfs decided was stale. The object has been
discarded from the cache and the lookup will be performed again.


(*) Indicate that the caching backend killed an object:

void fscache_object_mark_killed(struct fscache_object *object,
enum fscache_why_object_killed why);

This is called to indicate that the cache backend preemptively killed an
object. The why parameter should be set to indicate the reason:

FSCACHE_OBJECT_IS_STALE - the object was stale and needs discarding.
FSCACHE_OBJECT_NO_SPACE - there was insufficient cache space
FSCACHE_OBJECT_WAS_RETIRED - the object was retired when relinquished.
FSCACHE_OBJECT_WAS_CULLED - the object was culled to make space.


(*) Get and release references on a retrieval record:

void fscache_get_retrieval(struct fscache_retrieval *op);
Expand Down
7 changes: 6 additions & 1 deletion Documentation/filesystems/caching/fscache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,9 @@ proc files.
enq=N Number of times async ops queued for processing
can=N Number of async ops cancelled
rej=N Number of async ops rejected due to object lookup/create failure
ini=N Number of async ops initialised
dfr=N Number of async ops queued for deferred release
rel=N Number of async ops released
rel=N Number of async ops released (should equal ini=N when idle)
gc=N Number of deferred-release async ops garbage collected
CacheOp alo=N Number of in-progress alloc_object() cache ops
luo=N Number of in-progress lookup_object() cache ops
Expand All @@ -303,6 +304,10 @@ proc files.
wrp=N Number of in-progress write_page() cache ops
ucp=N Number of in-progress uncache_page() cache ops
dsp=N Number of in-progress dissociate_pages() cache ops
CacheEv nsp=N Number of object lookups/creations rejected due to lack of space
stl=N Number of stale objects deleted
rtr=N Number of objects retired when relinquished
cul=N Number of objects culled


(*) /proc/fs/fscache/histogram
Expand Down
1 change: 0 additions & 1 deletion fs/cachefiles/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ struct cachefiles_object {
loff_t i_size; /* object size */
unsigned long flags;
#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */
#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */
atomic_t usage; /* object usage count */
uint8_t type; /* object type */
uint8_t new; /* T if object new */
Expand Down
33 changes: 21 additions & 12 deletions fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object,
* call vfs_unlink(), vfs_rmdir() or vfs_rename()
*/
static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
struct dentry *dentry)
struct dentry *dentry,
enum fscache_why_object_killed why)
{
struct cachefiles_object *object;
struct rb_node *p;
Expand Down Expand Up @@ -132,8 +133,9 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
pr_err("\n");
pr_err("Error: Can't preemptively bury live object\n");
cachefiles_printk_object(object, NULL);
} else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
pr_err("Error: Object already preemptively buried\n");
} else {
if (why != FSCACHE_OBJECT_IS_STALE)
fscache_object_mark_killed(&object->fscache, why);
}

write_unlock(&cache->active_lock);
Expand Down Expand Up @@ -265,7 +267,8 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
static int cachefiles_bury_object(struct cachefiles_cache *cache,
struct dentry *dir,
struct dentry *rep,
bool preemptive)
bool preemptive,
enum fscache_why_object_killed why)
{
struct dentry *grave, *trap;
struct path path, path_to_graveyard;
Expand All @@ -289,7 +292,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
ret = vfs_unlink(d_inode(dir), rep, NULL);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);
cachefiles_mark_object_buried(cache, rep, why);
}

mutex_unlock(&d_inode(dir)->i_mutex);
Expand Down Expand Up @@ -394,7 +397,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
"Rename failed with error %d", ret);

if (preemptive)
cachefiles_mark_object_buried(cache, rep);
cachefiles_mark_object_buried(cache, rep, why);
}

unlock_rename(cache->graveyard, dir);
Expand Down Expand Up @@ -422,7 +425,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,

mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);

if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
if (test_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->fscache.flags)) {
/* object allocation for the same key preemptively deleted this
* object's file so that it could create its own file */
_debug("object preemptively buried");
Expand All @@ -433,7 +436,8 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
* may have been renamed */
if (dir == object->dentry->d_parent) {
ret = cachefiles_bury_object(cache, dir,
object->dentry, false);
object->dentry, false,
FSCACHE_OBJECT_WAS_RETIRED);
} else {
/* it got moved, presumably by cachefilesd culling it,
* so it's no longer in the key path and we can ignore
Expand Down Expand Up @@ -522,7 +526,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if (d_is_negative(next)) {
ret = cachefiles_has_space(cache, 1, 0);
if (ret < 0)
goto create_error;
goto no_space_error;

path.dentry = dir;
ret = security_path_mkdir(&path, next, 0);
Expand Down Expand Up @@ -551,7 +555,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if (d_is_negative(next)) {
ret = cachefiles_has_space(cache, 1, 0);
if (ret < 0)
goto create_error;
goto no_space_error;

path.dentry = dir;
ret = security_path_mknod(&path, next, S_IFREG, 0);
Expand Down Expand Up @@ -602,14 +606,16 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
* mutex) */
object->dentry = NULL;

ret = cachefiles_bury_object(cache, dir, next, true);
ret = cachefiles_bury_object(cache, dir, next, true,
FSCACHE_OBJECT_IS_STALE);
dput(next);
next = NULL;

if (ret < 0)
goto delete_error;

_debug("redo lookup");
fscache_object_retrying_stale(&object->fscache);
goto lookup_again;
}
}
Expand Down Expand Up @@ -662,6 +668,8 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
_leave(" = 0 [%lu]", d_backing_inode(object->dentry)->i_ino);
return 0;

no_space_error:
fscache_object_mark_killed(&object->fscache, FSCACHE_OBJECT_NO_SPACE);
create_error:
_debug("create error %d", ret);
if (ret == -EIO)
Expand Down Expand Up @@ -927,7 +935,8 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
/* actually remove the victim (drops the dir mutex) */
_debug("bury");

ret = cachefiles_bury_object(cache, dir, victim, false);
ret = cachefiles_bury_object(cache, dir, victim, false,
FSCACHE_OBJECT_WAS_CULLED);
if (ret < 0)
goto error;

Expand Down
8 changes: 4 additions & 4 deletions fs/fscache/cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ static int fscache_alloc_object(struct fscache_cache *cache,

object_already_extant:
ret = -ENOBUFS;
if (fscache_object_is_dead(object)) {
if (fscache_object_is_dying(object) ||
fscache_cache_is_broken(object)) {
spin_unlock(&cookie->lock);
goto error;
}
Expand Down Expand Up @@ -671,7 +672,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
if (!op)
return -ENOMEM;

fscache_operation_init(op, NULL, NULL);
fscache_operation_init(op, NULL, NULL, NULL);
op->flags = FSCACHE_OP_MYTHREAD |
(1 << FSCACHE_OP_WAITING) |
(1 << FSCACHE_OP_UNUSE_COOKIE);
Expand All @@ -695,8 +696,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
/* the work queue now carries its own ref on the object */
spin_unlock(&cookie->lock);

ret = fscache_wait_for_operation_activation(object, op,
NULL, NULL, NULL);
ret = fscache_wait_for_operation_activation(object, op, NULL, NULL);
if (ret == 0) {
/* ask the cache to honour the operation */
ret = object->cache->ops->check_consistency(op);
Expand Down
12 changes: 8 additions & 4 deletions fs/fscache/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ extern int fscache_submit_exclusive_op(struct fscache_object *,
struct fscache_operation *);
extern int fscache_submit_op(struct fscache_object *,
struct fscache_operation *);
extern int fscache_cancel_op(struct fscache_operation *,
void (*)(struct fscache_operation *));
extern int fscache_cancel_op(struct fscache_operation *, bool);
extern void fscache_cancel_all_ops(struct fscache_object *);
extern void fscache_abort_object(struct fscache_object *);
extern void fscache_start_operations(struct fscache_object *);
Expand All @@ -138,8 +137,7 @@ extern int fscache_wait_for_deferred_lookup(struct fscache_cookie *);
extern int fscache_wait_for_operation_activation(struct fscache_object *,
struct fscache_operation *,
atomic_t *,
atomic_t *,
void (*)(struct fscache_operation *));
atomic_t *);
extern void fscache_invalidate_writes(struct fscache_cookie *);

/*
Expand All @@ -164,6 +162,7 @@ extern atomic_t fscache_n_op_pend;
extern atomic_t fscache_n_op_run;
extern atomic_t fscache_n_op_enqueue;
extern atomic_t fscache_n_op_deferred_release;
extern atomic_t fscache_n_op_initialised;
extern atomic_t fscache_n_op_release;
extern atomic_t fscache_n_op_gc;
extern atomic_t fscache_n_op_cancelled;
Expand Down Expand Up @@ -271,6 +270,11 @@ extern atomic_t fscache_n_cop_write_page;
extern atomic_t fscache_n_cop_uncache_page;
extern atomic_t fscache_n_cop_dissociate_pages;

extern atomic_t fscache_n_cache_no_space_reject;
extern atomic_t fscache_n_cache_stale_objects;
extern atomic_t fscache_n_cache_retired_objects;
extern atomic_t fscache_n_cache_culled_objects;

static inline void fscache_stat(atomic_t *stat)
{
atomic_inc(stat);
Expand Down
69 changes: 65 additions & 4 deletions fs/fscache/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,17 @@ void fscache_object_init(struct fscache_object *object,
}
EXPORT_SYMBOL(fscache_object_init);

/*
* Mark the object as no longer being live, making sure that we synchronise
* against op submission.
*/
static inline void fscache_mark_object_dead(struct fscache_object *object)
{
spin_lock(&object->lock);
clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
spin_unlock(&object->lock);
}

/*
* Abort object initialisation before we start it.
*/
Expand Down Expand Up @@ -610,6 +621,8 @@ static const struct fscache_state *fscache_lookup_failure(struct fscache_object
object->cache->ops->lookup_complete(object);
fscache_stat_d(&fscache_n_cop_lookup_complete);

set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags);

cookie = object->cookie;
set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
Expand All @@ -629,7 +642,7 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
_enter("{OBJ%x,%d,%d},%d",
object->debug_id, object->n_ops, object->n_children, event);

clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
fscache_mark_object_dead(object);
object->oob_event_mask = 0;

if (list_empty(&object->dependents) &&
Expand Down Expand Up @@ -948,7 +961,8 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj
if (!op)
goto nomem;

fscache_operation_init(op, object->cache->ops->invalidate_object, NULL);
fscache_operation_init(op, object->cache->ops->invalidate_object,
NULL, NULL);
op->flags = FSCACHE_OP_ASYNC |
(1 << FSCACHE_OP_EXCLUSIVE) |
(1 << FSCACHE_OP_UNUSE_COOKIE);
Expand All @@ -974,13 +988,13 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj
return transit_to(UPDATE_OBJECT);

nomem:
clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
fscache_mark_object_dead(object);
fscache_unuse_cookie(object);
_leave(" [ENOMEM]");
return transit_to(KILL_OBJECT);

submit_op_failed:
clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags);
fscache_mark_object_dead(object);
spin_unlock(&cookie->lock);
fscache_unuse_cookie(object);
kfree(op);
Expand Down Expand Up @@ -1016,3 +1030,50 @@ static const struct fscache_state *fscache_update_object(struct fscache_object *
_leave("");
return transit_to(WAIT_FOR_CMD);
}

/**
* fscache_object_retrying_stale - Note retrying stale object
* @object: The object that will be retried
*
* Note that an object lookup found an on-disk object that was adjudged to be
* stale and has been deleted. The lookup will be retried.
*/
void fscache_object_retrying_stale(struct fscache_object *object)
{
fscache_stat(&fscache_n_cache_no_space_reject);
}
EXPORT_SYMBOL(fscache_object_retrying_stale);

/**
* fscache_object_mark_killed - Note that an object was killed
* @object: The object that was culled
* @why: The reason the object was killed.
*
* Note that an object was killed. Returns true if the object was
* already marked killed, false if it wasn't.
*/
void fscache_object_mark_killed(struct fscache_object *object,
enum fscache_why_object_killed why)
{
if (test_and_set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags)) {
pr_err("Error: Object already killed by cache [%s]\n",
object->cache->identifier);
return;
}

switch (why) {
case FSCACHE_OBJECT_NO_SPACE:
fscache_stat(&fscache_n_cache_no_space_reject);
break;
case FSCACHE_OBJECT_IS_STALE:
fscache_stat(&fscache_n_cache_stale_objects);
break;
case FSCACHE_OBJECT_WAS_RETIRED:
fscache_stat(&fscache_n_cache_retired_objects);
break;
case FSCACHE_OBJECT_WAS_CULLED:
fscache_stat(&fscache_n_cache_culled_objects);
break;
}
}
EXPORT_SYMBOL(fscache_object_mark_killed);
Loading

0 comments on commit 8ea3a7c

Please sign in to comment.