xref: /openbmc/linux/fs/9p/cache.c (revision 5d385153)
160e78d2cSAbhishek Kulkarni /*
260e78d2cSAbhishek Kulkarni  * V9FS cache definitions.
360e78d2cSAbhishek Kulkarni  *
460e78d2cSAbhishek Kulkarni  *  Copyright (C) 2009 by Abhishek Kulkarni <adkulkar@umail.iu.edu>
560e78d2cSAbhishek Kulkarni  *
660e78d2cSAbhishek Kulkarni  *  This program is free software; you can redistribute it and/or modify
760e78d2cSAbhishek Kulkarni  *  it under the terms of the GNU General Public License version 2
860e78d2cSAbhishek Kulkarni  *  as published by the Free Software Foundation.
960e78d2cSAbhishek Kulkarni  *
1060e78d2cSAbhishek Kulkarni  *  This program is distributed in the hope that it will be useful,
1160e78d2cSAbhishek Kulkarni  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1260e78d2cSAbhishek Kulkarni  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1360e78d2cSAbhishek Kulkarni  *  GNU General Public License for more details.
1460e78d2cSAbhishek Kulkarni  *
1560e78d2cSAbhishek Kulkarni  *  You should have received a copy of the GNU General Public License
1660e78d2cSAbhishek Kulkarni  *  along with this program; if not, write to:
1760e78d2cSAbhishek Kulkarni  *  Free Software Foundation
1860e78d2cSAbhishek Kulkarni  *  51 Franklin Street, Fifth Floor
1960e78d2cSAbhishek Kulkarni  *  Boston, MA  02111-1301  USA
2060e78d2cSAbhishek Kulkarni  *
2160e78d2cSAbhishek Kulkarni  */
2260e78d2cSAbhishek Kulkarni 
2360e78d2cSAbhishek Kulkarni #include <linux/jiffies.h>
2460e78d2cSAbhishek Kulkarni #include <linux/file.h>
255a0e3ad6STejun Heo #include <linux/slab.h>
2660e78d2cSAbhishek Kulkarni #include <linux/stat.h>
2760e78d2cSAbhishek Kulkarni #include <linux/sched.h>
2860e78d2cSAbhishek Kulkarni #include <linux/fs.h>
2960e78d2cSAbhishek Kulkarni #include <net/9p/9p.h>
3060e78d2cSAbhishek Kulkarni 
3160e78d2cSAbhishek Kulkarni #include "v9fs.h"
3260e78d2cSAbhishek Kulkarni #include "cache.h"
3360e78d2cSAbhishek Kulkarni 
3460e78d2cSAbhishek Kulkarni #define CACHETAG_LEN  11
3560e78d2cSAbhishek Kulkarni 
3660e78d2cSAbhishek Kulkarni struct fscache_netfs v9fs_cache_netfs = {
3760e78d2cSAbhishek Kulkarni 	.name 		= "9p",
3860e78d2cSAbhishek Kulkarni 	.version 	= 0,
3960e78d2cSAbhishek Kulkarni };
4060e78d2cSAbhishek Kulkarni 
4160e78d2cSAbhishek Kulkarni /**
4260e78d2cSAbhishek Kulkarni  * v9fs_random_cachetag - Generate a random tag to be associated
4360e78d2cSAbhishek Kulkarni  *			  with a new cache session.
4460e78d2cSAbhishek Kulkarni  *
4560e78d2cSAbhishek Kulkarni  * The value of jiffies is used for a fairly randomly cache tag.
4660e78d2cSAbhishek Kulkarni  */
4760e78d2cSAbhishek Kulkarni 
4860e78d2cSAbhishek Kulkarni static
4960e78d2cSAbhishek Kulkarni int v9fs_random_cachetag(struct v9fs_session_info *v9ses)
5060e78d2cSAbhishek Kulkarni {
5160e78d2cSAbhishek Kulkarni 	v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL);
5260e78d2cSAbhishek Kulkarni 	if (!v9ses->cachetag)
5360e78d2cSAbhishek Kulkarni 		return -ENOMEM;
5460e78d2cSAbhishek Kulkarni 
5560e78d2cSAbhishek Kulkarni 	return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies);
5660e78d2cSAbhishek Kulkarni }
5760e78d2cSAbhishek Kulkarni 
5860e78d2cSAbhishek Kulkarni static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data,
5960e78d2cSAbhishek Kulkarni 					   void *buffer, uint16_t bufmax)
6060e78d2cSAbhishek Kulkarni {
6160e78d2cSAbhishek Kulkarni 	struct v9fs_session_info *v9ses;
6260e78d2cSAbhishek Kulkarni 	uint16_t klen = 0;
6360e78d2cSAbhishek Kulkarni 
6460e78d2cSAbhishek Kulkarni 	v9ses = (struct v9fs_session_info *)cookie_netfs_data;
655d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "session %p buf %p size %u\n",
665d385153SJoe Perches 		 v9ses, buffer, bufmax);
6760e78d2cSAbhishek Kulkarni 
6860e78d2cSAbhishek Kulkarni 	if (v9ses->cachetag)
6960e78d2cSAbhishek Kulkarni 		klen = strlen(v9ses->cachetag);
7060e78d2cSAbhishek Kulkarni 
7160e78d2cSAbhishek Kulkarni 	if (klen > bufmax)
7260e78d2cSAbhishek Kulkarni 		return 0;
7360e78d2cSAbhishek Kulkarni 
7460e78d2cSAbhishek Kulkarni 	memcpy(buffer, v9ses->cachetag, klen);
755d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "cache session tag %s\n", v9ses->cachetag);
7660e78d2cSAbhishek Kulkarni 	return klen;
7760e78d2cSAbhishek Kulkarni }
7860e78d2cSAbhishek Kulkarni 
7960e78d2cSAbhishek Kulkarni const struct fscache_cookie_def v9fs_cache_session_index_def = {
8060e78d2cSAbhishek Kulkarni 	.name		= "9P.session",
8160e78d2cSAbhishek Kulkarni 	.type		= FSCACHE_COOKIE_TYPE_INDEX,
8260e78d2cSAbhishek Kulkarni 	.get_key	= v9fs_cache_session_get_key,
8360e78d2cSAbhishek Kulkarni };
8460e78d2cSAbhishek Kulkarni 
8560e78d2cSAbhishek Kulkarni void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
8660e78d2cSAbhishek Kulkarni {
8760e78d2cSAbhishek Kulkarni 	/* If no cache session tag was specified, we generate a random one. */
8860e78d2cSAbhishek Kulkarni 	if (!v9ses->cachetag)
8960e78d2cSAbhishek Kulkarni 		v9fs_random_cachetag(v9ses);
9060e78d2cSAbhishek Kulkarni 
9160e78d2cSAbhishek Kulkarni 	v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
9260e78d2cSAbhishek Kulkarni 						&v9fs_cache_session_index_def,
9360e78d2cSAbhishek Kulkarni 						v9ses);
945d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
955d385153SJoe Perches 		 v9ses, v9ses->fscache);
9660e78d2cSAbhishek Kulkarni }
9760e78d2cSAbhishek Kulkarni 
9860e78d2cSAbhishek Kulkarni void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
9960e78d2cSAbhishek Kulkarni {
1005d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n",
1015d385153SJoe Perches 		 v9ses, v9ses->fscache);
10260e78d2cSAbhishek Kulkarni 	fscache_relinquish_cookie(v9ses->fscache, 0);
10360e78d2cSAbhishek Kulkarni 	v9ses->fscache = NULL;
10460e78d2cSAbhishek Kulkarni }
10560e78d2cSAbhishek Kulkarni 
10660e78d2cSAbhishek Kulkarni 
10760e78d2cSAbhishek Kulkarni static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data,
10860e78d2cSAbhishek Kulkarni 					 void *buffer, uint16_t bufmax)
10960e78d2cSAbhishek Kulkarni {
110a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = cookie_netfs_data;
111fd2421f5SAneesh Kumar K.V 	memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path));
1125d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p get key %llu\n",
1135d385153SJoe Perches 		 &v9inode->vfs_inode, v9inode->qid.path);
114fd2421f5SAneesh Kumar K.V 	return sizeof(v9inode->qid.path);
11560e78d2cSAbhishek Kulkarni }
11660e78d2cSAbhishek Kulkarni 
11760e78d2cSAbhishek Kulkarni static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
11860e78d2cSAbhishek Kulkarni 				      uint64_t *size)
11960e78d2cSAbhishek Kulkarni {
120a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = cookie_netfs_data;
121a78ce05dSAneesh Kumar K.V 	*size = i_size_read(&v9inode->vfs_inode);
12260e78d2cSAbhishek Kulkarni 
1235d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p get attr %llu\n",
1245d385153SJoe Perches 		 &v9inode->vfs_inode, *size);
12560e78d2cSAbhishek Kulkarni }
12660e78d2cSAbhishek Kulkarni 
12760e78d2cSAbhishek Kulkarni static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data,
12860e78d2cSAbhishek Kulkarni 					 void *buffer, uint16_t buflen)
12960e78d2cSAbhishek Kulkarni {
130a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = cookie_netfs_data;
131fd2421f5SAneesh Kumar K.V 	memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version));
1325d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p get aux %u\n",
1335d385153SJoe Perches 		 &v9inode->vfs_inode, v9inode->qid.version);
134fd2421f5SAneesh Kumar K.V 	return sizeof(v9inode->qid.version);
13560e78d2cSAbhishek Kulkarni }
13660e78d2cSAbhishek Kulkarni 
13760e78d2cSAbhishek Kulkarni static enum
13860e78d2cSAbhishek Kulkarni fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
13960e78d2cSAbhishek Kulkarni 					    const void *buffer,
14060e78d2cSAbhishek Kulkarni 					    uint16_t buflen)
14160e78d2cSAbhishek Kulkarni {
142a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = cookie_netfs_data;
14360e78d2cSAbhishek Kulkarni 
144fd2421f5SAneesh Kumar K.V 	if (buflen != sizeof(v9inode->qid.version))
14560e78d2cSAbhishek Kulkarni 		return FSCACHE_CHECKAUX_OBSOLETE;
14660e78d2cSAbhishek Kulkarni 
147fd2421f5SAneesh Kumar K.V 	if (memcmp(buffer, &v9inode->qid.version,
148fd2421f5SAneesh Kumar K.V 		   sizeof(v9inode->qid.version)))
14960e78d2cSAbhishek Kulkarni 		return FSCACHE_CHECKAUX_OBSOLETE;
15060e78d2cSAbhishek Kulkarni 
15160e78d2cSAbhishek Kulkarni 	return FSCACHE_CHECKAUX_OKAY;
15260e78d2cSAbhishek Kulkarni }
15360e78d2cSAbhishek Kulkarni 
15460e78d2cSAbhishek Kulkarni static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data)
15560e78d2cSAbhishek Kulkarni {
156a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = cookie_netfs_data;
15760e78d2cSAbhishek Kulkarni 	struct pagevec pvec;
15860e78d2cSAbhishek Kulkarni 	pgoff_t first;
15960e78d2cSAbhishek Kulkarni 	int loop, nr_pages;
16060e78d2cSAbhishek Kulkarni 
16160e78d2cSAbhishek Kulkarni 	pagevec_init(&pvec, 0);
16260e78d2cSAbhishek Kulkarni 	first = 0;
16360e78d2cSAbhishek Kulkarni 
16460e78d2cSAbhishek Kulkarni 	for (;;) {
165a78ce05dSAneesh Kumar K.V 		nr_pages = pagevec_lookup(&pvec, v9inode->vfs_inode.i_mapping,
16660e78d2cSAbhishek Kulkarni 					  first,
16760e78d2cSAbhishek Kulkarni 					  PAGEVEC_SIZE - pagevec_count(&pvec));
16860e78d2cSAbhishek Kulkarni 		if (!nr_pages)
16960e78d2cSAbhishek Kulkarni 			break;
17060e78d2cSAbhishek Kulkarni 
17160e78d2cSAbhishek Kulkarni 		for (loop = 0; loop < nr_pages; loop++)
17260e78d2cSAbhishek Kulkarni 			ClearPageFsCache(pvec.pages[loop]);
17360e78d2cSAbhishek Kulkarni 
17460e78d2cSAbhishek Kulkarni 		first = pvec.pages[nr_pages - 1]->index + 1;
17560e78d2cSAbhishek Kulkarni 
17660e78d2cSAbhishek Kulkarni 		pvec.nr = nr_pages;
17760e78d2cSAbhishek Kulkarni 		pagevec_release(&pvec);
17860e78d2cSAbhishek Kulkarni 		cond_resched();
17960e78d2cSAbhishek Kulkarni 	}
18060e78d2cSAbhishek Kulkarni }
18160e78d2cSAbhishek Kulkarni 
18260e78d2cSAbhishek Kulkarni const struct fscache_cookie_def v9fs_cache_inode_index_def = {
18360e78d2cSAbhishek Kulkarni 	.name		= "9p.inode",
18460e78d2cSAbhishek Kulkarni 	.type		= FSCACHE_COOKIE_TYPE_DATAFILE,
18560e78d2cSAbhishek Kulkarni 	.get_key	= v9fs_cache_inode_get_key,
18660e78d2cSAbhishek Kulkarni 	.get_attr	= v9fs_cache_inode_get_attr,
18760e78d2cSAbhishek Kulkarni 	.get_aux	= v9fs_cache_inode_get_aux,
18860e78d2cSAbhishek Kulkarni 	.check_aux	= v9fs_cache_inode_check_aux,
18960e78d2cSAbhishek Kulkarni 	.now_uncached	= v9fs_cache_inode_now_uncached,
19060e78d2cSAbhishek Kulkarni };
19160e78d2cSAbhishek Kulkarni 
19260e78d2cSAbhishek Kulkarni void v9fs_cache_inode_get_cookie(struct inode *inode)
19360e78d2cSAbhishek Kulkarni {
194a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode;
19560e78d2cSAbhishek Kulkarni 	struct v9fs_session_info *v9ses;
19660e78d2cSAbhishek Kulkarni 
19760e78d2cSAbhishek Kulkarni 	if (!S_ISREG(inode->i_mode))
19860e78d2cSAbhishek Kulkarni 		return;
19960e78d2cSAbhishek Kulkarni 
200a78ce05dSAneesh Kumar K.V 	v9inode = V9FS_I(inode);
201a78ce05dSAneesh Kumar K.V 	if (v9inode->fscache)
20260e78d2cSAbhishek Kulkarni 		return;
20360e78d2cSAbhishek Kulkarni 
20460e78d2cSAbhishek Kulkarni 	v9ses = v9fs_inode2v9ses(inode);
205a78ce05dSAneesh Kumar K.V 	v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
20660e78d2cSAbhishek Kulkarni 						  &v9fs_cache_inode_index_def,
207a78ce05dSAneesh Kumar K.V 						  v9inode);
20860e78d2cSAbhishek Kulkarni 
2095d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
2105d385153SJoe Perches 		 inode, v9inode->fscache);
21160e78d2cSAbhishek Kulkarni }
21260e78d2cSAbhishek Kulkarni 
21360e78d2cSAbhishek Kulkarni void v9fs_cache_inode_put_cookie(struct inode *inode)
21460e78d2cSAbhishek Kulkarni {
215a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = V9FS_I(inode);
21660e78d2cSAbhishek Kulkarni 
217a78ce05dSAneesh Kumar K.V 	if (!v9inode->fscache)
21860e78d2cSAbhishek Kulkarni 		return;
2195d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n",
2205d385153SJoe Perches 		 inode, v9inode->fscache);
22160e78d2cSAbhishek Kulkarni 
222a78ce05dSAneesh Kumar K.V 	fscache_relinquish_cookie(v9inode->fscache, 0);
223a78ce05dSAneesh Kumar K.V 	v9inode->fscache = NULL;
22460e78d2cSAbhishek Kulkarni }
22560e78d2cSAbhishek Kulkarni 
22660e78d2cSAbhishek Kulkarni void v9fs_cache_inode_flush_cookie(struct inode *inode)
22760e78d2cSAbhishek Kulkarni {
228a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = V9FS_I(inode);
22960e78d2cSAbhishek Kulkarni 
230a78ce05dSAneesh Kumar K.V 	if (!v9inode->fscache)
23160e78d2cSAbhishek Kulkarni 		return;
2325d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n",
2335d385153SJoe Perches 		 inode, v9inode->fscache);
23460e78d2cSAbhishek Kulkarni 
235a78ce05dSAneesh Kumar K.V 	fscache_relinquish_cookie(v9inode->fscache, 1);
236a78ce05dSAneesh Kumar K.V 	v9inode->fscache = NULL;
23760e78d2cSAbhishek Kulkarni }
23860e78d2cSAbhishek Kulkarni 
23960e78d2cSAbhishek Kulkarni void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp)
24060e78d2cSAbhishek Kulkarni {
241a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = V9FS_I(inode);
24260e78d2cSAbhishek Kulkarni 	struct p9_fid *fid;
24360e78d2cSAbhishek Kulkarni 
244a78ce05dSAneesh Kumar K.V 	if (!v9inode->fscache)
24560e78d2cSAbhishek Kulkarni 		return;
24660e78d2cSAbhishek Kulkarni 
247a78ce05dSAneesh Kumar K.V 	spin_lock(&v9inode->fscache_lock);
24860e78d2cSAbhishek Kulkarni 	fid = filp->private_data;
24960e78d2cSAbhishek Kulkarni 	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
25060e78d2cSAbhishek Kulkarni 		v9fs_cache_inode_flush_cookie(inode);
25160e78d2cSAbhishek Kulkarni 	else
25260e78d2cSAbhishek Kulkarni 		v9fs_cache_inode_get_cookie(inode);
25360e78d2cSAbhishek Kulkarni 
254a78ce05dSAneesh Kumar K.V 	spin_unlock(&v9inode->fscache_lock);
25560e78d2cSAbhishek Kulkarni }
25660e78d2cSAbhishek Kulkarni 
25760e78d2cSAbhishek Kulkarni void v9fs_cache_inode_reset_cookie(struct inode *inode)
25860e78d2cSAbhishek Kulkarni {
259a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = V9FS_I(inode);
26060e78d2cSAbhishek Kulkarni 	struct v9fs_session_info *v9ses;
26160e78d2cSAbhishek Kulkarni 	struct fscache_cookie *old;
26260e78d2cSAbhishek Kulkarni 
263a78ce05dSAneesh Kumar K.V 	if (!v9inode->fscache)
26460e78d2cSAbhishek Kulkarni 		return;
26560e78d2cSAbhishek Kulkarni 
266a78ce05dSAneesh Kumar K.V 	old = v9inode->fscache;
26760e78d2cSAbhishek Kulkarni 
268a78ce05dSAneesh Kumar K.V 	spin_lock(&v9inode->fscache_lock);
269a78ce05dSAneesh Kumar K.V 	fscache_relinquish_cookie(v9inode->fscache, 1);
27060e78d2cSAbhishek Kulkarni 
27160e78d2cSAbhishek Kulkarni 	v9ses = v9fs_inode2v9ses(inode);
272a78ce05dSAneesh Kumar K.V 	v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
27360e78d2cSAbhishek Kulkarni 						  &v9fs_cache_inode_index_def,
274a78ce05dSAneesh Kumar K.V 						  v9inode);
2755d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
276a78ce05dSAneesh Kumar K.V 		 inode, old, v9inode->fscache);
27760e78d2cSAbhishek Kulkarni 
278a78ce05dSAneesh Kumar K.V 	spin_unlock(&v9inode->fscache_lock);
27960e78d2cSAbhishek Kulkarni }
28060e78d2cSAbhishek Kulkarni 
28160e78d2cSAbhishek Kulkarni int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
28260e78d2cSAbhishek Kulkarni {
28360e78d2cSAbhishek Kulkarni 	struct inode *inode = page->mapping->host;
284a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = V9FS_I(inode);
28560e78d2cSAbhishek Kulkarni 
286a78ce05dSAneesh Kumar K.V 	BUG_ON(!v9inode->fscache);
28760e78d2cSAbhishek Kulkarni 
288a78ce05dSAneesh Kumar K.V 	return fscache_maybe_release_page(v9inode->fscache, page, gfp);
28960e78d2cSAbhishek Kulkarni }
29060e78d2cSAbhishek Kulkarni 
29160e78d2cSAbhishek Kulkarni void __v9fs_fscache_invalidate_page(struct page *page)
29260e78d2cSAbhishek Kulkarni {
29360e78d2cSAbhishek Kulkarni 	struct inode *inode = page->mapping->host;
294a78ce05dSAneesh Kumar K.V 	struct v9fs_inode *v9inode = V9FS_I(inode);
29560e78d2cSAbhishek Kulkarni 
296a78ce05dSAneesh Kumar K.V 	BUG_ON(!v9inode->fscache);
29760e78d2cSAbhishek Kulkarni 
29860e78d2cSAbhishek Kulkarni 	if (PageFsCache(page)) {
299a78ce05dSAneesh Kumar K.V 		fscache_wait_on_page_write(v9inode->fscache, page);
30060e78d2cSAbhishek Kulkarni 		BUG_ON(!PageLocked(page));
301a78ce05dSAneesh Kumar K.V 		fscache_uncache_page(v9inode->fscache, page);
30260e78d2cSAbhishek Kulkarni 	}
30360e78d2cSAbhishek Kulkarni }
30460e78d2cSAbhishek Kulkarni 
30560e78d2cSAbhishek Kulkarni static void v9fs_vfs_readpage_complete(struct page *page, void *data,
30660e78d2cSAbhishek Kulkarni 				       int error)
30760e78d2cSAbhishek Kulkarni {
30860e78d2cSAbhishek Kulkarni 	if (!error)
30960e78d2cSAbhishek Kulkarni 		SetPageUptodate(page);
31060e78d2cSAbhishek Kulkarni 
31160e78d2cSAbhishek Kulkarni 	unlock_page(page);
31260e78d2cSAbhishek Kulkarni }
31360e78d2cSAbhishek Kulkarni 
31460e78d2cSAbhishek Kulkarni /**
31560e78d2cSAbhishek Kulkarni  * __v9fs_readpage_from_fscache - read a page from cache
31660e78d2cSAbhishek Kulkarni  *
31760e78d2cSAbhishek Kulkarni  * Returns 0 if the pages are in cache and a BIO is submitted,
31860e78d2cSAbhishek Kulkarni  * 1 if the pages are not in cache and -error otherwise.
31960e78d2cSAbhishek Kulkarni  */
32060e78d2cSAbhishek Kulkarni 
32160e78d2cSAbhishek Kulkarni int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
32260e78d2cSAbhishek Kulkarni {
32360e78d2cSAbhishek Kulkarni 	int ret;
324a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = V9FS_I(inode);
32560e78d2cSAbhishek Kulkarni 
3265d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
327a78ce05dSAneesh Kumar K.V 	if (!v9inode->fscache)
32860e78d2cSAbhishek Kulkarni 		return -ENOBUFS;
32960e78d2cSAbhishek Kulkarni 
330a78ce05dSAneesh Kumar K.V 	ret = fscache_read_or_alloc_page(v9inode->fscache,
33160e78d2cSAbhishek Kulkarni 					 page,
33260e78d2cSAbhishek Kulkarni 					 v9fs_vfs_readpage_complete,
33360e78d2cSAbhishek Kulkarni 					 NULL,
33460e78d2cSAbhishek Kulkarni 					 GFP_KERNEL);
33560e78d2cSAbhishek Kulkarni 	switch (ret) {
33660e78d2cSAbhishek Kulkarni 	case -ENOBUFS:
33760e78d2cSAbhishek Kulkarni 	case -ENODATA:
3385d385153SJoe Perches 		p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret);
33960e78d2cSAbhishek Kulkarni 		return 1;
34060e78d2cSAbhishek Kulkarni 	case 0:
3415d385153SJoe Perches 		p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
34260e78d2cSAbhishek Kulkarni 		return ret;
34360e78d2cSAbhishek Kulkarni 	default:
3445d385153SJoe Perches 		p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
34560e78d2cSAbhishek Kulkarni 		return ret;
34660e78d2cSAbhishek Kulkarni 	}
34760e78d2cSAbhishek Kulkarni }
34860e78d2cSAbhishek Kulkarni 
34960e78d2cSAbhishek Kulkarni /**
35060e78d2cSAbhishek Kulkarni  * __v9fs_readpages_from_fscache - read multiple pages from cache
35160e78d2cSAbhishek Kulkarni  *
35260e78d2cSAbhishek Kulkarni  * Returns 0 if the pages are in cache and a BIO is submitted,
35360e78d2cSAbhishek Kulkarni  * 1 if the pages are not in cache and -error otherwise.
35460e78d2cSAbhishek Kulkarni  */
35560e78d2cSAbhishek Kulkarni 
35660e78d2cSAbhishek Kulkarni int __v9fs_readpages_from_fscache(struct inode *inode,
35760e78d2cSAbhishek Kulkarni 				  struct address_space *mapping,
35860e78d2cSAbhishek Kulkarni 				  struct list_head *pages,
35960e78d2cSAbhishek Kulkarni 				  unsigned *nr_pages)
36060e78d2cSAbhishek Kulkarni {
36160e78d2cSAbhishek Kulkarni 	int ret;
362a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = V9FS_I(inode);
36360e78d2cSAbhishek Kulkarni 
3645d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages);
365a78ce05dSAneesh Kumar K.V 	if (!v9inode->fscache)
36660e78d2cSAbhishek Kulkarni 		return -ENOBUFS;
36760e78d2cSAbhishek Kulkarni 
368a78ce05dSAneesh Kumar K.V 	ret = fscache_read_or_alloc_pages(v9inode->fscache,
36960e78d2cSAbhishek Kulkarni 					  mapping, pages, nr_pages,
37060e78d2cSAbhishek Kulkarni 					  v9fs_vfs_readpage_complete,
37160e78d2cSAbhishek Kulkarni 					  NULL,
37260e78d2cSAbhishek Kulkarni 					  mapping_gfp_mask(mapping));
37360e78d2cSAbhishek Kulkarni 	switch (ret) {
37460e78d2cSAbhishek Kulkarni 	case -ENOBUFS:
37560e78d2cSAbhishek Kulkarni 	case -ENODATA:
3765d385153SJoe Perches 		p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret);
37760e78d2cSAbhishek Kulkarni 		return 1;
37860e78d2cSAbhishek Kulkarni 	case 0:
37960e78d2cSAbhishek Kulkarni 		BUG_ON(!list_empty(pages));
38060e78d2cSAbhishek Kulkarni 		BUG_ON(*nr_pages != 0);
3815d385153SJoe Perches 		p9_debug(P9_DEBUG_FSC, "BIO submitted\n");
38260e78d2cSAbhishek Kulkarni 		return ret;
38360e78d2cSAbhishek Kulkarni 	default:
3845d385153SJoe Perches 		p9_debug(P9_DEBUG_FSC, "ret %d\n", ret);
38560e78d2cSAbhishek Kulkarni 		return ret;
38660e78d2cSAbhishek Kulkarni 	}
38760e78d2cSAbhishek Kulkarni }
38860e78d2cSAbhishek Kulkarni 
38960e78d2cSAbhishek Kulkarni /**
39060e78d2cSAbhishek Kulkarni  * __v9fs_readpage_to_fscache - write a page to the cache
39160e78d2cSAbhishek Kulkarni  *
39260e78d2cSAbhishek Kulkarni  */
39360e78d2cSAbhishek Kulkarni 
39460e78d2cSAbhishek Kulkarni void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
39560e78d2cSAbhishek Kulkarni {
39660e78d2cSAbhishek Kulkarni 	int ret;
397a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = V9FS_I(inode);
39860e78d2cSAbhishek Kulkarni 
3995d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
400a78ce05dSAneesh Kumar K.V 	ret = fscache_write_page(v9inode->fscache, page, GFP_KERNEL);
4015d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "ret =  %d\n", ret);
40260e78d2cSAbhishek Kulkarni 	if (ret != 0)
40360e78d2cSAbhishek Kulkarni 		v9fs_uncache_page(inode, page);
40460e78d2cSAbhishek Kulkarni }
4052efda799SAneesh Kumar K.V 
4062efda799SAneesh Kumar K.V /*
4072efda799SAneesh Kumar K.V  * wait for a page to complete writing to the cache
4082efda799SAneesh Kumar K.V  */
4092efda799SAneesh Kumar K.V void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
4102efda799SAneesh Kumar K.V {
411a78ce05dSAneesh Kumar K.V 	const struct v9fs_inode *v9inode = V9FS_I(inode);
4125d385153SJoe Perches 	p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page);
4132efda799SAneesh Kumar K.V 	if (PageFsCache(page))
414a78ce05dSAneesh Kumar K.V 		fscache_wait_on_page_write(v9inode->fscache, page);
4152efda799SAneesh Kumar K.V }
416