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

TOMOYO Linux Cross Reference
Linux/fs/9p/cache.c

Version: ~ [ linux-5.1-rc5 ] ~ [ linux-5.0.7 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.34 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.111 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.168 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.178 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.138 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.65 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * V9FS cache definitions.
  3  *
  4  *  Copyright (C) 2009 by Abhishek Kulkarni <adkulkar@umail.iu.edu>
  5  *
  6  *  This program is free software; you can redistribute it and/or modify
  7  *  it under the terms of the GNU General Public License version 2
  8  *  as published by the Free Software Foundation.
  9  *
 10  *  This program is distributed in the hope that it will be useful,
 11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  *  GNU General Public License for more details.
 14  *
 15  *  You should have received a copy of the GNU General Public License
 16  *  along with this program; if not, write to:
 17  *  Free Software Foundation
 18  *  51 Franklin Street, Fifth Floor
 19  *  Boston, MA  02111-1301  USA
 20  *
 21  */
 22 
 23 #include <linux/jiffies.h>
 24 #include <linux/file.h>
 25 #include <linux/slab.h>
 26 #include <linux/stat.h>
 27 #include <linux/sched.h>
 28 #include <linux/fs.h>
 29 #include <net/9p/9p.h>
 30 
 31 #include "v9fs.h"
 32 #include "cache.h"
 33 
 34 #define CACHETAG_LEN  11
 35 
 36 struct fscache_netfs v9fs_cache_netfs = {
 37         .name           = "9p",
 38         .version        = 0,
 39 };
 40 
 41 /**
 42  * v9fs_random_cachetag - Generate a random tag to be associated
 43  *                        with a new cache session.
 44  *
 45  * The value of jiffies is used for a fairly randomly cache tag.
 46  */
 47 
 48 static
 49 int v9fs_random_cachetag(struct v9fs_session_info *v9ses)
 50 {
 51         v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL);
 52         if (!v9ses->cachetag)
 53                 return -ENOMEM;
 54 
 55         return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies);
 56 }
 57 
 58 const struct fscache_cookie_def v9fs_cache_session_index_def = {
 59         .name           = "9P.session",
 60         .type           = FSCACHE_COOKIE_TYPE_INDEX,
 61 };
 62 
 63 void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
 64 {
 65         /* If no cache session tag was specified, we generate a random one. */
 66         if (!v9ses->cachetag) {
 67                 if (v9fs_random_cachetag(v9ses) < 0) {
 68                         v9ses->fscache = NULL;
 69                         return;
 70                 }
 71         }
 72 
 73         v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
 74                                                 &v9fs_cache_session_index_def,
 75                                                 v9ses->cachetag,
 76                                                 strlen(v9ses->cachetag),
 77                                                 NULL, 0,
 78                                                 v9ses, 0, true);
 79         p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
 80                  v9ses, v9ses->fscache);
 81 }
 82 
 83 void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
 84 {
 85         p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n",
 86                  v9ses, v9ses->fscache);
 87         fscache_relinquish_cookie(v9ses->fscache, NULL, false);
 88         v9ses->fscache = NULL;
 89 }
 90 
 91 static enum
 92 fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
 93                                             const void *buffer,
 94                                             uint16_t buflen,
 95                                             loff_t object_size)
 96 {
 97         const struct v9fs_inode *v9inode = cookie_netfs_data;
 98 
 99         if (buflen != sizeof(v9inode->qid.version))
100                 return FSCACHE_CHECKAUX_OBSOLETE;
101 
102         if (memcmp(buffer, &v9inode->qid.version,
103                    sizeof(v9inode->qid.version)))
104                 return FSCACHE_CHECKAUX_OBSOLETE;
105 
106         return FSCACHE_CHECKAUX_OKAY;
107 }
108 
109 const struct fscache_cookie_def v9fs_cache_inode_index_def = {
110         .name           = "9p.inode",
111         .type           = FSCACHE_COOKIE_TYPE_DATAFILE,
112         .check_aux      = v9fs_cache_inode_check_aux,
113 };
114 
115 void v9fs_cache_inode_get_cookie(struct inode *inode)
116 {
117         struct v9fs_inode *v9inode;
118         struct v9fs_session_info *v9ses;
119 
120         if (!S_ISREG(inode->i_mode))
121                 return;
122 
123         v9inode = V9FS_I(inode);
124         if (v9inode->fscache)
125                 return;
126 
127         v9ses = v9fs_inode2v9ses(inode);
128         v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
129                                                   &v9fs_cache_inode_index_def,
130                                                   &v9inode->qid.path,
131                                                   sizeof(v9inode->qid.path),
132                                                   &v9inode->qid.version,
133                                                   sizeof(v9inode->qid.version),
134                                                   v9inode,
135                                                   i_size_read(&v9inode->vfs_inode),
136                                                   true);
137 
138         p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
139                  inode, v9inode->fscache);
140 }
141 
142 void v9fs_cache_inode_put_cookie(struct inode *inode)
143 {
144         struct v9fs_inode *v9inode = V9FS_I(inode);
145 
146         if (!v9inode->fscache)
147                 return;
148         p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n",
149                  inode, v9inode->fscache);
150 
151         fscache_relinquish_cookie(v9inode->fscache, &v9inode->qid.version,
152                                   false);
153         v9inode->fscache = NULL;
154 }
155 
156 void v9fs_cache_inode_flush_cookie(struct inode *inode)
157 {
158         struct v9fs_inode *v9inode = V9FS_I(inode);
159 
160         if (!v9inode->fscache)
161                 return;
162         p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n",
163                  inode, v9inode->fscache);
164 
165         fscache_relinquish_cookie(v9inode->fscache, NULL, true);
166         v9inode->fscache = NULL;
167 }
168 
169 void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp)
170 {
171         struct v9fs_inode *v9inode = V9FS_I(inode);
172 
173         if (!v9inode->fscache)
174                 return;
175 
176         mutex_lock(&v9inode->fscache_lock);
177 
178         if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
179                 v9fs_cache_inode_flush_cookie(inode);
180         else
181                 v9fs_cache_inode_get_cookie(inode);
182 
183         mutex_unlock(&v9inode->fscache_lock);
184 }
185 
186 void v9fs_cache_inode_reset_cookie(struct inode *inode)
187 {
188         struct v9fs_inode *v9inode = V9FS_I(inode);
189         struct v9fs_session_info *v9ses;
190         struct fscache_cookie *old;
191 
192         if (!v9inode->fscache)
193                 return;
194 
195         old = v9inode->fscache;
196 
197         mutex_lock(&v9inode->fscache_lock);
198         fscache_relinquish_cookie(v9inode->fscache, NULL, true);
199 
200         v9ses = v9fs_inode2v9ses(inode);
201         v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
202                                                   &v9fs_cache_inode_index_def,
203                                                   &v9inode->qid.path,
204                                                   sizeof(v9inode->qid.path),
205                                                   &v9inode->qid.version,
206                                                   sizeof(v9inode->qid.version),
207                                                   v9inode,
208                                                   i_size_read(&v9inode->vfs_inode),
209                                                   true);
210         p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
211                  inode, old, v9inode->fscache);
212 
213         mutex_unlock(&v9inode->fscache_lock);
214 }
215 
216 int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
217 {
218         struct inode *inode = page->mapping->host;
219         struct v9fs_inode *v9inode = V9FS_I(inode);
220 
221         BUG_ON(!v9inode->fscache);
222 
223         return fscache_maybe_release_page(v9inode->fscache, page, gfp);
224 }
225 
226 void __v9fs_fscache_invalidate_page(struct page *page)
227 {
228         struct inode *inode = page->mapping->host;
229         struct v9fs_inode *v9inode = V9FS_I(inode);
230 
231         BUG_ON(!v9inode->fscache);
232 
233         if (PageFsCache(page)) {
234                 fscache_wait_on_page_write(v9inode->fscache, page);
235                 BUG_ON(!PageLocked(page));
236                 fscache_uncache_page(v9inode->fscache, page);
237         }
238 }
239 
240 static void v9fs_vfs_readpage_complete(struct page *page, void *data,
241                                        int error)
242 {
243         if (!error)
244                 SetPageUptodate(page);
245 
246         unlock_page(page);
247 }
248 
249 /**
250  * __v9fs_readpage_from_fscache - read a page from cache
251  *
252  * Returns 0 if the pages are in cache and a BIO is submitted,
253  * 1 if the pages are not in cache and -error otherwise.
254  */
255 
256 int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
257 {
258         int ret;
259         const struct v9fs_inode *v9inode = V9FS_I(inode);
260 
261         p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
262         if (!v9inode->fscache)
263                 return -ENOBUFS;
264 
265         ret = fscache_read_or_alloc_page(v9inode->fscache,
266                                          page,
267                                          v9fs_vfs_readpage_complete,
268                                          NULL,
269                                          GFP_KERNEL);
270         switch (ret) {
271         case -ENOBUFS:
272         case -ENODATA:
273                 p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret);
274                 return 1;
275         case 0:
276                 p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
277                 return ret;
278         default:
279                 p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
280                 return ret;
281         }
282 }
283 
284 /**
285  * __v9fs_readpages_from_fscache - read multiple pages from cache
286  *
287  * Returns 0 if the pages are in cache and a BIO is submitted,
288  * 1 if the pages are not in cache and -error otherwise.
289  */
290 
291 int __v9fs_readpages_from_fscache(struct inode *inode,
292                                   struct address_space *mapping,
293                                   struct list_head *pages,
294                                   unsigned *nr_pages)
295 {
296         int ret;
297         const struct v9fs_inode *v9inode = V9FS_I(inode);
298 
299         p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages);
300         if (!v9inode->fscache)
301                 return -ENOBUFS;
302 
303         ret = fscache_read_or_alloc_pages(v9inode->fscache,
304                                           mapping, pages, nr_pages,
305                                           v9fs_vfs_readpage_complete,
306                                           NULL,
307                                           mapping_gfp_mask(mapping));
308         switch (ret) {
309         case -ENOBUFS:
310         case -ENODATA:
311                 p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret);
312                 return 1;
313         case 0:
314                 BUG_ON(!list_empty(pages));
315                 BUG_ON(*nr_pages != 0);
316                 p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
317                 return ret;
318         default:
319                 p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
320                 return ret;
321         }
322 }
323 
324 /**
325  * __v9fs_readpage_to_fscache - write a page to the cache
326  *
327  */
328 
329 void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
330 {
331         int ret;
332         const struct v9fs_inode *v9inode = V9FS_I(inode);
333 
334         p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
335         ret = fscache_write_page(v9inode->fscache, page,
336                                  i_size_read(&v9inode->vfs_inode), GFP_KERNEL);
337         p9_debug(P9_DEBUG_FSC, "ret =  %d\n", ret);
338         if (ret != 0)
339                 v9fs_uncache_page(inode, page);
340 }
341 
342 /*
343  * wait for a page to complete writing to the cache
344  */
345 void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
346 {
347         const struct v9fs_inode *v9inode = V9FS_I(inode);
348         p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
349         if (PageFsCache(page))
350                 fscache_wait_on_page_write(v9inode->fscache, page);
351 }
352 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp