2 * V9FS cache definitions.
4 * Copyright (C) 2009 by Abhishek Kulkarni <adkulkar@umail.iu.edu>
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.
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.
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
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>
29 #include <net/9p/9p.h>
34 #define CACHETAG_LEN 11
36 struct fscache_netfs v9fs_cache_netfs
= {
42 * v9fs_random_cachetag - Generate a random tag to be associated
43 * with a new cache session.
45 * The value of jiffies is used for a fairly randomly cache tag.
49 int v9fs_random_cachetag(struct v9fs_session_info
*v9ses
)
51 v9ses
->cachetag
= kmalloc(CACHETAG_LEN
, GFP_KERNEL
);
55 return scnprintf(v9ses
->cachetag
, CACHETAG_LEN
, "%lu", jiffies
);
58 const struct fscache_cookie_def v9fs_cache_session_index_def
= {
60 .type
= FSCACHE_COOKIE_TYPE_INDEX
,
63 void v9fs_cache_session_get_cookie(struct v9fs_session_info
*v9ses
)
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 kfree(v9ses
->cachetag
);
70 v9ses
->cachetag
= NULL
;
75 v9ses
->fscache
= fscache_acquire_cookie(v9fs_cache_netfs
.primary_index
,
76 &v9fs_cache_session_index_def
,
78 strlen(v9ses
->cachetag
),
81 p9_debug(P9_DEBUG_FSC
, "session %p get cookie %p\n",
82 v9ses
, v9ses
->fscache
);
85 void v9fs_cache_session_put_cookie(struct v9fs_session_info
*v9ses
)
87 p9_debug(P9_DEBUG_FSC
, "session %p put cookie %p\n",
88 v9ses
, v9ses
->fscache
);
89 fscache_relinquish_cookie(v9ses
->fscache
, NULL
, false);
90 v9ses
->fscache
= NULL
;
94 fscache_checkaux
v9fs_cache_inode_check_aux(void *cookie_netfs_data
,
99 const struct v9fs_inode
*v9inode
= cookie_netfs_data
;
101 if (buflen
!= sizeof(v9inode
->qid
.version
))
102 return FSCACHE_CHECKAUX_OBSOLETE
;
104 if (memcmp(buffer
, &v9inode
->qid
.version
,
105 sizeof(v9inode
->qid
.version
)))
106 return FSCACHE_CHECKAUX_OBSOLETE
;
108 return FSCACHE_CHECKAUX_OKAY
;
111 const struct fscache_cookie_def v9fs_cache_inode_index_def
= {
113 .type
= FSCACHE_COOKIE_TYPE_DATAFILE
,
114 .check_aux
= v9fs_cache_inode_check_aux
,
117 void v9fs_cache_inode_get_cookie(struct inode
*inode
)
119 struct v9fs_inode
*v9inode
;
120 struct v9fs_session_info
*v9ses
;
122 if (!S_ISREG(inode
->i_mode
))
125 v9inode
= V9FS_I(inode
);
126 if (v9inode
->fscache
)
129 v9ses
= v9fs_inode2v9ses(inode
);
130 v9inode
->fscache
= fscache_acquire_cookie(v9ses
->fscache
,
131 &v9fs_cache_inode_index_def
,
133 sizeof(v9inode
->qid
.path
),
134 &v9inode
->qid
.version
,
135 sizeof(v9inode
->qid
.version
),
137 i_size_read(&v9inode
->vfs_inode
),
140 p9_debug(P9_DEBUG_FSC
, "inode %p get cookie %p\n",
141 inode
, v9inode
->fscache
);
144 void v9fs_cache_inode_put_cookie(struct inode
*inode
)
146 struct v9fs_inode
*v9inode
= V9FS_I(inode
);
148 if (!v9inode
->fscache
)
150 p9_debug(P9_DEBUG_FSC
, "inode %p put cookie %p\n",
151 inode
, v9inode
->fscache
);
153 fscache_relinquish_cookie(v9inode
->fscache
, &v9inode
->qid
.version
,
155 v9inode
->fscache
= NULL
;
158 void v9fs_cache_inode_flush_cookie(struct inode
*inode
)
160 struct v9fs_inode
*v9inode
= V9FS_I(inode
);
162 if (!v9inode
->fscache
)
164 p9_debug(P9_DEBUG_FSC
, "inode %p flush cookie %p\n",
165 inode
, v9inode
->fscache
);
167 fscache_relinquish_cookie(v9inode
->fscache
, NULL
, true);
168 v9inode
->fscache
= NULL
;
171 void v9fs_cache_inode_set_cookie(struct inode
*inode
, struct file
*filp
)
173 struct v9fs_inode
*v9inode
= V9FS_I(inode
);
175 if (!v9inode
->fscache
)
178 mutex_lock(&v9inode
->fscache_lock
);
180 if ((filp
->f_flags
& O_ACCMODE
) != O_RDONLY
)
181 v9fs_cache_inode_flush_cookie(inode
);
183 v9fs_cache_inode_get_cookie(inode
);
185 mutex_unlock(&v9inode
->fscache_lock
);
188 void v9fs_cache_inode_reset_cookie(struct inode
*inode
)
190 struct v9fs_inode
*v9inode
= V9FS_I(inode
);
191 struct v9fs_session_info
*v9ses
;
192 struct fscache_cookie
*old
;
194 if (!v9inode
->fscache
)
197 old
= v9inode
->fscache
;
199 mutex_lock(&v9inode
->fscache_lock
);
200 fscache_relinquish_cookie(v9inode
->fscache
, NULL
, true);
202 v9ses
= v9fs_inode2v9ses(inode
);
203 v9inode
->fscache
= fscache_acquire_cookie(v9ses
->fscache
,
204 &v9fs_cache_inode_index_def
,
206 sizeof(v9inode
->qid
.path
),
207 &v9inode
->qid
.version
,
208 sizeof(v9inode
->qid
.version
),
210 i_size_read(&v9inode
->vfs_inode
),
212 p9_debug(P9_DEBUG_FSC
, "inode %p revalidating cookie old %p new %p\n",
213 inode
, old
, v9inode
->fscache
);
215 mutex_unlock(&v9inode
->fscache_lock
);
218 int __v9fs_fscache_release_page(struct page
*page
, gfp_t gfp
)
220 struct inode
*inode
= page
->mapping
->host
;
221 struct v9fs_inode
*v9inode
= V9FS_I(inode
);
223 BUG_ON(!v9inode
->fscache
);
225 return fscache_maybe_release_page(v9inode
->fscache
, page
, gfp
);
228 void __v9fs_fscache_invalidate_page(struct page
*page
)
230 struct inode
*inode
= page
->mapping
->host
;
231 struct v9fs_inode
*v9inode
= V9FS_I(inode
);
233 BUG_ON(!v9inode
->fscache
);
235 if (PageFsCache(page
)) {
236 fscache_wait_on_page_write(v9inode
->fscache
, page
);
237 BUG_ON(!PageLocked(page
));
238 fscache_uncache_page(v9inode
->fscache
, page
);
242 static void v9fs_vfs_readpage_complete(struct page
*page
, void *data
,
246 SetPageUptodate(page
);
252 * __v9fs_readpage_from_fscache - read a page from cache
254 * Returns 0 if the pages are in cache and a BIO is submitted,
255 * 1 if the pages are not in cache and -error otherwise.
258 int __v9fs_readpage_from_fscache(struct inode
*inode
, struct page
*page
)
261 const struct v9fs_inode
*v9inode
= V9FS_I(inode
);
263 p9_debug(P9_DEBUG_FSC
, "inode %p page %p\n", inode
, page
);
264 if (!v9inode
->fscache
)
267 ret
= fscache_read_or_alloc_page(v9inode
->fscache
,
269 v9fs_vfs_readpage_complete
,
275 p9_debug(P9_DEBUG_FSC
, "page/inode not in cache %d\n", ret
);
278 p9_debug(P9_DEBUG_FSC
, "BIO submitted\n");
281 p9_debug(P9_DEBUG_FSC
, "ret %d\n", ret
);
287 * __v9fs_readpages_from_fscache - read multiple pages from cache
289 * Returns 0 if the pages are in cache and a BIO is submitted,
290 * 1 if the pages are not in cache and -error otherwise.
293 int __v9fs_readpages_from_fscache(struct inode
*inode
,
294 struct address_space
*mapping
,
295 struct list_head
*pages
,
299 const struct v9fs_inode
*v9inode
= V9FS_I(inode
);
301 p9_debug(P9_DEBUG_FSC
, "inode %p pages %u\n", inode
, *nr_pages
);
302 if (!v9inode
->fscache
)
305 ret
= fscache_read_or_alloc_pages(v9inode
->fscache
,
306 mapping
, pages
, nr_pages
,
307 v9fs_vfs_readpage_complete
,
309 mapping_gfp_mask(mapping
));
313 p9_debug(P9_DEBUG_FSC
, "pages/inodes not in cache %d\n", ret
);
316 BUG_ON(!list_empty(pages
));
317 BUG_ON(*nr_pages
!= 0);
318 p9_debug(P9_DEBUG_FSC
, "BIO submitted\n");
321 p9_debug(P9_DEBUG_FSC
, "ret %d\n", ret
);
327 * __v9fs_readpage_to_fscache - write a page to the cache
331 void __v9fs_readpage_to_fscache(struct inode
*inode
, struct page
*page
)
334 const struct v9fs_inode
*v9inode
= V9FS_I(inode
);
336 p9_debug(P9_DEBUG_FSC
, "inode %p page %p\n", inode
, page
);
337 ret
= fscache_write_page(v9inode
->fscache
, page
,
338 i_size_read(&v9inode
->vfs_inode
), GFP_KERNEL
);
339 p9_debug(P9_DEBUG_FSC
, "ret = %d\n", ret
);
341 v9fs_uncache_page(inode
, page
);
345 * wait for a page to complete writing to the cache
347 void __v9fs_fscache_wait_on_page_write(struct inode
*inode
, struct page
*page
)
349 const struct v9fs_inode
*v9inode
= V9FS_I(inode
);
350 p9_debug(P9_DEBUG_FSC
, "inode %p page %p\n", inode
, page
);
351 if (PageFsCache(page
))
352 fscache_wait_on_page_write(v9inode
->fscache
, page
);