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

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

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /* Cache data I/O routines
  3  *
  4  * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
  5  * Written by David Howells (dhowells@redhat.com)
  6  */
  7 #define FSCACHE_DEBUG_LEVEL OPERATION
  8 #include <linux/fscache-cache.h>
  9 #include <linux/uio.h>
 10 #include <linux/bvec.h>
 11 #include <linux/slab.h>
 12 #include <linux/uio.h>
 13 #include "internal.h"
 14 
 15 /**
 16  * fscache_wait_for_operation - Wait for an object become accessible
 17  * @cres: The cache resources for the operation being performed
 18  * @want_state: The minimum state the object must be at
 19  *
 20  * See if the target cache object is at the specified minimum state of
 21  * accessibility yet, and if not, wait for it.
 22  */
 23 bool fscache_wait_for_operation(struct netfs_cache_resources *cres,
 24                                 enum fscache_want_state want_state)
 25 {
 26         struct fscache_cookie *cookie = fscache_cres_cookie(cres);
 27         enum fscache_cookie_state state;
 28 
 29 again:
 30         if (!fscache_cache_is_live(cookie->volume->cache)) {
 31                 _leave(" [broken]");
 32                 return false;
 33         }
 34 
 35         state = fscache_cookie_state(cookie);
 36         _enter("c=%08x{%u},%x", cookie->debug_id, state, want_state);
 37 
 38         switch (state) {
 39         case FSCACHE_COOKIE_STATE_CREATING:
 40         case FSCACHE_COOKIE_STATE_INVALIDATING:
 41                 if (want_state == FSCACHE_WANT_PARAMS)
 42                         goto ready; /* There can be no content */
 43                 fallthrough;
 44         case FSCACHE_COOKIE_STATE_LOOKING_UP:
 45         case FSCACHE_COOKIE_STATE_LRU_DISCARDING:
 46                 wait_var_event(&cookie->state,
 47                                fscache_cookie_state(cookie) != state);
 48                 goto again;
 49 
 50         case FSCACHE_COOKIE_STATE_ACTIVE:
 51                 goto ready;
 52         case FSCACHE_COOKIE_STATE_DROPPED:
 53         case FSCACHE_COOKIE_STATE_RELINQUISHING:
 54         default:
 55                 _leave(" [not live]");
 56                 return false;
 57         }
 58 
 59 ready:
 60         if (!cres->cache_priv2)
 61                 return cookie->volume->cache->ops->begin_operation(cres, want_state);
 62         return true;
 63 }
 64 EXPORT_SYMBOL(fscache_wait_for_operation);
 65 
 66 /*
 67  * Begin an I/O operation on the cache, waiting till we reach the right state.
 68  *
 69  * Attaches the resources required to the operation resources record.
 70  */
 71 static int fscache_begin_operation(struct netfs_cache_resources *cres,
 72                                    struct fscache_cookie *cookie,
 73                                    enum fscache_want_state want_state,
 74                                    enum fscache_access_trace why)
 75 {
 76         enum fscache_cookie_state state;
 77         long timeo;
 78         bool once_only = false;
 79 
 80         cres->ops               = NULL;
 81         cres->cache_priv        = cookie;
 82         cres->cache_priv2       = NULL;
 83         cres->debug_id          = cookie->debug_id;
 84         cres->inval_counter     = cookie->inval_counter;
 85 
 86         if (!fscache_begin_cookie_access(cookie, why)) {
 87                 cres->cache_priv = NULL;
 88                 return -ENOBUFS;
 89         }
 90 
 91 again:
 92         spin_lock(&cookie->lock);
 93 
 94         state = fscache_cookie_state(cookie);
 95         _enter("c=%08x{%u},%x", cookie->debug_id, state, want_state);
 96 
 97         switch (state) {
 98         case FSCACHE_COOKIE_STATE_LOOKING_UP:
 99         case FSCACHE_COOKIE_STATE_LRU_DISCARDING:
100         case FSCACHE_COOKIE_STATE_INVALIDATING:
101                 goto wait_for_file_wrangling;
102         case FSCACHE_COOKIE_STATE_CREATING:
103                 if (want_state == FSCACHE_WANT_PARAMS)
104                         goto ready; /* There can be no content */
105                 goto wait_for_file_wrangling;
106         case FSCACHE_COOKIE_STATE_ACTIVE:
107                 goto ready;
108         case FSCACHE_COOKIE_STATE_DROPPED:
109         case FSCACHE_COOKIE_STATE_RELINQUISHING:
110                 WARN(1, "Can't use cookie in state %u\n", cookie->state);
111                 goto not_live;
112         default:
113                 goto not_live;
114         }
115 
116 ready:
117         spin_unlock(&cookie->lock);
118         if (!cookie->volume->cache->ops->begin_operation(cres, want_state))
119                 goto failed;
120         return 0;
121 
122 wait_for_file_wrangling:
123         spin_unlock(&cookie->lock);
124         trace_fscache_access(cookie->debug_id, refcount_read(&cookie->ref),
125                              atomic_read(&cookie->n_accesses),
126                              fscache_access_io_wait);
127         timeo = wait_var_event_timeout(&cookie->state,
128                                        fscache_cookie_state(cookie) != state, 20 * HZ);
129         if (timeo <= 1 && !once_only) {
130                 pr_warn("%s: cookie state change wait timed out: cookie->state=%u state=%u",
131                         __func__, fscache_cookie_state(cookie), state);
132                 fscache_print_cookie(cookie, 'O');
133                 once_only = true;
134         }
135         goto again;
136 
137 not_live:
138         spin_unlock(&cookie->lock);
139 failed:
140         cres->cache_priv = NULL;
141         cres->ops = NULL;
142         fscache_end_cookie_access(cookie, fscache_access_io_not_live);
143         _leave(" = -ENOBUFS");
144         return -ENOBUFS;
145 }
146 
147 int __fscache_begin_read_operation(struct netfs_cache_resources *cres,
148                                    struct fscache_cookie *cookie)
149 {
150         return fscache_begin_operation(cres, cookie, FSCACHE_WANT_PARAMS,
151                                        fscache_access_io_read);
152 }
153 EXPORT_SYMBOL(__fscache_begin_read_operation);
154 
155 int __fscache_begin_write_operation(struct netfs_cache_resources *cres,
156                                     struct fscache_cookie *cookie)
157 {
158         return fscache_begin_operation(cres, cookie, FSCACHE_WANT_PARAMS,
159                                        fscache_access_io_write);
160 }
161 EXPORT_SYMBOL(__fscache_begin_write_operation);
162 
163 struct fscache_write_request {
164         struct netfs_cache_resources cache_resources;
165         struct address_space    *mapping;
166         loff_t                  start;
167         size_t                  len;
168         bool                    set_bits;
169         bool                    using_pgpriv2;
170         netfs_io_terminated_t   term_func;
171         void                    *term_func_priv;
172 };
173 
174 void __fscache_clear_page_bits(struct address_space *mapping,
175                                loff_t start, size_t len)
176 {
177         pgoff_t first = start / PAGE_SIZE;
178         pgoff_t last = (start + len - 1) / PAGE_SIZE;
179         struct page *page;
180 
181         if (len) {
182                 XA_STATE(xas, &mapping->i_pages, first);
183 
184                 rcu_read_lock();
185                 xas_for_each(&xas, page, last) {
186                         folio_end_private_2(page_folio(page));
187                 }
188                 rcu_read_unlock();
189         }
190 }
191 EXPORT_SYMBOL(__fscache_clear_page_bits);
192 
193 /*
194  * Deal with the completion of writing the data to the cache.
195  */
196 static void fscache_wreq_done(void *priv, ssize_t transferred_or_error,
197                               bool was_async)
198 {
199         struct fscache_write_request *wreq = priv;
200 
201         if (wreq->using_pgpriv2)
202                 fscache_clear_page_bits(wreq->mapping, wreq->start, wreq->len,
203                                         wreq->set_bits);
204 
205         if (wreq->term_func)
206                 wreq->term_func(wreq->term_func_priv, transferred_or_error,
207                                 was_async);
208         fscache_end_operation(&wreq->cache_resources);
209         kfree(wreq);
210 }
211 
212 void __fscache_write_to_cache(struct fscache_cookie *cookie,
213                               struct address_space *mapping,
214                               loff_t start, size_t len, loff_t i_size,
215                               netfs_io_terminated_t term_func,
216                               void *term_func_priv,
217                               bool using_pgpriv2, bool cond)
218 {
219         struct fscache_write_request *wreq;
220         struct netfs_cache_resources *cres;
221         struct iov_iter iter;
222         int ret = -ENOBUFS;
223 
224         if (len == 0)
225                 goto abandon;
226 
227         _enter("%llx,%zx", start, len);
228 
229         wreq = kzalloc(sizeof(struct fscache_write_request), GFP_NOFS);
230         if (!wreq)
231                 goto abandon;
232         wreq->mapping           = mapping;
233         wreq->start             = start;
234         wreq->len               = len;
235         wreq->using_pgpriv2     = using_pgpriv2;
236         wreq->set_bits          = cond;
237         wreq->term_func         = term_func;
238         wreq->term_func_priv    = term_func_priv;
239 
240         cres = &wreq->cache_resources;
241         if (fscache_begin_operation(cres, cookie, FSCACHE_WANT_WRITE,
242                                     fscache_access_io_write) < 0)
243                 goto abandon_free;
244 
245         ret = cres->ops->prepare_write(cres, &start, &len, len, i_size, false);
246         if (ret < 0)
247                 goto abandon_end;
248 
249         /* TODO: Consider clearing page bits now for space the write isn't
250          * covering.  This is more complicated than it appears when THPs are
251          * taken into account.
252          */
253 
254         iov_iter_xarray(&iter, ITER_SOURCE, &mapping->i_pages, start, len);
255         fscache_write(cres, start, &iter, fscache_wreq_done, wreq);
256         return;
257 
258 abandon_end:
259         return fscache_wreq_done(wreq, ret, false);
260 abandon_free:
261         kfree(wreq);
262 abandon:
263         if (using_pgpriv2)
264                 fscache_clear_page_bits(mapping, start, len, cond);
265         if (term_func)
266                 term_func(term_func_priv, ret, false);
267 }
268 EXPORT_SYMBOL(__fscache_write_to_cache);
269 
270 /*
271  * Change the size of a backing object.
272  */
273 void __fscache_resize_cookie(struct fscache_cookie *cookie, loff_t new_size)
274 {
275         struct netfs_cache_resources cres;
276 
277         trace_fscache_resize(cookie, new_size);
278         if (fscache_begin_operation(&cres, cookie, FSCACHE_WANT_WRITE,
279                                     fscache_access_io_resize) == 0) {
280                 fscache_stat(&fscache_n_resizes);
281                 set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &cookie->flags);
282 
283                 /* We cannot defer a resize as we need to do it inside the
284                  * netfs's inode lock so that we're serialised with respect to
285                  * writes.
286                  */
287                 cookie->volume->cache->ops->resize_cookie(&cres, new_size);
288                 fscache_end_operation(&cres);
289         } else {
290                 fscache_stat(&fscache_n_resizes_null);
291         }
292 }
293 EXPORT_SYMBOL(__fscache_resize_cookie);
294 

~ [ 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