afs: Add a tracepoint to track the lifetime of the afs_volume struct
Add a tracepoint to track the lifetime of the afs_volume struct. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
@@ -482,7 +482,7 @@ static void afs_cell_destroy(struct rcu_head *rcu)
|
|||||||
|
|
||||||
ASSERTCMP(atomic_read(&cell->usage), ==, 0);
|
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_vlserverlist(cell->net, rcu_access_pointer(cell->vl_servers));
|
||||||
afs_put_cell(cell->net, cell->alias_of);
|
afs_put_cell(cell->net, cell->alias_of);
|
||||||
key_put(cell->anonymous_key);
|
key_put(cell->anonymous_key);
|
||||||
|
@@ -36,7 +36,7 @@ struct afs_operation *afs_alloc_operation(struct key *key, struct afs_volume *vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
op->key = key;
|
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->net = volume->cell->net;
|
||||||
op->cb_v_break = volume->cb_v_break;
|
op->cb_v_break = volume->cb_v_break;
|
||||||
op->debug_id = atomic_inc_return(&afs_operation_debug_counter);
|
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_end_cursor(&op->ac);
|
||||||
afs_put_cb_interest(op->net, op->cbi);
|
afs_put_cb_interest(op->net, op->cbi);
|
||||||
afs_put_serverlist(op->net, op->server_list);
|
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);
|
kfree(op);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -1429,17 +1429,11 @@ extern struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *,
|
|||||||
/*
|
/*
|
||||||
* volume.c
|
* 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 struct afs_volume *afs_create_volume(struct afs_fs_context *);
|
||||||
extern void afs_activate_volume(struct afs_volume *);
|
extern void afs_activate_volume(struct afs_volume *);
|
||||||
extern void afs_deactivate_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 *);
|
extern int afs_check_volume_status(struct afs_volume *, struct afs_operation *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -376,7 +376,8 @@ static int afs_validate_fc(struct fs_context *fc)
|
|||||||
ctx->key = key;
|
ctx->key = key;
|
||||||
|
|
||||||
if (ctx->volume) {
|
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;
|
ctx->volume = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,7 +508,8 @@ static struct afs_super_info *afs_alloc_sbi(struct fs_context *fc)
|
|||||||
as->dyn_root = true;
|
as->dyn_root = true;
|
||||||
} else {
|
} else {
|
||||||
as->cell = afs_get_cell(ctx->cell);
|
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;
|
return as;
|
||||||
@@ -517,7 +519,7 @@ static void afs_destroy_sbi(struct afs_super_info *as)
|
|||||||
{
|
{
|
||||||
if (as) {
|
if (as) {
|
||||||
struct afs_net *net = afs_net(as->net_ns);
|
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);
|
afs_put_cell(net, as->cell);
|
||||||
put_net(as->net_ns);
|
put_net(as->net_ns);
|
||||||
kfree(as);
|
kfree(as);
|
||||||
@@ -605,7 +607,7 @@ static void afs_free_fc(struct fs_context *fc)
|
|||||||
struct afs_fs_context *ctx = fc->fs_private;
|
struct afs_fs_context *ctx = fc->fs_private;
|
||||||
|
|
||||||
afs_destroy_sbi(fc->s_fs_info);
|
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);
|
afs_put_cell(ctx->net, ctx->cell);
|
||||||
key_put(ctx->key);
|
key_put(ctx->key);
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
|
@@ -193,7 +193,8 @@ static int afs_query_for_alias_one(struct afs_cell *cell, struct key *key,
|
|||||||
read_lock(&p->proc_lock);
|
read_lock(&p->proc_lock);
|
||||||
if (!list_empty(&p->proc_volumes))
|
if (!list_empty(&p->proc_volumes))
|
||||||
pvol = afs_get_volume(list_first_entry(&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);
|
read_unlock(&p->proc_lock);
|
||||||
if (!pvol)
|
if (!pvol)
|
||||||
return 0;
|
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. */
|
/* And see if it's in the new cell. */
|
||||||
volume = afs_sample_volume(cell, key, pvol->name, pvol->name_len);
|
volume = afs_sample_volume(cell, key, pvol->name, pvol->name_len);
|
||||||
if (IS_ERR(volume)) {
|
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)
|
if (PTR_ERR(volume) != -ENOMEDIUM)
|
||||||
return PTR_ERR(volume);
|
return PTR_ERR(volume);
|
||||||
/* That volume is not in the new cell, so not an alias */
|
/* 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();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
afs_put_volume(cell->net, volume);
|
afs_put_volume(cell->net, volume, afs_volume_trace_put_query_alias);
|
||||||
afs_put_volume(cell->net, pvol);
|
afs_put_volume(cell->net, pvol, afs_volume_trace_put_query_alias);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,6 +52,7 @@ static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
|
|||||||
|
|
||||||
refcount_set(&slist->usage, 1);
|
refcount_set(&slist->usage, 1);
|
||||||
rcu_assign_pointer(volume->servers, slist);
|
rcu_assign_pointer(volume->servers, slist);
|
||||||
|
trace_afs_volume(volume->vid, 1, afs_volume_trace_alloc);
|
||||||
return volume;
|
return volume;
|
||||||
|
|
||||||
error_1:
|
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_serverlist(net, rcu_access_pointer(volume->servers));
|
||||||
afs_put_cell(net, volume->cell);
|
afs_put_cell(net, volume->cell);
|
||||||
|
trace_afs_volume(volume->vid, atomic_read(&volume->usage),
|
||||||
|
afs_volume_trace_free);
|
||||||
kfree(volume);
|
kfree(volume);
|
||||||
|
|
||||||
_leave(" [destroyed]");
|
_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) {
|
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);
|
afs_destroy_volume(net, volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,6 +50,23 @@ enum afs_server_trace {
|
|||||||
afs_server_trace_update,
|
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 {
|
enum afs_fs_operation {
|
||||||
afs_FS_FetchData = 130, /* AFS Fetch file data */
|
afs_FS_FetchData = 130, /* AFS Fetch file data */
|
||||||
afs_FS_FetchACL = 131, /* AFS Fetch file ACL */
|
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") \
|
EM(afs_server_trace_put_uuid_rsq, "PUT u-req") \
|
||||||
E_(afs_server_trace_update, "UPDATE")
|
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 \
|
#define afs_fs_operations \
|
||||||
EM(afs_FS_FetchData, "FS.FetchData") \
|
EM(afs_FS_FetchData, "FS.FetchData") \
|
||||||
EM(afs_FS_FetchStatus, "FS.FetchStatus") \
|
EM(afs_FS_FetchStatus, "FS.FetchStatus") \
|
||||||
@@ -1302,6 +1335,29 @@ TRACE_EVENT(afs_server,
|
|||||||
__entry->active)
|
__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 */
|
#endif /* _TRACE_AFS_H */
|
||||||
|
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
|
Reference in New Issue
Block a user