diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 4 | ||||
-rw-r--r-- | fs/nfs/file.c | 13 | ||||
-rw-r--r-- | fs/nfs/internal.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfsroot.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 30 |
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 | ||
1704 | int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | 1704 | int 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 | */ |
485 | static int nfs_release_page(struct page *page, gfp_t gfp) | 486 | static 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[]; | |||
205 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 205 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
206 | 206 | ||
207 | /* dir.c */ | 207 | /* dir.c */ |
208 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | 208 | extern 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 */ |
211 | extern struct workqueue_struct *nfsiod_workqueue; | 212 | extern 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 = ""; | |||
105 | static __be32 servaddr __initdata = 0; | 105 | static __be32 servaddr __initdata = 0; |
106 | 106 | ||
107 | /* Name of directory to mount */ | 107 | /* Name of directory to mount */ |
108 | static char nfs_export_path[NFS_MAXPATHLEN] __initdata = { 0, }; | 108 | static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, }; |
109 | 109 | ||
110 | /* NFS-related data */ | 110 | /* NFS-related data */ |
111 | static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */ | 111 | static 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 | ||
225 | static struct nfs_page *nfs_find_and_lock_request(struct page *page) | 225 | static 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 | */ |
258 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | 261 | static 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: | |||
283 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) | 286 | static 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 | ||
1385 | static int nfs_commit_inode(struct inode *inode, int how) | 1396 | int 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 |
1449 | static int nfs_commit_inode(struct inode *inode, int how) | ||
1450 | { | ||
1451 | return 0; | ||
1452 | } | ||
1453 | |||
1454 | static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) | 1460 | static 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; |