diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/file.c | 8 | ||||
| -rw-r--r-- | fs/nfs/idmap.c | 4 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 29 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 21 | ||||
| -rw-r--r-- | fs/nfs/read.c | 23 |
5 files changed, 61 insertions, 24 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index cc2b874ad5a4..48e892880d5b 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -312,7 +312,13 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
| 312 | 312 | ||
| 313 | static int nfs_release_page(struct page *page, gfp_t gfp) | 313 | static int nfs_release_page(struct page *page, gfp_t gfp) |
| 314 | { | 314 | { |
| 315 | return !nfs_wb_page(page->mapping->host, page); | 315 | if (gfp & __GFP_FS) |
| 316 | return !nfs_wb_page(page->mapping->host, page); | ||
| 317 | else | ||
| 318 | /* | ||
| 319 | * Avoid deadlock on nfs_wait_on_request(). | ||
| 320 | */ | ||
| 321 | return 0; | ||
| 316 | } | 322 | } |
| 317 | 323 | ||
| 318 | const struct address_space_operations nfs_file_aops = { | 324 | const struct address_space_operations nfs_file_aops = { |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b81e7ed3c902..07a5dd57646e 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
| @@ -130,9 +130,7 @@ nfs_idmap_delete(struct nfs4_client *clp) | |||
| 130 | 130 | ||
| 131 | if (!idmap) | 131 | if (!idmap) |
| 132 | return; | 132 | return; |
| 133 | dput(idmap->idmap_dentry); | 133 | rpc_unlink(idmap->idmap_dentry); |
| 134 | idmap->idmap_dentry = NULL; | ||
| 135 | rpc_unlink(idmap->idmap_path); | ||
| 136 | clp->cl_idmap = NULL; | 134 | clp->cl_idmap = NULL; |
| 137 | kfree(idmap); | 135 | kfree(idmap); |
| 138 | } | 136 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e6ee97f19d81..153898e1331f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2668,7 +2668,7 @@ out: | |||
| 2668 | nfs4_set_cached_acl(inode, acl); | 2668 | nfs4_set_cached_acl(inode, acl); |
| 2669 | } | 2669 | } |
| 2670 | 2670 | ||
| 2671 | static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) | 2671 | static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) |
| 2672 | { | 2672 | { |
| 2673 | struct page *pages[NFS4ACL_MAXPAGES]; | 2673 | struct page *pages[NFS4ACL_MAXPAGES]; |
| 2674 | struct nfs_getaclargs args = { | 2674 | struct nfs_getaclargs args = { |
| @@ -2721,6 +2721,19 @@ out_free: | |||
| 2721 | return ret; | 2721 | return ret; |
| 2722 | } | 2722 | } |
| 2723 | 2723 | ||
| 2724 | static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) | ||
| 2725 | { | ||
| 2726 | struct nfs4_exception exception = { }; | ||
| 2727 | ssize_t ret; | ||
| 2728 | do { | ||
| 2729 | ret = __nfs4_get_acl_uncached(inode, buf, buflen); | ||
| 2730 | if (ret >= 0) | ||
| 2731 | break; | ||
| 2732 | ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); | ||
| 2733 | } while (exception.retry); | ||
| 2734 | return ret; | ||
| 2735 | } | ||
| 2736 | |||
| 2724 | static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | 2737 | static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) |
| 2725 | { | 2738 | { |
| 2726 | struct nfs_server *server = NFS_SERVER(inode); | 2739 | struct nfs_server *server = NFS_SERVER(inode); |
| @@ -2737,7 +2750,7 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | |||
| 2737 | return nfs4_get_acl_uncached(inode, buf, buflen); | 2750 | return nfs4_get_acl_uncached(inode, buf, buflen); |
| 2738 | } | 2751 | } |
| 2739 | 2752 | ||
| 2740 | static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) | 2753 | static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) |
| 2741 | { | 2754 | { |
| 2742 | struct nfs_server *server = NFS_SERVER(inode); | 2755 | struct nfs_server *server = NFS_SERVER(inode); |
| 2743 | struct page *pages[NFS4ACL_MAXPAGES]; | 2756 | struct page *pages[NFS4ACL_MAXPAGES]; |
| @@ -2763,6 +2776,18 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
| 2763 | return ret; | 2776 | return ret; |
| 2764 | } | 2777 | } |
| 2765 | 2778 | ||
| 2779 | static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) | ||
| 2780 | { | ||
| 2781 | struct nfs4_exception exception = { }; | ||
| 2782 | int err; | ||
| 2783 | do { | ||
| 2784 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
| 2785 | __nfs4_proc_set_acl(inode, buf, buflen), | ||
| 2786 | &exception); | ||
| 2787 | } while (exception.retry); | ||
| 2788 | return err; | ||
| 2789 | } | ||
| 2790 | |||
| 2766 | static int | 2791 | static int |
| 2767 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) | 2792 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) |
| 2768 | { | 2793 | { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 1750d996f49f..730ec8fb31c6 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -3355,7 +3355,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3355 | struct kvec *iov = rcvbuf->head; | 3355 | struct kvec *iov = rcvbuf->head; |
| 3356 | unsigned int nr, pglen = rcvbuf->page_len; | 3356 | unsigned int nr, pglen = rcvbuf->page_len; |
| 3357 | uint32_t *end, *entry, *p, *kaddr; | 3357 | uint32_t *end, *entry, *p, *kaddr; |
| 3358 | uint32_t len, attrlen; | 3358 | uint32_t len, attrlen, xlen; |
| 3359 | int hdrlen, recvd, status; | 3359 | int hdrlen, recvd, status; |
| 3360 | 3360 | ||
| 3361 | status = decode_op_hdr(xdr, OP_READDIR); | 3361 | status = decode_op_hdr(xdr, OP_READDIR); |
| @@ -3377,10 +3377,10 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3377 | 3377 | ||
| 3378 | BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); | 3378 | BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); |
| 3379 | kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); | 3379 | kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); |
| 3380 | end = (uint32_t *) ((char *)p + pglen + readdir->pgbase); | 3380 | end = p + ((pglen + readdir->pgbase) >> 2); |
| 3381 | entry = p; | 3381 | entry = p; |
| 3382 | for (nr = 0; *p++; nr++) { | 3382 | for (nr = 0; *p++; nr++) { |
| 3383 | if (p + 3 > end) | 3383 | if (end - p < 3) |
| 3384 | goto short_pkt; | 3384 | goto short_pkt; |
| 3385 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); | 3385 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); |
| 3386 | p += 2; /* cookie */ | 3386 | p += 2; /* cookie */ |
| @@ -3389,18 +3389,19 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
| 3389 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); | 3389 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); |
| 3390 | goto err_unmap; | 3390 | goto err_unmap; |
| 3391 | } | 3391 | } |
| 3392 | dprintk("filename = %*s\n", len, (char *)p); | 3392 | xlen = XDR_QUADLEN(len); |
| 3393 | p += XDR_QUADLEN(len); | 3393 | if (end - p < xlen + 1) |
| 3394 | if (p + 1 > end) | ||
| 3395 | goto short_pkt; | 3394 | goto short_pkt; |
| 3395 | dprintk("filename = %*s\n", len, (char *)p); | ||
| 3396 | p += xlen; | ||
| 3396 | len = ntohl(*p++); /* bitmap length */ | 3397 | len = ntohl(*p++); /* bitmap length */ |
| 3397 | p += len; | 3398 | if (end - p < len + 1) |
| 3398 | if (p + 1 > end) | ||
| 3399 | goto short_pkt; | 3399 | goto short_pkt; |
| 3400 | p += len; | ||
| 3400 | attrlen = XDR_QUADLEN(ntohl(*p++)); | 3401 | attrlen = XDR_QUADLEN(ntohl(*p++)); |
| 3401 | p += attrlen; /* attributes */ | 3402 | if (end - p < attrlen + 2) |
| 3402 | if (p + 2 > end) | ||
| 3403 | goto short_pkt; | 3403 | goto short_pkt; |
| 3404 | p += attrlen; /* attributes */ | ||
| 3404 | entry = p; | 3405 | entry = p; |
| 3405 | } | 3406 | } |
| 3406 | if (!nr && (entry[0] != 0 || entry[1] == 0)) | 3407 | if (!nr && (entry[0] != 0 || entry[1] == 0)) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 65c0c5b32351..da9cf11c326f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -116,10 +116,17 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) | |||
| 116 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; | 116 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; |
| 117 | base &= ~PAGE_CACHE_MASK; | 117 | base &= ~PAGE_CACHE_MASK; |
| 118 | pglen = PAGE_CACHE_SIZE - base; | 118 | pglen = PAGE_CACHE_SIZE - base; |
| 119 | if (pglen < remainder) | 119 | for (;;) { |
| 120 | if (remainder <= pglen) { | ||
| 121 | memclear_highpage_flush(*pages, base, remainder); | ||
| 122 | break; | ||
| 123 | } | ||
| 120 | memclear_highpage_flush(*pages, base, pglen); | 124 | memclear_highpage_flush(*pages, base, pglen); |
| 121 | else | 125 | pages++; |
| 122 | memclear_highpage_flush(*pages, base, remainder); | 126 | remainder -= pglen; |
| 127 | pglen = PAGE_CACHE_SIZE; | ||
| 128 | base = 0; | ||
| 129 | } | ||
| 123 | } | 130 | } |
| 124 | 131 | ||
| 125 | /* | 132 | /* |
| @@ -476,6 +483,8 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) | |||
| 476 | unsigned int base = data->args.pgbase; | 483 | unsigned int base = data->args.pgbase; |
| 477 | struct page **pages; | 484 | struct page **pages; |
| 478 | 485 | ||
| 486 | if (data->res.eof) | ||
| 487 | count = data->args.count; | ||
| 479 | if (unlikely(count == 0)) | 488 | if (unlikely(count == 0)) |
| 480 | return; | 489 | return; |
| 481 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; | 490 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; |
| @@ -483,11 +492,7 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) | |||
| 483 | count += base; | 492 | count += base; |
| 484 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) | 493 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) |
| 485 | SetPageUptodate(*pages); | 494 | SetPageUptodate(*pages); |
| 486 | /* | 495 | if (count != 0) |
| 487 | * Was this an eof or a short read? If the latter, don't mark the page | ||
| 488 | * as uptodate yet. | ||
| 489 | */ | ||
| 490 | if (count > 0 && (data->res.eof || data->args.count == data->res.count)) | ||
| 491 | SetPageUptodate(*pages); | 496 | SetPageUptodate(*pages); |
| 492 | } | 497 | } |
| 493 | 498 | ||
| @@ -502,6 +507,8 @@ static void nfs_readpage_set_pages_error(struct nfs_read_data *data) | |||
| 502 | count += base; | 507 | count += base; |
| 503 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) | 508 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) |
| 504 | SetPageError(*pages); | 509 | SetPageError(*pages); |
| 510 | if (count != 0) | ||
| 511 | SetPageError(*pages); | ||
| 505 | } | 512 | } |
| 506 | 513 | ||
| 507 | /* | 514 | /* |
