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 kmem_cache *vcookie_cache; 3760e78d2cSAbhishek Kulkarni 3860e78d2cSAbhishek Kulkarni struct fscache_netfs v9fs_cache_netfs = { 3960e78d2cSAbhishek Kulkarni .name = "9p", 4060e78d2cSAbhishek Kulkarni .version = 0, 4160e78d2cSAbhishek Kulkarni }; 4260e78d2cSAbhishek Kulkarni 4360e78d2cSAbhishek Kulkarni static void init_once(void *foo) 4460e78d2cSAbhishek Kulkarni { 4560e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = (struct v9fs_cookie *) foo; 4660e78d2cSAbhishek Kulkarni vcookie->fscache = NULL; 4760e78d2cSAbhishek Kulkarni vcookie->qid = NULL; 4860e78d2cSAbhishek Kulkarni inode_init_once(&vcookie->inode); 4960e78d2cSAbhishek Kulkarni } 5060e78d2cSAbhishek Kulkarni 5160e78d2cSAbhishek Kulkarni /** 5260e78d2cSAbhishek Kulkarni * v9fs_init_vcookiecache - initialize a cache for vcookies to maintain 5360e78d2cSAbhishek Kulkarni * vcookie to inode mapping 5460e78d2cSAbhishek Kulkarni * 5560e78d2cSAbhishek Kulkarni * Returns 0 on success. 5660e78d2cSAbhishek Kulkarni */ 5760e78d2cSAbhishek Kulkarni 5860e78d2cSAbhishek Kulkarni static int v9fs_init_vcookiecache(void) 5960e78d2cSAbhishek Kulkarni { 6060e78d2cSAbhishek Kulkarni vcookie_cache = kmem_cache_create("vcookie_cache", 6160e78d2cSAbhishek Kulkarni sizeof(struct v9fs_cookie), 6260e78d2cSAbhishek Kulkarni 0, (SLAB_RECLAIM_ACCOUNT| 6360e78d2cSAbhishek Kulkarni SLAB_MEM_SPREAD), 6460e78d2cSAbhishek Kulkarni init_once); 6560e78d2cSAbhishek Kulkarni if (!vcookie_cache) 6660e78d2cSAbhishek Kulkarni return -ENOMEM; 6760e78d2cSAbhishek Kulkarni 6860e78d2cSAbhishek Kulkarni return 0; 6960e78d2cSAbhishek Kulkarni } 7060e78d2cSAbhishek Kulkarni 7160e78d2cSAbhishek Kulkarni /** 7260e78d2cSAbhishek Kulkarni * v9fs_destroy_vcookiecache - destroy the cache of vcookies 7360e78d2cSAbhishek Kulkarni * 7460e78d2cSAbhishek Kulkarni */ 7560e78d2cSAbhishek Kulkarni 7660e78d2cSAbhishek Kulkarni static void v9fs_destroy_vcookiecache(void) 7760e78d2cSAbhishek Kulkarni { 7860e78d2cSAbhishek Kulkarni kmem_cache_destroy(vcookie_cache); 7960e78d2cSAbhishek Kulkarni } 8060e78d2cSAbhishek Kulkarni 8160e78d2cSAbhishek Kulkarni int __v9fs_cache_register(void) 8260e78d2cSAbhishek Kulkarni { 8360e78d2cSAbhishek Kulkarni int ret; 8460e78d2cSAbhishek Kulkarni ret = v9fs_init_vcookiecache(); 8560e78d2cSAbhishek Kulkarni if (ret < 0) 8660e78d2cSAbhishek Kulkarni return ret; 8760e78d2cSAbhishek Kulkarni 8860e78d2cSAbhishek Kulkarni return fscache_register_netfs(&v9fs_cache_netfs); 8960e78d2cSAbhishek Kulkarni } 9060e78d2cSAbhishek Kulkarni 9160e78d2cSAbhishek Kulkarni void __v9fs_cache_unregister(void) 9260e78d2cSAbhishek Kulkarni { 9360e78d2cSAbhishek Kulkarni v9fs_destroy_vcookiecache(); 9460e78d2cSAbhishek Kulkarni fscache_unregister_netfs(&v9fs_cache_netfs); 9560e78d2cSAbhishek Kulkarni } 9660e78d2cSAbhishek Kulkarni 9760e78d2cSAbhishek Kulkarni /** 9860e78d2cSAbhishek Kulkarni * v9fs_random_cachetag - Generate a random tag to be associated 9960e78d2cSAbhishek Kulkarni * with a new cache session. 10060e78d2cSAbhishek Kulkarni * 10160e78d2cSAbhishek Kulkarni * The value of jiffies is used for a fairly randomly cache tag. 10260e78d2cSAbhishek Kulkarni */ 10360e78d2cSAbhishek Kulkarni 10460e78d2cSAbhishek Kulkarni static 10560e78d2cSAbhishek Kulkarni int v9fs_random_cachetag(struct v9fs_session_info *v9ses) 10660e78d2cSAbhishek Kulkarni { 10760e78d2cSAbhishek Kulkarni v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL); 10860e78d2cSAbhishek Kulkarni if (!v9ses->cachetag) 10960e78d2cSAbhishek Kulkarni return -ENOMEM; 11060e78d2cSAbhishek Kulkarni 11160e78d2cSAbhishek Kulkarni return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); 11260e78d2cSAbhishek Kulkarni } 11360e78d2cSAbhishek Kulkarni 11460e78d2cSAbhishek Kulkarni static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data, 11560e78d2cSAbhishek Kulkarni void *buffer, uint16_t bufmax) 11660e78d2cSAbhishek Kulkarni { 11760e78d2cSAbhishek Kulkarni struct v9fs_session_info *v9ses; 11860e78d2cSAbhishek Kulkarni uint16_t klen = 0; 11960e78d2cSAbhishek Kulkarni 12060e78d2cSAbhishek Kulkarni v9ses = (struct v9fs_session_info *)cookie_netfs_data; 12160e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "session %p buf %p size %u", v9ses, 12260e78d2cSAbhishek Kulkarni buffer, bufmax); 12360e78d2cSAbhishek Kulkarni 12460e78d2cSAbhishek Kulkarni if (v9ses->cachetag) 12560e78d2cSAbhishek Kulkarni klen = strlen(v9ses->cachetag); 12660e78d2cSAbhishek Kulkarni 12760e78d2cSAbhishek Kulkarni if (klen > bufmax) 12860e78d2cSAbhishek Kulkarni return 0; 12960e78d2cSAbhishek Kulkarni 13060e78d2cSAbhishek Kulkarni memcpy(buffer, v9ses->cachetag, klen); 13160e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "cache session tag %s", v9ses->cachetag); 13260e78d2cSAbhishek Kulkarni return klen; 13360e78d2cSAbhishek Kulkarni } 13460e78d2cSAbhishek Kulkarni 13560e78d2cSAbhishek Kulkarni const struct fscache_cookie_def v9fs_cache_session_index_def = { 13660e78d2cSAbhishek Kulkarni .name = "9P.session", 13760e78d2cSAbhishek Kulkarni .type = FSCACHE_COOKIE_TYPE_INDEX, 13860e78d2cSAbhishek Kulkarni .get_key = v9fs_cache_session_get_key, 13960e78d2cSAbhishek Kulkarni }; 14060e78d2cSAbhishek Kulkarni 14160e78d2cSAbhishek Kulkarni void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) 14260e78d2cSAbhishek Kulkarni { 14360e78d2cSAbhishek Kulkarni /* If no cache session tag was specified, we generate a random one. */ 14460e78d2cSAbhishek Kulkarni if (!v9ses->cachetag) 14560e78d2cSAbhishek Kulkarni v9fs_random_cachetag(v9ses); 14660e78d2cSAbhishek Kulkarni 14760e78d2cSAbhishek Kulkarni v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, 14860e78d2cSAbhishek Kulkarni &v9fs_cache_session_index_def, 14960e78d2cSAbhishek Kulkarni v9ses); 15060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "session %p get cookie %p", v9ses, 15160e78d2cSAbhishek Kulkarni v9ses->fscache); 15260e78d2cSAbhishek Kulkarni } 15360e78d2cSAbhishek Kulkarni 15460e78d2cSAbhishek Kulkarni void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) 15560e78d2cSAbhishek Kulkarni { 15660e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "session %p put cookie %p", v9ses, 15760e78d2cSAbhishek Kulkarni v9ses->fscache); 15860e78d2cSAbhishek Kulkarni fscache_relinquish_cookie(v9ses->fscache, 0); 15960e78d2cSAbhishek Kulkarni v9ses->fscache = NULL; 16060e78d2cSAbhishek Kulkarni } 16160e78d2cSAbhishek Kulkarni 16260e78d2cSAbhishek Kulkarni 16360e78d2cSAbhishek Kulkarni static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data, 16460e78d2cSAbhishek Kulkarni void *buffer, uint16_t bufmax) 16560e78d2cSAbhishek Kulkarni { 16660e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = cookie_netfs_data; 16760e78d2cSAbhishek Kulkarni memcpy(buffer, &vcookie->qid->path, sizeof(vcookie->qid->path)); 16860e78d2cSAbhishek Kulkarni 16960e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &vcookie->inode, 17060e78d2cSAbhishek Kulkarni vcookie->qid->path); 17160e78d2cSAbhishek Kulkarni return sizeof(vcookie->qid->path); 17260e78d2cSAbhishek Kulkarni } 17360e78d2cSAbhishek Kulkarni 17460e78d2cSAbhishek Kulkarni static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, 17560e78d2cSAbhishek Kulkarni uint64_t *size) 17660e78d2cSAbhishek Kulkarni { 17760e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = cookie_netfs_data; 17860e78d2cSAbhishek Kulkarni *size = i_size_read(&vcookie->inode); 17960e78d2cSAbhishek Kulkarni 18060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p get attr %llu", &vcookie->inode, 18160e78d2cSAbhishek Kulkarni *size); 18260e78d2cSAbhishek Kulkarni } 18360e78d2cSAbhishek Kulkarni 18460e78d2cSAbhishek Kulkarni static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, 18560e78d2cSAbhishek Kulkarni void *buffer, uint16_t buflen) 18660e78d2cSAbhishek Kulkarni { 18760e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = cookie_netfs_data; 18860e78d2cSAbhishek Kulkarni memcpy(buffer, &vcookie->qid->version, sizeof(vcookie->qid->version)); 18960e78d2cSAbhishek Kulkarni 19060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &vcookie->inode, 19160e78d2cSAbhishek Kulkarni vcookie->qid->version); 19260e78d2cSAbhishek Kulkarni return sizeof(vcookie->qid->version); 19360e78d2cSAbhishek Kulkarni } 19460e78d2cSAbhishek Kulkarni 19560e78d2cSAbhishek Kulkarni static enum 19660e78d2cSAbhishek Kulkarni fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, 19760e78d2cSAbhishek Kulkarni const void *buffer, 19860e78d2cSAbhishek Kulkarni uint16_t buflen) 19960e78d2cSAbhishek Kulkarni { 20060e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = cookie_netfs_data; 20160e78d2cSAbhishek Kulkarni 20260e78d2cSAbhishek Kulkarni if (buflen != sizeof(vcookie->qid->version)) 20360e78d2cSAbhishek Kulkarni return FSCACHE_CHECKAUX_OBSOLETE; 20460e78d2cSAbhishek Kulkarni 20560e78d2cSAbhishek Kulkarni if (memcmp(buffer, &vcookie->qid->version, 20660e78d2cSAbhishek Kulkarni sizeof(vcookie->qid->version))) 20760e78d2cSAbhishek Kulkarni return FSCACHE_CHECKAUX_OBSOLETE; 20860e78d2cSAbhishek Kulkarni 20960e78d2cSAbhishek Kulkarni return FSCACHE_CHECKAUX_OKAY; 21060e78d2cSAbhishek Kulkarni } 21160e78d2cSAbhishek Kulkarni 21260e78d2cSAbhishek Kulkarni static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data) 21360e78d2cSAbhishek Kulkarni { 21460e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = cookie_netfs_data; 21560e78d2cSAbhishek Kulkarni struct pagevec pvec; 21660e78d2cSAbhishek Kulkarni pgoff_t first; 21760e78d2cSAbhishek Kulkarni int loop, nr_pages; 21860e78d2cSAbhishek Kulkarni 21960e78d2cSAbhishek Kulkarni pagevec_init(&pvec, 0); 22060e78d2cSAbhishek Kulkarni first = 0; 22160e78d2cSAbhishek Kulkarni 22260e78d2cSAbhishek Kulkarni for (;;) { 22360e78d2cSAbhishek Kulkarni nr_pages = pagevec_lookup(&pvec, vcookie->inode.i_mapping, 22460e78d2cSAbhishek Kulkarni first, 22560e78d2cSAbhishek Kulkarni PAGEVEC_SIZE - pagevec_count(&pvec)); 22660e78d2cSAbhishek Kulkarni if (!nr_pages) 22760e78d2cSAbhishek Kulkarni break; 22860e78d2cSAbhishek Kulkarni 22960e78d2cSAbhishek Kulkarni for (loop = 0; loop < nr_pages; loop++) 23060e78d2cSAbhishek Kulkarni ClearPageFsCache(pvec.pages[loop]); 23160e78d2cSAbhishek Kulkarni 23260e78d2cSAbhishek Kulkarni first = pvec.pages[nr_pages - 1]->index + 1; 23360e78d2cSAbhishek Kulkarni 23460e78d2cSAbhishek Kulkarni pvec.nr = nr_pages; 23560e78d2cSAbhishek Kulkarni pagevec_release(&pvec); 23660e78d2cSAbhishek Kulkarni cond_resched(); 23760e78d2cSAbhishek Kulkarni } 23860e78d2cSAbhishek Kulkarni } 23960e78d2cSAbhishek Kulkarni 24060e78d2cSAbhishek Kulkarni const struct fscache_cookie_def v9fs_cache_inode_index_def = { 24160e78d2cSAbhishek Kulkarni .name = "9p.inode", 24260e78d2cSAbhishek Kulkarni .type = FSCACHE_COOKIE_TYPE_DATAFILE, 24360e78d2cSAbhishek Kulkarni .get_key = v9fs_cache_inode_get_key, 24460e78d2cSAbhishek Kulkarni .get_attr = v9fs_cache_inode_get_attr, 24560e78d2cSAbhishek Kulkarni .get_aux = v9fs_cache_inode_get_aux, 24660e78d2cSAbhishek Kulkarni .check_aux = v9fs_cache_inode_check_aux, 24760e78d2cSAbhishek Kulkarni .now_uncached = v9fs_cache_inode_now_uncached, 24860e78d2cSAbhishek Kulkarni }; 24960e78d2cSAbhishek Kulkarni 25060e78d2cSAbhishek Kulkarni void v9fs_cache_inode_get_cookie(struct inode *inode) 25160e78d2cSAbhishek Kulkarni { 25260e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie; 25360e78d2cSAbhishek Kulkarni struct v9fs_session_info *v9ses; 25460e78d2cSAbhishek Kulkarni 25560e78d2cSAbhishek Kulkarni if (!S_ISREG(inode->i_mode)) 25660e78d2cSAbhishek Kulkarni return; 25760e78d2cSAbhishek Kulkarni 25860e78d2cSAbhishek Kulkarni vcookie = v9fs_inode2cookie(inode); 25960e78d2cSAbhishek Kulkarni if (vcookie->fscache) 26060e78d2cSAbhishek Kulkarni return; 26160e78d2cSAbhishek Kulkarni 26260e78d2cSAbhishek Kulkarni v9ses = v9fs_inode2v9ses(inode); 26360e78d2cSAbhishek Kulkarni vcookie->fscache = fscache_acquire_cookie(v9ses->fscache, 26460e78d2cSAbhishek Kulkarni &v9fs_cache_inode_index_def, 26560e78d2cSAbhishek Kulkarni vcookie); 26660e78d2cSAbhishek Kulkarni 26760e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p get cookie %p", inode, 26860e78d2cSAbhishek Kulkarni vcookie->fscache); 26960e78d2cSAbhishek Kulkarni } 27060e78d2cSAbhishek Kulkarni 27160e78d2cSAbhishek Kulkarni void v9fs_cache_inode_put_cookie(struct inode *inode) 27260e78d2cSAbhishek Kulkarni { 27360e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 27460e78d2cSAbhishek Kulkarni 27560e78d2cSAbhishek Kulkarni if (!vcookie->fscache) 27660e78d2cSAbhishek Kulkarni return; 27760e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p put cookie %p", inode, 27860e78d2cSAbhishek Kulkarni vcookie->fscache); 27960e78d2cSAbhishek Kulkarni 28060e78d2cSAbhishek Kulkarni fscache_relinquish_cookie(vcookie->fscache, 0); 28160e78d2cSAbhishek Kulkarni vcookie->fscache = NULL; 28260e78d2cSAbhishek Kulkarni } 28360e78d2cSAbhishek Kulkarni 28460e78d2cSAbhishek Kulkarni void v9fs_cache_inode_flush_cookie(struct inode *inode) 28560e78d2cSAbhishek Kulkarni { 28660e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 28760e78d2cSAbhishek Kulkarni 28860e78d2cSAbhishek Kulkarni if (!vcookie->fscache) 28960e78d2cSAbhishek Kulkarni return; 29060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p flush cookie %p", inode, 29160e78d2cSAbhishek Kulkarni vcookie->fscache); 29260e78d2cSAbhishek Kulkarni 29360e78d2cSAbhishek Kulkarni fscache_relinquish_cookie(vcookie->fscache, 1); 29460e78d2cSAbhishek Kulkarni vcookie->fscache = NULL; 29560e78d2cSAbhishek Kulkarni } 29660e78d2cSAbhishek Kulkarni 29760e78d2cSAbhishek Kulkarni void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) 29860e78d2cSAbhishek Kulkarni { 29960e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 30060e78d2cSAbhishek Kulkarni struct p9_fid *fid; 30160e78d2cSAbhishek Kulkarni 30260e78d2cSAbhishek Kulkarni if (!vcookie->fscache) 30360e78d2cSAbhishek Kulkarni return; 30460e78d2cSAbhishek Kulkarni 30560e78d2cSAbhishek Kulkarni spin_lock(&vcookie->lock); 30660e78d2cSAbhishek Kulkarni fid = filp->private_data; 30760e78d2cSAbhishek Kulkarni if ((filp->f_flags & O_ACCMODE) != O_RDONLY) 30860e78d2cSAbhishek Kulkarni v9fs_cache_inode_flush_cookie(inode); 30960e78d2cSAbhishek Kulkarni else 31060e78d2cSAbhishek Kulkarni v9fs_cache_inode_get_cookie(inode); 31160e78d2cSAbhishek Kulkarni 31260e78d2cSAbhishek Kulkarni spin_unlock(&vcookie->lock); 31360e78d2cSAbhishek Kulkarni } 31460e78d2cSAbhishek Kulkarni 31560e78d2cSAbhishek Kulkarni void v9fs_cache_inode_reset_cookie(struct inode *inode) 31660e78d2cSAbhishek Kulkarni { 31760e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 31860e78d2cSAbhishek Kulkarni struct v9fs_session_info *v9ses; 31960e78d2cSAbhishek Kulkarni struct fscache_cookie *old; 32060e78d2cSAbhishek Kulkarni 32160e78d2cSAbhishek Kulkarni if (!vcookie->fscache) 32260e78d2cSAbhishek Kulkarni return; 32360e78d2cSAbhishek Kulkarni 32460e78d2cSAbhishek Kulkarni old = vcookie->fscache; 32560e78d2cSAbhishek Kulkarni 32660e78d2cSAbhishek Kulkarni spin_lock(&vcookie->lock); 32760e78d2cSAbhishek Kulkarni fscache_relinquish_cookie(vcookie->fscache, 1); 32860e78d2cSAbhishek Kulkarni 32960e78d2cSAbhishek Kulkarni v9ses = v9fs_inode2v9ses(inode); 33060e78d2cSAbhishek Kulkarni vcookie->fscache = fscache_acquire_cookie(v9ses->fscache, 33160e78d2cSAbhishek Kulkarni &v9fs_cache_inode_index_def, 33260e78d2cSAbhishek Kulkarni vcookie); 33360e78d2cSAbhishek Kulkarni 33460e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p", 33560e78d2cSAbhishek Kulkarni inode, old, vcookie->fscache); 33660e78d2cSAbhishek Kulkarni 33760e78d2cSAbhishek Kulkarni spin_unlock(&vcookie->lock); 33860e78d2cSAbhishek Kulkarni } 33960e78d2cSAbhishek Kulkarni 34060e78d2cSAbhishek Kulkarni int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) 34160e78d2cSAbhishek Kulkarni { 34260e78d2cSAbhishek Kulkarni struct inode *inode = page->mapping->host; 34360e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 34460e78d2cSAbhishek Kulkarni 34560e78d2cSAbhishek Kulkarni BUG_ON(!vcookie->fscache); 34660e78d2cSAbhishek Kulkarni 3476f054164SDavid Howells return fscache_maybe_release_page(vcookie->fscache, page, gfp); 34860e78d2cSAbhishek Kulkarni } 34960e78d2cSAbhishek Kulkarni 35060e78d2cSAbhishek Kulkarni void __v9fs_fscache_invalidate_page(struct page *page) 35160e78d2cSAbhishek Kulkarni { 35260e78d2cSAbhishek Kulkarni struct inode *inode = page->mapping->host; 35360e78d2cSAbhishek Kulkarni struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 35460e78d2cSAbhishek Kulkarni 35560e78d2cSAbhishek Kulkarni BUG_ON(!vcookie->fscache); 35660e78d2cSAbhishek Kulkarni 35760e78d2cSAbhishek Kulkarni if (PageFsCache(page)) { 35860e78d2cSAbhishek Kulkarni fscache_wait_on_page_write(vcookie->fscache, page); 35960e78d2cSAbhishek Kulkarni BUG_ON(!PageLocked(page)); 36060e78d2cSAbhishek Kulkarni fscache_uncache_page(vcookie->fscache, page); 36160e78d2cSAbhishek Kulkarni } 36260e78d2cSAbhishek Kulkarni } 36360e78d2cSAbhishek Kulkarni 36460e78d2cSAbhishek Kulkarni static void v9fs_vfs_readpage_complete(struct page *page, void *data, 36560e78d2cSAbhishek Kulkarni int error) 36660e78d2cSAbhishek Kulkarni { 36760e78d2cSAbhishek Kulkarni if (!error) 36860e78d2cSAbhishek Kulkarni SetPageUptodate(page); 36960e78d2cSAbhishek Kulkarni 37060e78d2cSAbhishek Kulkarni unlock_page(page); 37160e78d2cSAbhishek Kulkarni } 37260e78d2cSAbhishek Kulkarni 37360e78d2cSAbhishek Kulkarni /** 37460e78d2cSAbhishek Kulkarni * __v9fs_readpage_from_fscache - read a page from cache 37560e78d2cSAbhishek Kulkarni * 37660e78d2cSAbhishek Kulkarni * Returns 0 if the pages are in cache and a BIO is submitted, 37760e78d2cSAbhishek Kulkarni * 1 if the pages are not in cache and -error otherwise. 37860e78d2cSAbhishek Kulkarni */ 37960e78d2cSAbhishek Kulkarni 38060e78d2cSAbhishek Kulkarni int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page) 38160e78d2cSAbhishek Kulkarni { 38260e78d2cSAbhishek Kulkarni int ret; 38360e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 38460e78d2cSAbhishek Kulkarni 38560e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); 38660e78d2cSAbhishek Kulkarni if (!vcookie->fscache) 38760e78d2cSAbhishek Kulkarni return -ENOBUFS; 38860e78d2cSAbhishek Kulkarni 38960e78d2cSAbhishek Kulkarni ret = fscache_read_or_alloc_page(vcookie->fscache, 39060e78d2cSAbhishek Kulkarni page, 39160e78d2cSAbhishek Kulkarni v9fs_vfs_readpage_complete, 39260e78d2cSAbhishek Kulkarni NULL, 39360e78d2cSAbhishek Kulkarni GFP_KERNEL); 39460e78d2cSAbhishek Kulkarni switch (ret) { 39560e78d2cSAbhishek Kulkarni case -ENOBUFS: 39660e78d2cSAbhishek Kulkarni case -ENODATA: 39760e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "page/inode not in cache %d", ret); 39860e78d2cSAbhishek Kulkarni return 1; 39960e78d2cSAbhishek Kulkarni case 0: 40060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted"); 40160e78d2cSAbhishek Kulkarni return ret; 40260e78d2cSAbhishek Kulkarni default: 40360e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret); 40460e78d2cSAbhishek Kulkarni return ret; 40560e78d2cSAbhishek Kulkarni } 40660e78d2cSAbhishek Kulkarni } 40760e78d2cSAbhishek Kulkarni 40860e78d2cSAbhishek Kulkarni /** 40960e78d2cSAbhishek Kulkarni * __v9fs_readpages_from_fscache - read multiple pages from cache 41060e78d2cSAbhishek Kulkarni * 41160e78d2cSAbhishek Kulkarni * Returns 0 if the pages are in cache and a BIO is submitted, 41260e78d2cSAbhishek Kulkarni * 1 if the pages are not in cache and -error otherwise. 41360e78d2cSAbhishek Kulkarni */ 41460e78d2cSAbhishek Kulkarni 41560e78d2cSAbhishek Kulkarni int __v9fs_readpages_from_fscache(struct inode *inode, 41660e78d2cSAbhishek Kulkarni struct address_space *mapping, 41760e78d2cSAbhishek Kulkarni struct list_head *pages, 41860e78d2cSAbhishek Kulkarni unsigned *nr_pages) 41960e78d2cSAbhishek Kulkarni { 42060e78d2cSAbhishek Kulkarni int ret; 42160e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 42260e78d2cSAbhishek Kulkarni 42360e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p pages %u", inode, *nr_pages); 42460e78d2cSAbhishek Kulkarni if (!vcookie->fscache) 42560e78d2cSAbhishek Kulkarni return -ENOBUFS; 42660e78d2cSAbhishek Kulkarni 42760e78d2cSAbhishek Kulkarni ret = fscache_read_or_alloc_pages(vcookie->fscache, 42860e78d2cSAbhishek Kulkarni mapping, pages, nr_pages, 42960e78d2cSAbhishek Kulkarni v9fs_vfs_readpage_complete, 43060e78d2cSAbhishek Kulkarni NULL, 43160e78d2cSAbhishek Kulkarni mapping_gfp_mask(mapping)); 43260e78d2cSAbhishek Kulkarni switch (ret) { 43360e78d2cSAbhishek Kulkarni case -ENOBUFS: 43460e78d2cSAbhishek Kulkarni case -ENODATA: 43560e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "pages/inodes not in cache %d", ret); 43660e78d2cSAbhishek Kulkarni return 1; 43760e78d2cSAbhishek Kulkarni case 0: 43860e78d2cSAbhishek Kulkarni BUG_ON(!list_empty(pages)); 43960e78d2cSAbhishek Kulkarni BUG_ON(*nr_pages != 0); 44060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted"); 44160e78d2cSAbhishek Kulkarni return ret; 44260e78d2cSAbhishek Kulkarni default: 44360e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret); 44460e78d2cSAbhishek Kulkarni return ret; 44560e78d2cSAbhishek Kulkarni } 44660e78d2cSAbhishek Kulkarni } 44760e78d2cSAbhishek Kulkarni 44860e78d2cSAbhishek Kulkarni /** 44960e78d2cSAbhishek Kulkarni * __v9fs_readpage_to_fscache - write a page to the cache 45060e78d2cSAbhishek Kulkarni * 45160e78d2cSAbhishek Kulkarni */ 45260e78d2cSAbhishek Kulkarni 45360e78d2cSAbhishek Kulkarni void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page) 45460e78d2cSAbhishek Kulkarni { 45560e78d2cSAbhishek Kulkarni int ret; 45660e78d2cSAbhishek Kulkarni const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 45760e78d2cSAbhishek Kulkarni 45860e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); 45960e78d2cSAbhishek Kulkarni ret = fscache_write_page(vcookie->fscache, page, GFP_KERNEL); 46060e78d2cSAbhishek Kulkarni P9_DPRINTK(P9_DEBUG_FSC, "ret = %d", ret); 46160e78d2cSAbhishek Kulkarni if (ret != 0) 46260e78d2cSAbhishek Kulkarni v9fs_uncache_page(inode, page); 46360e78d2cSAbhishek Kulkarni } 4642efda799SAneesh Kumar K.V 4652efda799SAneesh Kumar K.V /* 4662efda799SAneesh Kumar K.V * wait for a page to complete writing to the cache 4672efda799SAneesh Kumar K.V */ 4682efda799SAneesh Kumar K.V void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page) 4692efda799SAneesh Kumar K.V { 4702efda799SAneesh Kumar K.V const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode); 4712efda799SAneesh Kumar K.V P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); 4722efda799SAneesh Kumar K.V if (PageFsCache(page)) 4732efda799SAneesh Kumar K.V fscache_wait_on_page_write(vcookie->fscache, page); 4742efda799SAneesh Kumar K.V } 475