Commit 45218193 authored by David Howells's avatar David Howells

afs: Trace afs_server usage

Add a tracepoint (afs_server) to track the afs_server object usage count.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 051d2525
...@@ -48,7 +48,7 @@ static struct afs_cb_interest *afs_create_interest(struct afs_server *server, ...@@ -48,7 +48,7 @@ static struct afs_cb_interest *afs_create_interest(struct afs_server *server,
refcount_set(&new->usage, 1); refcount_set(&new->usage, 1);
new->sb = vnode->vfs_inode.i_sb; new->sb = vnode->vfs_inode.i_sb;
new->vid = vnode->volume->vid; new->vid = vnode->volume->vid;
new->server = afs_get_server(server); new->server = afs_get_server(server, afs_server_trace_get_new_cbi);
INIT_HLIST_NODE(&new->cb_vlink); INIT_HLIST_NODE(&new->cb_vlink);
write_lock(&server->cb_break_lock); write_lock(&server->cb_break_lock);
...@@ -195,7 +195,7 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi) ...@@ -195,7 +195,7 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi)
write_unlock(&cbi->server->cb_break_lock); write_unlock(&cbi->server->cb_break_lock);
if (vi) if (vi)
kfree_rcu(vi, rcu); kfree_rcu(vi, rcu);
afs_put_server(net, cbi->server); afs_put_server(net, cbi->server, afs_server_trace_put_cbi);
} }
kfree_rcu(cbi, rcu); kfree_rcu(cbi, rcu);
} }
......
...@@ -260,8 +260,11 @@ static void SRXAFSCB_CallBack(struct work_struct *work) ...@@ -260,8 +260,11 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
* server holds up change visibility till it receives our reply so as * server holds up change visibility till it receives our reply so as
* to maintain cache coherency. * to maintain cache coherency.
*/ */
if (call->server) if (call->server) {
trace_afs_server(call->server, atomic_read(&call->server->usage),
afs_server_trace_callback);
afs_break_callbacks(call->server, call->count, call->request); afs_break_callbacks(call->server, call->count, call->request);
}
afs_send_empty_reply(call); afs_send_empty_reply(call);
afs_put_call(call); afs_put_call(call);
......
...@@ -1915,7 +1915,7 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net, ...@@ -1915,7 +1915,7 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
call->key = key; call->key = key;
call->server = afs_get_server(server); call->server = afs_get_server(server, afs_server_trace_get_caps);
call->server_index = server_index; call->server_index = server_index;
call->upgrade = true; call->upgrade = true;
call->async = true; call->async = true;
......
...@@ -518,6 +518,7 @@ struct afs_server { ...@@ -518,6 +518,7 @@ struct afs_server {
atomic_t usage; atomic_t usage;
u32 addr_version; /* Address list version */ u32 addr_version; /* Address list version */
u32 cm_epoch; /* Server RxRPC epoch */ u32 cm_epoch; /* Server RxRPC epoch */
unsigned int debug_id; /* Debugging ID for traces */
/* file service access */ /* file service access */
rwlock_t fs_lock; /* access lock */ rwlock_t fs_lock; /* access lock */
...@@ -1244,17 +1245,12 @@ extern void __exit afs_clean_up_permit_cache(void); ...@@ -1244,17 +1245,12 @@ extern void __exit afs_clean_up_permit_cache(void);
*/ */
extern spinlock_t afs_server_peer_lock; extern spinlock_t afs_server_peer_lock;
static inline struct afs_server *afs_get_server(struct afs_server *server)
{
atomic_inc(&server->usage);
return server;
}
extern struct afs_server *afs_find_server(struct afs_net *, extern struct afs_server *afs_find_server(struct afs_net *,
const struct sockaddr_rxrpc *); const struct sockaddr_rxrpc *);
extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *); extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *);
extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *); extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *);
extern void afs_put_server(struct afs_net *, struct afs_server *); extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);
extern void afs_put_server(struct afs_net *, struct afs_server *, enum afs_server_trace);
extern void afs_manage_servers(struct work_struct *); extern void afs_manage_servers(struct work_struct *);
extern void afs_servers_timer(struct timer_list *); extern void afs_servers_timer(struct timer_list *);
extern void __net_exit afs_purge_servers(struct afs_net *); extern void __net_exit afs_purge_servers(struct afs_net *);
......
...@@ -188,7 +188,7 @@ void afs_put_call(struct afs_call *call) ...@@ -188,7 +188,7 @@ void afs_put_call(struct afs_call *call)
if (call->type->destructor) if (call->type->destructor)
call->type->destructor(call); call->type->destructor(call);
afs_put_server(call->net, call->server); afs_put_server(call->net, call->server, afs_server_trace_put_call);
afs_put_cb_interest(call->net, call->cbi); afs_put_cb_interest(call->net, call->cbi);
afs_put_addrlist(call->alist); afs_put_addrlist(call->alist);
kfree(call->request); kfree(call->request);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */ static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */
static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */ static unsigned afs_server_update_delay = 30; /* Time till VLDB recheck in secs */
static atomic_t afs_server_debug_id;
static void afs_inc_servers_outstanding(struct afs_net *net) static void afs_inc_servers_outstanding(struct afs_net *net)
{ {
...@@ -51,7 +52,7 @@ struct afs_server *afs_find_server(struct afs_net *net, ...@@ -51,7 +52,7 @@ struct afs_server *afs_find_server(struct afs_net *net,
do { do {
if (server) if (server)
afs_put_server(net, server); afs_put_server(net, server, afs_server_trace_put_find_rsq);
server = NULL; server = NULL;
read_seqbegin_or_lock(&net->fs_addr_lock, &seq); read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
...@@ -116,7 +117,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu ...@@ -116,7 +117,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu
* changes. * changes.
*/ */
if (server) if (server)
afs_put_server(net, server); afs_put_server(net, server, afs_server_trace_put_uuid_rsq);
server = NULL; server = NULL;
read_seqbegin_or_lock(&net->fs_lock, &seq); read_seqbegin_or_lock(&net->fs_lock, &seq);
...@@ -131,7 +132,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu ...@@ -131,7 +132,7 @@ struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uu
} else if (diff > 0) { } else if (diff > 0) {
p = p->rb_right; p = p->rb_right;
} else { } else {
afs_get_server(server); afs_get_server(server, afs_server_trace_get_by_uuid);
break; break;
} }
...@@ -202,7 +203,7 @@ static struct afs_server *afs_install_server(struct afs_net *net, ...@@ -202,7 +203,7 @@ static struct afs_server *afs_install_server(struct afs_net *net,
ret = 0; ret = 0;
exists: exists:
afs_get_server(server); afs_get_server(server, afs_server_trace_get_install);
write_sequnlock(&net->fs_lock); write_sequnlock(&net->fs_lock);
return server; return server;
} }
...@@ -223,6 +224,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net, ...@@ -223,6 +224,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net,
goto enomem; goto enomem;
atomic_set(&server->usage, 1); atomic_set(&server->usage, 1);
server->debug_id = atomic_inc_return(&afs_server_debug_id);
RCU_INIT_POINTER(server->addresses, alist); RCU_INIT_POINTER(server->addresses, alist);
server->addr_version = alist->version; server->addr_version = alist->version;
server->uuid = *uuid; server->uuid = *uuid;
...@@ -234,6 +236,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net, ...@@ -234,6 +236,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net,
spin_lock_init(&server->probe_lock); spin_lock_init(&server->probe_lock);
afs_inc_servers_outstanding(net); afs_inc_servers_outstanding(net);
trace_afs_server(server, 1, afs_server_trace_alloc);
_leave(" = %p", server); _leave(" = %p", server);
return server; return server;
...@@ -328,10 +331,23 @@ void afs_servers_timer(struct timer_list *timer) ...@@ -328,10 +331,23 @@ void afs_servers_timer(struct timer_list *timer)
afs_dec_servers_outstanding(net); afs_dec_servers_outstanding(net);
} }
/*
* Get a reference on a server object.
*/
struct afs_server *afs_get_server(struct afs_server *server,
enum afs_server_trace reason)
{
unsigned int u = atomic_inc_return(&server->usage);
trace_afs_server(server, u, reason);
return server;
}
/* /*
* Release a reference on a server record. * Release a reference on a server record.
*/ */
void afs_put_server(struct afs_net *net, struct afs_server *server) void afs_put_server(struct afs_net *net, struct afs_server *server,
enum afs_server_trace reason)
{ {
unsigned int usage; unsigned int usage;
...@@ -342,7 +358,7 @@ void afs_put_server(struct afs_net *net, struct afs_server *server) ...@@ -342,7 +358,7 @@ void afs_put_server(struct afs_net *net, struct afs_server *server)
usage = atomic_dec_return(&server->usage); usage = atomic_dec_return(&server->usage);
_enter("{%u}", usage); trace_afs_server(server, usage, reason);
if (likely(usage > 0)) if (likely(usage > 0))
return; return;
...@@ -354,6 +370,8 @@ static void afs_server_rcu(struct rcu_head *rcu) ...@@ -354,6 +370,8 @@ static void afs_server_rcu(struct rcu_head *rcu)
{ {
struct afs_server *server = container_of(rcu, struct afs_server, rcu); struct afs_server *server = container_of(rcu, struct afs_server, rcu);
trace_afs_server(server, atomic_read(&server->usage),
afs_server_trace_free);
afs_put_addrlist(rcu_access_pointer(server->addresses)); afs_put_addrlist(rcu_access_pointer(server->addresses));
kfree(server); kfree(server);
} }
...@@ -369,7 +387,9 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) ...@@ -369,7 +387,9 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
.index = alist->preferred, .index = alist->preferred,
.error = 0, .error = 0,
}; };
_enter("%p", server);
trace_afs_server(server, atomic_read(&server->usage),
afs_server_trace_give_up_cb);
if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
afs_fs_give_up_all_callbacks(net, server, &ac, NULL); afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
...@@ -377,6 +397,8 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) ...@@ -377,6 +397,8 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
wait_var_event(&server->probe_outstanding, wait_var_event(&server->probe_outstanding,
atomic_read(&server->probe_outstanding) == 0); atomic_read(&server->probe_outstanding) == 0);
trace_afs_server(server, atomic_read(&server->usage),
afs_server_trace_destroy);
call_rcu(&server->rcu, afs_server_rcu); call_rcu(&server->rcu, afs_server_rcu);
afs_dec_servers_outstanding(net); afs_dec_servers_outstanding(net);
} }
...@@ -396,6 +418,7 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list) ...@@ -396,6 +418,7 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
write_seqlock(&net->fs_lock); write_seqlock(&net->fs_lock);
usage = 1; usage = 1;
deleted = atomic_try_cmpxchg(&server->usage, &usage, 0); deleted = atomic_try_cmpxchg(&server->usage, &usage, 0);
trace_afs_server(server, usage, afs_server_trace_gc);
if (deleted) { if (deleted) {
rb_erase(&server->uuid_rb, &net->fs_servers); rb_erase(&server->uuid_rb, &net->fs_servers);
hlist_del_rcu(&server->proc_link); hlist_del_rcu(&server->proc_link);
...@@ -518,6 +541,8 @@ static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct a ...@@ -518,6 +541,8 @@ static noinline bool afs_update_server_record(struct afs_fs_cursor *fc, struct a
_enter(""); _enter("");
trace_afs_server(server, atomic_read(&server->usage), afs_server_trace_update);
alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key, alist = afs_vl_lookup_addrs(fc->vnode->volume->cell, fc->key,
&server->uuid); &server->uuid);
if (IS_ERR(alist)) { if (IS_ERR(alist)) {
......
...@@ -20,7 +20,8 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist) ...@@ -20,7 +20,8 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
if (slist && refcount_dec_and_test(&slist->usage)) { if (slist && refcount_dec_and_test(&slist->usage)) {
for (i = 0; i < slist->nr_servers; i++) { for (i = 0; i < slist->nr_servers; i++) {
afs_put_cb_interest(net, slist->servers[i].cb_interest); afs_put_cb_interest(net, slist->servers[i].cb_interest);
afs_put_server(net, slist->servers[i].server); afs_put_server(net, slist->servers[i].server,
afs_server_trace_put_slist);
} }
kfree(slist); kfree(slist);
} }
...@@ -71,7 +72,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, ...@@ -71,7 +72,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
break; break;
if (j < slist->nr_servers) { if (j < slist->nr_servers) {
if (slist->servers[j].server == server) { if (slist->servers[j].server == server) {
afs_put_server(cell->net, server); afs_put_server(cell->net, server,
afs_server_trace_put_slist_isort);
continue; continue;
} }
......
...@@ -31,6 +31,26 @@ enum afs_call_trace { ...@@ -31,6 +31,26 @@ enum afs_call_trace {
afs_call_trace_work, afs_call_trace_work,
}; };
enum afs_server_trace {
afs_server_trace_alloc,
afs_server_trace_callback,
afs_server_trace_destroy,
afs_server_trace_free,
afs_server_trace_gc,
afs_server_trace_get_by_uuid,
afs_server_trace_get_caps,
afs_server_trace_get_install,
afs_server_trace_get_new_cbi,
afs_server_trace_give_up_cb,
afs_server_trace_put_call,
afs_server_trace_put_cbi,
afs_server_trace_put_find_rsq,
afs_server_trace_put_slist,
afs_server_trace_put_slist_isort,
afs_server_trace_put_uuid_rsq,
afs_server_trace_update,
};
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 */
...@@ -219,6 +239,25 @@ enum afs_cb_break_reason { ...@@ -219,6 +239,25 @@ enum afs_cb_break_reason {
EM(afs_call_trace_wake, "WAKE ") \ EM(afs_call_trace_wake, "WAKE ") \
E_(afs_call_trace_work, "WORK ") E_(afs_call_trace_work, "WORK ")
#define afs_server_traces \
EM(afs_server_trace_alloc, "ALLOC ") \
EM(afs_server_trace_callback, "CALLBACK ") \
EM(afs_server_trace_destroy, "DESTROY ") \
EM(afs_server_trace_free, "FREE ") \
EM(afs_server_trace_gc, "GC ") \
EM(afs_server_trace_get_by_uuid, "GET uuid ") \
EM(afs_server_trace_get_caps, "GET caps ") \
EM(afs_server_trace_get_install, "GET inst ") \
EM(afs_server_trace_get_new_cbi, "GET cbi ") \
EM(afs_server_trace_give_up_cb, "giveup-cb") \
EM(afs_server_trace_put_call, "PUT call ") \
EM(afs_server_trace_put_cbi, "PUT cbi ") \
EM(afs_server_trace_put_find_rsq, "PUT f-rsq") \
EM(afs_server_trace_put_slist, "PUT slist") \
EM(afs_server_trace_put_slist_isort, "PUT isort") \
EM(afs_server_trace_put_uuid_rsq, "PUT u-req") \
E_(afs_server_trace_update, "UPDATE")
#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") \
...@@ -404,6 +443,7 @@ enum afs_cb_break_reason { ...@@ -404,6 +443,7 @@ enum afs_cb_break_reason {
#define E_(a, b) TRACE_DEFINE_ENUM(a); #define E_(a, b) TRACE_DEFINE_ENUM(a);
afs_call_traces; afs_call_traces;
afs_server_traces;
afs_fs_operations; afs_fs_operations;
afs_vl_operations; afs_vl_operations;
afs_edit_dir_ops; afs_edit_dir_ops;
...@@ -1240,6 +1280,29 @@ TRACE_EVENT(afs_cb_miss, ...@@ -1240,6 +1280,29 @@ TRACE_EVENT(afs_cb_miss,
__print_symbolic(__entry->reason, afs_cb_break_reasons)) __print_symbolic(__entry->reason, afs_cb_break_reasons))
); );
TRACE_EVENT(afs_server,
TP_PROTO(struct afs_server *server, int usage, enum afs_server_trace reason),
TP_ARGS(server, usage, reason),
TP_STRUCT__entry(
__field(unsigned int, server )
__field(int, usage )
__field(int, reason )
),
TP_fast_assign(
__entry->server = server->debug_id;
__entry->usage = usage;
__entry->reason = reason;
),
TP_printk("s=%08x %s u=%d",
__entry->server,
__print_symbolic(__entry->reason, afs_server_traces),
__entry->usage)
);
#endif /* _TRACE_AFS_H */ #endif /* _TRACE_AFS_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment