From 7a40c83337cb4ff07646ea7c2cc0d6d98be94bff Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Wed, 22 May 2013 09:26:57 -0400 Subject: [PATCH] Linux: Fix tmpfs cache support As of kernel 3.1, tmpfs no longer has a readpage() operation in its address space operations. Some of the cache manager code relies on this, causing an oops if tmpfs is used as backing store for the cache. As a minimal fix, detect that there is no readpage() and disable the optimizations that depend on it. Reviewed-on: http://gerrit.openafs.org/9949 Tested-by: BuildBot Reviewed-by: Derrick Brashear (cherry picked from commit 3767cf8bf420bd59c3426a4287259b1e97178e96) Change-Id: I4fa0f2449eabf4dc82e5450c0b378b9ebe49d848 Reviewed-on: http://gerrit.openafs.org/9950 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Stephan Wiesand --- src/afs/LINUX/osi_vnodeops.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 25e544c..db8dbeb 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -47,6 +47,8 @@ #define MAX_ERRNO 1000L #endif +int cachefs_noreadpage = 0; + extern struct backing_dev_info *afs_backing_dev_info; extern struct vcache *afs_globalVp; @@ -1876,6 +1878,10 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep) if (cacheDiskType != AFS_FCACHE_TYPE_UFS) return 0; + /* No readpage (ex: tmpfs) , skip */ + if (cachefs_noreadpage) + return 0; + /* Can't do anything if the vcache isn't statd , or if the read * crosses a chunk boundary. */ @@ -1935,12 +1941,8 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep) /* Is the dcache we've been given currently up to date */ if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) || - (tdc->dflags & DFFetching)) { - ReleaseWriteLock(&avc->lock); - ReleaseReadLock(&tdc->lock); - afs_PutDCache(tdc); - return 0; - } + (tdc->dflags & DFFetching)) + goto out; /* Update our hint for future abuse */ avc->dchint = tdc; @@ -1950,6 +1952,11 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep) /* XXX - I suspect we should be locking the inodes before we use them! */ AFS_GUNLOCK(); cacheFp = afs_linux_raw_open(&tdc->f.inode); + if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) { + cachefs_noreadpage = 1; + AFS_GLOCK(); + goto out; + } pagevec_init(&lrupv, 0); code = afs_linux_read_cache(cacheFp, pp, tdc->f.chunk, &lrupv, NULL); @@ -1966,6 +1973,12 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep) *codep = code; return 1; + +out: + ReleaseWriteLock(&avc->lock); + ReleaseReadLock(&tdc->lock); + afs_PutDCache(tdc); + return 0; } /* afs_linux_readpage @@ -2307,6 +2320,10 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping, if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return 0; + /* No readpage (ex: tmpfs) , skip */ + if (cachefs_noreadpage) + return 0; + AFS_GLOCK(); if ((code = afs_linux_VerifyVCache(avc, NULL))) { AFS_GUNLOCK(); @@ -2341,14 +2358,20 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping, ObtainReadLock(&tdc->lock); if (!hsame(avc->f.m.DataVersion, tdc->f.versionNo) || (tdc->dflags & DFFetching)) { + goto out; ReleaseReadLock(&tdc->lock); afs_PutDCache(tdc); tdc = NULL; } } AFS_GUNLOCK(); - if (tdc) + if (tdc) { cacheFp = afs_linux_raw_open(&tdc->f.inode); + if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) { + cachefs_noreadpage = 1; + goto out; + } + } } if (tdc && !add_to_page_cache(page, mapping, page->index, @@ -2364,6 +2387,7 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping, if (pagevec_count(&lrupv)) __pagevec_lru_add_file(&lrupv); +out: if (tdc) filp_close(cacheFp, NULL); -- 1.9.4