@@ -81,56 +81,32 @@ int netfs_folio_written_back(struct folio *folio)
8181 return gcount ;
8282}
8383
84- /*
85- * Get hold of a folio we have under writeback. We don't want to get the
86- * refcount on it.
87- */
88- static struct folio * netfs_writeback_lookup_folio (struct netfs_io_request * wreq , loff_t pos )
89- {
90- XA_STATE (xas , & wreq -> mapping -> i_pages , pos / PAGE_SIZE );
91- struct folio * folio ;
92-
93- rcu_read_lock ();
94-
95- for (;;) {
96- xas_reset (& xas );
97- folio = xas_load (& xas );
98- if (xas_retry (& xas , folio ))
99- continue ;
100-
101- if (!folio || xa_is_value (folio ))
102- kdebug ("R=%08x: folio %lx (%llx) not present" ,
103- wreq -> debug_id , xas .xa_index , pos / PAGE_SIZE );
104- BUG_ON (!folio || xa_is_value (folio ));
105-
106- if (folio == xas_reload (& xas ))
107- break ;
108- }
109-
110- rcu_read_unlock ();
111-
112- if (WARN_ONCE (!folio_test_writeback (folio ),
113- "R=%08x: folio %lx is not under writeback\n" ,
114- wreq -> debug_id , folio -> index )) {
115- trace_netfs_folio (folio , netfs_folio_trace_not_under_wback );
116- }
117- return folio ;
118- }
119-
12084/*
12185 * Unlock any folios we've finished with.
12286 */
12387static void netfs_writeback_unlock_folios (struct netfs_io_request * wreq ,
12488 unsigned long long collected_to ,
12589 unsigned int * notes )
12690{
91+ struct folio_queue * folioq = wreq -> buffer ;
92+ unsigned int slot = wreq -> buffer_head_slot ;
93+
94+ if (slot >= folioq_nr_slots (folioq )) {
95+ folioq = netfs_delete_buffer_head (wreq );
96+ slot = 0 ;
97+ }
98+
12799 for (;;) {
128100 struct folio * folio ;
129101 struct netfs_folio * finfo ;
130102 unsigned long long fpos , fend ;
131103 size_t fsize , flen ;
132104
133- folio = netfs_writeback_lookup_folio (wreq , wreq -> cleaned_to );
105+ folio = folioq_folio (folioq , slot );
106+ if (WARN_ONCE (!folio_test_writeback (folio ),
107+ "R=%08x: folio %lx is not under writeback\n" ,
108+ wreq -> debug_id , folio -> index ))
109+ trace_netfs_folio (folio , netfs_folio_trace_not_under_wback );
134110
135111 fpos = folio_pos (folio );
136112 fsize = folio_size (folio );
@@ -155,9 +131,25 @@ static void netfs_writeback_unlock_folios(struct netfs_io_request *wreq,
155131 wreq -> cleaned_to = fpos + fsize ;
156132 * notes |= MADE_PROGRESS ;
157133
134+ /* Clean up the head folioq. If we clear an entire folioq, then
135+ * we can get rid of it provided it's not also the tail folioq
136+ * being filled by the issuer.
137+ */
138+ folioq_clear (folioq , slot );
139+ slot ++ ;
140+ if (slot >= folioq_nr_slots (folioq )) {
141+ if (READ_ONCE (wreq -> buffer_tail ) == folioq )
142+ break ;
143+ folioq = netfs_delete_buffer_head (wreq );
144+ slot = 0 ;
145+ }
146+
158147 if (fpos + fsize >= collected_to )
159148 break ;
160149 }
150+
151+ wreq -> buffer = folioq ;
152+ wreq -> buffer_head_slot = slot ;
161153}
162154
163155/*
@@ -188,9 +180,12 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
188180 if (test_bit (NETFS_SREQ_FAILED , & subreq -> flags ))
189181 break ;
190182 if (__test_and_clear_bit (NETFS_SREQ_NEED_RETRY , & subreq -> flags )) {
183+ struct iov_iter source = subreq -> io_iter ;
184+
185+ iov_iter_revert (& source , subreq -> len - source .count );
191186 __set_bit (NETFS_SREQ_RETRYING , & subreq -> flags );
192187 netfs_get_subrequest (subreq , netfs_sreq_trace_get_resubmit );
193- netfs_reissue_write (stream , subreq );
188+ netfs_reissue_write (stream , subreq , & source );
194189 }
195190 }
196191 return ;
@@ -200,6 +195,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
200195
201196 do {
202197 struct netfs_io_subrequest * subreq = NULL , * from , * to , * tmp ;
198+ struct iov_iter source ;
203199 unsigned long long start , len ;
204200 size_t part ;
205201 bool boundary = false;
@@ -227,6 +223,14 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
227223 len += to -> len ;
228224 }
229225
226+ /* Determine the set of buffers we're going to use. Each
227+ * subreq gets a subset of a single overall contiguous buffer.
228+ */
229+ source = from -> io_iter ;
230+ iov_iter_revert (& source , subreq -> len - source .count );
231+ iov_iter_advance (& source , from -> transferred );
232+ source .count = len ;
233+
230234 /* Work through the sublist. */
231235 subreq = from ;
232236 list_for_each_entry_from (subreq , & stream -> subrequests , rreq_link ) {
@@ -249,7 +253,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
249253 boundary = true;
250254
251255 netfs_get_subrequest (subreq , netfs_sreq_trace_get_resubmit );
252- netfs_reissue_write (stream , subreq );
256+ netfs_reissue_write (stream , subreq , & source );
253257 if (subreq == to )
254258 break ;
255259 }
@@ -316,7 +320,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
316320 boundary = false;
317321 }
318322
319- netfs_reissue_write (stream , subreq );
323+ netfs_reissue_write (stream , subreq , & source );
320324 if (!len )
321325 break ;
322326
0 commit comments