Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+197 -2
+86
fs/cachefiles/interface.c
··· 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,
+33 -2
fs/cachefiles/internal.h
··· 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 */ ··· 41 31 }; 42 32 43 33 /* 44 - * Data file records. 34 + * Backing file state. 45 35 */ 46 36 struct cachefiles_object { 47 - int debug_id; /* debugging ID */ 37 + struct fscache_cookie *cookie; /* Netfs data storage object cookie */ 38 + struct cachefiles_volume *volume; /* Cache volume that holds this object */ 39 + struct list_head cache_link; /* Link in cache->*_list */ 40 + struct file *file; /* The file representing this object */ 41 + char *d_name; /* Backing file name */ 42 + int debug_id; 43 + spinlock_t lock; 44 + refcount_t ref; 45 + u8 d_name_len; /* Length of filename */ 46 + enum cachefiles_content content_info:8; /* Info about content presence */ 47 + unsigned long flags; 48 48 }; 49 49 50 50 /* ··· 166 146 * interface.c 167 147 */ 168 148 extern const struct fscache_cache_ops cachefiles_cache_ops; 149 + extern void cachefiles_see_object(struct cachefiles_object *object, 150 + enum cachefiles_obj_ref_trace why); 151 + extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object, 152 + enum cachefiles_obj_ref_trace why); 153 + extern void cachefiles_put_object(struct cachefiles_object *object, 154 + enum cachefiles_obj_ref_trace why); 155 + 156 + /* 157 + * main.c 158 + */ 159 + extern struct kmem_cache *cachefiles_object_jar; 169 160 170 161 /* 171 162 * namei.c
+16
fs/cachefiles/main.c
··· 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", ··· 53 51 if (ret < 0) 54 52 goto error_dev; 55 53 54 + /* create an object jar */ 55 + ret = -ENOMEM; 56 + cachefiles_object_jar = 57 + kmem_cache_create("cachefiles_object_jar", 58 + sizeof(struct cachefiles_object), 59 + 0, SLAB_HWCACHE_ALIGN, NULL); 60 + if (!cachefiles_object_jar) { 61 + pr_notice("Failed to allocate an object jar\n"); 62 + goto error_object_jar; 63 + } 64 + 56 65 pr_info("Loaded\n"); 57 66 return 0; 58 67 68 + error_object_jar: 69 + misc_deregister(&cachefiles_dev); 59 70 error_dev: 60 71 cachefiles_unregister_error_injection(); 61 72 error_einj: ··· 85 70 { 86 71 pr_info("Unloading\n"); 87 72 73 + kmem_cache_destroy(cachefiles_object_jar); 88 74 misc_deregister(&cachefiles_dev); 89 75 cachefiles_unregister_error_injection(); 90 76 }
+58
include/trace/events/cachefiles.h
··· 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, ··· 81 66 EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \ 82 67 E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled") 83 68 69 + #define cachefiles_obj_ref_traces \ 70 + EM(cachefiles_obj_get_ioreq, "GET ioreq") \ 71 + EM(cachefiles_obj_new, "NEW obj") \ 72 + EM(cachefiles_obj_put_alloc_fail, "PUT alloc_fail") \ 73 + EM(cachefiles_obj_put_detach, "PUT detach") \ 74 + EM(cachefiles_obj_put_ioreq, "PUT ioreq") \ 75 + EM(cachefiles_obj_see_clean_commit, "SEE clean_commit") \ 76 + EM(cachefiles_obj_see_clean_delete, "SEE clean_delete") \ 77 + EM(cachefiles_obj_see_clean_drop_tmp, "SEE clean_drop_tmp") \ 78 + EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \ 79 + EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \ 80 + EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ 81 + E_(cachefiles_obj_see_withdrawal, "SEE withdrawal") 82 + 84 83 #define cachefiles_trunc_traces \ 85 84 EM(cachefiles_trunc_dio_adjust, "DIOADJ") \ 86 85 EM(cachefiles_trunc_expand_tmpfile, "EXPTMP") \ ··· 129 100 #define E_(a, b) TRACE_DEFINE_ENUM(a); 130 101 131 102 cachefiles_obj_kill_traces; 103 + cachefiles_obj_ref_traces; 132 104 cachefiles_trunc_traces; 133 105 cachefiles_error_traces; 134 106 ··· 142 112 #define EM(a, b) { a, b }, 143 113 #define E_(a, b) { a, b } 144 114 115 + 116 + TRACE_EVENT(cachefiles_ref, 117 + TP_PROTO(unsigned int object_debug_id, 118 + unsigned int cookie_debug_id, 119 + int usage, 120 + enum cachefiles_obj_ref_trace why), 121 + 122 + TP_ARGS(object_debug_id, cookie_debug_id, usage, why), 123 + 124 + /* Note that obj may be NULL */ 125 + TP_STRUCT__entry( 126 + __field(unsigned int, obj ) 127 + __field(unsigned int, cookie ) 128 + __field(enum cachefiles_obj_ref_trace, why ) 129 + __field(int, usage ) 130 + ), 131 + 132 + TP_fast_assign( 133 + __entry->obj = object_debug_id; 134 + __entry->cookie = cookie_debug_id; 135 + __entry->usage = usage; 136 + __entry->why = why; 137 + ), 138 + 139 + TP_printk("c=%08x o=%08x u=%d %s", 140 + __entry->cookie, __entry->obj, __entry->usage, 141 + __print_symbolic(__entry->why, cachefiles_obj_ref_traces)) 142 + ); 145 143 146 144 TRACE_EVENT(cachefiles_lookup, 147 145 TP_PROTO(struct cachefiles_object *obj,
+4
include/trace/events/fscache.h
··· 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, ··· 58 57 fscache_cookie_new_acquire, 59 58 fscache_cookie_put_hash_collision, 60 59 fscache_cookie_put_lru, 60 + fscache_cookie_put_object, 61 61 fscache_cookie_put_over_queued, 62 62 fscache_cookie_put_relinquish, 63 63 fscache_cookie_put_withdrawn, ··· 124 122 #define fscache_cookie_traces \ 125 123 EM(fscache_cookie_collision, "*COLLIDE*") \ 126 124 EM(fscache_cookie_discard, "DISCARD ") \ 125 + EM(fscache_cookie_get_attach_object, "GET attch") \ 127 126 EM(fscache_cookie_get_hash_collision, "GET hcoll") \ 128 127 EM(fscache_cookie_get_end_access, "GQ endac") \ 129 128 EM(fscache_cookie_get_inval_work, "GQ inval") \ ··· 133 130 EM(fscache_cookie_new_acquire, "NEW acq ") \ 134 131 EM(fscache_cookie_put_hash_collision, "PUT hcoll") \ 135 132 EM(fscache_cookie_put_lru, "PUT lru ") \ 133 + EM(fscache_cookie_put_object, "PUT obj ") \ 136 134 EM(fscache_cookie_put_over_queued, "PQ overq") \ 137 135 EM(fscache_cookie_put_relinquish, "PUT relnq") \ 138 136 EM(fscache_cookie_put_withdrawn, "PUT wthdn") \