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 | 13 | #include <trace/events/fscache.h> |
| 14 | 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 | 102 | const struct fscache_cache_ops cachefiles_cache_ops = { |
| 17 | 103 | .name = "cachefiles", |
| 18 | 104 | .acquire_volume = cachefiles_acquire_volume, |
| @@ -19,6 +19,16 @@ · 18 unmodified lines | ||
| 19 | 19 | struct cachefiles_cache; |
| 20 | 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 | 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 | 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 | 166 | * interface.c |
| 147 | 167 | */ |
| 148 | 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 | 182 | * namei.c |
| @@ -31,6 +31,8 @@ MODULE_DESCRIPTION("Mounted-filesystem based cache"); · 30 unmodified lines | ||
| 31 | 31 | MODULE_AUTHOR("Red Hat, Inc."); |
| 32 | 32 | MODULE_LICENSE("GPL"); |
| 33 | 33 | |
| 34 | +struct kmem_cache *cachefiles_object_jar; | |
| 35 | + | |
| 34 | 36 | static struct miscdevice cachefiles_dev = { |
| 35 | 37 | .minor = MISC_DYNAMIC_MINOR, |
| 36 | 38 | .name = "cachefiles", |
| @@ -51,9 +53,22 @@ static int __init cachefiles_init(void) · 14 unmodified lines | ||
| 51 | 53 | if (ret < 0) |
| 52 | 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 | 67 | pr_info("Loaded\n"); |
| 55 | 68 | return 0; |
| 56 | 69 | |
| 70 | +error_object_jar: | |
| 71 | + misc_deregister(&cachefiles_dev); | |
| 57 | 72 | error_dev: |
| 58 | 73 | cachefiles_unregister_error_injection(); |
| 59 | 74 | error_einj: |
| @@ -70,6 +85,7 @@ static void __exit cachefiles_exit(void) · 10 unmodified lines | ||
| 70 | 85 | { |
| 71 | 86 | pr_info("Unloading\n"); |
| 72 | 87 | |
| 88 | + kmem_cache_destroy(cachefiles_object_jar); | |
| 73 | 89 | misc_deregister(&cachefiles_dev); |
| 74 | 90 | cachefiles_unregister_error_injection(); |
| 75 | 91 | } |
| @@ -18,6 +18,21 @@ · 17 unmodified lines | ||
| 18 | 18 | #ifndef __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY |
| 19 | 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 | 36 | enum fscache_why_object_killed { |
| 22 | 37 | FSCACHE_OBJECT_IS_STALE, |
| 23 | 38 | FSCACHE_OBJECT_IS_WEIRD, |
| @@ -66,6 +81,20 @@ enum cachefiles_error_trace { · 42 unmodified lines | ||
| 66 | 81 | EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \ |
| 67 | 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 | 98 | #define cachefiles_trunc_traces \ |
| 70 | 99 | EM(cachefiles_trunc_dio_adjust, "DIOADJ") \ |
| 71 | 100 | EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \ |
| @@ -100,6 +129,7 @@ enum cachefiles_error_trace { · 28 unmodified lines | ||
| 100 | 129 | #define E_(a, b) TRACE_DEFINE_ENUM(a); |
| 101 | 130 | |
| 102 | 131 | cachefiles_obj_kill_traces; |
| 132 | +cachefiles_obj_ref_traces; | |
| 103 | 133 | cachefiles_trunc_traces; |
| 104 | 134 | cachefiles_error_traces; |
| 105 | 135 | |
| @@ -113,6 +143,34 @@ cachefiles_error_traces; · 7 unmodified lines | ||
| 113 | 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 | 174 | TRACE_EVENT(cachefiles_lookup, |
| 117 | 175 | TP_PROTO(struct cachefiles_object *obj, |
| 118 | 176 | struct dentry *de), |
| @@ -49,6 +49,7 @@ enum fscache_volume_trace { · 48 unmodified lines | ||
| 49 | 49 | enum fscache_cookie_trace { |
| 50 | 50 | fscache_cookie_collision, |
| 51 | 51 | fscache_cookie_discard, |
| 52 | + fscache_cookie_get_attach_object, | |
| 52 | 53 | fscache_cookie_get_end_access, |
| 53 | 54 | fscache_cookie_get_hash_collision, |
| 54 | 55 | fscache_cookie_get_inval_work, |
| @@ -57,6 +58,7 @@ enum fscache_cookie_trace { · 2 unmodified lines | ||
| 57 | 58 | fscache_cookie_new_acquire, |
| 58 | 59 | fscache_cookie_put_hash_collision, |
| 59 | 60 | fscache_cookie_put_lru, |
| 61 | + fscache_cookie_put_object, | |
| 60 | 62 | fscache_cookie_put_over_queued, |
| 61 | 63 | fscache_cookie_put_relinquish, |
| 62 | 64 | fscache_cookie_put_withdrawn, |
| @@ -122,6 +124,7 @@ enum fscache_access_trace { · 59 unmodified lines | ||
| 122 | 124 | #define fscache_cookie_traces \ |
| 123 | 125 | EM(fscache_cookie_collision, "*COLLIDE*") \ |
| 124 | 126 | EM(fscache_cookie_discard, "DISCARD ") \ |
| 127 | + EM(fscache_cookie_get_attach_object, "GET attch") \ | |
| 125 | 128 | EM(fscache_cookie_get_hash_collision, "GET hcoll") \ |
| 126 | 129 | EM(fscache_cookie_get_end_access, "GQ endac") \ |
| 127 | 130 | EM(fscache_cookie_get_inval_work, "GQ inval") \ |
| @@ -130,6 +133,7 @@ enum fscache_access_trace { · 2 unmodified lines | ||
| 130 | 133 | EM(fscache_cookie_new_acquire, "NEW acq ") \ |
| 131 | 134 | EM(fscache_cookie_put_hash_collision, "PUT hcoll") \ |
| 132 | 135 | EM(fscache_cookie_put_lru, "PUT lru ") \ |
| 136 | + EM(fscache_cookie_put_object, "PUT obj ") \ | |
| 133 | 137 | EM(fscache_cookie_put_over_queued, "PQ overq") \ |
| 134 | 138 | EM(fscache_cookie_put_relinquish, "PUT relnq") \ |
| 135 | 139 | EM(fscache_cookie_put_withdrawn, "PUT wthdn") \ |