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.
Unified · Split
| @@ -13,6 +13,92 @@ · 12 unmodified lines | |||
| 13 | #include <trace/events/fscache.h> | 13 | #include <trace/events/fscache.h> |
| 14 | #include "internal.h" | 14 | #include "internal.h" |
| 15 | 15 | ||
| 16 | static atomic_t cachefiles_object_debug_id; | ||
| 17 | |||
| 18 | /* | ||
| 19 | * Allocate a cache object record. | ||
| 20 | */ | ||
| 21 | static | ||
| 22 | struct cachefiles_object *cachefiles_alloc_object(struct fscache_cookie *cookie) | ||
| 23 | { | ||
| 24 | struct fscache_volume *vcookie = cookie->volume; | ||
| 25 | struct cachefiles_volume *volume = vcookie->cache_priv; | ||
| 26 | struct cachefiles_object *object; | ||
| 27 | |||
| 28 | _enter("{%s},%x,", vcookie->key, cookie->debug_id); | ||
| 29 | |||
| 30 | object = kmem_cache_zalloc(cachefiles_object_jar, GFP_KERNEL); | ||
| 31 | if (!object) | ||
| 32 | return NULL; | ||
| 33 | |||
| 34 | refcount_set(&object->ref, 1); | ||
| 35 | |||
| 36 | spin_lock_init(&object->lock); | ||
| 37 | INIT_LIST_HEAD(&object->cache_link); | ||
| 38 | object->volume = volume; | ||
| 39 | object->debug_id = atomic_inc_return(&cachefiles_object_debug_id); | ||
| 40 | object->cookie = fscache_get_cookie(cookie, fscache_cookie_get_attach_object); | ||
| 41 | |||
| 42 | fscache_count_object(vcookie->cache); | ||
| 43 | trace_cachefiles_ref(object->debug_id, cookie->debug_id, 1, | ||
| 44 | cachefiles_obj_new); | ||
| 45 | return object; | ||
| 46 | } | ||
| 47 | |||
| 48 | /* | ||
| 49 | * Note that an object has been seen. | ||
| 50 | */ | ||
| 51 | void cachefiles_see_object(struct cachefiles_object *object, | ||
| 52 | enum cachefiles_obj_ref_trace why) | ||
| 53 | { | ||
| 54 | trace_cachefiles_ref(object->debug_id, object->cookie->debug_id, | ||
| 55 | refcount_read(&object->ref), why); | ||
| 56 | } | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Increment the usage count on an object; | ||
| 60 | */ | ||
| 61 | struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object, | ||
| 62 | enum cachefiles_obj_ref_trace why) | ||
| 63 | { | ||
| 64 | int r; | ||
| 65 | |||
| 66 | __refcount_inc(&object->ref, &r); | ||
| 67 | trace_cachefiles_ref(object->debug_id, object->cookie->debug_id, r, why); | ||
| 68 | return object; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* | ||
| 72 | * dispose of a reference to an object | ||
| 73 | */ | ||
| 74 | void cachefiles_put_object(struct cachefiles_object *object, | ||
| 75 | enum cachefiles_obj_ref_trace why) | ||
| 76 | { | ||
| 77 | unsigned int object_debug_id = object->debug_id; | ||
| 78 | unsigned int cookie_debug_id = object->cookie->debug_id; | ||
| 79 | struct fscache_cache *cache; | ||
| 80 | bool done; | ||
| 81 | int r; | ||
| 82 | |||
| 83 | done = __refcount_dec_and_test(&object->ref, &r); | ||
| 84 | trace_cachefiles_ref(object_debug_id, cookie_debug_id, r, why); | ||
| 85 | if (done) { | ||
| 86 | _debug("- kill object OBJ%x", object_debug_id); | ||
| 87 | |||
| 88 | ASSERTCMP(object->file, ==, NULL); | ||
| 89 | |||
| 90 | kfree(object->d_name); | ||
| 91 | |||
| 92 | cache = object->volume->cache->cache; | ||
| 93 | fscache_put_cookie(object->cookie, fscache_cookie_put_object); | ||
| 94 | object->cookie = NULL; | ||
| 95 | kmem_cache_free(cachefiles_object_jar, object); | ||
| 96 | fscache_uncount_object(cache); | ||
| 97 | } | ||
| 98 | |||
| 99 | _leave(""); | ||
| 100 | } | ||
| 101 | |||
| 16 | const struct fscache_cache_ops cachefiles_cache_ops = { | 102 | const struct fscache_cache_ops cachefiles_cache_ops = { |
| 17 | .name = "cachefiles", | 103 | .name = "cachefiles", |
| 18 | .acquire_volume = cachefiles_acquire_volume, | 104 | .acquire_volume = cachefiles_acquire_volume, |
| @@ -19,6 +19,16 @@ · 18 unmodified lines | |||
| 19 | struct cachefiles_cache; | 19 | struct cachefiles_cache; |
| 20 | struct cachefiles_object; | 20 | struct cachefiles_object; |
| 21 | 21 | ||
| 22 | enum cachefiles_content { | ||
| 23 | /* These values are saved on disk */ | ||
| 24 | CACHEFILES_CONTENT_NO_DATA = 0, /* No content stored */ | ||
| 25 | CACHEFILES_CONTENT_SINGLE = 1, /* Content is monolithic, all is present */ | ||
| 26 | CACHEFILES_CONTENT_ALL = 2, /* Content is all present, no map */ | ||
| 27 | CACHEFILES_CONTENT_BACKFS_MAP = 3, /* Content is piecemeal, mapped through backing fs */ | ||
| 28 | CACHEFILES_CONTENT_DIRTY = 4, /* Content is dirty (only seen on disk) */ | ||
| 29 | nr__cachefiles_content | ||
| 30 | }; | ||
| 31 | |||
| 22 | /* | 32 | /* |
| 23 | * Cached volume representation. | 33 | * Cached volume representation. |
| 24 | */ | 34 | */ |
| @@ -31,10 +41,20 @@ struct cachefiles_volume { · 6 unmodified lines | |||
| 31 | }; | 41 | }; |
| 32 | 42 | ||
| 33 | /* | 43 | /* |
| 34 | * Data file records. | 44 | * Backing file state. |
| 35 | */ | 45 | */ |
| 36 | struct cachefiles_object { | 46 | struct cachefiles_object { |
| 37 | int debug_id; /* debugging ID */ | 47 | struct fscache_cookie *cookie; /* Netfs data storage object cookie */ |
| 48 | struct cachefiles_volume *volume; /* Cache volume that holds this object */ | ||
| 49 | struct list_head cache_link; /* Link in cache->*_list */ | ||
| 50 | struct file *file; /* The file representing this object */ | ||
| 51 | char *d_name; /* Backing file name */ | ||
| 52 | int debug_id; | ||
| 53 | spinlock_t lock; | ||
| 54 | refcount_t ref; | ||
| 55 | u8 d_name_len; /* Length of filename */ | ||
| 56 | enum cachefiles_content content_info:8; /* Info about content presence */ | ||
| 57 | unsigned long flags; | ||
| 38 | }; | 58 | }; |
| 39 | 59 | ||
| 40 | /* | 60 | /* |
| @@ -146,6 +166,17 @@ static inline int cachefiles_inject_remove_error(void) · 105 unmodified lines | |||
| 146 | * interface.c | 166 | * interface.c |
| 147 | */ | 167 | */ |
| 148 | extern const struct fscache_cache_ops cachefiles_cache_ops; | 168 | extern const struct fscache_cache_ops cachefiles_cache_ops; |
| 169 | extern void cachefiles_see_object(struct cachefiles_object *object, | ||
| 170 | enum cachefiles_obj_ref_trace why); | ||
| 171 | extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object, | ||
| 172 | enum cachefiles_obj_ref_trace why); | ||
| 173 | extern void cachefiles_put_object(struct cachefiles_object *object, | ||
| 174 | enum cachefiles_obj_ref_trace why); | ||
| 175 | |||
| 176 | /* | ||
| 177 | * main.c | ||
| 178 | */ | ||
| 179 | extern struct kmem_cache *cachefiles_object_jar; | ||
| 149 | 180 | ||
| 150 | /* | 181 | /* |
| 151 | * namei.c | 182 | * namei.c |
| @@ -31,6 +31,8 @@ MODULE_DESCRIPTION("Mounted-filesystem based cache"); · 30 unmodified lines | |||
| 31 | MODULE_AUTHOR("Red Hat, Inc."); | 31 | MODULE_AUTHOR("Red Hat, Inc."); |
| 32 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
| 33 | 33 | ||
| 34 | struct kmem_cache *cachefiles_object_jar; | ||
| 35 | |||
| 34 | static struct miscdevice cachefiles_dev = { | 36 | static struct miscdevice cachefiles_dev = { |
| 35 | .minor = MISC_DYNAMIC_MINOR, | 37 | .minor = MISC_DYNAMIC_MINOR, |
| 36 | .name = "cachefiles", | 38 | .name = "cachefiles", |
| @@ -51,9 +53,22 @@ static int __init cachefiles_init(void) · 14 unmodified lines | |||
| 51 | if (ret < 0) | 53 | if (ret < 0) |
| 52 | goto error_dev; | 54 | goto error_dev; |
| 53 | 55 | ||
| 56 | /* create an object jar */ | ||
| 57 | ret = -ENOMEM; | ||
| 58 | cachefiles_object_jar = | ||
| 59 | kmem_cache_create("cachefiles_object_jar", | ||
| 60 | sizeof(struct cachefiles_object), | ||
| 61 | 0, SLAB_HWCACHE_ALIGN, NULL); | ||
| 62 | if (!cachefiles_object_jar) { | ||
| 63 | pr_notice("Failed to allocate an object jar\n"); | ||
| 64 | goto error_object_jar; | ||
| 65 | } | ||
| 66 | |||
| 54 | pr_info("Loaded\n"); | 67 | pr_info("Loaded\n"); |
| 55 | return 0; | 68 | return 0; |
| 56 | 69 | ||
| 70 | error_object_jar: | ||
| 71 | misc_deregister(&cachefiles_dev); | ||
| 57 | error_dev: | 72 | error_dev: |
| 58 | cachefiles_unregister_error_injection(); | 73 | cachefiles_unregister_error_injection(); |
| 59 | error_einj: | 74 | error_einj: |
| @@ -70,6 +85,7 @@ static void __exit cachefiles_exit(void) · 10 unmodified lines | |||
| 70 | { | 85 | { |
| 71 | pr_info("Unloading\n"); | 86 | pr_info("Unloading\n"); |
| 72 | 87 | ||
| 88 | kmem_cache_destroy(cachefiles_object_jar); | ||
| 73 | misc_deregister(&cachefiles_dev); | 89 | misc_deregister(&cachefiles_dev); |
| 74 | cachefiles_unregister_error_injection(); | 90 | cachefiles_unregister_error_injection(); |
| 75 | } | 91 | } |
| @@ -18,6 +18,21 @@ · 17 unmodified lines | |||
| 18 | #ifndef __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY | 18 | #ifndef __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY |
| 19 | #define __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY | 19 | #define __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY |
| 20 | 20 | ||
| 21 | enum cachefiles_obj_ref_trace { | ||
| 22 | cachefiles_obj_get_ioreq, | ||
| 23 | cachefiles_obj_new, | ||
| 24 | cachefiles_obj_put_alloc_fail, | ||
| 25 | cachefiles_obj_put_detach, | ||
| 26 | cachefiles_obj_put_ioreq, | ||
| 27 | cachefiles_obj_see_clean_commit, | ||
| 28 | cachefiles_obj_see_clean_delete, | ||
| 29 | cachefiles_obj_see_clean_drop_tmp, | ||
| 30 | cachefiles_obj_see_lookup_cookie, | ||
| 31 | cachefiles_obj_see_lookup_failed, | ||
| 32 | cachefiles_obj_see_withdraw_cookie, | ||
| 33 | cachefiles_obj_see_withdrawal, | ||
| 34 | }; | ||
| 35 | |||
| 21 | enum fscache_why_object_killed { | 36 | enum fscache_why_object_killed { |
| 22 | FSCACHE_OBJECT_IS_STALE, | 37 | FSCACHE_OBJECT_IS_STALE, |
| 23 | FSCACHE_OBJECT_IS_WEIRD, | 38 | FSCACHE_OBJECT_IS_WEIRD, |
| @@ -66,6 +81,20 @@ enum cachefiles_error_trace { · 42 unmodified lines | |||
| 66 | EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \ | 81 | EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \ |
| 67 | E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled") | 82 | E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled") |
| 68 | 83 | ||
| 84 | #define cachefiles_obj_ref_traces \ | ||
| 85 | EM(cachefiles_obj_get_ioreq, "GET ioreq") \ | ||
| 86 | EM(cachefiles_obj_new, "NEW obj") \ | ||
| 87 | EM(cachefiles_obj_put_alloc_fail, "PUT alloc_fail") \ | ||
| 88 | EM(cachefiles_obj_put_detach, "PUT detach") \ | ||
| 89 | EM(cachefiles_obj_put_ioreq, "PUT ioreq") \ | ||
| 90 | EM(cachefiles_obj_see_clean_commit, "SEE clean_commit") \ | ||
| 91 | EM(cachefiles_obj_see_clean_delete, "SEE clean_delete") \ | ||
| 92 | EM(cachefiles_obj_see_clean_drop_tmp, "SEE clean_drop_tmp") \ | ||
| 93 | EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \ | ||
| 94 | EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \ | ||
| 95 | EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ | ||
| 96 | E_(cachefiles_obj_see_withdrawal, "SEE withdrawal") | ||
| 97 | |||
| 69 | #define cachefiles_trunc_traces \ | 98 | #define cachefiles_trunc_traces \ |
| 70 | EM(cachefiles_trunc_dio_adjust, "DIOADJ") \ | 99 | EM(cachefiles_trunc_dio_adjust, "DIOADJ") \ |
| 71 | EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \ | 100 | EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \ |
| @@ -100,6 +129,7 @@ enum cachefiles_error_trace { · 28 unmodified lines | |||
| 100 | #define E_(a, b) TRACE_DEFINE_ENUM(a); | 129 | #define E_(a, b) TRACE_DEFINE_ENUM(a); |
| 101 | 130 | ||
| 102 | cachefiles_obj_kill_traces; | 131 | cachefiles_obj_kill_traces; |
| 132 | cachefiles_obj_ref_traces; | ||
| 103 | cachefiles_trunc_traces; | 133 | cachefiles_trunc_traces; |
| 104 | cachefiles_error_traces; | 134 | cachefiles_error_traces; |
| 105 | 135 | ||
| @@ -113,6 +143,34 @@ cachefiles_error_traces; · 7 unmodified lines | |||
| 113 | #define E_(a, b) { a, b } | 143 | #define E_(a, b) { a, b } |
| 114 | 144 | ||
| 115 | 145 | ||
| 146 | TRACE_EVENT(cachefiles_ref, | ||
| 147 | TP_PROTO(unsigned int object_debug_id, | ||
| 148 | unsigned int cookie_debug_id, | ||
| 149 | int usage, | ||
| 150 | enum cachefiles_obj_ref_trace why), | ||
| 151 | |||
| 152 | TP_ARGS(object_debug_id, cookie_debug_id, usage, why), | ||
| 153 | |||
| 154 | /* Note that obj may be NULL */ | ||
| 155 | TP_STRUCT__entry( | ||
| 156 | __field(unsigned int, obj ) | ||
| 157 | __field(unsigned int, cookie ) | ||
| 158 | __field(enum cachefiles_obj_ref_trace, why ) | ||
| 159 | __field(int, usage ) | ||
| 160 | ), | ||
| 161 | |||
| 162 | TP_fast_assign( | ||
| 163 | __entry->obj = object_debug_id; | ||
| 164 | __entry->cookie = cookie_debug_id; | ||
| 165 | __entry->usage = usage; | ||
| 166 | __entry->why = why; | ||
| 167 | ), | ||
| 168 | |||
| 169 | TP_printk("c=%08x o=%08x u=%d %s", | ||
| 170 | __entry->cookie, __entry->obj, __entry->usage, | ||
| 171 | __print_symbolic(__entry->why, cachefiles_obj_ref_traces)) | ||
| 172 | ); | ||
| 173 | |||
| 116 | TRACE_EVENT(cachefiles_lookup, | 174 | TRACE_EVENT(cachefiles_lookup, |
| 117 | TP_PROTO(struct cachefiles_object *obj, | 175 | TP_PROTO(struct cachefiles_object *obj, |
| 118 | struct dentry *de), | 176 | struct dentry *de), |
| @@ -49,6 +49,7 @@ enum fscache_volume_trace { · 48 unmodified lines | |||
| 49 | enum fscache_cookie_trace { | 49 | enum fscache_cookie_trace { |
| 50 | fscache_cookie_collision, | 50 | fscache_cookie_collision, |
| 51 | fscache_cookie_discard, | 51 | fscache_cookie_discard, |
| 52 | fscache_cookie_get_attach_object, | ||
| 52 | fscache_cookie_get_end_access, | 53 | fscache_cookie_get_end_access, |
| 53 | fscache_cookie_get_hash_collision, | 54 | fscache_cookie_get_hash_collision, |
| 54 | fscache_cookie_get_inval_work, | 55 | fscache_cookie_get_inval_work, |
| @@ -57,6 +58,7 @@ enum fscache_cookie_trace { · 2 unmodified lines | |||
| 57 | fscache_cookie_new_acquire, | 58 | fscache_cookie_new_acquire, |
| 58 | fscache_cookie_put_hash_collision, | 59 | fscache_cookie_put_hash_collision, |
| 59 | fscache_cookie_put_lru, | 60 | fscache_cookie_put_lru, |
| 61 | fscache_cookie_put_object, | ||
| 60 | fscache_cookie_put_over_queued, | 62 | fscache_cookie_put_over_queued, |
| 61 | fscache_cookie_put_relinquish, | 63 | fscache_cookie_put_relinquish, |
| 62 | fscache_cookie_put_withdrawn, | 64 | fscache_cookie_put_withdrawn, |
| @@ -122,6 +124,7 @@ enum fscache_access_trace { · 59 unmodified lines | |||
| 122 | #define fscache_cookie_traces \ | 124 | #define fscache_cookie_traces \ |
| 123 | EM(fscache_cookie_collision, "*COLLIDE*") \ | 125 | EM(fscache_cookie_collision, "*COLLIDE*") \ |
| 124 | EM(fscache_cookie_discard, "DISCARD ") \ | 126 | EM(fscache_cookie_discard, "DISCARD ") \ |
| 127 | EM(fscache_cookie_get_attach_object, "GET attch") \ | ||
| 125 | EM(fscache_cookie_get_hash_collision, "GET hcoll") \ | 128 | EM(fscache_cookie_get_hash_collision, "GET hcoll") \ |
| 126 | EM(fscache_cookie_get_end_access, "GQ endac") \ | 129 | EM(fscache_cookie_get_end_access, "GQ endac") \ |
| 127 | EM(fscache_cookie_get_inval_work, "GQ inval") \ | 130 | EM(fscache_cookie_get_inval_work, "GQ inval") \ |
| @@ -130,6 +133,7 @@ enum fscache_access_trace { · 2 unmodified lines | |||
| 130 | EM(fscache_cookie_new_acquire, "NEW acq ") \ | 133 | EM(fscache_cookie_new_acquire, "NEW acq ") \ |
| 131 | EM(fscache_cookie_put_hash_collision, "PUT hcoll") \ | 134 | EM(fscache_cookie_put_hash_collision, "PUT hcoll") \ |
| 132 | EM(fscache_cookie_put_lru, "PUT lru ") \ | 135 | EM(fscache_cookie_put_lru, "PUT lru ") \ |
| 136 | EM(fscache_cookie_put_object, "PUT obj ") \ | ||
| 133 | EM(fscache_cookie_put_over_queued, "PQ overq") \ | 137 | EM(fscache_cookie_put_over_queued, "PQ overq") \ |
| 134 | EM(fscache_cookie_put_relinquish, "PUT relnq") \ | 138 | EM(fscache_cookie_put_relinquish, "PUT relnq") \ |
| 135 | EM(fscache_cookie_put_withdrawn, "PUT wthdn") \ | 139 | EM(fscache_cookie_put_withdrawn, "PUT wthdn") \ |