fscache: Fix fscache_cookie_put() to not deref after dec
authorDavid Howells <dhowells@redhat.com>
Fri, 18 Jun 2021 10:19:49 +0000 (11:19 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 27 Aug 2021 12:34:02 +0000 (13:34 +0100)
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: a18feb55769b ("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/
fs/fscache/cookie.c
fs/fscache/internal.h
fs/fscache/netfs.c
include/trace/events/fscache.h

index 2558814193e9ba9ff7e943702b16b985aa7df99c..6df3732cf1b4681a7591e753010339f0156ec6f8 100644 (file)
@@ -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;
index a49136c63e4b0fa59806b4aced22892a215021a2..345105dbbfd1b9a7b54fca61e4cd69fafc4524ec 100644 (file)
@@ -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);
 }
 
 /*
index cce92216fa28b7e8bb3a91b66588fa596fb07b87..d6bdb7b5e72321f62aef46cccfe6a6d6e28953ef 100644 (file)
@@ -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);
        }
 
index 33d1fd5d0383bc4079732980f50a996caf565cff..19d65d9d4357794e6cecd74ae644b8b659630154 100644 (file)
@@ -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,