mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
cachefiles: Implement object lifecycle funcs
Implement allocate, get, see and put functions for the cachefiles_object struct. The members of the struct we're going to need are also added. Additionally, implement a lifecycle tracepoint. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/163819639457.215744.4600093239395728232.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/163906939569.143852.3594314410666551982.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/163967148857.1823006.6332962598220464364.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/164021547762.640689.8422781599594931000.stgit@warthog.procyon.org.uk/ # v4
This commit is contained in:
parent
13871bad1e
commit
df98e87f20
@ -13,6 +13,92 @@
|
|||||||
#include <trace/events/fscache.h>
|
#include <trace/events/fscache.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
static atomic_t cachefiles_object_debug_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a cache object record.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
struct cachefiles_object *cachefiles_alloc_object(struct fscache_cookie *cookie)
|
||||||
|
{
|
||||||
|
struct fscache_volume *vcookie = cookie->volume;
|
||||||
|
struct cachefiles_volume *volume = vcookie->cache_priv;
|
||||||
|
struct cachefiles_object *object;
|
||||||
|
|
||||||
|
_enter("{%s},%x,", vcookie->key, cookie->debug_id);
|
||||||
|
|
||||||
|
object = kmem_cache_zalloc(cachefiles_object_jar, GFP_KERNEL);
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
refcount_set(&object->ref, 1);
|
||||||
|
|
||||||
|
spin_lock_init(&object->lock);
|
||||||
|
INIT_LIST_HEAD(&object->cache_link);
|
||||||
|
object->volume = volume;
|
||||||
|
object->debug_id = atomic_inc_return(&cachefiles_object_debug_id);
|
||||||
|
object->cookie = fscache_get_cookie(cookie, fscache_cookie_get_attach_object);
|
||||||
|
|
||||||
|
fscache_count_object(vcookie->cache);
|
||||||
|
trace_cachefiles_ref(object->debug_id, cookie->debug_id, 1,
|
||||||
|
cachefiles_obj_new);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that an object has been seen.
|
||||||
|
*/
|
||||||
|
void cachefiles_see_object(struct cachefiles_object *object,
|
||||||
|
enum cachefiles_obj_ref_trace why)
|
||||||
|
{
|
||||||
|
trace_cachefiles_ref(object->debug_id, object->cookie->debug_id,
|
||||||
|
refcount_read(&object->ref), why);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increment the usage count on an object;
|
||||||
|
*/
|
||||||
|
struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object,
|
||||||
|
enum cachefiles_obj_ref_trace why)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
__refcount_inc(&object->ref, &r);
|
||||||
|
trace_cachefiles_ref(object->debug_id, object->cookie->debug_id, r, why);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dispose of a reference to an object
|
||||||
|
*/
|
||||||
|
void cachefiles_put_object(struct cachefiles_object *object,
|
||||||
|
enum cachefiles_obj_ref_trace why)
|
||||||
|
{
|
||||||
|
unsigned int object_debug_id = object->debug_id;
|
||||||
|
unsigned int cookie_debug_id = object->cookie->debug_id;
|
||||||
|
struct fscache_cache *cache;
|
||||||
|
bool done;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
done = __refcount_dec_and_test(&object->ref, &r);
|
||||||
|
trace_cachefiles_ref(object_debug_id, cookie_debug_id, r, why);
|
||||||
|
if (done) {
|
||||||
|
_debug("- kill object OBJ%x", object_debug_id);
|
||||||
|
|
||||||
|
ASSERTCMP(object->file, ==, NULL);
|
||||||
|
|
||||||
|
kfree(object->d_name);
|
||||||
|
|
||||||
|
cache = object->volume->cache->cache;
|
||||||
|
fscache_put_cookie(object->cookie, fscache_cookie_put_object);
|
||||||
|
object->cookie = NULL;
|
||||||
|
kmem_cache_free(cachefiles_object_jar, object);
|
||||||
|
fscache_uncount_object(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
_leave("");
|
||||||
|
}
|
||||||
|
|
||||||
const struct fscache_cache_ops cachefiles_cache_ops = {
|
const struct fscache_cache_ops cachefiles_cache_ops = {
|
||||||
.name = "cachefiles",
|
.name = "cachefiles",
|
||||||
.acquire_volume = cachefiles_acquire_volume,
|
.acquire_volume = cachefiles_acquire_volume,
|
||||||
|
@ -19,6 +19,16 @@
|
|||||||
struct cachefiles_cache;
|
struct cachefiles_cache;
|
||||||
struct cachefiles_object;
|
struct cachefiles_object;
|
||||||
|
|
||||||
|
enum cachefiles_content {
|
||||||
|
/* These values are saved on disk */
|
||||||
|
CACHEFILES_CONTENT_NO_DATA = 0, /* No content stored */
|
||||||
|
CACHEFILES_CONTENT_SINGLE = 1, /* Content is monolithic, all is present */
|
||||||
|
CACHEFILES_CONTENT_ALL = 2, /* Content is all present, no map */
|
||||||
|
CACHEFILES_CONTENT_BACKFS_MAP = 3, /* Content is piecemeal, mapped through backing fs */
|
||||||
|
CACHEFILES_CONTENT_DIRTY = 4, /* Content is dirty (only seen on disk) */
|
||||||
|
nr__cachefiles_content
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cached volume representation.
|
* Cached volume representation.
|
||||||
*/
|
*/
|
||||||
@ -31,10 +41,20 @@ struct cachefiles_volume {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data file records.
|
* Backing file state.
|
||||||
*/
|
*/
|
||||||
struct cachefiles_object {
|
struct cachefiles_object {
|
||||||
int debug_id; /* debugging ID */
|
struct fscache_cookie *cookie; /* Netfs data storage object cookie */
|
||||||
|
struct cachefiles_volume *volume; /* Cache volume that holds this object */
|
||||||
|
struct list_head cache_link; /* Link in cache->*_list */
|
||||||
|
struct file *file; /* The file representing this object */
|
||||||
|
char *d_name; /* Backing file name */
|
||||||
|
int debug_id;
|
||||||
|
spinlock_t lock;
|
||||||
|
refcount_t ref;
|
||||||
|
u8 d_name_len; /* Length of filename */
|
||||||
|
enum cachefiles_content content_info:8; /* Info about content presence */
|
||||||
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -146,6 +166,17 @@ static inline int cachefiles_inject_remove_error(void)
|
|||||||
* interface.c
|
* interface.c
|
||||||
*/
|
*/
|
||||||
extern const struct fscache_cache_ops cachefiles_cache_ops;
|
extern const struct fscache_cache_ops cachefiles_cache_ops;
|
||||||
|
extern void cachefiles_see_object(struct cachefiles_object *object,
|
||||||
|
enum cachefiles_obj_ref_trace why);
|
||||||
|
extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object,
|
||||||
|
enum cachefiles_obj_ref_trace why);
|
||||||
|
extern void cachefiles_put_object(struct cachefiles_object *object,
|
||||||
|
enum cachefiles_obj_ref_trace why);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* main.c
|
||||||
|
*/
|
||||||
|
extern struct kmem_cache *cachefiles_object_jar;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* namei.c
|
* namei.c
|
||||||
|
@ -31,6 +31,8 @@ MODULE_DESCRIPTION("Mounted-filesystem based cache");
|
|||||||
MODULE_AUTHOR("Red Hat, Inc.");
|
MODULE_AUTHOR("Red Hat, Inc.");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
struct kmem_cache *cachefiles_object_jar;
|
||||||
|
|
||||||
static struct miscdevice cachefiles_dev = {
|
static struct miscdevice cachefiles_dev = {
|
||||||
.minor = MISC_DYNAMIC_MINOR,
|
.minor = MISC_DYNAMIC_MINOR,
|
||||||
.name = "cachefiles",
|
.name = "cachefiles",
|
||||||
@ -51,9 +53,22 @@ static int __init cachefiles_init(void)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_dev;
|
goto error_dev;
|
||||||
|
|
||||||
|
/* create an object jar */
|
||||||
|
ret = -ENOMEM;
|
||||||
|
cachefiles_object_jar =
|
||||||
|
kmem_cache_create("cachefiles_object_jar",
|
||||||
|
sizeof(struct cachefiles_object),
|
||||||
|
0, SLAB_HWCACHE_ALIGN, NULL);
|
||||||
|
if (!cachefiles_object_jar) {
|
||||||
|
pr_notice("Failed to allocate an object jar\n");
|
||||||
|
goto error_object_jar;
|
||||||
|
}
|
||||||
|
|
||||||
pr_info("Loaded\n");
|
pr_info("Loaded\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_object_jar:
|
||||||
|
misc_deregister(&cachefiles_dev);
|
||||||
error_dev:
|
error_dev:
|
||||||
cachefiles_unregister_error_injection();
|
cachefiles_unregister_error_injection();
|
||||||
error_einj:
|
error_einj:
|
||||||
@ -70,6 +85,7 @@ static void __exit cachefiles_exit(void)
|
|||||||
{
|
{
|
||||||
pr_info("Unloading\n");
|
pr_info("Unloading\n");
|
||||||
|
|
||||||
|
kmem_cache_destroy(cachefiles_object_jar);
|
||||||
misc_deregister(&cachefiles_dev);
|
misc_deregister(&cachefiles_dev);
|
||||||
cachefiles_unregister_error_injection();
|
cachefiles_unregister_error_injection();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,21 @@
|
|||||||
#ifndef __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
#ifndef __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
||||||
#define __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
#define __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
||||||
|
|
||||||
|
enum cachefiles_obj_ref_trace {
|
||||||
|
cachefiles_obj_get_ioreq,
|
||||||
|
cachefiles_obj_new,
|
||||||
|
cachefiles_obj_put_alloc_fail,
|
||||||
|
cachefiles_obj_put_detach,
|
||||||
|
cachefiles_obj_put_ioreq,
|
||||||
|
cachefiles_obj_see_clean_commit,
|
||||||
|
cachefiles_obj_see_clean_delete,
|
||||||
|
cachefiles_obj_see_clean_drop_tmp,
|
||||||
|
cachefiles_obj_see_lookup_cookie,
|
||||||
|
cachefiles_obj_see_lookup_failed,
|
||||||
|
cachefiles_obj_see_withdraw_cookie,
|
||||||
|
cachefiles_obj_see_withdrawal,
|
||||||
|
};
|
||||||
|
|
||||||
enum fscache_why_object_killed {
|
enum fscache_why_object_killed {
|
||||||
FSCACHE_OBJECT_IS_STALE,
|
FSCACHE_OBJECT_IS_STALE,
|
||||||
FSCACHE_OBJECT_IS_WEIRD,
|
FSCACHE_OBJECT_IS_WEIRD,
|
||||||
@ -66,6 +81,20 @@ enum cachefiles_error_trace {
|
|||||||
EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \
|
EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \
|
||||||
E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled")
|
E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled")
|
||||||
|
|
||||||
|
#define cachefiles_obj_ref_traces \
|
||||||
|
EM(cachefiles_obj_get_ioreq, "GET ioreq") \
|
||||||
|
EM(cachefiles_obj_new, "NEW obj") \
|
||||||
|
EM(cachefiles_obj_put_alloc_fail, "PUT alloc_fail") \
|
||||||
|
EM(cachefiles_obj_put_detach, "PUT detach") \
|
||||||
|
EM(cachefiles_obj_put_ioreq, "PUT ioreq") \
|
||||||
|
EM(cachefiles_obj_see_clean_commit, "SEE clean_commit") \
|
||||||
|
EM(cachefiles_obj_see_clean_delete, "SEE clean_delete") \
|
||||||
|
EM(cachefiles_obj_see_clean_drop_tmp, "SEE clean_drop_tmp") \
|
||||||
|
EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \
|
||||||
|
EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \
|
||||||
|
EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \
|
||||||
|
E_(cachefiles_obj_see_withdrawal, "SEE withdrawal")
|
||||||
|
|
||||||
#define cachefiles_trunc_traces \
|
#define cachefiles_trunc_traces \
|
||||||
EM(cachefiles_trunc_dio_adjust, "DIOADJ") \
|
EM(cachefiles_trunc_dio_adjust, "DIOADJ") \
|
||||||
EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \
|
EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \
|
||||||
@ -100,6 +129,7 @@ enum cachefiles_error_trace {
|
|||||||
#define E_(a, b) TRACE_DEFINE_ENUM(a);
|
#define E_(a, b) TRACE_DEFINE_ENUM(a);
|
||||||
|
|
||||||
cachefiles_obj_kill_traces;
|
cachefiles_obj_kill_traces;
|
||||||
|
cachefiles_obj_ref_traces;
|
||||||
cachefiles_trunc_traces;
|
cachefiles_trunc_traces;
|
||||||
cachefiles_error_traces;
|
cachefiles_error_traces;
|
||||||
|
|
||||||
@ -113,6 +143,34 @@ cachefiles_error_traces;
|
|||||||
#define E_(a, b) { a, b }
|
#define E_(a, b) { a, b }
|
||||||
|
|
||||||
|
|
||||||
|
TRACE_EVENT(cachefiles_ref,
|
||||||
|
TP_PROTO(unsigned int object_debug_id,
|
||||||
|
unsigned int cookie_debug_id,
|
||||||
|
int usage,
|
||||||
|
enum cachefiles_obj_ref_trace why),
|
||||||
|
|
||||||
|
TP_ARGS(object_debug_id, cookie_debug_id, usage, why),
|
||||||
|
|
||||||
|
/* Note that obj may be NULL */
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(unsigned int, obj )
|
||||||
|
__field(unsigned int, cookie )
|
||||||
|
__field(enum cachefiles_obj_ref_trace, why )
|
||||||
|
__field(int, usage )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->obj = object_debug_id;
|
||||||
|
__entry->cookie = cookie_debug_id;
|
||||||
|
__entry->usage = usage;
|
||||||
|
__entry->why = why;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("c=%08x o=%08x u=%d %s",
|
||||||
|
__entry->cookie, __entry->obj, __entry->usage,
|
||||||
|
__print_symbolic(__entry->why, cachefiles_obj_ref_traces))
|
||||||
|
);
|
||||||
|
|
||||||
TRACE_EVENT(cachefiles_lookup,
|
TRACE_EVENT(cachefiles_lookup,
|
||||||
TP_PROTO(struct cachefiles_object *obj,
|
TP_PROTO(struct cachefiles_object *obj,
|
||||||
struct dentry *de),
|
struct dentry *de),
|
||||||
|
@ -49,6 +49,7 @@ enum fscache_volume_trace {
|
|||||||
enum fscache_cookie_trace {
|
enum fscache_cookie_trace {
|
||||||
fscache_cookie_collision,
|
fscache_cookie_collision,
|
||||||
fscache_cookie_discard,
|
fscache_cookie_discard,
|
||||||
|
fscache_cookie_get_attach_object,
|
||||||
fscache_cookie_get_end_access,
|
fscache_cookie_get_end_access,
|
||||||
fscache_cookie_get_hash_collision,
|
fscache_cookie_get_hash_collision,
|
||||||
fscache_cookie_get_inval_work,
|
fscache_cookie_get_inval_work,
|
||||||
@ -57,6 +58,7 @@ enum fscache_cookie_trace {
|
|||||||
fscache_cookie_new_acquire,
|
fscache_cookie_new_acquire,
|
||||||
fscache_cookie_put_hash_collision,
|
fscache_cookie_put_hash_collision,
|
||||||
fscache_cookie_put_lru,
|
fscache_cookie_put_lru,
|
||||||
|
fscache_cookie_put_object,
|
||||||
fscache_cookie_put_over_queued,
|
fscache_cookie_put_over_queued,
|
||||||
fscache_cookie_put_relinquish,
|
fscache_cookie_put_relinquish,
|
||||||
fscache_cookie_put_withdrawn,
|
fscache_cookie_put_withdrawn,
|
||||||
@ -122,6 +124,7 @@ enum fscache_access_trace {
|
|||||||
#define fscache_cookie_traces \
|
#define fscache_cookie_traces \
|
||||||
EM(fscache_cookie_collision, "*COLLIDE*") \
|
EM(fscache_cookie_collision, "*COLLIDE*") \
|
||||||
EM(fscache_cookie_discard, "DISCARD ") \
|
EM(fscache_cookie_discard, "DISCARD ") \
|
||||||
|
EM(fscache_cookie_get_attach_object, "GET attch") \
|
||||||
EM(fscache_cookie_get_hash_collision, "GET hcoll") \
|
EM(fscache_cookie_get_hash_collision, "GET hcoll") \
|
||||||
EM(fscache_cookie_get_end_access, "GQ endac") \
|
EM(fscache_cookie_get_end_access, "GQ endac") \
|
||||||
EM(fscache_cookie_get_inval_work, "GQ inval") \
|
EM(fscache_cookie_get_inval_work, "GQ inval") \
|
||||||
@ -130,6 +133,7 @@ enum fscache_access_trace {
|
|||||||
EM(fscache_cookie_new_acquire, "NEW acq ") \
|
EM(fscache_cookie_new_acquire, "NEW acq ") \
|
||||||
EM(fscache_cookie_put_hash_collision, "PUT hcoll") \
|
EM(fscache_cookie_put_hash_collision, "PUT hcoll") \
|
||||||
EM(fscache_cookie_put_lru, "PUT lru ") \
|
EM(fscache_cookie_put_lru, "PUT lru ") \
|
||||||
|
EM(fscache_cookie_put_object, "PUT obj ") \
|
||||||
EM(fscache_cookie_put_over_queued, "PQ overq") \
|
EM(fscache_cookie_put_over_queued, "PQ overq") \
|
||||||
EM(fscache_cookie_put_relinquish, "PUT relnq") \
|
EM(fscache_cookie_put_relinquish, "PUT relnq") \
|
||||||
EM(fscache_cookie_put_withdrawn, "PUT wthdn") \
|
EM(fscache_cookie_put_withdrawn, "PUT wthdn") \
|
||||||
|
Loading…
Reference in New Issue
Block a user