OSDN Git Service

cachefiles: Implement object lifecycle funcs
authorDavid Howells <dhowells@redhat.com>
Wed, 17 Nov 2021 16:22:21 +0000 (16:22 +0000)
committerDavid Howells <dhowells@redhat.com>
Fri, 7 Jan 2022 13:42:08 +0000 (13:42 +0000)
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/
Link: https://lore.kernel.org/r/163906939569.143852.3594314410666551982.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/163967148857.1823006.6332962598220464364.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/164021547762.640689.8422781599594931000.stgit@warthog.procyon.org.uk/
fs/cachefiles/interface.c
fs/cachefiles/internal.h
fs/cachefiles/main.c
include/trace/events/cachefiles.h
include/trace/events/fscache.h

index 1793e46..68bb7b6 100644 (file)
 #include <trace/events/fscache.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 = {
        .name                   = "cachefiles",
        .acquire_volume         = cachefiles_acquire_volume,
index ab0e930..8763ee4 100644 (file)
 struct cachefiles_cache;
 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.
  */
@@ -31,10 +41,20 @@ struct cachefiles_volume {
 };
 
 /*
- * Data file records.
+ * Backing file state.
  */
 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
  */
 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
index 533e306..3f369c6 100644 (file)
@@ -31,6 +31,8 @@ MODULE_DESCRIPTION("Mounted-filesystem based cache");
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
+struct kmem_cache *cachefiles_object_jar;
+
 static struct miscdevice cachefiles_dev = {
        .minor  = MISC_DYNAMIC_MINOR,
        .name   = "cachefiles",
@@ -51,9 +53,22 @@ static int __init cachefiles_init(void)
        if (ret < 0)
                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");
        return 0;
 
+error_object_jar:
+       misc_deregister(&cachefiles_dev);
 error_dev:
        cachefiles_unregister_error_injection();
 error_einj:
@@ -70,6 +85,7 @@ static void __exit cachefiles_exit(void)
 {
        pr_info("Unloading\n");
 
+       kmem_cache_destroy(cachefiles_object_jar);
        misc_deregister(&cachefiles_dev);
        cachefiles_unregister_error_injection();
 }
index 5975ea4..54815cc 100644 (file)
 #ifndef __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 {
        FSCACHE_OBJECT_IS_STALE,
        FSCACHE_OBJECT_IS_WEIRD,
@@ -66,6 +81,20 @@ enum cachefiles_error_trace {
        EM(FSCACHE_OBJECT_WAS_RETIRED,  "was_retired")          \
        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                                                \
        EM(cachefiles_trunc_dio_adjust,         "DIOADJ")               \
        EM(cachefiles_trunc_expand_tmpfile,     "EXPTMP")               \
@@ -100,6 +129,7 @@ enum cachefiles_error_trace {
 #define E_(a, b) TRACE_DEFINE_ENUM(a);
 
 cachefiles_obj_kill_traces;
+cachefiles_obj_ref_traces;
 cachefiles_trunc_traces;
 cachefiles_error_traces;
 
@@ -113,6 +143,34 @@ cachefiles_error_traces;
 #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,
            TP_PROTO(struct cachefiles_object *obj,
                     struct dentry *de),
index 5fa37a8..d9d8302 100644 (file)
@@ -49,6 +49,7 @@ enum fscache_volume_trace {
 enum fscache_cookie_trace {
        fscache_cookie_collision,
        fscache_cookie_discard,
+       fscache_cookie_get_attach_object,
        fscache_cookie_get_end_access,
        fscache_cookie_get_hash_collision,
        fscache_cookie_get_inval_work,
@@ -57,6 +58,7 @@ enum fscache_cookie_trace {
        fscache_cookie_new_acquire,
        fscache_cookie_put_hash_collision,
        fscache_cookie_put_lru,
+       fscache_cookie_put_object,
        fscache_cookie_put_over_queued,
        fscache_cookie_put_relinquish,
        fscache_cookie_put_withdrawn,
@@ -122,6 +124,7 @@ enum fscache_access_trace {
 #define fscache_cookie_traces                                          \
        EM(fscache_cookie_collision,            "*COLLIDE*")            \
        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_end_access,       "GQ  endac")            \
        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_put_hash_collision,   "PUT hcoll")            \
        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_relinquish,       "PUT relnq")            \
        EM(fscache_cookie_put_withdrawn,        "PUT wthdn")            \