diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-26 22:42:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-26 22:42:59 -0500 |
commit | 423eaf8f00d89ca79bb2c9d4d22e92c9774e2d8a (patch) | |
tree | e160521a6b059d50045ea47c3f730bf2c83c1f85 /fs | |
parent | 0685ab4fb8e527639d9867df60d49dccba85d842 (diff) | |
parent | 02fe494619d525ea803ab1f4f671186dc8a52f7a (diff) |
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6:
NFS: Clean up new multi-segment direct I/O changes
NFS: Ensure we return zero if applications attempt to write zero bytes
NFS: Support multiple segment iovecs in the NFS direct I/O path
NFS: Introduce iovec I/O helpers to fs/nfs/direct.c
SUNRPC: Add missing "space" to net/sunrpc/auth_gss.c
SUNRPC: make sunrpc/xprtsock.c:xs_setup_{udp,tcp}() static
NFS: fs/nfs/dir.c should #include "internal.h"
NFS: make nfs_wb_page_priority() static
NFS: mount failure causes bad page state
SUNRPC: remove NFS/RDMA client's binary sysctls
kernel BUG at fs/nfs/namespace.c:108! - can be triggered by bad server
sunrpc: rpc_pipe_poll may miss available data in some cases
sunrpc: return error if unsupported enctype or cksumtype is encountered
sunrpc: gss_pipe_downcall(), don't assume all errors are transient
NFS: Fix the ustat() regression
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/dir.c | 1 | ||||
-rw-r--r-- | fs/nfs/direct.c | 142 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 81 | ||||
-rw-r--r-- | fs/nfs/super.c | 11 | ||||
-rw-r--r-- | fs/nfs/write.c | 3 |
5 files changed, 138 insertions, 100 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 35334539d947..f697b5c74b7c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "nfs4_fs.h" | 38 | #include "nfs4_fs.h" |
39 | #include "delegation.h" | 39 | #include "delegation.h" |
40 | #include "iostat.h" | 40 | #include "iostat.h" |
41 | #include "internal.h" | ||
41 | 42 | ||
42 | /* #define NFS_DEBUG_VERBOSE 1 */ | 43 | /* #define NFS_DEBUG_VERBOSE 1 */ |
43 | 44 | ||
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index afcab007a22b..5e8d82f6666b 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -263,17 +263,19 @@ static const struct rpc_call_ops nfs_read_direct_ops = { | |||
263 | * handled automatically by nfs_direct_read_result(). Otherwise, if | 263 | * handled automatically by nfs_direct_read_result(). Otherwise, if |
264 | * no requests have been sent, just return an error. | 264 | * no requests have been sent, just return an error. |
265 | */ | 265 | */ |
266 | static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos) | 266 | static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, |
267 | const struct iovec *iov, | ||
268 | loff_t pos) | ||
267 | { | 269 | { |
268 | struct nfs_open_context *ctx = dreq->ctx; | 270 | struct nfs_open_context *ctx = dreq->ctx; |
269 | struct inode *inode = ctx->path.dentry->d_inode; | 271 | struct inode *inode = ctx->path.dentry->d_inode; |
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | ||
273 | size_t count = iov->iov_len; | ||
270 | size_t rsize = NFS_SERVER(inode)->rsize; | 274 | size_t rsize = NFS_SERVER(inode)->rsize; |
271 | unsigned int pgbase; | 275 | unsigned int pgbase; |
272 | int result; | 276 | int result; |
273 | ssize_t started = 0; | 277 | ssize_t started = 0; |
274 | 278 | ||
275 | get_dreq(dreq); | ||
276 | |||
277 | do { | 279 | do { |
278 | struct nfs_read_data *data; | 280 | struct nfs_read_data *data; |
279 | size_t bytes; | 281 | size_t bytes; |
@@ -347,15 +349,46 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo | |||
347 | count -= bytes; | 349 | count -= bytes; |
348 | } while (count != 0); | 350 | } while (count != 0); |
349 | 351 | ||
352 | if (started) | ||
353 | return started; | ||
354 | return result < 0 ? (ssize_t) result : -EFAULT; | ||
355 | } | ||
356 | |||
357 | static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | ||
358 | const struct iovec *iov, | ||
359 | unsigned long nr_segs, | ||
360 | loff_t pos) | ||
361 | { | ||
362 | ssize_t result = -EINVAL; | ||
363 | size_t requested_bytes = 0; | ||
364 | unsigned long seg; | ||
365 | |||
366 | get_dreq(dreq); | ||
367 | |||
368 | for (seg = 0; seg < nr_segs; seg++) { | ||
369 | const struct iovec *vec = &iov[seg]; | ||
370 | result = nfs_direct_read_schedule_segment(dreq, vec, pos); | ||
371 | if (result < 0) | ||
372 | break; | ||
373 | requested_bytes += result; | ||
374 | if ((size_t)result < vec->iov_len) | ||
375 | break; | ||
376 | pos += vec->iov_len; | ||
377 | } | ||
378 | |||
350 | if (put_dreq(dreq)) | 379 | if (put_dreq(dreq)) |
351 | nfs_direct_complete(dreq); | 380 | nfs_direct_complete(dreq); |
352 | 381 | ||
353 | if (started) | 382 | if (requested_bytes != 0) |
354 | return 0; | 383 | return 0; |
355 | return result < 0 ? (ssize_t) result : -EFAULT; | 384 | |
385 | if (result < 0) | ||
386 | return result; | ||
387 | return -EIO; | ||
356 | } | 388 | } |
357 | 389 | ||
358 | static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) | 390 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, |
391 | unsigned long nr_segs, loff_t pos) | ||
359 | { | 392 | { |
360 | ssize_t result = 0; | 393 | ssize_t result = 0; |
361 | sigset_t oldset; | 394 | sigset_t oldset; |
@@ -372,9 +405,8 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size | |||
372 | if (!is_sync_kiocb(iocb)) | 405 | if (!is_sync_kiocb(iocb)) |
373 | dreq->iocb = iocb; | 406 | dreq->iocb = iocb; |
374 | 407 | ||
375 | nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count); | ||
376 | rpc_clnt_sigmask(clnt, &oldset); | 408 | rpc_clnt_sigmask(clnt, &oldset); |
377 | result = nfs_direct_read_schedule(dreq, user_addr, count, pos); | 409 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
378 | if (!result) | 410 | if (!result) |
379 | result = nfs_direct_wait(dreq); | 411 | result = nfs_direct_wait(dreq); |
380 | rpc_clnt_sigunmask(clnt, &oldset); | 412 | rpc_clnt_sigunmask(clnt, &oldset); |
@@ -601,17 +633,19 @@ static const struct rpc_call_ops nfs_write_direct_ops = { | |||
601 | * handled automatically by nfs_direct_write_result(). Otherwise, if | 633 | * handled automatically by nfs_direct_write_result(). Otherwise, if |
602 | * no requests have been sent, just return an error. | 634 | * no requests have been sent, just return an error. |
603 | */ | 635 | */ |
604 | static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync) | 636 | static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, |
637 | const struct iovec *iov, | ||
638 | loff_t pos, int sync) | ||
605 | { | 639 | { |
606 | struct nfs_open_context *ctx = dreq->ctx; | 640 | struct nfs_open_context *ctx = dreq->ctx; |
607 | struct inode *inode = ctx->path.dentry->d_inode; | 641 | struct inode *inode = ctx->path.dentry->d_inode; |
642 | unsigned long user_addr = (unsigned long)iov->iov_base; | ||
643 | size_t count = iov->iov_len; | ||
608 | size_t wsize = NFS_SERVER(inode)->wsize; | 644 | size_t wsize = NFS_SERVER(inode)->wsize; |
609 | unsigned int pgbase; | 645 | unsigned int pgbase; |
610 | int result; | 646 | int result; |
611 | ssize_t started = 0; | 647 | ssize_t started = 0; |
612 | 648 | ||
613 | get_dreq(dreq); | ||
614 | |||
615 | do { | 649 | do { |
616 | struct nfs_write_data *data; | 650 | struct nfs_write_data *data; |
617 | size_t bytes; | 651 | size_t bytes; |
@@ -689,15 +723,48 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l | |||
689 | count -= bytes; | 723 | count -= bytes; |
690 | } while (count != 0); | 724 | } while (count != 0); |
691 | 725 | ||
726 | if (started) | ||
727 | return started; | ||
728 | return result < 0 ? (ssize_t) result : -EFAULT; | ||
729 | } | ||
730 | |||
731 | static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | ||
732 | const struct iovec *iov, | ||
733 | unsigned long nr_segs, | ||
734 | loff_t pos, int sync) | ||
735 | { | ||
736 | ssize_t result = 0; | ||
737 | size_t requested_bytes = 0; | ||
738 | unsigned long seg; | ||
739 | |||
740 | get_dreq(dreq); | ||
741 | |||
742 | for (seg = 0; seg < nr_segs; seg++) { | ||
743 | const struct iovec *vec = &iov[seg]; | ||
744 | result = nfs_direct_write_schedule_segment(dreq, vec, | ||
745 | pos, sync); | ||
746 | if (result < 0) | ||
747 | break; | ||
748 | requested_bytes += result; | ||
749 | if ((size_t)result < vec->iov_len) | ||
750 | break; | ||
751 | pos += vec->iov_len; | ||
752 | } | ||
753 | |||
692 | if (put_dreq(dreq)) | 754 | if (put_dreq(dreq)) |
693 | nfs_direct_write_complete(dreq, inode); | 755 | nfs_direct_write_complete(dreq, dreq->inode); |
694 | 756 | ||
695 | if (started) | 757 | if (requested_bytes != 0) |
696 | return 0; | 758 | return 0; |
697 | return result < 0 ? (ssize_t) result : -EFAULT; | 759 | |
760 | if (result < 0) | ||
761 | return result; | ||
762 | return -EIO; | ||
698 | } | 763 | } |
699 | 764 | ||
700 | static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) | 765 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, |
766 | unsigned long nr_segs, loff_t pos, | ||
767 | size_t count) | ||
701 | { | 768 | { |
702 | ssize_t result = 0; | 769 | ssize_t result = 0; |
703 | sigset_t oldset; | 770 | sigset_t oldset; |
@@ -720,10 +787,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz | |||
720 | if (!is_sync_kiocb(iocb)) | 787 | if (!is_sync_kiocb(iocb)) |
721 | dreq->iocb = iocb; | 788 | dreq->iocb = iocb; |
722 | 789 | ||
723 | nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count); | ||
724 | |||
725 | rpc_clnt_sigmask(clnt, &oldset); | 790 | rpc_clnt_sigmask(clnt, &oldset); |
726 | result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); | 791 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
727 | if (!result) | 792 | if (!result) |
728 | result = nfs_direct_wait(dreq); | 793 | result = nfs_direct_wait(dreq); |
729 | rpc_clnt_sigunmask(clnt, &oldset); | 794 | rpc_clnt_sigunmask(clnt, &oldset); |
@@ -759,21 +824,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
759 | ssize_t retval = -EINVAL; | 824 | ssize_t retval = -EINVAL; |
760 | struct file *file = iocb->ki_filp; | 825 | struct file *file = iocb->ki_filp; |
761 | struct address_space *mapping = file->f_mapping; | 826 | struct address_space *mapping = file->f_mapping; |
762 | /* XXX: temporary */ | 827 | size_t count; |
763 | const char __user *buf = iov[0].iov_base; | 828 | |
764 | size_t count = iov[0].iov_len; | 829 | count = iov_length(iov, nr_segs); |
830 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); | ||
765 | 831 | ||
766 | dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", | 832 | dprintk("nfs: direct read(%s/%s, %zd@%Ld)\n", |
767 | file->f_path.dentry->d_parent->d_name.name, | 833 | file->f_path.dentry->d_parent->d_name.name, |
768 | file->f_path.dentry->d_name.name, | 834 | file->f_path.dentry->d_name.name, |
769 | (unsigned long) count, (long long) pos); | 835 | count, (long long) pos); |
770 | |||
771 | if (nr_segs != 1) | ||
772 | goto out; | ||
773 | 836 | ||
774 | retval = -EFAULT; | ||
775 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
776 | goto out; | ||
777 | retval = 0; | 837 | retval = 0; |
778 | if (!count) | 838 | if (!count) |
779 | goto out; | 839 | goto out; |
@@ -782,7 +842,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
782 | if (retval) | 842 | if (retval) |
783 | goto out; | 843 | goto out; |
784 | 844 | ||
785 | retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos); | 845 | retval = nfs_direct_read(iocb, iov, nr_segs, pos); |
786 | if (retval > 0) | 846 | if (retval > 0) |
787 | iocb->ki_pos = pos + retval; | 847 | iocb->ki_pos = pos + retval; |
788 | 848 | ||
@@ -821,21 +881,21 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
821 | ssize_t retval = -EINVAL; | 881 | ssize_t retval = -EINVAL; |
822 | struct file *file = iocb->ki_filp; | 882 | struct file *file = iocb->ki_filp; |
823 | struct address_space *mapping = file->f_mapping; | 883 | struct address_space *mapping = file->f_mapping; |
824 | /* XXX: temporary */ | 884 | size_t count; |
825 | const char __user *buf = iov[0].iov_base; | 885 | |
826 | size_t count = iov[0].iov_len; | 886 | count = iov_length(iov, nr_segs); |
887 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); | ||
827 | 888 | ||
828 | dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n", | 889 | dfprintk(VFS, "nfs: direct write(%s/%s, %zd@%Ld)\n", |
829 | file->f_path.dentry->d_parent->d_name.name, | 890 | file->f_path.dentry->d_parent->d_name.name, |
830 | file->f_path.dentry->d_name.name, | 891 | file->f_path.dentry->d_name.name, |
831 | (unsigned long) count, (long long) pos); | 892 | count, (long long) pos); |
832 | |||
833 | if (nr_segs != 1) | ||
834 | goto out; | ||
835 | 893 | ||
836 | retval = generic_write_checks(file, &pos, &count, 0); | 894 | retval = generic_write_checks(file, &pos, &count, 0); |
837 | if (retval) | 895 | if (retval) |
838 | goto out; | 896 | goto out; |
897 | if (!count) | ||
898 | goto out; /* return 0 */ | ||
839 | 899 | ||
840 | retval = -EINVAL; | 900 | retval = -EINVAL; |
841 | if ((ssize_t) count < 0) | 901 | if ((ssize_t) count < 0) |
@@ -844,15 +904,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
844 | if (!count) | 904 | if (!count) |
845 | goto out; | 905 | goto out; |
846 | 906 | ||
847 | retval = -EFAULT; | ||
848 | if (!access_ok(VERIFY_READ, buf, count)) | ||
849 | goto out; | ||
850 | |||
851 | retval = nfs_sync_mapping(mapping); | 907 | retval = nfs_sync_mapping(mapping); |
852 | if (retval) | 908 | if (retval) |
853 | goto out; | 909 | goto out; |
854 | 910 | ||
855 | retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); | 911 | retval = nfs_direct_write(iocb, iov, nr_segs, pos, count); |
856 | 912 | ||
857 | if (retval > 0) | 913 | if (retval > 0) |
858 | iocb->ki_pos = pos + retval; | 914 | iocb->ki_pos = pos + retval; |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 522e5ad4d8ad..0ee43843f4ec 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -43,6 +43,25 @@ | |||
43 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 43 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Set the superblock root dentry. | ||
47 | * Note that this function frees the inode in case of error. | ||
48 | */ | ||
49 | static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode) | ||
50 | { | ||
51 | /* The mntroot acts as the dummy root dentry for this superblock */ | ||
52 | if (sb->s_root == NULL) { | ||
53 | sb->s_root = d_alloc_root(inode); | ||
54 | if (sb->s_root == NULL) { | ||
55 | iput(inode); | ||
56 | return -ENOMEM; | ||
57 | } | ||
58 | /* Circumvent igrab(): we know the inode is not being freed */ | ||
59 | atomic_inc(&inode->i_count); | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* | ||
46 | * get an NFS2/NFS3 root dentry from the root filehandle | 65 | * get an NFS2/NFS3 root dentry from the root filehandle |
47 | */ | 66 | */ |
48 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 67 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) |
@@ -54,33 +73,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
54 | struct inode *inode; | 73 | struct inode *inode; |
55 | int error; | 74 | int error; |
56 | 75 | ||
57 | /* create a dummy root dentry with dummy inode for this superblock */ | ||
58 | if (!sb->s_root) { | ||
59 | struct nfs_fh dummyfh; | ||
60 | struct dentry *root; | ||
61 | struct inode *iroot; | ||
62 | |||
63 | memset(&dummyfh, 0, sizeof(dummyfh)); | ||
64 | memset(&fattr, 0, sizeof(fattr)); | ||
65 | nfs_fattr_init(&fattr); | ||
66 | fattr.valid = NFS_ATTR_FATTR; | ||
67 | fattr.type = NFDIR; | ||
68 | fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | ||
69 | fattr.nlink = 2; | ||
70 | |||
71 | iroot = nfs_fhget(sb, &dummyfh, &fattr); | ||
72 | if (IS_ERR(iroot)) | ||
73 | return ERR_PTR(PTR_ERR(iroot)); | ||
74 | |||
75 | root = d_alloc_root(iroot); | ||
76 | if (!root) { | ||
77 | iput(iroot); | ||
78 | return ERR_PTR(-ENOMEM); | ||
79 | } | ||
80 | |||
81 | sb->s_root = root; | ||
82 | } | ||
83 | |||
84 | /* get the actual root for this mount */ | 76 | /* get the actual root for this mount */ |
85 | fsinfo.fattr = &fattr; | 77 | fsinfo.fattr = &fattr; |
86 | 78 | ||
@@ -96,6 +88,10 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
96 | return ERR_PTR(PTR_ERR(inode)); | 88 | return ERR_PTR(PTR_ERR(inode)); |
97 | } | 89 | } |
98 | 90 | ||
91 | error = nfs_superblock_set_dummy_root(sb, inode); | ||
92 | if (error != 0) | ||
93 | return ERR_PTR(error); | ||
94 | |||
99 | /* root dentries normally start off anonymous and get spliced in later | 95 | /* root dentries normally start off anonymous and get spliced in later |
100 | * if the dentry tree reaches them; however if the dentry already | 96 | * if the dentry tree reaches them; however if the dentry already |
101 | * exists, we'll pick it up at this point and use it as the root | 97 | * exists, we'll pick it up at this point and use it as the root |
@@ -241,33 +237,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
241 | 237 | ||
242 | dprintk("--> nfs4_get_root()\n"); | 238 | dprintk("--> nfs4_get_root()\n"); |
243 | 239 | ||
244 | /* create a dummy root dentry with dummy inode for this superblock */ | ||
245 | if (!sb->s_root) { | ||
246 | struct nfs_fh dummyfh; | ||
247 | struct dentry *root; | ||
248 | struct inode *iroot; | ||
249 | |||
250 | memset(&dummyfh, 0, sizeof(dummyfh)); | ||
251 | memset(&fattr, 0, sizeof(fattr)); | ||
252 | nfs_fattr_init(&fattr); | ||
253 | fattr.valid = NFS_ATTR_FATTR; | ||
254 | fattr.type = NFDIR; | ||
255 | fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | ||
256 | fattr.nlink = 2; | ||
257 | |||
258 | iroot = nfs_fhget(sb, &dummyfh, &fattr); | ||
259 | if (IS_ERR(iroot)) | ||
260 | return ERR_PTR(PTR_ERR(iroot)); | ||
261 | |||
262 | root = d_alloc_root(iroot); | ||
263 | if (!root) { | ||
264 | iput(iroot); | ||
265 | return ERR_PTR(-ENOMEM); | ||
266 | } | ||
267 | |||
268 | sb->s_root = root; | ||
269 | } | ||
270 | |||
271 | /* get the info about the server and filesystem */ | 240 | /* get the info about the server and filesystem */ |
272 | error = nfs4_server_capabilities(server, mntfh); | 241 | error = nfs4_server_capabilities(server, mntfh); |
273 | if (error < 0) { | 242 | if (error < 0) { |
@@ -289,6 +258,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
289 | return ERR_PTR(PTR_ERR(inode)); | 258 | return ERR_PTR(PTR_ERR(inode)); |
290 | } | 259 | } |
291 | 260 | ||
261 | error = nfs_superblock_set_dummy_root(sb, inode); | ||
262 | if (error != 0) | ||
263 | return ERR_PTR(error); | ||
264 | |||
292 | /* root dentries normally start off anonymous and get spliced in later | 265 | /* root dentries normally start off anonymous and get spliced in later |
293 | * if the dentry tree reaches them; however if the dentry already | 266 | * if the dentry tree reaches them; however if the dentry already |
294 | * exists, we'll pick it up at this point and use it as the root | 267 | * exists, we'll pick it up at this point and use it as the root |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index fa517ae9207f..2426e713b77f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1054,10 +1054,11 @@ static int nfs_validate_mount_data(void *options, | |||
1054 | { | 1054 | { |
1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; | 1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
1056 | 1056 | ||
1057 | memset(args, 0, sizeof(*args)); | ||
1058 | |||
1057 | if (data == NULL) | 1059 | if (data == NULL) |
1058 | goto out_no_data; | 1060 | goto out_no_data; |
1059 | 1061 | ||
1060 | memset(args, 0, sizeof(*args)); | ||
1061 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); | 1062 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); |
1062 | args->rsize = NFS_MAX_FILE_IO_SIZE; | 1063 | args->rsize = NFS_MAX_FILE_IO_SIZE; |
1063 | args->wsize = NFS_MAX_FILE_IO_SIZE; | 1064 | args->wsize = NFS_MAX_FILE_IO_SIZE; |
@@ -1474,6 +1475,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1474 | error = PTR_ERR(mntroot); | 1475 | error = PTR_ERR(mntroot); |
1475 | goto error_splat_super; | 1476 | goto error_splat_super; |
1476 | } | 1477 | } |
1478 | if (mntroot->d_inode->i_op != &nfs_dir_inode_operations) { | ||
1479 | dput(mntroot); | ||
1480 | error = -ESTALE; | ||
1481 | goto error_splat_super; | ||
1482 | } | ||
1477 | 1483 | ||
1478 | s->s_flags |= MS_ACTIVE; | 1484 | s->s_flags |= MS_ACTIVE; |
1479 | mnt->mnt_sb = s; | 1485 | mnt->mnt_sb = s; |
@@ -1531,10 +1537,11 @@ static int nfs4_validate_mount_data(void *options, | |||
1531 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; | 1537 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
1532 | char *c; | 1538 | char *c; |
1533 | 1539 | ||
1540 | memset(args, 0, sizeof(*args)); | ||
1541 | |||
1534 | if (data == NULL) | 1542 | if (data == NULL) |
1535 | goto out_no_data; | 1543 | goto out_no_data; |
1536 | 1544 | ||
1537 | memset(args, 0, sizeof(*args)); | ||
1538 | args->rsize = NFS_MAX_FILE_IO_SIZE; | 1545 | args->rsize = NFS_MAX_FILE_IO_SIZE; |
1539 | args->wsize = NFS_MAX_FILE_IO_SIZE; | 1546 | args->wsize = NFS_MAX_FILE_IO_SIZE; |
1540 | args->timeo = 600; | 1547 | args->timeo = 600; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 89527a487ed7..51cc1bd6a116 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1436,7 +1436,8 @@ out: | |||
1436 | return ret; | 1436 | return ret; |
1437 | } | 1437 | } |
1438 | 1438 | ||
1439 | int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) | 1439 | static int nfs_wb_page_priority(struct inode *inode, struct page *page, |
1440 | int how) | ||
1440 | { | 1441 | { |
1441 | loff_t range_start = page_offset(page); | 1442 | loff_t range_start = page_offset(page); |
1442 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | 1443 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); |