~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/netfs/read_pgpriv2.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /* Read with PG_private_2 [DEPRECATED].
  3  *
  4  * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved.
  5  * Written by David Howells (dhowells@redhat.com)
  6  */
  7 
  8 #include <linux/export.h>
  9 #include <linux/fs.h>
 10 #include <linux/mm.h>
 11 #include <linux/pagemap.h>
 12 #include <linux/slab.h>
 13 #include <linux/task_io_accounting_ops.h>
 14 #include "internal.h"
 15 
 16 /*
 17  * [DEPRECATED] Mark page as requiring copy-to-cache using PG_private_2.  The
 18  * third mark in the folio queue is used to indicate that this folio needs
 19  * writing.
 20  */
 21 void netfs_pgpriv2_mark_copy_to_cache(struct netfs_io_subrequest *subreq,
 22                                       struct netfs_io_request *rreq,
 23                                       struct folio_queue *folioq,
 24                                       int slot)
 25 {
 26         struct folio *folio = folioq_folio(folioq, slot);
 27 
 28         trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache);
 29         folio_start_private_2(folio);
 30         folioq_mark3(folioq, slot);
 31 }
 32 
 33 /*
 34  * [DEPRECATED] Cancel PG_private_2 on all marked folios in the event of an
 35  * unrecoverable error.
 36  */
 37 static void netfs_pgpriv2_cancel(struct folio_queue *folioq)
 38 {
 39         struct folio *folio;
 40         int slot;
 41 
 42         while (folioq) {
 43                 if (!folioq->marks3) {
 44                         folioq = folioq->next;
 45                         continue;
 46                 }
 47 
 48                 slot = __ffs(folioq->marks3);
 49                 folio = folioq_folio(folioq, slot);
 50 
 51                 trace_netfs_folio(folio, netfs_folio_trace_cancel_copy);
 52                 folio_end_private_2(folio);
 53                 folioq_unmark3(folioq, slot);
 54         }
 55 }
 56 
 57 /*
 58  * [DEPRECATED] Copy a folio to the cache with PG_private_2 set.
 59  */
 60 static int netfs_pgpriv2_copy_folio(struct netfs_io_request *wreq, struct folio *folio)
 61 {
 62         struct netfs_io_stream *cache  = &wreq->io_streams[1];
 63         size_t fsize = folio_size(folio), flen = fsize;
 64         loff_t fpos = folio_pos(folio), i_size;
 65         bool to_eof = false;
 66 
 67         _enter("");
 68 
 69         /* netfs_perform_write() may shift i_size around the page or from out
 70          * of the page to beyond it, but cannot move i_size into or through the
 71          * page since we have it locked.
 72          */
 73         i_size = i_size_read(wreq->inode);
 74 
 75         if (fpos >= i_size) {
 76                 /* mmap beyond eof. */
 77                 _debug("beyond eof");
 78                 folio_end_private_2(folio);
 79                 return 0;
 80         }
 81 
 82         if (fpos + fsize > wreq->i_size)
 83                 wreq->i_size = i_size;
 84 
 85         if (flen > i_size - fpos) {
 86                 flen = i_size - fpos;
 87                 to_eof = true;
 88         } else if (flen == i_size - fpos) {
 89                 to_eof = true;
 90         }
 91 
 92         _debug("folio %zx %zx", flen, fsize);
 93 
 94         trace_netfs_folio(folio, netfs_folio_trace_store_copy);
 95 
 96         /* Attach the folio to the rolling buffer. */
 97         if (netfs_buffer_append_folio(wreq, folio, false) < 0)
 98                 return -ENOMEM;
 99 
100         cache->submit_extendable_to = fsize;
101         cache->submit_off = 0;
102         cache->submit_len = flen;
103 
104         /* Attach the folio to one or more subrequests.  For a big folio, we
105          * could end up with thousands of subrequests if the wsize is small -
106          * but we might need to wait during the creation of subrequests for
107          * network resources (eg. SMB credits).
108          */
109         do {
110                 ssize_t part;
111 
112                 wreq->io_iter.iov_offset = cache->submit_off;
113 
114                 atomic64_set(&wreq->issued_to, fpos + cache->submit_off);
115                 cache->submit_extendable_to = fsize - cache->submit_off;
116                 part = netfs_advance_write(wreq, cache, fpos + cache->submit_off,
117                                            cache->submit_len, to_eof);
118                 cache->submit_off += part;
119                 if (part > cache->submit_len)
120                         cache->submit_len = 0;
121                 else
122                         cache->submit_len -= part;
123         } while (cache->submit_len > 0);
124 
125         wreq->io_iter.iov_offset = 0;
126         iov_iter_advance(&wreq->io_iter, fsize);
127         atomic64_set(&wreq->issued_to, fpos + fsize);
128 
129         if (flen < fsize)
130                 netfs_issue_write(wreq, cache);
131 
132         _leave(" = 0");
133         return 0;
134 }
135 
136 /*
137  * [DEPRECATED] Go through the buffer and write any folios that are marked with
138  * the third mark to the cache.
139  */
140 void netfs_pgpriv2_write_to_the_cache(struct netfs_io_request *rreq)
141 {
142         struct netfs_io_request *wreq;
143         struct folio_queue *folioq;
144         struct folio *folio;
145         int error = 0;
146         int slot = 0;
147 
148         _enter("");
149 
150         if (!fscache_resources_valid(&rreq->cache_resources))
151                 goto couldnt_start;
152 
153         /* Need the first folio to be able to set up the op. */
154         for (folioq = rreq->buffer; folioq; folioq = folioq->next) {
155                 if (folioq->marks3) {
156                         slot = __ffs(folioq->marks3);
157                         break;
158                 }
159         }
160         if (!folioq)
161                 return;
162         folio = folioq_folio(folioq, slot);
163 
164         wreq = netfs_create_write_req(rreq->mapping, NULL, folio_pos(folio),
165                                       NETFS_PGPRIV2_COPY_TO_CACHE);
166         if (IS_ERR(wreq)) {
167                 kleave(" [create %ld]", PTR_ERR(wreq));
168                 goto couldnt_start;
169         }
170 
171         trace_netfs_write(wreq, netfs_write_trace_copy_to_cache);
172         netfs_stat(&netfs_n_wh_copy_to_cache);
173 
174         for (;;) {
175                 error = netfs_pgpriv2_copy_folio(wreq, folio);
176                 if (error < 0)
177                         break;
178 
179                 folioq_unmark3(folioq, slot);
180                 if (!folioq->marks3) {
181                         folioq = folioq->next;
182                         if (!folioq)
183                                 break;
184                 }
185 
186                 slot = __ffs(folioq->marks3);
187                 folio = folioq_folio(folioq, slot);
188         }
189 
190         netfs_issue_write(wreq, &wreq->io_streams[1]);
191         smp_wmb(); /* Write lists before ALL_QUEUED. */
192         set_bit(NETFS_RREQ_ALL_QUEUED, &wreq->flags);
193 
194         netfs_put_request(wreq, false, netfs_rreq_trace_put_return);
195         _leave(" = %d", error);
196 couldnt_start:
197         netfs_pgpriv2_cancel(rreq->buffer);
198 }
199 
200 /*
201  * [DEPRECATED] Remove the PG_private_2 mark from any folios we've finished
202  * copying.
203  */
204 bool netfs_pgpriv2_unlock_copied_folios(struct netfs_io_request *wreq)
205 {
206         struct folio_queue *folioq = wreq->buffer;
207         unsigned long long collected_to = wreq->collected_to;
208         unsigned int slot = wreq->buffer_head_slot;
209         bool made_progress = false;
210 
211         if (slot >= folioq_nr_slots(folioq)) {
212                 folioq = netfs_delete_buffer_head(wreq);
213                 slot = 0;
214         }
215 
216         for (;;) {
217                 struct folio *folio;
218                 unsigned long long fpos, fend;
219                 size_t fsize, flen;
220 
221                 folio = folioq_folio(folioq, slot);
222                 if (WARN_ONCE(!folio_test_private_2(folio),
223                               "R=%08x: folio %lx is not marked private_2\n",
224                               wreq->debug_id, folio->index))
225                         trace_netfs_folio(folio, netfs_folio_trace_not_under_wback);
226 
227                 fpos = folio_pos(folio);
228                 fsize = folio_size(folio);
229                 flen = fsize;
230 
231                 fend = min_t(unsigned long long, fpos + flen, wreq->i_size);
232 
233                 trace_netfs_collect_folio(wreq, folio, fend, collected_to);
234 
235                 /* Unlock any folio we've transferred all of. */
236                 if (collected_to < fend)
237                         break;
238 
239                 trace_netfs_folio(folio, netfs_folio_trace_end_copy);
240                 folio_end_private_2(folio);
241                 wreq->cleaned_to = fpos + fsize;
242                 made_progress = true;
243 
244                 /* Clean up the head folioq.  If we clear an entire folioq, then
245                  * we can get rid of it provided it's not also the tail folioq
246                  * being filled by the issuer.
247                  */
248                 folioq_clear(folioq, slot);
249                 slot++;
250                 if (slot >= folioq_nr_slots(folioq)) {
251                         if (READ_ONCE(wreq->buffer_tail) == folioq)
252                                 break;
253                         folioq = netfs_delete_buffer_head(wreq);
254                         slot = 0;
255                 }
256 
257                 if (fpos + fsize >= collected_to)
258                         break;
259         }
260 
261         wreq->buffer = folioq;
262         wreq->buffer_head_slot = slot;
263         return made_progress;
264 }
265 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php