Commit 33cba859 authored by David Howells's avatar David Howells

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: a18feb55 ("fscache: Add tracepoints")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/162431203107.2908479.3259582550347000088.stgit@warthog.procyon.org.uk/
parent 35b72573
......@@ -225,8 +225,8 @@ struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *candidate)
collision:
if (test_and_set_bit(FSCACHE_COOKIE_ACQUIRED, &cursor->flags)) {
trace_fscache_cookie(cursor, fscache_cookie_collision,
atomic_read(&cursor->usage));
trace_fscache_cookie(cursor->debug_id, atomic_read(&cursor->usage),
fscache_cookie_collision);
pr_err("Duplicate cookie detected\n");
fscache_print_cookie(cursor, 'O');
fscache_print_cookie(candidate, 'N');
......@@ -305,7 +305,8 @@ struct fscache_cookie *__fscache_acquire_cookie(
cookie = fscache_hash_cookie(candidate);
if (!cookie) {
trace_fscache_cookie(candidate, fscache_cookie_discard, 1);
trace_fscache_cookie(candidate->debug_id, 1,
fscache_cookie_discard);
goto out;
}
......@@ -866,8 +867,9 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
_enter("%x", cookie->debug_id);
do {
unsigned int cookie_debug_id = cookie->debug_id;
usage = atomic_dec_return(&cookie->usage);
trace_fscache_cookie(cookie, where, usage);
trace_fscache_cookie(cookie_debug_id, usage, where);
if (usage > 0)
return;
......
......@@ -291,7 +291,7 @@ static inline void fscache_cookie_get(struct fscache_cookie *cookie,
{
int usage = atomic_inc_return(&cookie->usage);
trace_fscache_cookie(cookie, where, usage);
trace_fscache_cookie(cookie->debug_id, usage, where);
}
/*
......
......@@ -37,7 +37,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
if (!cookie)
goto already_registered;
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);
}
......
......@@ -160,37 +160,27 @@ fscache_cookie_traces;
TRACE_EVENT(fscache_cookie,
TP_PROTO(struct fscache_cookie *cookie,
enum fscache_cookie_trace where,
int usage),
TP_PROTO(unsigned int cookie_debug_id,
int usage,
enum fscache_cookie_trace where),
TP_ARGS(cookie, where, usage),
TP_ARGS(cookie_debug_id, usage, where),
TP_STRUCT__entry(
__field(unsigned int, cookie )
__field(unsigned int, parent )
__field(enum fscache_cookie_trace, where )
__field(int, usage )
__field(int, n_children )
__field(int, n_active )
__field(u8, flags )
),
TP_fast_assign(
__entry->cookie = cookie->debug_id;
__entry->parent = cookie->parent ? cookie->parent->debug_id : 0;
__entry->cookie = cookie_debug_id;
__entry->where = where;
__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),
__entry->cookie, __entry->usage,
__entry->parent, __entry->n_children, __entry->n_active,
__entry->flags)
__entry->cookie, __entry->usage)
);
TRACE_EVENT(fscache_netfs,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment