1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Network filesystem write retrying. 3 * 4 * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/fs.h> 9 #include <linux/mm.h> 10 #include <linux/pagemap.h> 11 #include <linux/slab.h> 12 #include "internal.h" 13 14 /* 15 * Perform retries on the streams that need it. 16 */ 17 static void netfs_retry_write_stream(struct netfs_io_request *wreq, 18 struct netfs_io_stream *stream) 19 { 20 struct list_head *next; 21 22 _enter("R=%x[%x:]", wreq->debug_id, stream->stream_nr); 23 24 if (list_empty(&stream->subrequests)) 25 return; 26 27 if (stream->source == NETFS_UPLOAD_TO_SERVER && 28 wreq->netfs_ops->retry_request) 29 wreq->netfs_ops->retry_request(wreq, stream); 30 31 if (unlikely(stream->failed)) 32 return; 33 34 /* If there's no renegotiation to do, just resend each failed subreq. */ 35 if (!stream->prepare_write) { 36 struct netfs_io_subrequest *subreq; 37 38 list_for_each_entry(subreq, &stream->subrequests, rreq_link) { 39 if (test_bit(NETFS_SREQ_FAILED, &subreq->flags)) 40 break; 41 if (__test_and_clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) { 42 struct iov_iter source; 43 44 netfs_reset_iter(subreq); 45 source = subreq->io_iter; 46 netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); 47 netfs_reissue_write(stream, subreq, &source); 48 } 49 } 50 return; 51 } 52 53 next = stream->subrequests.next; 54 55 do { 56 struct netfs_io_subrequest *subreq = NULL, *from, *to, *tmp; 57 struct iov_iter source; 58 unsigned long long start, len; 59 size_t part; 60 bool boundary = false; 61 62 /* Go through the stream and find the next span of contiguous 63 * data that we then rejig (cifs, for example, needs the wsize 64 * renegotiating) and reissue. 65 */ 66 from = list_entry(next, struct netfs_io_subrequest, rreq_link); 67 to = from; 68 start = from->start + from->transferred; 69 len = from->len - from->transferred; 70 71 if (test_bit(NETFS_SREQ_FAILED, &from->flags) || 72 !test_bit(NETFS_SREQ_NEED_RETRY, &from->flags)) 73 return; 74 75 for (;;) { 76 /* Read pointer to subreq before reading subreq state. */ 77 next = smp_load_acquire(&next->next); 78 if (next == &stream->subrequests) 79 break; 80 81 subreq = list_entry(next, struct netfs_io_subrequest, rreq_link); 82 if (subreq->start + subreq->transferred != start + len || 83 test_bit(NETFS_SREQ_BOUNDARY, &subreq->flags) || 84 !test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) 85 break; 86 to = subreq; 87 len += to->len; 88 } 89 90 /* Determine the set of buffers we're going to use. Each 91 * subreq gets a subset of a single overall contiguous buffer. 92 */ 93 netfs_reset_iter(from); 94 source = from->io_iter; 95 source.count = len; 96 97 /* Work through the sublist. */ 98 subreq = from; 99 list_for_each_entry_from(subreq, &stream->subrequests, rreq_link) { 100 if (!len) 101 break; 102 103 subreq->start = start; 104 subreq->len = len; 105 __clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags); 106 trace_netfs_sreq(subreq, netfs_sreq_trace_retry); 107 108 /* Renegotiate max_len (wsize) */ 109 stream->sreq_max_len = len; 110 stream->prepare_write(subreq); 111 112 part = umin(len, stream->sreq_max_len); 113 if (unlikely(stream->sreq_max_segs)) 114 part = netfs_limit_iter(&source, 0, part, stream->sreq_max_segs); 115 subreq->len = part; 116 subreq->transferred = 0; 117 len -= part; 118 start += part; 119 if (len && subreq == to && 120 __test_and_clear_bit(NETFS_SREQ_BOUNDARY, &to->flags)) 121 boundary = true; 122 123 netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); 124 netfs_reissue_write(stream, subreq, &source); 125 if (subreq == to) 126 break; 127 } 128 129 /* If we managed to use fewer subreqs, we can discard the 130 * excess; if we used the same number, then we're done. 131 */ 132 if (!len) { 133 if (subreq == to) 134 continue; 135 list_for_each_entry_safe_from(subreq, tmp, 136 &stream->subrequests, rreq_link) { 137 trace_netfs_sreq(subreq, netfs_sreq_trace_discard); 138 spin_lock(&wreq->lock); 139 list_del(&subreq->rreq_link); 140 spin_unlock(&wreq->lock); 141 netfs_put_subrequest(subreq, netfs_sreq_trace_put_done); 142 if (subreq == to) 143 break; 144 } 145 continue; 146 } 147 148 /* We ran out of subrequests, so we need to allocate some more 149 * and insert them after. 150 */ 151 do { 152 subreq = netfs_alloc_subrequest(wreq); 153 subreq->source = to->source; 154 subreq->start = start; 155 subreq->stream_nr = to->stream_nr; 156 subreq->retry_count = 1; 157 158 trace_netfs_sreq_ref(wreq->debug_id, subreq->debug_index, 159 refcount_read(&subreq->ref), 160 netfs_sreq_trace_new); 161 trace_netfs_sreq(subreq, netfs_sreq_trace_split); 162 163 spin_lock(&wreq->lock); 164 list_add(&subreq->rreq_link, &to->rreq_link); 165 spin_unlock(&wreq->lock); 166 to = subreq; 167 trace_netfs_sreq(subreq, netfs_sreq_trace_retry); 168 169 stream->sreq_max_len = len; 170 stream->sreq_max_segs = INT_MAX; 171 switch (stream->source) { 172 case NETFS_UPLOAD_TO_SERVER: 173 netfs_stat(&netfs_n_wh_upload); 174 stream->sreq_max_len = umin(len, wreq->wsize); 175 break; 176 case NETFS_WRITE_TO_CACHE: 177 netfs_stat(&netfs_n_wh_write); 178 break; 179 default: 180 WARN_ON_ONCE(1); 181 } 182 183 stream->prepare_write(subreq); 184 185 part = umin(len, stream->sreq_max_len); 186 subreq->len = subreq->transferred + part; 187 len -= part; 188 start += part; 189 if (!len && boundary) { 190 __set_bit(NETFS_SREQ_BOUNDARY, &to->flags); 191 boundary = false; 192 } 193 194 netfs_reissue_write(stream, subreq, &source); 195 if (!len) 196 break; 197 198 } while (len); 199 200 } while (!list_is_head(next, &stream->subrequests)); 201 } 202 203 /* 204 * Perform retries on the streams that need it. If we're doing content 205 * encryption and the server copy changed due to a third-party write, we may 206 * need to do an RMW cycle and also rewrite the data to the cache. 207 */ 208 void netfs_retry_writes(struct netfs_io_request *wreq) 209 { 210 struct netfs_io_stream *stream; 211 int s; 212 213 netfs_stat(&netfs_n_wh_retry_write_req); 214 215 /* Wait for all outstanding I/O to quiesce before performing retries as 216 * we may need to renegotiate the I/O sizes. 217 */ 218 set_bit(NETFS_RREQ_RETRYING, &wreq->flags); 219 for (s = 0; s < NR_IO_STREAMS; s++) { 220 stream = &wreq->io_streams[s]; 221 if (stream->active) 222 netfs_wait_for_in_progress_stream(wreq, stream); 223 } 224 clear_bit(NETFS_RREQ_RETRYING, &wreq->flags); 225 226 // TODO: Enc: Fetch changed partial pages 227 // TODO: Enc: Reencrypt content if needed. 228 // TODO: Enc: Wind back transferred point. 229 // TODO: Enc: Mark cache pages for retry. 230 231 for (s = 0; s < NR_IO_STREAMS; s++) { 232 stream = &wreq->io_streams[s]; 233 if (stream->need_retry) { 234 stream->need_retry = false; 235 netfs_retry_write_stream(wreq, stream); 236 } 237 } 238 } 239