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
Родитель 35b72573e9
Коммит 33cba85922
4 изменённых файлов: 15 добавлений и 23 удалений

Просмотреть файл

@ -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,