Skip to content

Commit 6cd3d6f

Browse files
committed
netfs: Trace refcounting on the netfs_io_subrequest struct
Add refcount tracing for the netfs_io_subrequest 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/164622998584.3564931.5052255990645723639.stgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/164678202603.1200972.14726007419792315578.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/164692901860.2099075.4845820886851239935.stgit@warthog.procyon.org.uk/ # v3
1 parent de74023 commit 6cd3d6f

5 files changed

Lines changed: 81 additions & 21 deletions

File tree

fs/netfs/internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async);
2525
void netfs_put_request(struct netfs_io_request *rreq, bool was_async,
2626
enum netfs_rreq_ref_trace what);
2727
struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq);
28-
void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async);
29-
void netfs_get_subrequest(struct netfs_io_subrequest *subreq);
3028

3129
static inline void netfs_see_request(struct netfs_io_request *rreq,
3230
enum netfs_rreq_ref_trace what)

fs/netfs/objects.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ void netfs_clear_subrequests(struct netfs_io_request *rreq, bool was_async)
5353
subreq = list_first_entry(&rreq->subrequests,
5454
struct netfs_io_subrequest, rreq_link);
5555
list_del(&subreq->rreq_link);
56-
netfs_put_subrequest(subreq, was_async);
56+
netfs_put_subrequest(subreq, was_async,
57+
netfs_sreq_trace_put_clear);
5758
}
5859
}
5960

@@ -101,7 +102,7 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq
101102
subreq = kzalloc(sizeof(struct netfs_io_subrequest), GFP_KERNEL);
102103
if (subreq) {
103104
INIT_LIST_HEAD(&subreq->rreq_link);
104-
refcount_set(&subreq->usage, 2);
105+
refcount_set(&subreq->ref, 2);
105106
subreq->rreq = rreq;
106107
netfs_get_request(rreq, netfs_rreq_trace_get_subreq);
107108
netfs_stat(&netfs_n_rh_sreq);
@@ -110,13 +111,18 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq
110111
return subreq;
111112
}
112113

113-
void netfs_get_subrequest(struct netfs_io_subrequest *subreq)
114+
void netfs_get_subrequest(struct netfs_io_subrequest *subreq,
115+
enum netfs_sreq_ref_trace what)
114116
{
115-
refcount_inc(&subreq->usage);
117+
int r;
118+
119+
__refcount_inc(&subreq->ref, &r);
120+
trace_netfs_sreq_ref(subreq->rreq->debug_id, subreq->debug_index, r + 1,
121+
what);
116122
}
117123

118-
static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq,
119-
bool was_async)
124+
static void netfs_free_subrequest(struct netfs_io_subrequest *subreq,
125+
bool was_async)
120126
{
121127
struct netfs_io_request *rreq = subreq->rreq;
122128

@@ -126,8 +132,16 @@ static void __netfs_put_subrequest(struct netfs_io_subrequest *subreq,
126132
netfs_put_request(rreq, was_async, netfs_rreq_trace_put_subreq);
127133
}
128134

129-
void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async)
135+
void netfs_put_subrequest(struct netfs_io_subrequest *subreq, bool was_async,
136+
enum netfs_sreq_ref_trace what)
130137
{
131-
if (refcount_dec_and_test(&subreq->usage))
132-
__netfs_put_subrequest(subreq, was_async);
138+
unsigned int debug_index = subreq->debug_index;
139+
unsigned int debug_id = subreq->rreq->debug_id;
140+
bool dead;
141+
int r;
142+
143+
dead = __refcount_dec_and_test(&subreq->ref, &r);
144+
trace_netfs_sreq_ref(debug_id, debug_index, r - 1, what);
145+
if (dead)
146+
netfs_free_subrequest(subreq, was_async);
133147
}

fs/netfs/read_helper.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_error,
167167
if (atomic_dec_and_test(&rreq->nr_copy_ops))
168168
netfs_rreq_unmark_after_write(rreq, was_async);
169169

170-
netfs_put_subrequest(subreq, was_async);
170+
netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated);
171171
}
172172

173173
/*
@@ -191,7 +191,8 @@ static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq)
191191
list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) {
192192
if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) {
193193
list_del_init(&subreq->rreq_link);
194-
netfs_put_subrequest(subreq, false);
194+
netfs_put_subrequest(subreq, false,
195+
netfs_sreq_trace_put_no_copy);
195196
}
196197
}
197198

@@ -203,7 +204,8 @@ static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq)
203204
break;
204205
subreq->len += next->len;
205206
list_del_init(&next->rreq_link);
206-
netfs_put_subrequest(next, false);
207+
netfs_put_subrequest(next, false,
208+
netfs_sreq_trace_put_merged);
207209
}
208210

209211
ret = cres->ops->prepare_write(cres, &subreq->start, &subreq->len,
@@ -219,7 +221,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq)
219221

220222
atomic_inc(&rreq->nr_copy_ops);
221223
netfs_stat(&netfs_n_rh_write);
222-
netfs_get_subrequest(subreq);
224+
netfs_get_subrequest(subreq, netfs_sreq_trace_get_copy_to_cache);
223225
trace_netfs_sreq(subreq, netfs_sreq_trace_write);
224226
cres->ops->write(cres, subreq->start, &iter,
225227
netfs_rreq_copy_terminated, subreq);
@@ -342,7 +344,7 @@ static void netfs_rreq_short_read(struct netfs_io_request *rreq,
342344
netfs_stat(&netfs_n_rh_short_read);
343345
trace_netfs_sreq(subreq, netfs_sreq_trace_resubmit_short);
344346

345-
netfs_get_subrequest(subreq);
347+
netfs_get_subrequest(subreq, netfs_sreq_trace_get_short_read);
346348
atomic_inc(&rreq->nr_outstanding);
347349
if (subreq->source == NETFS_READ_FROM_CACHE)
348350
netfs_read_from_cache(rreq, subreq, NETFS_READ_HOLE_CLEAR);
@@ -376,7 +378,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq)
376378
subreq->error = 0;
377379
netfs_stat(&netfs_n_rh_download_instead);
378380
trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead);
379-
netfs_get_subrequest(subreq);
381+
netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit);
380382
atomic_inc(&rreq->nr_outstanding);
381383
netfs_read_from_server(rreq, subreq);
382384
} else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) {
@@ -538,7 +540,7 @@ void netfs_subreq_terminated(struct netfs_io_subrequest *subreq,
538540
else if (u == 1)
539541
wake_up_var(&rreq->nr_outstanding);
540542

541-
netfs_put_subrequest(subreq, was_async);
543+
netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated);
542544
return;
543545

544546
incomplete:
@@ -683,7 +685,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq,
683685

684686
subreq_failed:
685687
rreq->error = subreq->error;
686-
netfs_put_subrequest(subreq, false);
688+
netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_failed);
687689
return false;
688690
}
689691

@@ -1030,13 +1032,13 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
10301032
*/
10311033
ractl._nr_pages = folio_nr_pages(folio);
10321034
netfs_rreq_expand(rreq, &ractl);
1035+
netfs_get_request(rreq, netfs_rreq_trace_get_hold);
10331036

10341037
/* We hold the folio locks, so we can drop the references */
10351038
folio_get(folio);
10361039
while (readahead_folio(&ractl))
10371040
;
10381041

1039-
netfs_get_request(rreq, netfs_rreq_trace_get_hold);
10401042
atomic_set(&rreq->nr_outstanding, 1);
10411043
do {
10421044
if (!netfs_rreq_submit_slice(rreq, &debug_index))

include/linux/netfs.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <linux/fs.h>
1919
#include <linux/pagemap.h>
2020

21+
enum netfs_sreq_ref_trace;
22+
2123
/*
2224
* Overload PG_private_2 to give us PG_fscache - this is used to indicate that
2325
* a page is currently backed by a local disk cache
@@ -136,7 +138,7 @@ struct netfs_io_subrequest {
136138
loff_t start; /* Where to start the I/O */
137139
size_t len; /* Size of the I/O */
138140
size_t transferred; /* Amount of data transferred */
139-
refcount_t usage;
141+
refcount_t ref;
140142
short error; /* 0 or error that occurred */
141143
unsigned short debug_index; /* Index in list (for debugging output) */
142144
enum netfs_io_source source; /* Where to read from/write to */
@@ -268,6 +270,10 @@ extern int netfs_write_begin(struct file *, struct address_space *,
268270
void *);
269271

270272
extern void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool);
273+
extern void netfs_get_subrequest(struct netfs_io_subrequest *subreq,
274+
enum netfs_sreq_ref_trace what);
275+
extern void netfs_put_subrequest(struct netfs_io_subrequest *subreq,
276+
bool was_async, enum netfs_sreq_ref_trace what);
271277
extern void netfs_stats_show(struct seq_file *);
272278

273279
#endif /* _LINUX_NETFS_H */

include/trace/events/netfs.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@
6464
EM(netfs_rreq_trace_put_subreq, "PUT SUBREQ ") \
6565
E_(netfs_rreq_trace_new, "NEW ")
6666

67+
#define netfs_sreq_ref_traces \
68+
EM(netfs_sreq_trace_get_copy_to_cache, "GET COPY2C ") \
69+
EM(netfs_sreq_trace_get_resubmit, "GET RESUBMIT") \
70+
EM(netfs_sreq_trace_get_short_read, "GET SHORTRD") \
71+
EM(netfs_sreq_trace_new, "NEW ") \
72+
EM(netfs_sreq_trace_put_clear, "PUT CLEAR ") \
73+
EM(netfs_sreq_trace_put_failed, "PUT FAILED ") \
74+
EM(netfs_sreq_trace_put_merged, "PUT MERGED ") \
75+
EM(netfs_sreq_trace_put_no_copy, "PUT NO COPY") \
76+
E_(netfs_sreq_trace_put_terminated, "PUT TERM ")
77+
6778
#ifndef __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
6879
#define __NETFS_DECLARE_TRACE_ENUMS_ONCE_ONLY
6980

@@ -77,6 +88,7 @@ enum netfs_rreq_trace { netfs_rreq_traces } __mode(byte);
7788
enum netfs_sreq_trace { netfs_sreq_traces } __mode(byte);
7889
enum netfs_failure { netfs_failures } __mode(byte);
7990
enum netfs_rreq_ref_trace { netfs_rreq_ref_traces } __mode(byte);
91+
enum netfs_sreq_ref_trace { netfs_sreq_ref_traces } __mode(byte);
8092

8193
#endif
8294

@@ -94,6 +106,7 @@ netfs_sreq_sources;
94106
netfs_sreq_traces;
95107
netfs_failures;
96108
netfs_rreq_ref_traces;
109+
netfs_sreq_ref_traces;
97110

98111
/*
99112
* Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -264,6 +277,33 @@ TRACE_EVENT(netfs_rreq_ref,
264277
__entry->ref)
265278
);
266279

280+
TRACE_EVENT(netfs_sreq_ref,
281+
TP_PROTO(unsigned int rreq_debug_id, unsigned int subreq_debug_index,
282+
int ref, enum netfs_sreq_ref_trace what),
283+
284+
TP_ARGS(rreq_debug_id, subreq_debug_index, ref, what),
285+
286+
TP_STRUCT__entry(
287+
__field(unsigned int, rreq )
288+
__field(unsigned int, subreq )
289+
__field(int, ref )
290+
__field(enum netfs_sreq_ref_trace, what )
291+
),
292+
293+
TP_fast_assign(
294+
__entry->rreq = rreq_debug_id;
295+
__entry->subreq = subreq_debug_index;
296+
__entry->ref = ref;
297+
__entry->what = what;
298+
),
299+
300+
TP_printk("R=%08x[%x] %s r=%u",
301+
__entry->rreq,
302+
__entry->subreq,
303+
__print_symbolic(__entry->what, netfs_sreq_ref_traces),
304+
__entry->ref)
305+
);
306+
267307
#undef EM
268308
#undef E_
269309
#endif /* _TRACE_NETFS_H */

0 commit comments

Comments
 (0)