Skip to content

Commit de74023

Browse files
committed
netfs: Trace refcounting on the netfs_io_request struct
Add refcount tracing for the netfs_io_request structure. Changes ======= ver #3) - Switch 'W=' to 'R=' in the traceline to match other request debug IDs. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com Link: https://lore.kernel.org/r/164622997668.3564931.14456171619219324968.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678200943.1200972.7241495532327787765.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/164692900920.2099075.11847712419940675791.stgit@warthog.procyon.org.uk/ # v3
1 parent 18b3ff9 commit de74023

5 files changed

Lines changed: 69 additions & 17 deletions

File tree

fs/netfs/internal.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,20 @@
2020
struct netfs_io_request *netfs_alloc_request(const struct netfs_request_ops *ops,
2121
void *netfs_priv,
2222
struct file *file);
23-
void netfs_get_request(struct netfs_io_request *rreq);
23+
void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what);
2424
void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async);
25-
void netfs_put_request(struct netfs_io_request *rreq, bool was_async);
25+
void netfs_put_request(struct netfs_io_request *rreq, bool was_async,
26+
enum netfs_rreq_ref_trace what);
2627
struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq);
2728
void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async);
2829
void netfs_get_subrequest(struct netfs_io_subrequest *subreq);
2930

31+
static inline void netfs_see_request(struct netfs_io_request *rreq,
32+
enum netfs_rreq_ref_trace what)
33+
{
34+
trace_netfs_rreq_ref(rreq->debug_id, refcount_read(&rreq->ref), what);
35+
}
36+
3037
/*
3138
* read_helper.c
3239
*/

fs/netfs/objects.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct netfs_io_request *netfs_alloc_request(
2727
rreq->debug_id = atomic_inc_return(&debug_ids);
2828
INIT_LIST_HEAD(&rreq->subrequests);
2929
INIT_WORK(&rreq->work, netfs_rreq_work);
30-
refcount_set(&rreq->usage, 1);
30+
refcount_set(&rreq->ref, 1);
3131
__set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags);
3232
if (ops->init_request)
3333
ops->init_request(rreq, file);
@@ -37,9 +37,12 @@ struct netfs_io_request *netfs_alloc_request(
3737
return rreq;
3838
}
3939

40-
void netfs_get_request(struct netfs_io_request *rreq)
40+
void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what)
4141
{
42-
refcount_inc(&rreq->usage);
42+
int r;
43+
44+
__refcount_inc(&rreq->ref, &r);
45+
trace_netfs_rreq_ref(rreq->debug_id, r + 1, what);
4346
}
4447

4548
void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async)
@@ -68,9 +71,16 @@ static void netfs_free_request(struct work_struct *work)
6871
netfs_stat_d(&netfs_n_rh_rreq);
6972
}
7073

71-
void netfs_put_request(struct netfs_io_request *rreq, bool was_async)
74+
void netfs_put_request(struct netfs_io_request *rreq, bool was_async,
75+
enum netfs_rreq_ref_trace what)
7276
{
73-
if (refcount_dec_and_test(&rreq->usage)) {
77+
unsigned int debug_id = rreq->debug_id;
78+
bool dead;
79+
int r;
80+
81+
dead = __refcount_dec_and_test(&rreq->ref, &r);
82+
trace_netfs_rreq_ref(debug_id, r - 1, what);
83+
if (dead) {
7484
if (was_async) {
7585
rreq->work.func = netfs_free_request;
7686
if (!queue_work(system_unbound_wq, &rreq->work))
@@ -93,7 +103,7 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq
93103
INIT_LIST_HEAD(&subreq->rreq_link);
94104
refcount_set(&subreq->usage, 2);
95105
subreq->rreq = rreq;
96-
netfs_get_request(rreq);
106+
netfs_get_request(rreq, netfs_rreq_trace_get_subreq);
97107
netfs_stat(&netfs_n_rh_sreq);
98108
}
99109

@@ -113,7 +123,7 @@ static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq,
113123
trace_netfs_sreq(subreq, netfs_sreq_trace_free);
114124
kfree(subreq);
115125
netfs_stat_d(&netfs_n_rh_sreq);
116-
netfs_put_request(rreq, was_async);
126+
netfs_put_request(rreq, was_async, netfs_rreq_trace_put_subreq);
117127
}
118128

119129
void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async)

fs/netfs/read_helper.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_async)
109109
{
110110
trace_netfs_rreq(rreq, netfs_rreq_trace_done);
111111
netfs_clear_subrequests(rreq, was_async);
112-
netfs_put_request(rreq, was_async);
112+
netfs_put_request(rreq, was_async, netfs_rreq_trace_put_complete);
113113
}
114114

115115
/*
@@ -799,7 +799,7 @@ void netfs_readahead(struct readahead_control *ractl,
799799
return;
800800

801801
cleanup_free:
802-
netfs_put_request(rreq, false);
802+
netfs_put_request(rreq, false, netfs_rreq_trace_put_failed);
803803
return;
804804
cleanup:
805805
if (netfs_priv)
@@ -858,7 +858,7 @@ int netfs_readpage(struct file *file,
858858
netfs_stat(&netfs_n_rh_readpage);
859859
trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage);
860860

861-
netfs_get_request(rreq);
861+
netfs_get_request(rreq, netfs_rreq_trace_get_hold);
862862

863863
atomic_set(&rreq->nr_outstanding, 1);
864864
do {
@@ -883,7 +883,7 @@ int netfs_readpage(struct file *file,
883883
ret = -EIO;
884884
}
885885
out:
886-
netfs_put_request(rreq, false);
886+
netfs_put_request(rreq, false, netfs_rreq_trace_put_hold);
887887
return ret;
888888
}
889889
EXPORT_SYMBOL(netfs_readpage);
@@ -1030,13 +1030,13 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
10301030
*/
10311031
ractl._nr_pages = folio_nr_pages(folio);
10321032
netfs_rreq_expand(rreq, &ractl);
1033-
netfs_get_request(rreq);
10341033

10351034
/* We hold the folio locks, so we can drop the references */
10361035
folio_get(folio);
10371036
while (readahead_folio(&ractl))
10381037
;
10391038

1039+
netfs_get_request(rreq, netfs_rreq_trace_get_hold);
10401040
atomic_set(&rreq->nr_outstanding, 1);
10411041
do {
10421042
if (!netfs_rreq_submit_slice(rreq, &debug_index))
@@ -1062,7 +1062,7 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
10621062
trace_netfs_failure(rreq, NULL, ret, netfs_fail_short_write_begin);
10631063
ret = -EIO;
10641064
}
1065-
netfs_put_request(rreq, false);
1065+
netfs_put_request(rreq, false, netfs_rreq_trace_put_hold);
10661066
if (ret < 0)
10671067
goto error;
10681068

@@ -1078,7 +1078,7 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
10781078
return 0;
10791079

10801080
error_put:
1081-
netfs_put_request(rreq, false);
1081+
netfs_put_request(rreq, false, netfs_rreq_trace_put_failed);
10821082
error:
10831083
folio_unlock(folio);
10841084
folio_put(folio);

include/linux/netfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ struct netfs_io_request {
168168
loff_t i_size; /* Size of the file */
169169
loff_t start; /* Start position */
170170
pgoff_t no_unlock_folio; /* Don't unlock this folio after read */
171-
refcount_t usage;
171+
refcount_t ref;
172172
unsigned long flags;
173173
#define NETFS_RREQ_INCOMPLETE_IO 0 /* Some ioreqs terminated short or with error */
174174
#define NETFS_RREQ_COPY_TO_CACHE 1 /* Need to write to the cache */

include/trace/events/netfs.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@
5555
EM(netfs_fail_short_write_begin, "short-write-begin") \
5656
E_(netfs_fail_prepare_write, "prep-write")
5757

58+
#define netfs_rreq_ref_traces \
59+
EM(netfs_rreq_trace_get_hold, "GET HOLD ") \
60+
EM(netfs_rreq_trace_get_subreq, "GET SUBREQ ") \
61+
EM(netfs_rreq_trace_put_complete, "PUT COMPLT ") \
62+
EM(netfs_rreq_trace_put_failed, "PUT FAILED ") \
63+
EM(netfs_rreq_trace_put_hold, "PUT HOLD ") \
64+
EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \
65+
E_(netfs_rreq_trace_new, "NEW ")
66+
5867
#ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
5968
#define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
6069

@@ -67,6 +76,7 @@ enum netfs_read_trace { netfs_read_traces } __mode(byte);
6776
enum netfs_rreq_trace { netfs_rreq_traces } __mode(byte);
6877
enum netfs_sreq_trace { netfs_sreq_traces } __mode(byte);
6978
enum netfs_failure { netfs_failures } __mode(byte);
79+
enum netfs_rreq_ref_trace { netfs_rreq_ref_traces } __mode(byte);
7080

7181
#endif
7282

@@ -83,6 +93,7 @@ netfs_rreq_traces;
8393
netfs_sreq_sources;
8494
netfs_sreq_traces;
8595
netfs_failures;
96+
netfs_rreq_ref_traces;
8697

8798
/*
8899
* Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -229,6 +240,30 @@ TRACE_EVENT(netfs_failure,
229240
__entry->error)
230241
);
231242

243+
TRACE_EVENT(netfs_rreq_ref,
244+
TP_PROTO(unsigned int rreq_debug_id, int ref,
245+
enum netfs_rreq_ref_trace what),
246+
247+
TP_ARGS(rreq_debug_id, ref, what),
248+
249+
TP_STRUCT__entry(
250+
__field(unsigned int, rreq )
251+
__field(int, ref )
252+
__field(enum netfs_rreq_ref_trace, what )
253+
),
254+
255+
TP_fast_assign(
256+
__entry->rreq = rreq_debug_id;
257+
__entry->ref = ref;
258+
__entry->what = what;
259+
),
260+
261+
TP_printk("R=%08x %s r=%u",
262+
__entry->rreq,
263+
__print_symbolic(__entry->what, netfs_rreq_ref_traces),
264+
__entry->ref)
265+
);
266+
232267
#undef EM
233268
#undef E_
234269
#endif /* _TRACE_NETFS_H */

0 commit comments

Comments
 (0)