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:
parent
35b72573e9
commit
33cba85922
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue