diff options
-rw-r--r-- | fs/cachefiles/interface.c | 18 | ||||
-rw-r--r-- | fs/cachefiles/internal.h | 2 | ||||
-rw-r--r-- | fs/cachefiles/main.c | 1 | ||||
-rw-r--r-- | fs/cachefiles/namei.c | 42 | ||||
-rw-r--r-- | fs/fscache/cookie.c | 46 | ||||
-rw-r--r-- | fs/fscache/internal.h | 16 | ||||
-rw-r--r-- | fs/fscache/main.c | 1 | ||||
-rw-r--r-- | fs/fscache/netfs.c | 3 | ||||
-rw-r--r-- | fs/fscache/object.c | 36 | ||||
-rw-r--r-- | include/linux/fscache-cache.h | 18 | ||||
-rw-r--r-- | include/trace/events/cachefiles.h | 325 | ||||
-rw-r--r-- | include/trace/events/fscache.h | 277 |
12 files changed, 731 insertions, 54 deletions
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index e7f16a77a22a..405ebc3932c2 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c | |||
@@ -177,10 +177,12 @@ static void cachefiles_lookup_complete(struct fscache_object *_object) | |||
177 | * increment the usage count on an inode object (may fail if unmounting) | 177 | * increment the usage count on an inode object (may fail if unmounting) |
178 | */ | 178 | */ |
179 | static | 179 | static |
180 | struct fscache_object *cachefiles_grab_object(struct fscache_object *_object) | 180 | struct fscache_object *cachefiles_grab_object(struct fscache_object *_object, |
181 | enum fscache_obj_ref_trace why) | ||
181 | { | 182 | { |
182 | struct cachefiles_object *object = | 183 | struct cachefiles_object *object = |
183 | container_of(_object, struct cachefiles_object, fscache); | 184 | container_of(_object, struct cachefiles_object, fscache); |
185 | int u; | ||
184 | 186 | ||
185 | _enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage)); | 187 | _enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage)); |
186 | 188 | ||
@@ -188,7 +190,9 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object) | |||
188 | ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000); | 190 | ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000); |
189 | #endif | 191 | #endif |
190 | 192 | ||
191 | atomic_inc(&object->usage); | 193 | u = atomic_inc_return(&object->usage); |
194 | trace_cachefiles_ref(object, _object->cookie, | ||
195 | (enum cachefiles_obj_ref_trace)why, u); | ||
192 | return &object->fscache; | 196 | return &object->fscache; |
193 | } | 197 | } |
194 | 198 | ||
@@ -309,10 +313,12 @@ static void cachefiles_drop_object(struct fscache_object *_object) | |||
309 | /* | 313 | /* |
310 | * dispose of a reference to an object | 314 | * dispose of a reference to an object |
311 | */ | 315 | */ |
312 | static void cachefiles_put_object(struct fscache_object *_object) | 316 | static void cachefiles_put_object(struct fscache_object *_object, |
317 | enum fscache_obj_ref_trace why) | ||
313 | { | 318 | { |
314 | struct cachefiles_object *object; | 319 | struct cachefiles_object *object; |
315 | struct fscache_cache *cache; | 320 | struct fscache_cache *cache; |
321 | int u; | ||
316 | 322 | ||
317 | ASSERT(_object); | 323 | ASSERT(_object); |
318 | 324 | ||
@@ -328,7 +334,11 @@ static void cachefiles_put_object(struct fscache_object *_object) | |||
328 | ASSERTIFCMP(object->fscache.parent, | 334 | ASSERTIFCMP(object->fscache.parent, |
329 | object->fscache.parent->n_children, >, 0); | 335 | object->fscache.parent->n_children, >, 0); |
330 | 336 | ||
331 | if (atomic_dec_and_test(&object->usage)) { | 337 | u = atomic_dec_return(&object->usage); |
338 | trace_cachefiles_ref(object, _object->cookie, | ||
339 | (enum cachefiles_obj_ref_trace)why, u); | ||
340 | ASSERTCMP(u, !=, -1); | ||
341 | if (u == 0) { | ||
332 | _debug("- kill object OBJ%x", object->fscache.debug_id); | 342 | _debug("- kill object OBJ%x", object->fscache.debug_id); |
333 | 343 | ||
334 | ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)); | 344 | ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)); |
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index bb3a02ca9da4..d2f6f996e65a 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h | |||
@@ -124,6 +124,8 @@ struct cachefiles_xattr { | |||
124 | uint8_t data[]; | 124 | uint8_t data[]; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | #include <trace/events/cachefiles.h> | ||
128 | |||
127 | /* | 129 | /* |
128 | * note change of state for daemon | 130 | * note change of state for daemon |
129 | */ | 131 | */ |
diff --git a/fs/cachefiles/main.c b/fs/cachefiles/main.c index 711f13d8c2de..f54d3f5b2e40 100644 --- a/fs/cachefiles/main.c +++ b/fs/cachefiles/main.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/statfs.h> | 22 | #include <linux/statfs.h> |
23 | #include <linux/sysctl.h> | 23 | #include <linux/sysctl.h> |
24 | #include <linux/miscdevice.h> | 24 | #include <linux/miscdevice.h> |
25 | #define CREATE_TRACE_POINTS | ||
25 | #include "internal.h" | 26 | #include "internal.h" |
26 | 27 | ||
27 | unsigned cachefiles_debug; | 28 | unsigned cachefiles_debug; |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 3978b324cbca..5fc214256316 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -120,6 +120,7 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache, | |||
120 | } | 120 | } |
121 | 121 | ||
122 | write_unlock(&cache->active_lock); | 122 | write_unlock(&cache->active_lock); |
123 | trace_cachefiles_mark_buried(NULL, dentry, why); | ||
123 | _leave(" [no owner]"); | 124 | _leave(" [no owner]"); |
124 | return; | 125 | return; |
125 | 126 | ||
@@ -130,6 +131,8 @@ found_dentry: | |||
130 | object->fscache.state->name, | 131 | object->fscache.state->name, |
131 | dentry); | 132 | dentry); |
132 | 133 | ||
134 | trace_cachefiles_mark_buried(object, dentry, why); | ||
135 | |||
133 | if (fscache_object_is_live(&object->fscache)) { | 136 | if (fscache_object_is_live(&object->fscache)) { |
134 | pr_err("\n"); | 137 | pr_err("\n"); |
135 | pr_err("Error: Can't preemptively bury live object\n"); | 138 | pr_err("Error: Can't preemptively bury live object\n"); |
@@ -158,13 +161,15 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache, | |||
158 | try_again: | 161 | try_again: |
159 | write_lock(&cache->active_lock); | 162 | write_lock(&cache->active_lock); |
160 | 163 | ||
164 | dentry = object->dentry; | ||
165 | trace_cachefiles_mark_active(object, dentry); | ||
166 | |||
161 | if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) { | 167 | if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) { |
162 | pr_err("Error: Object already active\n"); | 168 | pr_err("Error: Object already active\n"); |
163 | cachefiles_printk_object(object, NULL); | 169 | cachefiles_printk_object(object, NULL); |
164 | BUG(); | 170 | BUG(); |
165 | } | 171 | } |
166 | 172 | ||
167 | dentry = object->dentry; | ||
168 | _p = &cache->active_nodes.rb_node; | 173 | _p = &cache->active_nodes.rb_node; |
169 | while (*_p) { | 174 | while (*_p) { |
170 | _parent = *_p; | 175 | _parent = *_p; |
@@ -191,6 +196,8 @@ try_again: | |||
191 | /* an old object from a previous incarnation is hogging the slot - we | 196 | /* an old object from a previous incarnation is hogging the slot - we |
192 | * need to wait for it to be destroyed */ | 197 | * need to wait for it to be destroyed */ |
193 | wait_for_old_object: | 198 | wait_for_old_object: |
199 | trace_cachefiles_wait_active(object, dentry, xobject); | ||
200 | |||
194 | if (fscache_object_is_live(&xobject->fscache)) { | 201 | if (fscache_object_is_live(&xobject->fscache)) { |
195 | pr_err("\n"); | 202 | pr_err("\n"); |
196 | pr_err("Error: Unexpected object collision\n"); | 203 | pr_err("Error: Unexpected object collision\n"); |
@@ -248,12 +255,12 @@ wait_for_old_object: | |||
248 | 255 | ||
249 | ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)); | 256 | ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)); |
250 | 257 | ||
251 | cache->cache.ops->put_object(&xobject->fscache); | 258 | cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_retry); |
252 | goto try_again; | 259 | goto try_again; |
253 | 260 | ||
254 | requeue: | 261 | requeue: |
255 | clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); | 262 | clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); |
256 | cache->cache.ops->put_object(&xobject->fscache); | 263 | cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo); |
257 | _leave(" = -ETIMEDOUT"); | 264 | _leave(" = -ETIMEDOUT"); |
258 | return -ETIMEDOUT; | 265 | return -ETIMEDOUT; |
259 | } | 266 | } |
@@ -265,6 +272,11 @@ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, | |||
265 | struct cachefiles_object *object, | 272 | struct cachefiles_object *object, |
266 | blkcnt_t i_blocks) | 273 | blkcnt_t i_blocks) |
267 | { | 274 | { |
275 | struct dentry *dentry = object->dentry; | ||
276 | struct inode *inode = d_backing_inode(dentry); | ||
277 | |||
278 | trace_cachefiles_mark_inactive(object, dentry, inode); | ||
279 | |||
268 | write_lock(&cache->active_lock); | 280 | write_lock(&cache->active_lock); |
269 | rb_erase(&object->active_node, &cache->active_nodes); | 281 | rb_erase(&object->active_node, &cache->active_nodes); |
270 | clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); | 282 | clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); |
@@ -288,6 +300,7 @@ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, | |||
288 | * - unlocks the directory mutex | 300 | * - unlocks the directory mutex |
289 | */ | 301 | */ |
290 | static int cachefiles_bury_object(struct cachefiles_cache *cache, | 302 | static int cachefiles_bury_object(struct cachefiles_cache *cache, |
303 | struct cachefiles_object *object, | ||
291 | struct dentry *dir, | 304 | struct dentry *dir, |
292 | struct dentry *rep, | 305 | struct dentry *rep, |
293 | bool preemptive, | 306 | bool preemptive, |
@@ -312,6 +325,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, | |||
312 | if (ret < 0) { | 325 | if (ret < 0) { |
313 | cachefiles_io_error(cache, "Unlink security error"); | 326 | cachefiles_io_error(cache, "Unlink security error"); |
314 | } else { | 327 | } else { |
328 | trace_cachefiles_unlink(object, rep, why); | ||
315 | ret = vfs_unlink(d_inode(dir), rep, NULL); | 329 | ret = vfs_unlink(d_inode(dir), rep, NULL); |
316 | 330 | ||
317 | if (preemptive) | 331 | if (preemptive) |
@@ -413,6 +427,7 @@ try_again: | |||
413 | if (ret < 0) { | 427 | if (ret < 0) { |
414 | cachefiles_io_error(cache, "Rename security error %d", ret); | 428 | cachefiles_io_error(cache, "Rename security error %d", ret); |
415 | } else { | 429 | } else { |
430 | trace_cachefiles_rename(object, rep, grave, why); | ||
416 | ret = vfs_rename(d_inode(dir), rep, | 431 | ret = vfs_rename(d_inode(dir), rep, |
417 | d_inode(cache->graveyard), grave, NULL, 0); | 432 | d_inode(cache->graveyard), grave, NULL, 0); |
418 | if (ret != 0 && ret != -ENOMEM) | 433 | if (ret != 0 && ret != -ENOMEM) |
@@ -458,7 +473,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, | |||
458 | /* we need to check that our parent is _still_ our parent - it | 473 | /* we need to check that our parent is _still_ our parent - it |
459 | * may have been renamed */ | 474 | * may have been renamed */ |
460 | if (dir == object->dentry->d_parent) { | 475 | if (dir == object->dentry->d_parent) { |
461 | ret = cachefiles_bury_object(cache, dir, | 476 | ret = cachefiles_bury_object(cache, object, dir, |
462 | object->dentry, false, | 477 | object->dentry, false, |
463 | FSCACHE_OBJECT_WAS_RETIRED); | 478 | FSCACHE_OBJECT_WAS_RETIRED); |
464 | } else { | 479 | } else { |
@@ -486,6 +501,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, | |||
486 | { | 501 | { |
487 | struct cachefiles_cache *cache; | 502 | struct cachefiles_cache *cache; |
488 | struct dentry *dir, *next = NULL; | 503 | struct dentry *dir, *next = NULL; |
504 | struct inode *inode; | ||
489 | struct path path; | 505 | struct path path; |
490 | unsigned long start; | 506 | unsigned long start; |
491 | const char *name; | 507 | const char *name; |
@@ -529,13 +545,17 @@ lookup_again: | |||
529 | start = jiffies; | 545 | start = jiffies; |
530 | next = lookup_one_len(name, dir, nlen); | 546 | next = lookup_one_len(name, dir, nlen); |
531 | cachefiles_hist(cachefiles_lookup_histogram, start); | 547 | cachefiles_hist(cachefiles_lookup_histogram, start); |
532 | if (IS_ERR(next)) | 548 | if (IS_ERR(next)) { |
549 | trace_cachefiles_lookup(object, next, NULL); | ||
533 | goto lookup_error; | 550 | goto lookup_error; |
551 | } | ||
534 | 552 | ||
535 | _debug("next -> %p %s", next, d_backing_inode(next) ? "positive" : "negative"); | 553 | inode = d_backing_inode(next); |
554 | trace_cachefiles_lookup(object, next, inode); | ||
555 | _debug("next -> %p %s", next, inode ? "positive" : "negative"); | ||
536 | 556 | ||
537 | if (!key) | 557 | if (!key) |
538 | object->new = !d_backing_inode(next); | 558 | object->new = !inode; |
539 | 559 | ||
540 | /* if this element of the path doesn't exist, then the lookup phase | 560 | /* if this element of the path doesn't exist, then the lookup phase |
541 | * failed, and we can release any readers in the certain knowledge that | 561 | * failed, and we can release any readers in the certain knowledge that |
@@ -558,6 +578,8 @@ lookup_again: | |||
558 | start = jiffies; | 578 | start = jiffies; |
559 | ret = vfs_mkdir(d_inode(dir), next, 0); | 579 | ret = vfs_mkdir(d_inode(dir), next, 0); |
560 | cachefiles_hist(cachefiles_mkdir_histogram, start); | 580 | cachefiles_hist(cachefiles_mkdir_histogram, start); |
581 | if (!key) | ||
582 | trace_cachefiles_mkdir(object, next, ret); | ||
561 | if (ret < 0) | 583 | if (ret < 0) |
562 | goto create_error; | 584 | goto create_error; |
563 | 585 | ||
@@ -587,6 +609,7 @@ lookup_again: | |||
587 | start = jiffies; | 609 | start = jiffies; |
588 | ret = vfs_create(d_inode(dir), next, S_IFREG, true); | 610 | ret = vfs_create(d_inode(dir), next, S_IFREG, true); |
589 | cachefiles_hist(cachefiles_create_histogram, start); | 611 | cachefiles_hist(cachefiles_create_histogram, start); |
612 | trace_cachefiles_create(object, next, ret); | ||
590 | if (ret < 0) | 613 | if (ret < 0) |
591 | goto create_error; | 614 | goto create_error; |
592 | 615 | ||
@@ -629,7 +652,8 @@ lookup_again: | |||
629 | * mutex) */ | 652 | * mutex) */ |
630 | object->dentry = NULL; | 653 | object->dentry = NULL; |
631 | 654 | ||
632 | ret = cachefiles_bury_object(cache, dir, next, true, | 655 | ret = cachefiles_bury_object(cache, object, dir, next, |
656 | true, | ||
633 | FSCACHE_OBJECT_IS_STALE); | 657 | FSCACHE_OBJECT_IS_STALE); |
634 | dput(next); | 658 | dput(next); |
635 | next = NULL; | 659 | next = NULL; |
@@ -955,7 +979,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, | |||
955 | /* actually remove the victim (drops the dir mutex) */ | 979 | /* actually remove the victim (drops the dir mutex) */ |
956 | _debug("bury"); | 980 | _debug("bury"); |
957 | 981 | ||
958 | ret = cachefiles_bury_object(cache, dir, victim, false, | 982 | ret = cachefiles_bury_object(cache, NULL, dir, victim, false, |
959 | FSCACHE_OBJECT_WAS_CULLED); | 983 | FSCACHE_OBJECT_WAS_CULLED); |
960 | if (ret < 0) | 984 | if (ret < 0) |
961 | goto error; | 985 | goto error; |
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 98d22f495cd8..20bc3341f113 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c | |||
@@ -101,7 +101,7 @@ struct fscache_cookie *__fscache_acquire_cookie( | |||
101 | */ | 101 | */ |
102 | atomic_set(&cookie->n_active, 1); | 102 | atomic_set(&cookie->n_active, 1); |
103 | 103 | ||
104 | atomic_inc(&parent->usage); | 104 | fscache_cookie_get(parent, fscache_cookie_get_acquire_parent); |
105 | atomic_inc(&parent->n_children); | 105 | atomic_inc(&parent->n_children); |
106 | 106 | ||
107 | cookie->def = def; | 107 | cookie->def = def; |
@@ -125,6 +125,8 @@ struct fscache_cookie *__fscache_acquire_cookie( | |||
125 | break; | 125 | break; |
126 | } | 126 | } |
127 | 127 | ||
128 | trace_fscache_acquire(cookie); | ||
129 | |||
128 | if (enable) { | 130 | if (enable) { |
129 | /* if the object is an index then we need do nothing more here | 131 | /* if the object is an index then we need do nothing more here |
130 | * - we create indices on disk when we need them as an index | 132 | * - we create indices on disk when we need them as an index |
@@ -134,7 +136,8 @@ struct fscache_cookie *__fscache_acquire_cookie( | |||
134 | set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); | 136 | set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); |
135 | } else { | 137 | } else { |
136 | atomic_dec(&parent->n_children); | 138 | atomic_dec(&parent->n_children); |
137 | __fscache_cookie_put(cookie); | 139 | fscache_cookie_put(cookie, |
140 | fscache_cookie_put_acquire_nobufs); | ||
138 | fscache_stat(&fscache_n_acquires_nobufs); | 141 | fscache_stat(&fscache_n_acquires_nobufs); |
139 | _leave(" = NULL"); | 142 | _leave(" = NULL"); |
140 | return NULL; | 143 | return NULL; |
@@ -159,6 +162,8 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie, | |||
159 | { | 162 | { |
160 | _enter("%p", cookie); | 163 | _enter("%p", cookie); |
161 | 164 | ||
165 | trace_fscache_enable(cookie); | ||
166 | |||
162 | wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK, | 167 | wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK, |
163 | TASK_UNINTERRUPTIBLE); | 168 | TASK_UNINTERRUPTIBLE); |
164 | 169 | ||
@@ -318,7 +323,7 @@ static int fscache_alloc_object(struct fscache_cache *cache, | |||
318 | * attached to the cookie */ | 323 | * attached to the cookie */ |
319 | if (fscache_attach_object(cookie, object) < 0) { | 324 | if (fscache_attach_object(cookie, object) < 0) { |
320 | fscache_stat(&fscache_n_cop_put_object); | 325 | fscache_stat(&fscache_n_cop_put_object); |
321 | cache->ops->put_object(object); | 326 | cache->ops->put_object(object, fscache_obj_put_attach_fail); |
322 | fscache_stat_d(&fscache_n_cop_put_object); | 327 | fscache_stat_d(&fscache_n_cop_put_object); |
323 | } | 328 | } |
324 | 329 | ||
@@ -338,7 +343,7 @@ object_already_extant: | |||
338 | 343 | ||
339 | error_put: | 344 | error_put: |
340 | fscache_stat(&fscache_n_cop_put_object); | 345 | fscache_stat(&fscache_n_cop_put_object); |
341 | cache->ops->put_object(object); | 346 | cache->ops->put_object(object, fscache_obj_put_alloc_fail); |
342 | fscache_stat_d(&fscache_n_cop_put_object); | 347 | fscache_stat_d(&fscache_n_cop_put_object); |
343 | error: | 348 | error: |
344 | _leave(" = %d", ret); | 349 | _leave(" = %d", ret); |
@@ -398,7 +403,7 @@ static int fscache_attach_object(struct fscache_cookie *cookie, | |||
398 | 403 | ||
399 | /* attach to the cookie */ | 404 | /* attach to the cookie */ |
400 | object->cookie = cookie; | 405 | object->cookie = cookie; |
401 | atomic_inc(&cookie->usage); | 406 | fscache_cookie_get(cookie, fscache_cookie_get_attach_object); |
402 | hlist_add_head(&object->cookie_link, &cookie->backing_objects); | 407 | hlist_add_head(&object->cookie_link, &cookie->backing_objects); |
403 | 408 | ||
404 | fscache_objlist_add(object); | 409 | fscache_objlist_add(object); |
@@ -516,6 +521,8 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) | |||
516 | 521 | ||
517 | _enter("%p,%u", cookie, invalidate); | 522 | _enter("%p,%u", cookie, invalidate); |
518 | 523 | ||
524 | trace_fscache_disable(cookie); | ||
525 | |||
519 | ASSERTCMP(atomic_read(&cookie->n_active), >, 0); | 526 | ASSERTCMP(atomic_read(&cookie->n_active), >, 0); |
520 | 527 | ||
521 | if (atomic_read(&cookie->n_children) != 0) { | 528 | if (atomic_read(&cookie->n_children) != 0) { |
@@ -601,6 +608,8 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire) | |||
601 | cookie, cookie->def->name, cookie->netfs_data, | 608 | cookie, cookie->def->name, cookie->netfs_data, |
602 | atomic_read(&cookie->n_active), retire); | 609 | atomic_read(&cookie->n_active), retire); |
603 | 610 | ||
611 | trace_fscache_relinquish(cookie, retire); | ||
612 | |||
604 | /* No further netfs-accessing operations on this cookie permitted */ | 613 | /* No further netfs-accessing operations on this cookie permitted */ |
605 | if (test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) | 614 | if (test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) |
606 | BUG(); | 615 | BUG(); |
@@ -620,35 +629,38 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire) | |||
620 | 629 | ||
621 | /* Dispose of the netfs's link to the cookie */ | 630 | /* Dispose of the netfs's link to the cookie */ |
622 | ASSERTCMP(atomic_read(&cookie->usage), >, 0); | 631 | ASSERTCMP(atomic_read(&cookie->usage), >, 0); |
623 | fscache_cookie_put(cookie); | 632 | fscache_cookie_put(cookie, fscache_cookie_put_relinquish); |
624 | 633 | ||
625 | _leave(""); | 634 | _leave(""); |
626 | } | 635 | } |
627 | EXPORT_SYMBOL(__fscache_relinquish_cookie); | 636 | EXPORT_SYMBOL(__fscache_relinquish_cookie); |
628 | 637 | ||
629 | /* | 638 | /* |
630 | * destroy a cookie | 639 | * Drop a reference to a cookie. |
631 | */ | 640 | */ |
632 | void __fscache_cookie_put(struct fscache_cookie *cookie) | 641 | void fscache_cookie_put(struct fscache_cookie *cookie, |
642 | enum fscache_cookie_trace where) | ||
633 | { | 643 | { |
634 | struct fscache_cookie *parent; | 644 | struct fscache_cookie *parent; |
645 | int usage; | ||
635 | 646 | ||
636 | _enter("%p", cookie); | 647 | _enter("%p", cookie); |
637 | 648 | ||
638 | for (;;) { | 649 | do { |
639 | _debug("FREE COOKIE %p", cookie); | 650 | usage = atomic_dec_return(&cookie->usage); |
651 | trace_fscache_cookie(cookie, where, usage); | ||
652 | |||
653 | if (usage > 0) | ||
654 | return; | ||
655 | BUG_ON(usage < 0); | ||
656 | |||
640 | parent = cookie->parent; | 657 | parent = cookie->parent; |
641 | BUG_ON(!hlist_empty(&cookie->backing_objects)); | 658 | BUG_ON(!hlist_empty(&cookie->backing_objects)); |
642 | kmem_cache_free(fscache_cookie_jar, cookie); | 659 | kmem_cache_free(fscache_cookie_jar, cookie); |
643 | 660 | ||
644 | if (!parent) | ||
645 | break; | ||
646 | |||
647 | cookie = parent; | 661 | cookie = parent; |
648 | BUG_ON(atomic_read(&cookie->usage) <= 0); | 662 | where = fscache_cookie_put_parent; |
649 | if (!atomic_dec_and_test(&cookie->usage)) | 663 | } while (cookie); |
650 | break; | ||
651 | } | ||
652 | 664 | ||
653 | _leave(""); | 665 | _leave(""); |
654 | } | 666 | } |
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 0ff4b49a0037..c27e2db3004e 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define pr_fmt(fmt) "FS-Cache: " fmt | 29 | #define pr_fmt(fmt) "FS-Cache: " fmt |
30 | 30 | ||
31 | #include <linux/fscache-cache.h> | 31 | #include <linux/fscache-cache.h> |
32 | #include <trace/events/fscache.h> | ||
32 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
33 | 34 | ||
34 | #define FSCACHE_MIN_THREADS 4 | 35 | #define FSCACHE_MIN_THREADS 4 |
@@ -49,7 +50,8 @@ extern struct fscache_cache *fscache_select_cache_for_object( | |||
49 | extern struct kmem_cache *fscache_cookie_jar; | 50 | extern struct kmem_cache *fscache_cookie_jar; |
50 | 51 | ||
51 | extern void fscache_cookie_init_once(void *); | 52 | extern void fscache_cookie_init_once(void *); |
52 | extern void __fscache_cookie_put(struct fscache_cookie *); | 53 | extern void fscache_cookie_put(struct fscache_cookie *, |
54 | enum fscache_cookie_trace); | ||
53 | 55 | ||
54 | /* | 56 | /* |
55 | * fsdef.c | 57 | * fsdef.c |
@@ -311,14 +313,12 @@ static inline void fscache_raise_event(struct fscache_object *object, | |||
311 | fscache_enqueue_object(object); | 313 | fscache_enqueue_object(object); |
312 | } | 314 | } |
313 | 315 | ||
314 | /* | 316 | static inline void fscache_cookie_get(struct fscache_cookie *cookie, |
315 | * drop a reference to a cookie | 317 | enum fscache_cookie_trace where) |
316 | */ | ||
317 | static inline void fscache_cookie_put(struct fscache_cookie *cookie) | ||
318 | { | 318 | { |
319 | BUG_ON(atomic_read(&cookie->usage) <= 0); | 319 | int usage = atomic_inc_return(&cookie->usage); |
320 | if (atomic_dec_and_test(&cookie->usage)) | 320 | |
321 | __fscache_cookie_put(cookie); | 321 | trace_fscache_cookie(cookie, where, usage); |
322 | } | 322 | } |
323 | 323 | ||
324 | /* | 324 | /* |
diff --git a/fs/fscache/main.c b/fs/fscache/main.c index 249968dcbf5c..7dce110bf17d 100644 --- a/fs/fscache/main.c +++ b/fs/fscache/main.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/completion.h> | 16 | #include <linux/completion.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #define CREATE_TRACE_POINTS | ||
19 | #include "internal.h" | 20 | #include "internal.h" |
20 | 21 | ||
21 | MODULE_DESCRIPTION("FS Cache Manager"); | 22 | MODULE_DESCRIPTION("FS Cache Manager"); |
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c index a8aa00be4444..c816600d1dde 100644 --- a/fs/fscache/netfs.c +++ b/fs/fscache/netfs.c | |||
@@ -60,7 +60,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) | |||
60 | goto already_registered; | 60 | goto already_registered; |
61 | } | 61 | } |
62 | 62 | ||
63 | atomic_inc(&cookie->parent->usage); | 63 | fscache_cookie_get(cookie->parent, fscache_cookie_get_register_netfs); |
64 | atomic_inc(&cookie->parent->n_children); | 64 | atomic_inc(&cookie->parent->n_children); |
65 | 65 | ||
66 | netfs->primary_index = cookie; | 66 | netfs->primary_index = cookie; |
@@ -68,6 +68,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) | |||
68 | ret = 0; | 68 | ret = 0; |
69 | 69 | ||
70 | pr_notice("Netfs '%s' registered for caching\n", netfs->name); | 70 | pr_notice("Netfs '%s' registered for caching\n", netfs->name); |
71 | trace_fscache_netfs(netfs); | ||
71 | 72 | ||
72 | already_registered: | 73 | already_registered: |
73 | up_write(&fscache_addremove_sem); | 74 | up_write(&fscache_addremove_sem); |
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 7a182c87f378..99afe64352a5 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
@@ -138,8 +138,10 @@ static const struct fscache_transition fscache_osm_run_oob[] = { | |||
138 | { 0, NULL } | 138 | { 0, NULL } |
139 | }; | 139 | }; |
140 | 140 | ||
141 | static int fscache_get_object(struct fscache_object *); | 141 | static int fscache_get_object(struct fscache_object *, |
142 | static void fscache_put_object(struct fscache_object *); | 142 | enum fscache_obj_ref_trace); |
143 | static void fscache_put_object(struct fscache_object *, | ||
144 | enum fscache_obj_ref_trace); | ||
143 | static bool fscache_enqueue_dependents(struct fscache_object *, int); | 145 | static bool fscache_enqueue_dependents(struct fscache_object *, int); |
144 | static void fscache_dequeue_object(struct fscache_object *); | 146 | static void fscache_dequeue_object(struct fscache_object *); |
145 | 147 | ||
@@ -170,6 +172,7 @@ static void fscache_object_sm_dispatcher(struct fscache_object *object) | |||
170 | const struct fscache_transition *t; | 172 | const struct fscache_transition *t; |
171 | const struct fscache_state *state, *new_state; | 173 | const struct fscache_state *state, *new_state; |
172 | unsigned long events, event_mask; | 174 | unsigned long events, event_mask; |
175 | bool oob; | ||
173 | int event = -1; | 176 | int event = -1; |
174 | 177 | ||
175 | ASSERT(object != NULL); | 178 | ASSERT(object != NULL); |
@@ -188,6 +191,7 @@ restart_masked: | |||
188 | if (events & object->oob_event_mask) { | 191 | if (events & object->oob_event_mask) { |
189 | _debug("{OBJ%x} oob %lx", | 192 | _debug("{OBJ%x} oob %lx", |
190 | object->debug_id, events & object->oob_event_mask); | 193 | object->debug_id, events & object->oob_event_mask); |
194 | oob = true; | ||
191 | for (t = object->oob_table; t->events; t++) { | 195 | for (t = object->oob_table; t->events; t++) { |
192 | if (events & t->events) { | 196 | if (events & t->events) { |
193 | state = t->transit_to; | 197 | state = t->transit_to; |
@@ -199,6 +203,7 @@ restart_masked: | |||
199 | } | 203 | } |
200 | } | 204 | } |
201 | } | 205 | } |
206 | oob = false; | ||
202 | 207 | ||
203 | /* Wait states are just transition tables */ | 208 | /* Wait states are just transition tables */ |
204 | if (!state->work) { | 209 | if (!state->work) { |
@@ -207,6 +212,8 @@ restart_masked: | |||
207 | if (events & t->events) { | 212 | if (events & t->events) { |
208 | new_state = t->transit_to; | 213 | new_state = t->transit_to; |
209 | event = fls(events & t->events) - 1; | 214 | event = fls(events & t->events) - 1; |
215 | trace_fscache_osm(object, state, | ||
216 | true, false, event); | ||
210 | clear_bit(event, &object->events); | 217 | clear_bit(event, &object->events); |
211 | _debug("{OBJ%x} ev %d: %s -> %s", | 218 | _debug("{OBJ%x} ev %d: %s -> %s", |
212 | object->debug_id, event, | 219 | object->debug_id, event, |
@@ -226,6 +233,7 @@ restart_masked: | |||
226 | execute_work_state: | 233 | execute_work_state: |
227 | _debug("{OBJ%x} exec %s", object->debug_id, state->name); | 234 | _debug("{OBJ%x} exec %s", object->debug_id, state->name); |
228 | 235 | ||
236 | trace_fscache_osm(object, state, false, oob, event); | ||
229 | new_state = state->work(object, event); | 237 | new_state = state->work(object, event); |
230 | event = -1; | 238 | event = -1; |
231 | if (new_state == NO_TRANSIT) { | 239 | if (new_state == NO_TRANSIT) { |
@@ -279,7 +287,7 @@ static void fscache_object_work_func(struct work_struct *work) | |||
279 | start = jiffies; | 287 | start = jiffies; |
280 | fscache_object_sm_dispatcher(object); | 288 | fscache_object_sm_dispatcher(object); |
281 | fscache_hist(fscache_objs_histogram, start); | 289 | fscache_hist(fscache_objs_histogram, start); |
282 | fscache_put_object(object); | 290 | fscache_put_object(object, fscache_obj_put_work); |
283 | } | 291 | } |
284 | 292 | ||
285 | /** | 293 | /** |
@@ -397,7 +405,7 @@ static const struct fscache_state *fscache_initialise_object(struct fscache_obje | |||
397 | fscache_stat(&fscache_n_cop_grab_object); | 405 | fscache_stat(&fscache_n_cop_grab_object); |
398 | success = false; | 406 | success = false; |
399 | if (fscache_object_is_live(parent) && | 407 | if (fscache_object_is_live(parent) && |
400 | object->cache->ops->grab_object(object)) { | 408 | object->cache->ops->grab_object(object, fscache_obj_get_add_to_deps)) { |
401 | list_add(&object->dep_link, &parent->dependents); | 409 | list_add(&object->dep_link, &parent->dependents); |
402 | success = true; | 410 | success = true; |
403 | } | 411 | } |
@@ -745,7 +753,7 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob | |||
745 | } | 753 | } |
746 | 754 | ||
747 | /* this just shifts the object release to the work processor */ | 755 | /* this just shifts the object release to the work processor */ |
748 | fscache_put_object(object); | 756 | fscache_put_object(object, fscache_obj_put_drop_obj); |
749 | fscache_stat(&fscache_n_object_dead); | 757 | fscache_stat(&fscache_n_object_dead); |
750 | 758 | ||
751 | _leave(""); | 759 | _leave(""); |
@@ -755,12 +763,13 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob | |||
755 | /* | 763 | /* |
756 | * get a ref on an object | 764 | * get a ref on an object |
757 | */ | 765 | */ |
758 | static int fscache_get_object(struct fscache_object *object) | 766 | static int fscache_get_object(struct fscache_object *object, |
767 | enum fscache_obj_ref_trace why) | ||
759 | { | 768 | { |
760 | int ret; | 769 | int ret; |
761 | 770 | ||
762 | fscache_stat(&fscache_n_cop_grab_object); | 771 | fscache_stat(&fscache_n_cop_grab_object); |
763 | ret = object->cache->ops->grab_object(object) ? 0 : -EAGAIN; | 772 | ret = object->cache->ops->grab_object(object, why) ? 0 : -EAGAIN; |
764 | fscache_stat_d(&fscache_n_cop_grab_object); | 773 | fscache_stat_d(&fscache_n_cop_grab_object); |
765 | return ret; | 774 | return ret; |
766 | } | 775 | } |
@@ -768,10 +777,11 @@ static int fscache_get_object(struct fscache_object *object) | |||
768 | /* | 777 | /* |
769 | * Discard a ref on an object | 778 | * Discard a ref on an object |
770 | */ | 779 | */ |
771 | static void fscache_put_object(struct fscache_object *object) | 780 | static void fscache_put_object(struct fscache_object *object, |
781 | enum fscache_obj_ref_trace why) | ||
772 | { | 782 | { |
773 | fscache_stat(&fscache_n_cop_put_object); | 783 | fscache_stat(&fscache_n_cop_put_object); |
774 | object->cache->ops->put_object(object); | 784 | object->cache->ops->put_object(object, why); |
775 | fscache_stat_d(&fscache_n_cop_put_object); | 785 | fscache_stat_d(&fscache_n_cop_put_object); |
776 | } | 786 | } |
777 | 787 | ||
@@ -786,7 +796,7 @@ void fscache_object_destroy(struct fscache_object *object) | |||
786 | fscache_objlist_remove(object); | 796 | fscache_objlist_remove(object); |
787 | 797 | ||
788 | /* We can get rid of the cookie now */ | 798 | /* We can get rid of the cookie now */ |
789 | fscache_cookie_put(object->cookie); | 799 | fscache_cookie_put(object->cookie, fscache_cookie_put_object); |
790 | object->cookie = NULL; | 800 | object->cookie = NULL; |
791 | } | 801 | } |
792 | EXPORT_SYMBOL(fscache_object_destroy); | 802 | EXPORT_SYMBOL(fscache_object_destroy); |
@@ -798,7 +808,7 @@ void fscache_enqueue_object(struct fscache_object *object) | |||
798 | { | 808 | { |
799 | _enter("{OBJ%x}", object->debug_id); | 809 | _enter("{OBJ%x}", object->debug_id); |
800 | 810 | ||
801 | if (fscache_get_object(object) >= 0) { | 811 | if (fscache_get_object(object, fscache_obj_get_queue) >= 0) { |
802 | wait_queue_head_t *cong_wq = | 812 | wait_queue_head_t *cong_wq = |
803 | &get_cpu_var(fscache_object_cong_wait); | 813 | &get_cpu_var(fscache_object_cong_wait); |
804 | 814 | ||
@@ -806,7 +816,7 @@ void fscache_enqueue_object(struct fscache_object *object) | |||
806 | if (fscache_object_congested()) | 816 | if (fscache_object_congested()) |
807 | wake_up(cong_wq); | 817 | wake_up(cong_wq); |
808 | } else | 818 | } else |
809 | fscache_put_object(object); | 819 | fscache_put_object(object, fscache_obj_put_queue); |
810 | 820 | ||
811 | put_cpu_var(fscache_object_cong_wait); | 821 | put_cpu_var(fscache_object_cong_wait); |
812 | } | 822 | } |
@@ -866,7 +876,7 @@ static bool fscache_enqueue_dependents(struct fscache_object *object, int event) | |||
866 | list_del_init(&dep->dep_link); | 876 | list_del_init(&dep->dep_link); |
867 | 877 | ||
868 | fscache_raise_event(dep, event); | 878 | fscache_raise_event(dep, event); |
869 | fscache_put_object(dep); | 879 | fscache_put_object(dep, fscache_obj_put_enq_dep); |
870 | 880 | ||
871 | if (!list_empty(&object->dependents) && need_resched()) { | 881 | if (!list_empty(&object->dependents) && need_resched()) { |
872 | ret = false; | 882 | ret = false; |
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index b19fa8592fc2..fbe102f37074 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h | |||
@@ -29,6 +29,18 @@ struct fscache_cache_ops; | |||
29 | struct fscache_object; | 29 | struct fscache_object; |
30 | struct fscache_operation; | 30 | struct fscache_operation; |
31 | 31 | ||
32 | enum fscache_obj_ref_trace { | ||
33 | fscache_obj_get_add_to_deps, | ||
34 | fscache_obj_get_queue, | ||
35 | fscache_obj_put_alloc_fail, | ||
36 | fscache_obj_put_attach_fail, | ||
37 | fscache_obj_put_drop_obj, | ||
38 | fscache_obj_put_enq_dep, | ||
39 | fscache_obj_put_queue, | ||
40 | fscache_obj_put_work, | ||
41 | fscache_obj_ref__nr_traces | ||
42 | }; | ||
43 | |||
32 | /* | 44 | /* |
33 | * cache tag definition | 45 | * cache tag definition |
34 | */ | 46 | */ |
@@ -231,7 +243,8 @@ struct fscache_cache_ops { | |||
231 | void (*lookup_complete)(struct fscache_object *object); | 243 | void (*lookup_complete)(struct fscache_object *object); |
232 | 244 | ||
233 | /* increment the usage count on this object (may fail if unmounting) */ | 245 | /* increment the usage count on this object (may fail if unmounting) */ |
234 | struct fscache_object *(*grab_object)(struct fscache_object *object); | 246 | struct fscache_object *(*grab_object)(struct fscache_object *object, |
247 | enum fscache_obj_ref_trace why); | ||
235 | 248 | ||
236 | /* pin an object in the cache */ | 249 | /* pin an object in the cache */ |
237 | int (*pin_object)(struct fscache_object *object); | 250 | int (*pin_object)(struct fscache_object *object); |
@@ -254,7 +267,8 @@ struct fscache_cache_ops { | |||
254 | void (*drop_object)(struct fscache_object *object); | 267 | void (*drop_object)(struct fscache_object *object); |
255 | 268 | ||
256 | /* dispose of a reference to an object */ | 269 | /* dispose of a reference to an object */ |
257 | void (*put_object)(struct fscache_object *object); | 270 | void (*put_object)(struct fscache_object *object, |
271 | enum fscache_obj_ref_trace why); | ||
258 | 272 | ||
259 | /* sync a cache */ | 273 | /* sync a cache */ |
260 | void (*sync_cache)(struct fscache_cache *cache); | 274 | void (*sync_cache)(struct fscache_cache *cache); |
diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h new file mode 100644 index 000000000000..aa86e7dba511 --- /dev/null +++ b/include/trace/events/cachefiles.h | |||
@@ -0,0 +1,325 @@ | |||
1 | /* CacheFiles tracepoints | ||
2 | * | ||
3 | * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #undef TRACE_SYSTEM | ||
12 | #define TRACE_SYSTEM cachefiles | ||
13 | |||
14 | #if !defined(_TRACE_CACHEFILES_H) || defined(TRACE_HEADER_MULTI_READ) | ||
15 | #define _TRACE_CACHEFILES_H | ||
16 | |||
17 | #include <linux/tracepoint.h> | ||
18 | |||
19 | /* | ||
20 | * Define enums for tracing information. | ||
21 | */ | ||
22 | #ifndef __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY | ||
23 | #define __CACHEFILES_DECLARE_TRACE_ENUMS_ONCE_ONLY | ||
24 | |||
25 | enum cachefiles_obj_ref_trace { | ||
26 | cachefiles_obj_put_wait_retry = fscache_obj_ref__nr_traces, | ||
27 | cachefiles_obj_put_wait_timeo, | ||
28 | cachefiles_obj_ref__nr_traces | ||
29 | }; | ||
30 | |||
31 | #endif | ||
32 | |||
33 | /* | ||
34 | * Define enum -> string mappings for display. | ||
35 | */ | ||
36 | #define cachefiles_obj_kill_traces \ | ||
37 | EM(FSCACHE_OBJECT_IS_STALE, "stale") \ | ||
38 | EM(FSCACHE_OBJECT_NO_SPACE, "no_space") \ | ||
39 | EM(FSCACHE_OBJECT_WAS_RETIRED, "was_retired") \ | ||
40 | E_(FSCACHE_OBJECT_WAS_CULLED, "was_culled") | ||
41 | |||
42 | #define cachefiles_obj_ref_traces \ | ||
43 | EM(fscache_obj_get_add_to_deps, "GET add_to_deps") \ | ||
44 | EM(fscache_obj_get_queue, "GET queue") \ | ||
45 | EM(fscache_obj_put_alloc_fail, "PUT alloc_fail") \ | ||
46 | EM(fscache_obj_put_attach_fail, "PUT attach_fail") \ | ||
47 | EM(fscache_obj_put_drop_obj, "PUT drop_obj") \ | ||
48 | EM(fscache_obj_put_enq_dep, "PUT enq_dep") \ | ||
49 | EM(fscache_obj_put_queue, "PUT queue") \ | ||
50 | EM(fscache_obj_put_work, "PUT work") \ | ||
51 | EM(cachefiles_obj_put_wait_retry, "PUT wait_retry") \ | ||
52 | E_(cachefiles_obj_put_wait_timeo, "PUT wait_timeo") | ||
53 | |||
54 | /* | ||
55 | * Export enum symbols via userspace. | ||
56 | */ | ||
57 | #undef EM | ||
58 | #undef E_ | ||
59 | #define EM(a, b) TRACE_DEFINE_ENUM(a); | ||
60 | #define E_(a, b) TRACE_DEFINE_ENUM(a); | ||
61 | |||
62 | cachefiles_obj_kill_traces; | ||
63 | cachefiles_obj_ref_traces; | ||
64 | |||
65 | /* | ||
66 | * Now redefine the EM() and E_() macros to map the enums to the strings that | ||
67 | * will be printed in the output. | ||
68 | */ | ||
69 | #undef EM | ||
70 | #undef E_ | ||
71 | #define EM(a, b) { a, b }, | ||
72 | #define E_(a, b) { a, b } | ||
73 | |||
74 | |||
75 | TRACE_EVENT(cachefiles_ref, | ||
76 | TP_PROTO(struct cachefiles_object *obj, | ||
77 | struct fscache_cookie *cookie, | ||
78 | enum cachefiles_obj_ref_trace why, | ||
79 | int usage), | ||
80 | |||
81 | TP_ARGS(obj, cookie, why, usage), | ||
82 | |||
83 | /* Note that obj may be NULL */ | ||
84 | TP_STRUCT__entry( | ||
85 | __field(struct cachefiles_object *, obj ) | ||
86 | __field(struct fscache_cookie *, cookie ) | ||
87 | __field(enum cachefiles_obj_ref_trace, why ) | ||
88 | __field(int, usage ) | ||
89 | ), | ||
90 | |||
91 | TP_fast_assign( | ||
92 | __entry->obj = obj; | ||
93 | __entry->cookie = cookie; | ||
94 | __entry->usage = usage; | ||
95 | __entry->why = why; | ||
96 | ), | ||
97 | |||
98 | TP_printk("c=%p o=%p u=%d %s", | ||
99 | __entry->cookie, __entry->obj, __entry->usage, | ||
100 | __print_symbolic(__entry->why, cachefiles_obj_ref_traces)) | ||
101 | ); | ||
102 | |||
103 | TRACE_EVENT(cachefiles_lookup, | ||
104 | TP_PROTO(struct cachefiles_object *obj, | ||
105 | struct dentry *de, | ||
106 | struct inode *inode), | ||
107 | |||
108 | TP_ARGS(obj, de, inode), | ||
109 | |||
110 | TP_STRUCT__entry( | ||
111 | __field(struct cachefiles_object *, obj ) | ||
112 | __field(struct dentry *, de ) | ||
113 | __field(struct inode *, inode ) | ||
114 | ), | ||
115 | |||
116 | TP_fast_assign( | ||
117 | __entry->obj = obj; | ||
118 | __entry->de = de; | ||
119 | __entry->inode = inode; | ||
120 | ), | ||
121 | |||
122 | TP_printk("o=%p d=%p i=%p", | ||
123 | __entry->obj, __entry->de, __entry->inode) | ||
124 | ); | ||
125 | |||
126 | TRACE_EVENT(cachefiles_mkdir, | ||
127 | TP_PROTO(struct cachefiles_object *obj, | ||
128 | struct dentry *de, int ret), | ||
129 | |||
130 | TP_ARGS(obj, de, ret), | ||
131 | |||
132 | TP_STRUCT__entry( | ||
133 | __field(struct cachefiles_object *, obj ) | ||
134 | __field(struct dentry *, de ) | ||
135 | __field(int, ret ) | ||
136 | ), | ||
137 | |||
138 | TP_fast_assign( | ||
139 | __entry->obj = obj; | ||
140 | __entry->de = de; | ||
141 | __entry->ret = ret; | ||
142 | ), | ||
143 | |||
144 | TP_printk("o=%p d=%p r=%u", | ||
145 | __entry->obj, __entry->de, __entry->ret) | ||
146 | ); | ||
147 | |||
148 | TRACE_EVENT(cachefiles_create, | ||
149 | TP_PROTO(struct cachefiles_object *obj, | ||
150 | struct dentry *de, int ret), | ||
151 | |||
152 | TP_ARGS(obj, de, ret), | ||
153 | |||
154 | TP_STRUCT__entry( | ||
155 | __field(struct cachefiles_object *, obj ) | ||
156 | __field(struct dentry *, de ) | ||
157 | __field(int, ret ) | ||
158 | ), | ||
159 | |||
160 | TP_fast_assign( | ||
161 | __entry->obj = obj; | ||
162 | __entry->de = de; | ||
163 | __entry->ret = ret; | ||
164 | ), | ||
165 | |||
166 | TP_printk("o=%p d=%p r=%u", | ||
167 | __entry->obj, __entry->de, __entry->ret) | ||
168 | ); | ||
169 | |||
170 | TRACE_EVENT(cachefiles_unlink, | ||
171 | TP_PROTO(struct cachefiles_object *obj, | ||
172 | struct dentry *de, | ||
173 | enum fscache_why_object_killed why), | ||
174 | |||
175 | TP_ARGS(obj, de, why), | ||
176 | |||
177 | /* Note that obj may be NULL */ | ||
178 | TP_STRUCT__entry( | ||
179 | __field(struct cachefiles_object *, obj ) | ||
180 | __field(struct dentry *, de ) | ||
181 | __field(enum fscache_why_object_killed, why ) | ||
182 | ), | ||
183 | |||
184 | TP_fast_assign( | ||
185 | __entry->obj = obj; | ||
186 | __entry->de = de; | ||
187 | __entry->why = why; | ||
188 | ), | ||
189 | |||
190 | TP_printk("o=%p d=%p w=%s", | ||
191 | __entry->obj, __entry->de, | ||
192 | __print_symbolic(__entry->why, cachefiles_obj_kill_traces)) | ||
193 | ); | ||
194 | |||
195 | TRACE_EVENT(cachefiles_rename, | ||
196 | TP_PROTO(struct cachefiles_object *obj, | ||
197 | struct dentry *de, | ||
198 | struct dentry *to, | ||
199 | enum fscache_why_object_killed why), | ||
200 | |||
201 | TP_ARGS(obj, de, to, why), | ||
202 | |||
203 | /* Note that obj may be NULL */ | ||
204 | TP_STRUCT__entry( | ||
205 | __field(struct cachefiles_object *, obj ) | ||
206 | __field(struct dentry *, de ) | ||
207 | __field(struct dentry *, to ) | ||
208 | __field(enum fscache_why_object_killed, why ) | ||
209 | ), | ||
210 | |||
211 | TP_fast_assign( | ||
212 | __entry->obj = obj; | ||
213 | __entry->de = de; | ||
214 | __entry->to = to; | ||
215 | __entry->why = why; | ||
216 | ), | ||
217 | |||
218 | TP_printk("o=%p d=%p t=%p w=%s", | ||
219 | __entry->obj, __entry->de, __entry->to, | ||
220 | __print_symbolic(__entry->why, cachefiles_obj_kill_traces)) | ||
221 | ); | ||
222 | |||
223 | TRACE_EVENT(cachefiles_mark_active, | ||
224 | TP_PROTO(struct cachefiles_object *obj, | ||
225 | struct dentry *de), | ||
226 | |||
227 | TP_ARGS(obj, de), | ||
228 | |||
229 | /* Note that obj may be NULL */ | ||
230 | TP_STRUCT__entry( | ||
231 | __field(struct cachefiles_object *, obj ) | ||
232 | __field(struct dentry *, de ) | ||
233 | ), | ||
234 | |||
235 | TP_fast_assign( | ||
236 | __entry->obj = obj; | ||
237 | __entry->de = de; | ||
238 | ), | ||
239 | |||
240 | TP_printk("o=%p d=%p", | ||
241 | __entry->obj, __entry->de) | ||
242 | ); | ||
243 | |||
244 | TRACE_EVENT(cachefiles_wait_active, | ||
245 | TP_PROTO(struct cachefiles_object *obj, | ||
246 | struct dentry *de, | ||
247 | struct cachefiles_object *xobj), | ||
248 | |||
249 | TP_ARGS(obj, de, xobj), | ||
250 | |||
251 | /* Note that obj may be NULL */ | ||
252 | TP_STRUCT__entry( | ||
253 | __field(struct cachefiles_object *, obj ) | ||
254 | __field(struct dentry *, de ) | ||
255 | __field(struct cachefiles_object *, xobj ) | ||
256 | __field(u16, flags ) | ||
257 | __field(u16, fsc_flags ) | ||
258 | ), | ||
259 | |||
260 | TP_fast_assign( | ||
261 | __entry->obj = obj; | ||
262 | __entry->de = de; | ||
263 | __entry->xobj = xobj; | ||
264 | __entry->flags = xobj->flags; | ||
265 | __entry->fsc_flags = xobj->fscache.flags; | ||
266 | ), | ||
267 | |||
268 | TP_printk("o=%p d=%p wo=%p wf=%x wff=%x", | ||
269 | __entry->obj, __entry->de, __entry->xobj, | ||
270 | __entry->flags, __entry->fsc_flags) | ||
271 | ); | ||
272 | |||
273 | TRACE_EVENT(cachefiles_mark_inactive, | ||
274 | TP_PROTO(struct cachefiles_object *obj, | ||
275 | struct dentry *de, | ||
276 | struct inode *inode), | ||
277 | |||
278 | TP_ARGS(obj, de, inode), | ||
279 | |||
280 | /* Note that obj may be NULL */ | ||
281 | TP_STRUCT__entry( | ||
282 | __field(struct cachefiles_object *, obj ) | ||
283 | __field(struct dentry *, de ) | ||
284 | __field(struct inode *, inode ) | ||
285 | ), | ||
286 | |||
287 | TP_fast_assign( | ||
288 | __entry->obj = obj; | ||
289 | __entry->de = de; | ||
290 | __entry->inode = inode; | ||
291 | ), | ||
292 | |||
293 | TP_printk("o=%p d=%p i=%p", | ||
294 | __entry->obj, __entry->de, __entry->inode) | ||
295 | ); | ||
296 | |||
297 | TRACE_EVENT(cachefiles_mark_buried, | ||
298 | TP_PROTO(struct cachefiles_object *obj, | ||
299 | struct dentry *de, | ||
300 | enum fscache_why_object_killed why), | ||
301 | |||
302 | TP_ARGS(obj, de, why), | ||
303 | |||
304 | /* Note that obj may be NULL */ | ||
305 | TP_STRUCT__entry( | ||
306 | __field(struct cachefiles_object *, obj ) | ||
307 | __field(struct dentry *, de ) | ||
308 | __field(enum fscache_why_object_killed, why ) | ||
309 | ), | ||
310 | |||
311 | TP_fast_assign( | ||
312 | __entry->obj = obj; | ||
313 | __entry->de = de; | ||
314 | __entry->why = why; | ||
315 | ), | ||
316 | |||
317 | TP_printk("o=%p d=%p w=%s", | ||
318 | __entry->obj, __entry->de, | ||
319 | __print_symbolic(__entry->why, cachefiles_obj_kill_traces)) | ||
320 | ); | ||
321 | |||
322 | #endif /* _TRACE_CACHEFILES_H */ | ||
323 | |||
324 | /* This part must be outside protection */ | ||
325 | #include <trace/define_trace.h> | ||
diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h new file mode 100644 index 000000000000..99f5355d6281 --- /dev/null +++ b/include/trace/events/fscache.h | |||
@@ -0,0 +1,277 @@ | |||
1 | /* FS-Cache tracepoints | ||
2 | * | ||
3 | * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #undef TRACE_SYSTEM | ||
12 | #define TRACE_SYSTEM fscache | ||
13 | |||
14 | #if !defined(_TRACE_FSCACHE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
15 | #define _TRACE_FSCACHE_H | ||
16 | |||
17 | #include <linux/fscache.h> | ||
18 | #include <linux/tracepoint.h> | ||
19 | |||
20 | /* | ||
21 | * Define enums for tracing information. | ||
22 | */ | ||
23 | #ifndef __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY | ||
24 | #define __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY | ||
25 | |||
26 | enum fscache_cookie_trace { | ||
27 | fscache_cookie_get_acquire_parent, | ||
28 | fscache_cookie_get_attach_object, | ||
29 | fscache_cookie_get_register_netfs, | ||
30 | fscache_cookie_put_acquire_nobufs, | ||
31 | fscache_cookie_put_relinquish, | ||
32 | fscache_cookie_put_object, | ||
33 | fscache_cookie_put_parent, | ||
34 | }; | ||
35 | |||
36 | #endif | ||
37 | |||
38 | /* | ||
39 | * Declare tracing information enums and their string mappings for display. | ||
40 | */ | ||
41 | #define fscache_cookie_traces \ | ||
42 | EM(fscache_cookie_get_acquire_parent, "GET prn") \ | ||
43 | EM(fscache_cookie_get_attach_object, "GET obj") \ | ||
44 | EM(fscache_cookie_get_register_netfs, "GET net") \ | ||
45 | EM(fscache_cookie_put_acquire_nobufs, "PUT nbf") \ | ||
46 | EM(fscache_cookie_put_relinquish, "PUT rlq") \ | ||
47 | EM(fscache_cookie_put_object, "PUT obj") \ | ||
48 | E_(fscache_cookie_put_parent, "PUT prn") | ||
49 | |||
50 | /* | ||
51 | * Export enum symbols via userspace. | ||
52 | */ | ||
53 | #undef EM | ||
54 | #undef E_ | ||
55 | #define EM(a, b) TRACE_DEFINE_ENUM(a); | ||
56 | #define E_(a, b) TRACE_DEFINE_ENUM(a); | ||
57 | |||
58 | fscache_cookie_traces; | ||
59 | |||
60 | /* | ||
61 | * Now redefine the EM() and E_() macros to map the enums to the strings that | ||
62 | * will be printed in the output. | ||
63 | */ | ||
64 | #undef EM | ||
65 | #undef E_ | ||
66 | #define EM(a, b) { a, b }, | ||
67 | #define E_(a, b) { a, b } | ||
68 | |||
69 | |||
70 | TRACE_EVENT(fscache_cookie, | ||
71 | TP_PROTO(struct fscache_cookie *cookie, | ||
72 | enum fscache_cookie_trace where, | ||
73 | int usage), | ||
74 | |||
75 | TP_ARGS(cookie, where, usage), | ||
76 | |||
77 | TP_STRUCT__entry( | ||
78 | __field(struct fscache_cookie *, cookie ) | ||
79 | __field(struct fscache_cookie *, parent ) | ||
80 | __field(enum fscache_cookie_trace, where ) | ||
81 | __field(int, usage ) | ||
82 | __field(int, n_children ) | ||
83 | __field(int, n_active ) | ||
84 | __field(u8, flags ) | ||
85 | ), | ||
86 | |||
87 | TP_fast_assign( | ||
88 | __entry->cookie = cookie; | ||
89 | __entry->parent = cookie->parent; | ||
90 | __entry->where = where; | ||
91 | __entry->usage = usage; | ||
92 | __entry->n_children = atomic_read(&cookie->n_children); | ||
93 | __entry->n_active = atomic_read(&cookie->n_active); | ||
94 | __entry->flags = cookie->flags; | ||
95 | ), | ||
96 | |||
97 | TP_printk("%s c=%p u=%d p=%p Nc=%d Na=%d f=%02x", | ||
98 | __print_symbolic(__entry->where, fscache_cookie_traces), | ||
99 | __entry->cookie, __entry->usage, | ||
100 | __entry->parent, __entry->n_children, __entry->n_active, | ||
101 | __entry->flags) | ||
102 | ); | ||
103 | |||
104 | TRACE_EVENT(fscache_netfs, | ||
105 | TP_PROTO(struct fscache_netfs *netfs), | ||
106 | |||
107 | TP_ARGS(netfs), | ||
108 | |||
109 | TP_STRUCT__entry( | ||
110 | __field(struct fscache_cookie *, cookie ) | ||
111 | __array(char, name, 8 ) | ||
112 | ), | ||
113 | |||
114 | TP_fast_assign( | ||
115 | __entry->cookie = netfs->primary_index; | ||
116 | strncpy(__entry->name, netfs->name, 8); | ||
117 | __entry->name[7] = 0; | ||
118 | ), | ||
119 | |||
120 | TP_printk("c=%p n=%s", | ||
121 | __entry->cookie, __entry->name) | ||
122 | ); | ||
123 | |||
124 | TRACE_EVENT(fscache_acquire, | ||
125 | TP_PROTO(struct fscache_cookie *cookie), | ||
126 | |||
127 | TP_ARGS(cookie), | ||
128 | |||
129 | TP_STRUCT__entry( | ||
130 | __field(struct fscache_cookie *, cookie ) | ||
131 | __field(struct fscache_cookie *, parent ) | ||
132 | __array(char, name, 8 ) | ||
133 | __field(int, p_usage ) | ||
134 | __field(int, p_n_children ) | ||
135 | __field(u8, p_flags ) | ||
136 | ), | ||
137 | |||
138 | TP_fast_assign( | ||
139 | __entry->cookie = cookie; | ||
140 | __entry->parent = cookie->parent; | ||
141 | __entry->p_usage = atomic_read(&cookie->parent->usage); | ||
142 | __entry->p_n_children = atomic_read(&cookie->parent->n_children); | ||
143 | __entry->p_flags = cookie->parent->flags; | ||
144 | memcpy(__entry->name, cookie->def->name, 8); | ||
145 | __entry->name[7] = 0; | ||
146 | ), | ||
147 | |||
148 | TP_printk("c=%p p=%p pu=%d pc=%d pf=%02x n=%s", | ||
149 | __entry->cookie, __entry->parent, __entry->p_usage, | ||
150 | __entry->p_n_children, __entry->p_flags, __entry->name) | ||
151 | ); | ||
152 | |||
153 | TRACE_EVENT(fscache_relinquish, | ||
154 | TP_PROTO(struct fscache_cookie *cookie, bool retire), | ||
155 | |||
156 | TP_ARGS(cookie, retire), | ||
157 | |||
158 | TP_STRUCT__entry( | ||
159 | __field(struct fscache_cookie *, cookie ) | ||
160 | __field(struct fscache_cookie *, parent ) | ||
161 | __field(int, usage ) | ||
162 | __field(int, n_children ) | ||
163 | __field(int, n_active ) | ||
164 | __field(u8, flags ) | ||
165 | __field(bool, retire ) | ||
166 | ), | ||
167 | |||
168 | TP_fast_assign( | ||
169 | __entry->cookie = cookie; | ||
170 | __entry->parent = cookie->parent; | ||
171 | __entry->usage = atomic_read(&cookie->usage); | ||
172 | __entry->n_children = atomic_read(&cookie->n_children); | ||
173 | __entry->n_active = atomic_read(&cookie->n_active); | ||
174 | __entry->flags = cookie->flags; | ||
175 | __entry->retire = retire; | ||
176 | ), | ||
177 | |||
178 | TP_printk("c=%p u=%d p=%p Nc=%d Na=%d f=%02x r=%u", | ||
179 | __entry->cookie, __entry->usage, | ||
180 | __entry->parent, __entry->n_children, __entry->n_active, | ||
181 | __entry->flags, __entry->retire) | ||
182 | ); | ||
183 | |||
184 | TRACE_EVENT(fscache_enable, | ||
185 | TP_PROTO(struct fscache_cookie *cookie), | ||
186 | |||
187 | TP_ARGS(cookie), | ||
188 | |||
189 | TP_STRUCT__entry( | ||
190 | __field(struct fscache_cookie *, cookie ) | ||
191 | __field(int, usage ) | ||
192 | __field(int, n_children ) | ||
193 | __field(int, n_active ) | ||
194 | __field(u8, flags ) | ||
195 | ), | ||
196 | |||
197 | TP_fast_assign( | ||
198 | __entry->cookie = cookie; | ||
199 | __entry->usage = atomic_read(&cookie->usage); | ||
200 | __entry->n_children = atomic_read(&cookie->n_children); | ||
201 | __entry->n_active = atomic_read(&cookie->n_active); | ||
202 | __entry->flags = cookie->flags; | ||
203 | ), | ||
204 | |||
205 | TP_printk("c=%p u=%d Nc=%d Na=%d f=%02x", | ||
206 | __entry->cookie, __entry->usage, | ||
207 | __entry->n_children, __entry->n_active, __entry->flags) | ||
208 | ); | ||
209 | |||
210 | TRACE_EVENT(fscache_disable, | ||
211 | TP_PROTO(struct fscache_cookie *cookie), | ||
212 | |||
213 | TP_ARGS(cookie), | ||
214 | |||
215 | TP_STRUCT__entry( | ||
216 | __field(struct fscache_cookie *, cookie ) | ||
217 | __field(int, usage ) | ||
218 | __field(int, n_children ) | ||
219 | __field(int, n_active ) | ||
220 | __field(u8, flags ) | ||
221 | ), | ||
222 | |||
223 | TP_fast_assign( | ||
224 | __entry->cookie = cookie; | ||
225 | __entry->usage = atomic_read(&cookie->usage); | ||
226 | __entry->n_children = atomic_read(&cookie->n_children); | ||
227 | __entry->n_active = atomic_read(&cookie->n_active); | ||
228 | __entry->flags = cookie->flags; | ||
229 | ), | ||
230 | |||
231 | TP_printk("c=%p u=%d Nc=%d Na=%d f=%02x", | ||
232 | __entry->cookie, __entry->usage, | ||
233 | __entry->n_children, __entry->n_active, __entry->flags) | ||
234 | ); | ||
235 | |||
236 | TRACE_EVENT(fscache_osm, | ||
237 | TP_PROTO(struct fscache_object *object, | ||
238 | const struct fscache_state *state, | ||
239 | bool wait, bool oob, s8 event_num), | ||
240 | |||
241 | TP_ARGS(object, state, wait, oob, event_num), | ||
242 | |||
243 | TP_STRUCT__entry( | ||
244 | __field(struct fscache_cookie *, cookie ) | ||
245 | __field(struct fscache_object *, object ) | ||
246 | __array(char, state, 8 ) | ||
247 | __field(bool, wait ) | ||
248 | __field(bool, oob ) | ||
249 | __field(s8, event_num ) | ||
250 | ), | ||
251 | |||
252 | TP_fast_assign( | ||
253 | __entry->cookie = object->cookie; | ||
254 | __entry->object = object; | ||
255 | __entry->wait = wait; | ||
256 | __entry->oob = oob; | ||
257 | __entry->event_num = event_num; | ||
258 | memcpy(__entry->state, state->short_name, 8); | ||
259 | ), | ||
260 | |||
261 | TP_printk("c=%p o=%p %s %s%sev=%d", | ||
262 | __entry->cookie, | ||
263 | __entry->object, | ||
264 | __entry->state, | ||
265 | __print_symbolic(__entry->wait, | ||
266 | { true, "WAIT" }, | ||
267 | { false, "WORK" }), | ||
268 | __print_symbolic(__entry->oob, | ||
269 | { true, " OOB " }, | ||
270 | { false, " " }), | ||
271 | __entry->event_num) | ||
272 | ); | ||
273 | |||
274 | #endif /* _TRACE_FSCACHE_H */ | ||
275 | |||
276 | /* This part must be outside protection */ | ||
277 | #include <trace/define_trace.h> | ||