aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c4
-rw-r--r--fs/nfs/file.c13
-rw-r--r--fs/nfs/internal.h3
-rw-r--r--fs/nfs/nfsroot.c2
-rw-r--r--fs/nfs/write.c30
5 files changed, 34 insertions, 18 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 067a051397ba..29539ceeb745 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1701,7 +1701,7 @@ static void nfs_access_free_list(struct list_head *head)
1701 } 1701 }
1702} 1702}
1703 1703
1704int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) 1704int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
1705{ 1705{
1706 LIST_HEAD(head); 1706 LIST_HEAD(head);
1707 struct nfs_inode *nfsi; 1707 struct nfs_inode *nfsi;
@@ -1944,7 +1944,7 @@ int nfs_permission(struct inode *inode, int mask)
1944 if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) 1944 if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
1945 goto out; 1945 goto out;
1946 /* Is this sys_access() ? */ 1946 /* Is this sys_access() ? */
1947 if (mask & MAY_ACCESS) 1947 if (mask & (MAY_ACCESS | MAY_CHDIR))
1948 goto force_lookup; 1948 goto force_lookup;
1949 1949
1950 switch (inode->i_mode & S_IFMT) { 1950 switch (inode->i_mode & S_IFMT) {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f36581cd4767..2d141a74ae82 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -27,6 +27,7 @@
27#include <linux/pagemap.h> 27#include <linux/pagemap.h>
28#include <linux/aio.h> 28#include <linux/aio.h>
29#include <linux/gfp.h> 29#include <linux/gfp.h>
30#include <linux/swap.h>
30 31
31#include <asm/uaccess.h> 32#include <asm/uaccess.h>
32#include <asm/system.h> 33#include <asm/system.h>
@@ -484,11 +485,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset)
484 */ 485 */
485static int nfs_release_page(struct page *page, gfp_t gfp) 486static int nfs_release_page(struct page *page, gfp_t gfp)
486{ 487{
488 struct address_space *mapping = page->mapping;
489
487 dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); 490 dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
488 491
489 /* Only do I/O if gfp is a superset of GFP_KERNEL */ 492 /* Only do I/O if gfp is a superset of GFP_KERNEL */
490 if ((gfp & GFP_KERNEL) == GFP_KERNEL) 493 if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
491 nfs_wb_page(page->mapping->host, page); 494 int how = FLUSH_SYNC;
495
496 /* Don't let kswapd deadlock waiting for OOM RPC calls */
497 if (current_is_kswapd())
498 how = 0;
499 nfs_commit_inode(mapping->host, how);
500 }
492 /* If PagePrivate() is set, then the page is not freeable */ 501 /* If PagePrivate() is set, then the page is not freeable */
493 if (PagePrivate(page)) 502 if (PagePrivate(page))
494 return 0; 503 return 0;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 699725fee34f..4c2150d86714 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -205,7 +205,8 @@ extern struct rpc_procinfo nfs4_procedures[];
205void nfs_close_context(struct nfs_open_context *ctx, int is_sync); 205void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
206 206
207/* dir.c */ 207/* dir.c */
208extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); 208extern int nfs_access_cache_shrinker(struct shrinker *shrink,
209 int nr_to_scan, gfp_t gfp_mask);
209 210
210/* inode.c */ 211/* inode.c */
211extern struct workqueue_struct *nfsiod_workqueue; 212extern struct workqueue_struct *nfsiod_workqueue;
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 6bd19d843af7..df101d9f546a 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -105,7 +105,7 @@ static char nfs_root_name[256] __initdata = "";
105static __be32 servaddr __initdata = 0; 105static __be32 servaddr __initdata = 0;
106 106
107/* Name of directory to mount */ 107/* Name of directory to mount */
108static char nfs_export_path[NFS_MAXPATHLEN] __initdata = { 0, }; 108static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, };
109 109
110/* NFS-related data */ 110/* NFS-related data */
111static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */ 111static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 5eccea127cac..874972d9427c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -222,7 +222,7 @@ static void nfs_end_page_writeback(struct page *page)
222 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); 222 clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC);
223} 223}
224 224
225static struct nfs_page *nfs_find_and_lock_request(struct page *page) 225static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblock)
226{ 226{
227 struct inode *inode = page->mapping->host; 227 struct inode *inode = page->mapping->host;
228 struct nfs_page *req; 228 struct nfs_page *req;
@@ -241,7 +241,10 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page)
241 * request as dirty (in which case we don't care). 241 * request as dirty (in which case we don't care).
242 */ 242 */
243 spin_unlock(&inode->i_lock); 243 spin_unlock(&inode->i_lock);
244 ret = nfs_wait_on_request(req); 244 if (!nonblock)
245 ret = nfs_wait_on_request(req);
246 else
247 ret = -EAGAIN;
245 nfs_release_request(req); 248 nfs_release_request(req);
246 if (ret != 0) 249 if (ret != 0)
247 return ERR_PTR(ret); 250 return ERR_PTR(ret);
@@ -256,12 +259,12 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page)
256 * May return an error if the user signalled nfs_wait_on_request(). 259 * May return an error if the user signalled nfs_wait_on_request().
257 */ 260 */
258static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, 261static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
259 struct page *page) 262 struct page *page, bool nonblock)
260{ 263{
261 struct nfs_page *req; 264 struct nfs_page *req;
262 int ret = 0; 265 int ret = 0;
263 266
264 req = nfs_find_and_lock_request(page); 267 req = nfs_find_and_lock_request(page, nonblock);
265 if (!req) 268 if (!req)
266 goto out; 269 goto out;
267 ret = PTR_ERR(req); 270 ret = PTR_ERR(req);
@@ -283,12 +286,20 @@ out:
283static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) 286static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio)
284{ 287{
285 struct inode *inode = page->mapping->host; 288 struct inode *inode = page->mapping->host;
289 int ret;
286 290
287 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); 291 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
288 nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); 292 nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
289 293
290 nfs_pageio_cond_complete(pgio, page->index); 294 nfs_pageio_cond_complete(pgio, page->index);
291 return nfs_page_async_flush(pgio, page); 295 ret = nfs_page_async_flush(pgio, page,
296 wbc->sync_mode == WB_SYNC_NONE ||
297 wbc->nonblocking != 0);
298 if (ret == -EAGAIN) {
299 redirty_page_for_writepage(wbc, page);
300 ret = 0;
301 }
302 return ret;
292} 303}
293 304
294/* 305/*
@@ -1382,7 +1393,7 @@ static const struct rpc_call_ops nfs_commit_ops = {
1382 .rpc_release = nfs_commit_release, 1393 .rpc_release = nfs_commit_release,
1383}; 1394};
1384 1395
1385static int nfs_commit_inode(struct inode *inode, int how) 1396int nfs_commit_inode(struct inode *inode, int how)
1386{ 1397{
1387 LIST_HEAD(head); 1398 LIST_HEAD(head);
1388 int may_wait = how & FLUSH_SYNC; 1399 int may_wait = how & FLUSH_SYNC;
@@ -1446,11 +1457,6 @@ out_mark_dirty:
1446 return ret; 1457 return ret;
1447} 1458}
1448#else 1459#else
1449static int nfs_commit_inode(struct inode *inode, int how)
1450{
1451 return 0;
1452}
1453
1454static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) 1460static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc)
1455{ 1461{
1456 return 0; 1462 return 0;
@@ -1549,7 +1555,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
1549 1555
1550 nfs_fscache_release_page(page, GFP_KERNEL); 1556 nfs_fscache_release_page(page, GFP_KERNEL);
1551 1557
1552 req = nfs_find_and_lock_request(page); 1558 req = nfs_find_and_lock_request(page, false);
1553 ret = PTR_ERR(req); 1559 ret = PTR_ERR(req);
1554 if (IS_ERR(req)) 1560 if (IS_ERR(req))
1555 goto out; 1561 goto out;