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