fscache: Fix fscache_cookie_put() to not deref after dec

fscache_cookie_put() accesses the cookie it has just put inside the
tracepoint that monitors the change - but this is something it's not
allowed to do if we didn't reduce the count to zero.

Fix this by dropping most of those values from the tracepoint and grabbing
the cookie debug ID before doing the dec.

Also take the opportunity to switch over the usage and where arguments on
the tracepoint to put the reason last.

Fixes: a18feb5576 ("fscache: Add tracepoints")
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/162431203107.2908479.3259582550347000088.stgit@warthog.procyon.org.uk/
This commit is contained in:
David Howells 2021-06-18 11:19:49 +01:00
parent 35b72573e9
commit 33cba85922
4 changed files with 15 additions and 23 deletions

View File

@ -225,8 +225,8 @@ struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate)
collision: collision:
if (test_and_set_bit(FSCACHE_COOKIE_ACQUIRED, &cursor->flags)) { if (test_and_set_bit(FSCACHE_COOKIE_ACQUIRED, &cursor->flags)) {
trace_fscache_cookie(cursor, fscache_cookie_collision, trace_fscache_cookie(cursor->debug_id, atomic_read(&cursor->usage),
atomic_read(&cursor->usage)); fscache_cookie_collision);
pr_err("Duplicate cookie detected\n"); pr_err("Duplicate cookie detected\n");
fscache_print_cookie(cursor, 'O'); fscache_print_cookie(cursor, 'O');
fscache_print_cookie(candidate, 'N'); fscache_print_cookie(candidate, 'N');
@ -305,7 +305,8 @@ struct fscache_cookie *__fscache_acquire_cookie(
cookie = fscache_hash_cookie(candidate); cookie = fscache_hash_cookie(candidate);
if (!cookie) { if (!cookie) {
trace_fscache_cookie(candidate, fscache_cookie_discard, 1); trace_fscache_cookie(candidate->debug_id, 1,
fscache_cookie_discard);
goto out; goto out;
} }
@ -866,8 +867,9 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
_enter("%x", cookie->debug_id); _enter("%x", cookie->debug_id);
do { do {
unsigned int cookie_debug_id = cookie->debug_id;
usage = atomic_dec_return(&cookie->usage); usage = atomic_dec_return(&cookie->usage);
trace_fscache_cookie(cookie, where, usage); trace_fscache_cookie(cookie_debug_id, usage, where);
if (usage > 0) if (usage > 0)
return; return;

View File

@ -291,7 +291,7 @@ static inline void fscache_cookie_get(struct fscache_cookie *cookie,
{ {
int usage = atomic_inc_return(&cookie->usage); int usage = atomic_inc_return(&cookie->usage);
trace_fscache_cookie(cookie, where, usage); trace_fscache_cookie(cookie->debug_id, usage, where);
} }
/* /*

View File

@ -37,7 +37,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
if (!cookie) if (!cookie)
goto already_registered; goto already_registered;
if (cookie != candidate) { if (cookie != candidate) {
trace_fscache_cookie(candidate, fscache_cookie_discard, 1); trace_fscache_cookie(candidate->debug_id, 1, fscache_cookie_discard);
fscache_free_cookie(candidate); fscache_free_cookie(candidate);
} }

View File

@ -160,37 +160,27 @@ fscache_cookie_traces;
TRACE_EVENT(fscache_cookie, TRACE_EVENT(fscache_cookie,
TP_PROTO(struct fscache_cookie *cookie, TP_PROTO(unsigned int cookie_debug_id,
enum fscache_cookie_trace where, int usage,
int usage), enum fscache_cookie_trace where),
TP_ARGS(cookie, where, usage), TP_ARGS(cookie_debug_id, usage, where),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(unsigned int, cookie ) __field(unsigned int, cookie )
__field(unsigned int, parent )
__field(enum fscache_cookie_trace, where ) __field(enum fscache_cookie_trace, where )
__field(int, usage ) __field(int, usage )
__field(int, n_children )
__field(int, n_active )
__field(u8, flags )
), ),
TP_fast_assign( TP_fast_assign(
__entry->cookie = cookie->debug_id; __entry->cookie = cookie_debug_id;
__entry->parent = cookie->parent ? cookie->parent->debug_id : 0;
__entry->where = where; __entry->where = where;
__entry->usage = usage; __entry->usage = usage;
__entry->n_children = atomic_read(&cookie->n_children);
__entry->n_active = atomic_read(&cookie->n_active);
__entry->flags = cookie->flags;
), ),
TP_printk("%s c=%08x u=%d p=%08x Nc=%d Na=%d f=%02x", TP_printk("%s c=%08x u=%d",
__print_symbolic(__entry->where, fscache_cookie_traces), __print_symbolic(__entry->where, fscache_cookie_traces),
__entry->cookie, __entry->usage, __entry->cookie, __entry->usage)
__entry->parent, __entry->n_children, __entry->n_active,
__entry->flags)
); );
TRACE_EVENT(fscache_netfs, TRACE_EVENT(fscache_netfs,