afs: Add a tracepoint to track the lifetime of the afs_volume struct
authorDavid Howells <dhowells@redhat.com>
Wed, 29 Apr 2020 16:02:04 +0000 (17:02 +0100)
committerDavid Howells <dhowells@redhat.com>
Thu, 4 Jun 2020 14:37:57 +0000 (15:37 +0100)
Add a tracepoint to track the lifetime of the afs_volume struct.

Signed-off-by: David Howells <dhowells@redhat.com>
fs/afs/cell.c
fs/afs/fs_operation.c
fs/afs/internal.h
fs/afs/super.c
fs/afs/vl_alias.c
fs/afs/volume.c
include/trace/events/afs.h

index 2120985..8bfc8a0 100644 (file)
@@ -482,7 +482,7 @@ static void afs_cell_destroy(struct rcu_head *rcu)
 
        ASSERTCMP(atomic_read(&cell->usage), ==, 0);
 
-       afs_put_volume(cell->net, cell->root_volume);
+       afs_put_volume(cell->net, cell->root_volume, afs_volume_trace_put_cell_root);
        afs_put_vlserverlist(cell->net, rcu_access_pointer(cell->vl_servers));
        afs_put_cell(cell->net, cell->alias_of);
        key_put(cell->anonymous_key);
index f7a768d..f57efd9 100644 (file)
@@ -36,7 +36,7 @@ struct afs_operation *afs_alloc_operation(struct key *key, struct afs_volume *vo
        }
 
        op->key         = key;
-       op->volume      = afs_get_volume(volume);
+       op->volume      = afs_get_volume(volume, afs_volume_trace_get_new_op);
        op->net         = volume->cell->net;
        op->cb_v_break  = volume->cb_v_break;
        op->debug_id    = atomic_inc_return(&afs_operation_debug_counter);
@@ -233,7 +233,7 @@ int afs_put_operation(struct afs_operation *op)
        afs_end_cursor(&op->ac);
        afs_put_cb_interest(op->net, op->cbi);
        afs_put_serverlist(op->net, op->server_list);
-       afs_put_volume(op->net, op->volume);
+       afs_put_volume(op->net, op->volume, afs_volume_trace_put_put_op);
        kfree(op);
        return ret;
 }
index a3ef97d..e084936 100644 (file)
@@ -1429,17 +1429,11 @@ extern struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *,
 /*
  * volume.c
  */
-static inline struct afs_volume *afs_get_volume(struct afs_volume *volume)
-{
-       if (volume)
-               atomic_inc(&volume->usage);
-       return volume;
-}
-
 extern struct afs_volume *afs_create_volume(struct afs_fs_context *);
 extern void afs_activate_volume(struct afs_volume *);
 extern void afs_deactivate_volume(struct afs_volume *);
-extern void afs_put_volume(struct afs_net *, struct afs_volume *);
+extern struct afs_volume *afs_get_volume(struct afs_volume *, enum afs_volume_trace);
+extern void afs_put_volume(struct afs_net *, struct afs_volume *, enum afs_volume_trace);
 extern int afs_check_volume_status(struct afs_volume *, struct afs_operation *);
 
 /*
index aae6866..f92ccda 100644 (file)
@@ -376,7 +376,8 @@ static int afs_validate_fc(struct fs_context *fc)
                ctx->key = key;
 
                if (ctx->volume) {
-                       afs_put_volume(ctx->net, ctx->volume);
+                       afs_put_volume(ctx->net, ctx->volume,
+                                      afs_volume_trace_put_validate_fc);
                        ctx->volume = NULL;
                }
 
@@ -507,7 +508,8 @@ static struct afs_super_info *afs_alloc_sbi(struct fs_context *fc)
                        as->dyn_root = true;
                } else {
                        as->cell = afs_get_cell(ctx->cell);
-                       as->volume = afs_get_volume(ctx->volume);
+                       as->volume = afs_get_volume(ctx->volume,
+                                                   afs_volume_trace_get_alloc_sbi);
                }
        }
        return as;
@@ -517,7 +519,7 @@ static void afs_destroy_sbi(struct afs_super_info *as)
 {
        if (as) {
                struct afs_net *net = afs_net(as->net_ns);
-               afs_put_volume(net, as->volume);
+               afs_put_volume(net, as->volume, afs_volume_trace_put_destroy_sbi);
                afs_put_cell(net, as->cell);
                put_net(as->net_ns);
                kfree(as);
@@ -605,7 +607,7 @@ static void afs_free_fc(struct fs_context *fc)
        struct afs_fs_context *ctx = fc->fs_private;
 
        afs_destroy_sbi(fc->s_fs_info);
-       afs_put_volume(ctx->net, ctx->volume);
+       afs_put_volume(ctx->net, ctx->volume, afs_volume_trace_put_free_fc);
        afs_put_cell(ctx->net, ctx->cell);
        key_put(ctx->key);
        kfree(ctx);
index ac7a59e..c61dd94 100644 (file)
@@ -193,7 +193,8 @@ static int afs_query_for_alias_one(struct afs_cell *cell, struct key *key,
        read_lock(&p->proc_lock);
        if (!list_empty(&p->proc_volumes))
                pvol = afs_get_volume(list_first_entry(&p->proc_volumes,
-                                                      struct afs_volume, proc_link));
+                                                      struct afs_volume, proc_link),
+                                     afs_volume_trace_get_query_alias);
        read_unlock(&p->proc_lock);
        if (!pvol)
                return 0;
@@ -203,7 +204,7 @@ static int afs_query_for_alias_one(struct afs_cell *cell, struct key *key,
        /* And see if it's in the new cell. */
        volume = afs_sample_volume(cell, key, pvol->name, pvol->name_len);
        if (IS_ERR(volume)) {
-               afs_put_volume(cell->net, pvol);
+               afs_put_volume(cell->net, pvol, afs_volume_trace_put_query_alias);
                if (PTR_ERR(volume) != -ENOMEDIUM)
                        return PTR_ERR(volume);
                /* That volume is not in the new cell, so not an alias */
@@ -221,8 +222,8 @@ static int afs_query_for_alias_one(struct afs_cell *cell, struct key *key,
                rcu_read_unlock();
        }
 
-       afs_put_volume(cell->net, volume);
-       afs_put_volume(cell->net, pvol);
+       afs_put_volume(cell->net, volume, afs_volume_trace_put_query_alias);
+       afs_put_volume(cell->net, pvol, afs_volume_trace_put_query_alias);
        return ret;
 }
 
index d4d9a8f..0393f49 100644 (file)
@@ -52,6 +52,7 @@ static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
 
        refcount_set(&slist->usage, 1);
        rcu_assign_pointer(volume->servers, slist);
+       trace_afs_volume(volume->vid, 1, afs_volume_trace_alloc);
        return volume;
 
 error_1:
@@ -158,20 +159,38 @@ static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume)
 
        afs_put_serverlist(net, rcu_access_pointer(volume->servers));
        afs_put_cell(net, volume->cell);
+       trace_afs_volume(volume->vid, atomic_read(&volume->usage),
+                        afs_volume_trace_free);
        kfree(volume);
 
        _leave(" [destroyed]");
 }
 
 /*
- * Drop a reference on a volume record.
+ * Get a reference on a volume record.
  */
-void afs_put_volume(struct afs_net *net, struct afs_volume *volume)
+struct afs_volume *afs_get_volume(struct afs_volume *volume,
+                                 enum afs_volume_trace reason)
 {
        if (volume) {
-               _enter("%s", volume->name);
+               int u = atomic_inc_return(&volume->usage);
+               trace_afs_volume(volume->vid, u, reason);
+       }
+       return volume;
+}
+
 
-               if (atomic_dec_and_test(&volume->usage))
+/*
+ * Drop a reference on a volume record.
+ */
+void afs_put_volume(struct afs_net *net, struct afs_volume *volume,
+                   enum afs_volume_trace reason)
+{
+       if (volume) {
+               afs_volid_t vid = volume->vid;
+               int u = atomic_dec_return(&volume->usage);
+               trace_afs_volume(vid, u, reason);
+               if (u == 0)
                        afs_destroy_volume(net, volume);
        }
 }
index f320b3a..5f0c1cf 100644 (file)
@@ -50,6 +50,23 @@ enum afs_server_trace {
        afs_server_trace_update,
 };
 
+enum afs_volume_trace {
+       afs_volume_trace_alloc,
+       afs_volume_trace_free,
+       afs_volume_trace_get_alloc_sbi,
+       afs_volume_trace_get_cell_insert,
+       afs_volume_trace_get_new_op,
+       afs_volume_trace_get_query_alias,
+       afs_volume_trace_put_cell_dup,
+       afs_volume_trace_put_cell_root,
+       afs_volume_trace_put_destroy_sbi,
+       afs_volume_trace_put_free_fc,
+       afs_volume_trace_put_put_op,
+       afs_volume_trace_put_query_alias,
+       afs_volume_trace_put_validate_fc,
+       afs_volume_trace_remove,
+};
+
 enum afs_fs_operation {
        afs_FS_FetchData                = 130,  /* AFS Fetch file data */
        afs_FS_FetchACL                 = 131,  /* AFS Fetch file ACL */
@@ -262,6 +279,22 @@ enum afs_cb_break_reason {
        EM(afs_server_trace_put_uuid_rsq,       "PUT u-req") \
        E_(afs_server_trace_update,             "UPDATE")
 
+#define afs_volume_traces \
+       EM(afs_volume_trace_alloc,              "ALLOC         ") \
+       EM(afs_volume_trace_free,               "FREE          ") \
+       EM(afs_volume_trace_get_alloc_sbi,      "GET sbi-alloc ") \
+       EM(afs_volume_trace_get_cell_insert,    "GET cell-insrt") \
+       EM(afs_volume_trace_get_new_op,         "GET op-new    ") \
+       EM(afs_volume_trace_get_query_alias,    "GET cell-alias") \
+       EM(afs_volume_trace_put_cell_dup,       "PUT cell-dup  ") \
+       EM(afs_volume_trace_put_cell_root,      "PUT cell-root ") \
+       EM(afs_volume_trace_put_destroy_sbi,    "PUT sbi-destry") \
+       EM(afs_volume_trace_put_free_fc,        "PUT fc-free   ") \
+       EM(afs_volume_trace_put_put_op,         "PUT op-put    ") \
+       EM(afs_volume_trace_put_query_alias,    "PUT cell-alias") \
+       EM(afs_volume_trace_put_validate_fc,    "PUT fc-validat") \
+       E_(afs_volume_trace_remove,             "REMOVE        ")
+
 #define afs_fs_operations \
        EM(afs_FS_FetchData,                    "FS.FetchData") \
        EM(afs_FS_FetchStatus,                  "FS.FetchStatus") \
@@ -1302,6 +1335,29 @@ TRACE_EVENT(afs_server,
                      __entry->active)
            );
 
+TRACE_EVENT(afs_volume,
+           TP_PROTO(afs_volid_t vid, int ref, enum afs_volume_trace reason),
+
+           TP_ARGS(vid, ref, reason),
+
+           TP_STRUCT__entry(
+                   __field(afs_volid_t,                vid             )
+                   __field(int,                        ref             )
+                   __field(enum afs_volume_trace,      reason          )
+                            ),
+
+           TP_fast_assign(
+                   __entry->vid = vid;
+                   __entry->ref = ref;
+                   __entry->reason = reason;
+                          ),
+
+           TP_printk("V=%llx %s u=%d",
+                     __entry->vid,
+                     __print_symbolic(__entry->reason, afs_volume_traces),
+                     __entry->ref)
+           );
+
 #endif /* _TRACE_AFS_H */
 
 /* This part must be outside protection */