diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-06-17 21:13:00 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-06-18 21:13:44 -0400 |
commit | 1f84603c0940d5bed17f7e4d2e0b2a4b8b8f1b81 (patch) | |
tree | 143956f878290e85de7c9130f465e862f587ee53 /fs | |
parent | 301933a0acfdec837fd8b4884093b3f0fff01d8a (diff) | |
parent | 4bf259e3ae5015e73282ba66716c4a917e1264ac (diff) |
Merge branch 'devel-for-2.6.31' into for-2.6.31
Conflicts:
fs/nfs/client.c
fs/nfs/super.c
Diffstat (limited to 'fs')
-rw-r--r-- | fs/lockd/clntproc.c | 4 | ||||
-rw-r--r-- | fs/lockd/mon.c | 19 | ||||
-rw-r--r-- | fs/nfs/callback.c | 4 | ||||
-rw-r--r-- | fs/nfs/client.c | 9 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 32 | ||||
-rw-r--r-- | fs/nfs/file.c | 37 | ||||
-rw-r--r-- | fs/nfs/internal.h | 8 | ||||
-rw-r--r-- | fs/nfs/mount_clnt.c | 337 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 61 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 37 | ||||
-rw-r--r-- | fs/nfs/nfsroot.c | 5 | ||||
-rw-r--r-- | fs/nfs/super.c | 288 |
13 files changed, 626 insertions, 217 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index dd7957064a8c..f2fdcbce143e 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -126,7 +126,6 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) | |||
126 | struct nlm_lock *lock = &argp->lock; | 126 | struct nlm_lock *lock = &argp->lock; |
127 | 127 | ||
128 | nlmclnt_next_cookie(&argp->cookie); | 128 | nlmclnt_next_cookie(&argp->cookie); |
129 | argp->state = nsm_local_state; | ||
130 | memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh)); | 129 | memcpy(&lock->fh, NFS_FH(fl->fl_file->f_path.dentry->d_inode), sizeof(struct nfs_fh)); |
131 | lock->caller = utsname()->nodename; | 130 | lock->caller = utsname()->nodename; |
132 | lock->oh.data = req->a_owner; | 131 | lock->oh.data = req->a_owner; |
@@ -165,6 +164,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl) | |||
165 | /* Set up the argument struct */ | 164 | /* Set up the argument struct */ |
166 | nlmclnt_setlockargs(call, fl); | 165 | nlmclnt_setlockargs(call, fl); |
167 | 166 | ||
167 | lock_kernel(); | ||
168 | if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { | 168 | if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { |
169 | if (fl->fl_type != F_UNLCK) { | 169 | if (fl->fl_type != F_UNLCK) { |
170 | call->a_args.block = IS_SETLKW(cmd) ? 1 : 0; | 170 | call->a_args.block = IS_SETLKW(cmd) ? 1 : 0; |
@@ -178,6 +178,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl) | |||
178 | 178 | ||
179 | fl->fl_ops->fl_release_private(fl); | 179 | fl->fl_ops->fl_release_private(fl); |
180 | fl->fl_ops = NULL; | 180 | fl->fl_ops = NULL; |
181 | unlock_kernel(); | ||
181 | 182 | ||
182 | dprintk("lockd: clnt proc returns %d\n", status); | 183 | dprintk("lockd: clnt proc returns %d\n", status); |
183 | return status; | 184 | return status; |
@@ -519,6 +520,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) | |||
519 | 520 | ||
520 | if (nsm_monitor(host) < 0) | 521 | if (nsm_monitor(host) < 0) |
521 | goto out; | 522 | goto out; |
523 | req->a_args.state = nsm_local_state; | ||
522 | 524 | ||
523 | fl->fl_flags |= FL_ACCESS; | 525 | fl->fl_flags |= FL_ACCESS; |
524 | status = do_vfs_lock(fl); | 526 | status = do_vfs_lock(fl); |
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 6d5d4a4169e5..7fce1b525849 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
@@ -53,7 +53,7 @@ static DEFINE_SPINLOCK(nsm_lock); | |||
53 | /* | 53 | /* |
54 | * Local NSM state | 54 | * Local NSM state |
55 | */ | 55 | */ |
56 | int __read_mostly nsm_local_state; | 56 | u32 __read_mostly nsm_local_state; |
57 | int __read_mostly nsm_use_hostnames; | 57 | int __read_mostly nsm_use_hostnames; |
58 | 58 | ||
59 | static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm) | 59 | static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm) |
@@ -112,6 +112,7 @@ static struct rpc_clnt *nsm_create(void) | |||
112 | .program = &nsm_program, | 112 | .program = &nsm_program, |
113 | .version = NSM_VERSION, | 113 | .version = NSM_VERSION, |
114 | .authflavor = RPC_AUTH_NULL, | 114 | .authflavor = RPC_AUTH_NULL, |
115 | .flags = RPC_CLNT_CREATE_NOPING, | ||
115 | }; | 116 | }; |
116 | 117 | ||
117 | return rpc_create(&args); | 118 | return rpc_create(&args); |
@@ -184,13 +185,19 @@ int nsm_monitor(const struct nlm_host *host) | |||
184 | nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; | 185 | nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; |
185 | 186 | ||
186 | status = nsm_mon_unmon(nsm, NSMPROC_MON, &res); | 187 | status = nsm_mon_unmon(nsm, NSMPROC_MON, &res); |
187 | if (res.status != 0) | 188 | if (unlikely(res.status != 0)) |
188 | status = -EIO; | 189 | status = -EIO; |
189 | if (status < 0) | 190 | if (unlikely(status < 0)) { |
190 | printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); | 191 | printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); |
191 | else | 192 | return status; |
192 | nsm->sm_monitored = 1; | 193 | } |
193 | return status; | 194 | |
195 | nsm->sm_monitored = 1; | ||
196 | if (unlikely(nsm_local_state != res.state)) { | ||
197 | nsm_local_state = res.state; | ||
198 | dprintk("lockd: NSM state changed to %d\n", nsm_local_state); | ||
199 | } | ||
200 | return 0; | ||
194 | } | 201 | } |
195 | 202 | ||
196 | /** | 203 | /** |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index e69b8f61189e..7f604c7941fb 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -123,7 +123,9 @@ nfs4_callback_up(struct svc_serv *serv) | |||
123 | nfs_callback_tcpport6 = ret; | 123 | nfs_callback_tcpport6 = ret; |
124 | dprintk("NFS: Callback listener port = %u (af %u)\n", | 124 | dprintk("NFS: Callback listener port = %u (af %u)\n", |
125 | nfs_callback_tcpport6, PF_INET6); | 125 | nfs_callback_tcpport6, PF_INET6); |
126 | } else if (ret != -EAFNOSUPPORT) | 126 | } else if (ret == -EAFNOSUPPORT) |
127 | ret = 0; | ||
128 | else | ||
127 | goto out_err; | 129 | goto out_err; |
128 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | 130 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |
129 | 131 | ||
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4f75ec593be8..c2d061675d80 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -116,6 +116,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
116 | { | 116 | { |
117 | struct nfs_client *clp; | 117 | struct nfs_client *clp; |
118 | struct rpc_cred *cred; | 118 | struct rpc_cred *cred; |
119 | int err = -ENOMEM; | ||
119 | 120 | ||
120 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) | 121 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) |
121 | goto error_0; | 122 | goto error_0; |
@@ -129,6 +130,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
129 | clp->cl_addrlen = cl_init->addrlen; | 130 | clp->cl_addrlen = cl_init->addrlen; |
130 | 131 | ||
131 | if (cl_init->hostname) { | 132 | if (cl_init->hostname) { |
133 | err = -ENOMEM; | ||
132 | clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); | 134 | clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); |
133 | if (!clp->cl_hostname) | 135 | if (!clp->cl_hostname) |
134 | goto error_cleanup; | 136 | goto error_cleanup; |
@@ -159,7 +161,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
159 | error_cleanup: | 161 | error_cleanup: |
160 | kfree(clp); | 162 | kfree(clp); |
161 | error_0: | 163 | error_0: |
162 | return NULL; | 164 | return ERR_PTR(err); |
163 | } | 165 | } |
164 | 166 | ||
165 | static void nfs4_shutdown_client(struct nfs_client *clp) | 167 | static void nfs4_shutdown_client(struct nfs_client *clp) |
@@ -480,9 +482,10 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_in | |||
480 | spin_unlock(&nfs_client_lock); | 482 | spin_unlock(&nfs_client_lock); |
481 | 483 | ||
482 | new = nfs_alloc_client(cl_init); | 484 | new = nfs_alloc_client(cl_init); |
483 | } while (new); | 485 | } while (!IS_ERR(new)); |
484 | 486 | ||
485 | return ERR_PTR(-ENOMEM); | 487 | dprintk("--> nfs_get_client() = %ld [failed]\n", PTR_ERR(new)); |
488 | return new; | ||
486 | 489 | ||
487 | /* install a new client and return with it unready */ | 490 | /* install a new client and return with it unready */ |
488 | install_client: | 491 | install_client: |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 968225a88015..af05b918cb5b 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -68,29 +68,26 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ | |||
68 | { | 68 | { |
69 | struct inode *inode = state->inode; | 69 | struct inode *inode = state->inode; |
70 | struct file_lock *fl; | 70 | struct file_lock *fl; |
71 | int status; | 71 | int status = 0; |
72 | |||
73 | if (inode->i_flock == NULL) | ||
74 | goto out; | ||
72 | 75 | ||
76 | /* Protect inode->i_flock using the BKL */ | ||
77 | lock_kernel(); | ||
73 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 78 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
74 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 79 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
75 | continue; | 80 | continue; |
76 | if (nfs_file_open_context(fl->fl_file) != ctx) | 81 | if (nfs_file_open_context(fl->fl_file) != ctx) |
77 | continue; | 82 | continue; |
83 | unlock_kernel(); | ||
78 | status = nfs4_lock_delegation_recall(state, fl); | 84 | status = nfs4_lock_delegation_recall(state, fl); |
79 | if (status >= 0) | 85 | if (status < 0) |
80 | continue; | 86 | goto out; |
81 | switch (status) { | 87 | lock_kernel(); |
82 | default: | ||
83 | printk(KERN_ERR "%s: unhandled error %d.\n", | ||
84 | __func__, status); | ||
85 | case -NFS4ERR_EXPIRED: | ||
86 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | ||
87 | case -NFS4ERR_STALE_CLIENTID: | ||
88 | nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client); | ||
89 | goto out_err; | ||
90 | } | ||
91 | } | 88 | } |
92 | return 0; | 89 | unlock_kernel(); |
93 | out_err: | 90 | out: |
94 | return status; | 91 | return status; |
95 | } | 92 | } |
96 | 93 | ||
@@ -268,7 +265,10 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat | |||
268 | struct nfs_inode *nfsi = NFS_I(inode); | 265 | struct nfs_inode *nfsi = NFS_I(inode); |
269 | 266 | ||
270 | nfs_msync_inode(inode); | 267 | nfs_msync_inode(inode); |
271 | /* Guard against new delegated open calls */ | 268 | /* |
269 | * Guard against new delegated open/lock/unlock calls and against | ||
270 | * state recovery | ||
271 | */ | ||
272 | down_write(&nfsi->rwsem); | 272 | down_write(&nfsi->rwsem); |
273 | nfs_delegation_claim_opens(inode, &delegation->stateid); | 273 | nfs_delegation_claim_opens(inode, &delegation->stateid); |
274 | up_write(&nfsi->rwsem); | 274 | up_write(&nfsi->rwsem); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index ec7e27d00bc6..0055b813ec2c 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -48,6 +48,9 @@ static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
48 | size_t count, unsigned int flags); | 48 | size_t count, unsigned int flags); |
49 | static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, | 49 | static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, |
50 | unsigned long nr_segs, loff_t pos); | 50 | unsigned long nr_segs, loff_t pos); |
51 | static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | ||
52 | struct file *filp, loff_t *ppos, | ||
53 | size_t count, unsigned int flags); | ||
51 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, | 54 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, |
52 | unsigned long nr_segs, loff_t pos); | 55 | unsigned long nr_segs, loff_t pos); |
53 | static int nfs_file_flush(struct file *, fl_owner_t id); | 56 | static int nfs_file_flush(struct file *, fl_owner_t id); |
@@ -73,6 +76,7 @@ const struct file_operations nfs_file_operations = { | |||
73 | .lock = nfs_lock, | 76 | .lock = nfs_lock, |
74 | .flock = nfs_flock, | 77 | .flock = nfs_flock, |
75 | .splice_read = nfs_file_splice_read, | 78 | .splice_read = nfs_file_splice_read, |
79 | .splice_write = nfs_file_splice_write, | ||
76 | .check_flags = nfs_check_flags, | 80 | .check_flags = nfs_check_flags, |
77 | .setlease = nfs_setlease, | 81 | .setlease = nfs_setlease, |
78 | }; | 82 | }; |
@@ -587,12 +591,38 @@ out_swapfile: | |||
587 | goto out; | 591 | goto out; |
588 | } | 592 | } |
589 | 593 | ||
594 | static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | ||
595 | struct file *filp, loff_t *ppos, | ||
596 | size_t count, unsigned int flags) | ||
597 | { | ||
598 | struct dentry *dentry = filp->f_path.dentry; | ||
599 | struct inode *inode = dentry->d_inode; | ||
600 | ssize_t ret; | ||
601 | |||
602 | dprintk("NFS splice_write(%s/%s, %lu@%llu)\n", | ||
603 | dentry->d_parent->d_name.name, dentry->d_name.name, | ||
604 | (unsigned long) count, (unsigned long long) *ppos); | ||
605 | |||
606 | /* | ||
607 | * The combination of splice and an O_APPEND destination is disallowed. | ||
608 | */ | ||
609 | |||
610 | nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count); | ||
611 | |||
612 | ret = generic_file_splice_write(pipe, filp, ppos, count, flags); | ||
613 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | ||
614 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | ||
615 | if (err < 0) | ||
616 | ret = err; | ||
617 | } | ||
618 | return ret; | ||
619 | } | ||
620 | |||
590 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 621 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) |
591 | { | 622 | { |
592 | struct inode *inode = filp->f_mapping->host; | 623 | struct inode *inode = filp->f_mapping->host; |
593 | int status = 0; | 624 | int status = 0; |
594 | 625 | ||
595 | lock_kernel(); | ||
596 | /* Try local locking first */ | 626 | /* Try local locking first */ |
597 | posix_test_lock(filp, fl); | 627 | posix_test_lock(filp, fl); |
598 | if (fl->fl_type != F_UNLCK) { | 628 | if (fl->fl_type != F_UNLCK) { |
@@ -608,7 +638,6 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
608 | 638 | ||
609 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 639 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
610 | out: | 640 | out: |
611 | unlock_kernel(); | ||
612 | return status; | 641 | return status; |
613 | out_noconflict: | 642 | out_noconflict: |
614 | fl->fl_type = F_UNLCK; | 643 | fl->fl_type = F_UNLCK; |
@@ -650,13 +679,11 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl) | |||
650 | * If we're signalled while cleaning up locks on process exit, we | 679 | * If we're signalled while cleaning up locks on process exit, we |
651 | * still need to complete the unlock. | 680 | * still need to complete the unlock. |
652 | */ | 681 | */ |
653 | lock_kernel(); | ||
654 | /* Use local locking if mounted with "-onolock" */ | 682 | /* Use local locking if mounted with "-onolock" */ |
655 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 683 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) |
656 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 684 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
657 | else | 685 | else |
658 | status = do_vfs_lock(filp, fl); | 686 | status = do_vfs_lock(filp, fl); |
659 | unlock_kernel(); | ||
660 | return status; | 687 | return status; |
661 | } | 688 | } |
662 | 689 | ||
@@ -673,13 +700,11 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
673 | if (status != 0) | 700 | if (status != 0) |
674 | goto out; | 701 | goto out; |
675 | 702 | ||
676 | lock_kernel(); | ||
677 | /* Use local locking if mounted with "-onolock" */ | 703 | /* Use local locking if mounted with "-onolock" */ |
678 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 704 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) |
679 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 705 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
680 | else | 706 | else |
681 | status = do_vfs_lock(filp, fl); | 707 | status = do_vfs_lock(filp, fl); |
682 | unlock_kernel(); | ||
683 | if (status < 0) | 708 | if (status < 0) |
684 | goto out; | 709 | goto out; |
685 | /* | 710 | /* |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index acee3274d275..7dd90a6769d0 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -43,6 +43,12 @@ struct nfs_clone_mount { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Note: RFC 1813 doesn't limit the number of auth flavors that | ||
47 | * a server can return, so make something up. | ||
48 | */ | ||
49 | #define NFS_MAX_SECFLAVORS (12) | ||
50 | |||
51 | /* | ||
46 | * In-kernel mount arguments | 52 | * In-kernel mount arguments |
47 | */ | 53 | */ |
48 | struct nfs_parsed_mount_data { | 54 | struct nfs_parsed_mount_data { |
@@ -91,6 +97,8 @@ struct nfs_mount_request { | |||
91 | unsigned short protocol; | 97 | unsigned short protocol; |
92 | struct nfs_fh *fh; | 98 | struct nfs_fh *fh; |
93 | int noresvport; | 99 | int noresvport; |
100 | unsigned int *auth_flav_len; | ||
101 | rpc_authflavor_t *auth_flavs; | ||
94 | }; | 102 | }; |
95 | 103 | ||
96 | extern int nfs_mount(struct nfs_mount_request *info); | 104 | extern int nfs_mount(struct nfs_mount_request *info); |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index ca905a5bb1ba..38ef9eaec407 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -20,8 +20,116 @@ | |||
20 | # define NFSDBG_FACILITY NFSDBG_MOUNT | 20 | # define NFSDBG_FACILITY NFSDBG_MOUNT |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | /* | ||
24 | * Defined by RFC 1094, section A.3; and RFC 1813, section 5.1.4 | ||
25 | */ | ||
26 | #define MNTPATHLEN (1024) | ||
27 | |||
28 | /* | ||
29 | * XDR data type sizes | ||
30 | */ | ||
31 | #define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN)) | ||
32 | #define MNT_status_sz (1) | ||
33 | #define MNT_fhs_status_sz (1) | ||
34 | #define MNT_fhandle_sz XDR_QUADLEN(NFS2_FHSIZE) | ||
35 | #define MNT_fhandle3_sz (1 + XDR_QUADLEN(NFS3_FHSIZE)) | ||
36 | #define MNT_authflav3_sz (1 + NFS_MAX_SECFLAVORS) | ||
37 | |||
38 | /* | ||
39 | * XDR argument and result sizes | ||
40 | */ | ||
41 | #define MNT_enc_dirpath_sz encode_dirpath_sz | ||
42 | #define MNT_dec_mountres_sz (MNT_status_sz + MNT_fhandle_sz) | ||
43 | #define MNT_dec_mountres3_sz (MNT_status_sz + MNT_fhandle_sz + \ | ||
44 | MNT_authflav3_sz) | ||
45 | |||
46 | /* | ||
47 | * Defined by RFC 1094, section A.5 | ||
48 | */ | ||
49 | enum { | ||
50 | MOUNTPROC_NULL = 0, | ||
51 | MOUNTPROC_MNT = 1, | ||
52 | MOUNTPROC_DUMP = 2, | ||
53 | MOUNTPROC_UMNT = 3, | ||
54 | MOUNTPROC_UMNTALL = 4, | ||
55 | MOUNTPROC_EXPORT = 5, | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * Defined by RFC 1813, section 5.2 | ||
60 | */ | ||
61 | enum { | ||
62 | MOUNTPROC3_NULL = 0, | ||
63 | MOUNTPROC3_MNT = 1, | ||
64 | MOUNTPROC3_DUMP = 2, | ||
65 | MOUNTPROC3_UMNT = 3, | ||
66 | MOUNTPROC3_UMNTALL = 4, | ||
67 | MOUNTPROC3_EXPORT = 5, | ||
68 | }; | ||
69 | |||
23 | static struct rpc_program mnt_program; | 70 | static struct rpc_program mnt_program; |
24 | 71 | ||
72 | /* | ||
73 | * Defined by OpenGroup XNFS Version 3W, chapter 8 | ||
74 | */ | ||
75 | enum mountstat { | ||
76 | MNT_OK = 0, | ||
77 | MNT_EPERM = 1, | ||
78 | MNT_ENOENT = 2, | ||
79 | MNT_EACCES = 13, | ||
80 | MNT_EINVAL = 22, | ||
81 | }; | ||
82 | |||
83 | static struct { | ||
84 | u32 status; | ||
85 | int errno; | ||
86 | } mnt_errtbl[] = { | ||
87 | { .status = MNT_OK, .errno = 0, }, | ||
88 | { .status = MNT_EPERM, .errno = -EPERM, }, | ||
89 | { .status = MNT_ENOENT, .errno = -ENOENT, }, | ||
90 | { .status = MNT_EACCES, .errno = -EACCES, }, | ||
91 | { .status = MNT_EINVAL, .errno = -EINVAL, }, | ||
92 | }; | ||
93 | |||
94 | /* | ||
95 | * Defined by RFC 1813, section 5.1.5 | ||
96 | */ | ||
97 | enum mountstat3 { | ||
98 | MNT3_OK = 0, /* no error */ | ||
99 | MNT3ERR_PERM = 1, /* Not owner */ | ||
100 | MNT3ERR_NOENT = 2, /* No such file or directory */ | ||
101 | MNT3ERR_IO = 5, /* I/O error */ | ||
102 | MNT3ERR_ACCES = 13, /* Permission denied */ | ||
103 | MNT3ERR_NOTDIR = 20, /* Not a directory */ | ||
104 | MNT3ERR_INVAL = 22, /* Invalid argument */ | ||
105 | MNT3ERR_NAMETOOLONG = 63, /* Filename too long */ | ||
106 | MNT3ERR_NOTSUPP = 10004, /* Operation not supported */ | ||
107 | MNT3ERR_SERVERFAULT = 10006, /* A failure on the server */ | ||
108 | }; | ||
109 | |||
110 | static struct { | ||
111 | u32 status; | ||
112 | int errno; | ||
113 | } mnt3_errtbl[] = { | ||
114 | { .status = MNT3_OK, .errno = 0, }, | ||
115 | { .status = MNT3ERR_PERM, .errno = -EPERM, }, | ||
116 | { .status = MNT3ERR_NOENT, .errno = -ENOENT, }, | ||
117 | { .status = MNT3ERR_IO, .errno = -EIO, }, | ||
118 | { .status = MNT3ERR_ACCES, .errno = -EACCES, }, | ||
119 | { .status = MNT3ERR_NOTDIR, .errno = -ENOTDIR, }, | ||
120 | { .status = MNT3ERR_INVAL, .errno = -EINVAL, }, | ||
121 | { .status = MNT3ERR_NAMETOOLONG, .errno = -ENAMETOOLONG, }, | ||
122 | { .status = MNT3ERR_NOTSUPP, .errno = -ENOTSUPP, }, | ||
123 | { .status = MNT3ERR_SERVERFAULT, .errno = -ESERVERFAULT, }, | ||
124 | }; | ||
125 | |||
126 | struct mountres { | ||
127 | int errno; | ||
128 | struct nfs_fh *fh; | ||
129 | unsigned int *auth_count; | ||
130 | rpc_authflavor_t *auth_flavors; | ||
131 | }; | ||
132 | |||
25 | struct mnt_fhstatus { | 133 | struct mnt_fhstatus { |
26 | u32 status; | 134 | u32 status; |
27 | struct nfs_fh *fh; | 135 | struct nfs_fh *fh; |
@@ -35,8 +143,10 @@ struct mnt_fhstatus { | |||
35 | */ | 143 | */ |
36 | int nfs_mount(struct nfs_mount_request *info) | 144 | int nfs_mount(struct nfs_mount_request *info) |
37 | { | 145 | { |
38 | struct mnt_fhstatus result = { | 146 | struct mountres result = { |
39 | .fh = info->fh | 147 | .fh = info->fh, |
148 | .auth_count = info->auth_flav_len, | ||
149 | .auth_flavors = info->auth_flavs, | ||
40 | }; | 150 | }; |
41 | struct rpc_message msg = { | 151 | struct rpc_message msg = { |
42 | .rpc_argp = info->dirpath, | 152 | .rpc_argp = info->dirpath, |
@@ -68,14 +178,14 @@ int nfs_mount(struct nfs_mount_request *info) | |||
68 | if (info->version == NFS_MNT3_VERSION) | 178 | if (info->version == NFS_MNT3_VERSION) |
69 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; | 179 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; |
70 | else | 180 | else |
71 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT]; | 181 | msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; |
72 | 182 | ||
73 | status = rpc_call_sync(mnt_clnt, &msg, 0); | 183 | status = rpc_call_sync(mnt_clnt, &msg, 0); |
74 | rpc_shutdown_client(mnt_clnt); | 184 | rpc_shutdown_client(mnt_clnt); |
75 | 185 | ||
76 | if (status < 0) | 186 | if (status < 0) |
77 | goto out_call_err; | 187 | goto out_call_err; |
78 | if (result.status != 0) | 188 | if (result.errno != 0) |
79 | goto out_mnt_err; | 189 | goto out_mnt_err; |
80 | 190 | ||
81 | dprintk("NFS: MNT request succeeded\n"); | 191 | dprintk("NFS: MNT request succeeded\n"); |
@@ -86,72 +196,215 @@ out: | |||
86 | 196 | ||
87 | out_clnt_err: | 197 | out_clnt_err: |
88 | status = PTR_ERR(mnt_clnt); | 198 | status = PTR_ERR(mnt_clnt); |
89 | dprintk("NFS: failed to create RPC client, status=%d\n", status); | 199 | dprintk("NFS: failed to create MNT RPC client, status=%d\n", status); |
90 | goto out; | 200 | goto out; |
91 | 201 | ||
92 | out_call_err: | 202 | out_call_err: |
93 | dprintk("NFS: failed to start MNT request, status=%d\n", status); | 203 | dprintk("NFS: MNT request failed, status=%d\n", status); |
94 | goto out; | 204 | goto out; |
95 | 205 | ||
96 | out_mnt_err: | 206 | out_mnt_err: |
97 | dprintk("NFS: MNT server returned result %d\n", result.status); | 207 | dprintk("NFS: MNT server returned result %d\n", result.errno); |
98 | status = nfs_stat_to_errno(result.status); | 208 | status = result.errno; |
99 | goto out; | 209 | goto out; |
100 | } | 210 | } |
101 | 211 | ||
102 | /* | 212 | /* |
103 | * XDR encode/decode functions for MOUNT | 213 | * XDR encode/decode functions for MOUNT |
104 | */ | 214 | */ |
105 | static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, | 215 | |
106 | const char *path) | 216 | static int encode_mntdirpath(struct xdr_stream *xdr, const char *pathname) |
217 | { | ||
218 | const u32 pathname_len = strlen(pathname); | ||
219 | __be32 *p; | ||
220 | |||
221 | if (unlikely(pathname_len > MNTPATHLEN)) | ||
222 | return -EIO; | ||
223 | |||
224 | p = xdr_reserve_space(xdr, sizeof(u32) + pathname_len); | ||
225 | if (unlikely(p == NULL)) | ||
226 | return -EIO; | ||
227 | xdr_encode_opaque(p, pathname, pathname_len); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int mnt_enc_dirpath(struct rpc_rqst *req, __be32 *p, | ||
233 | const char *dirpath) | ||
234 | { | ||
235 | struct xdr_stream xdr; | ||
236 | |||
237 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
238 | return encode_mntdirpath(&xdr, dirpath); | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * RFC 1094: "A non-zero status indicates some sort of error. In this | ||
243 | * case, the status is a UNIX error number." This can be problematic | ||
244 | * if the server and client use different errno values for the same | ||
245 | * error. | ||
246 | * | ||
247 | * However, the OpenGroup XNFS spec provides a simple mapping that is | ||
248 | * independent of local errno values on the server and the client. | ||
249 | */ | ||
250 | static int decode_status(struct xdr_stream *xdr, struct mountres *res) | ||
107 | { | 251 | { |
108 | p = xdr_encode_string(p, path); | 252 | unsigned int i; |
253 | u32 status; | ||
254 | __be32 *p; | ||
255 | |||
256 | p = xdr_inline_decode(xdr, sizeof(status)); | ||
257 | if (unlikely(p == NULL)) | ||
258 | return -EIO; | ||
259 | status = ntohl(*p); | ||
109 | 260 | ||
110 | req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); | 261 | for (i = 0; i <= ARRAY_SIZE(mnt_errtbl); i++) { |
262 | if (mnt_errtbl[i].status == status) { | ||
263 | res->errno = mnt_errtbl[i].errno; | ||
264 | return 0; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | dprintk("NFS: unrecognized MNT status code: %u\n", status); | ||
269 | res->errno = -EACCES; | ||
111 | return 0; | 270 | return 0; |
112 | } | 271 | } |
113 | 272 | ||
114 | static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, | 273 | static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res) |
115 | struct mnt_fhstatus *res) | ||
116 | { | 274 | { |
117 | struct nfs_fh *fh = res->fh; | 275 | struct nfs_fh *fh = res->fh; |
276 | __be32 *p; | ||
277 | |||
278 | p = xdr_inline_decode(xdr, NFS2_FHSIZE); | ||
279 | if (unlikely(p == NULL)) | ||
280 | return -EIO; | ||
281 | |||
282 | fh->size = NFS2_FHSIZE; | ||
283 | memcpy(fh->data, p, NFS2_FHSIZE); | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static int mnt_dec_mountres(struct rpc_rqst *req, __be32 *p, | ||
288 | struct mountres *res) | ||
289 | { | ||
290 | struct xdr_stream xdr; | ||
291 | int status; | ||
292 | |||
293 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | ||
294 | |||
295 | status = decode_status(&xdr, res); | ||
296 | if (unlikely(status != 0 || res->errno != 0)) | ||
297 | return status; | ||
298 | return decode_fhandle(&xdr, res); | ||
299 | } | ||
300 | |||
301 | static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res) | ||
302 | { | ||
303 | unsigned int i; | ||
304 | u32 status; | ||
305 | __be32 *p; | ||
118 | 306 | ||
119 | if ((res->status = ntohl(*p++)) == 0) { | 307 | p = xdr_inline_decode(xdr, sizeof(status)); |
120 | fh->size = NFS2_FHSIZE; | 308 | if (unlikely(p == NULL)) |
121 | memcpy(fh->data, p, NFS2_FHSIZE); | 309 | return -EIO; |
310 | status = ntohl(*p); | ||
311 | |||
312 | for (i = 0; i <= ARRAY_SIZE(mnt3_errtbl); i++) { | ||
313 | if (mnt3_errtbl[i].status == status) { | ||
314 | res->errno = mnt3_errtbl[i].errno; | ||
315 | return 0; | ||
316 | } | ||
122 | } | 317 | } |
318 | |||
319 | dprintk("NFS: unrecognized MNT3 status code: %u\n", status); | ||
320 | res->errno = -EACCES; | ||
123 | return 0; | 321 | return 0; |
124 | } | 322 | } |
125 | 323 | ||
126 | static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, | 324 | static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res) |
127 | struct mnt_fhstatus *res) | ||
128 | { | 325 | { |
129 | struct nfs_fh *fh = res->fh; | 326 | struct nfs_fh *fh = res->fh; |
130 | unsigned size; | 327 | u32 size; |
131 | 328 | __be32 *p; | |
132 | if ((res->status = ntohl(*p++)) == 0) { | 329 | |
133 | size = ntohl(*p++); | 330 | p = xdr_inline_decode(xdr, sizeof(size)); |
134 | if (size <= NFS3_FHSIZE && size != 0) { | 331 | if (unlikely(p == NULL)) |
135 | fh->size = size; | 332 | return -EIO; |
136 | memcpy(fh->data, p, size); | 333 | |
137 | } else | 334 | size = ntohl(*p++); |
138 | res->status = -EBADHANDLE; | 335 | if (size > NFS3_FHSIZE || size == 0) |
336 | return -EIO; | ||
337 | |||
338 | p = xdr_inline_decode(xdr, size); | ||
339 | if (unlikely(p == NULL)) | ||
340 | return -EIO; | ||
341 | |||
342 | fh->size = size; | ||
343 | memcpy(fh->data, p, size); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res) | ||
348 | { | ||
349 | rpc_authflavor_t *flavors = res->auth_flavors; | ||
350 | unsigned int *count = res->auth_count; | ||
351 | u32 entries, i; | ||
352 | __be32 *p; | ||
353 | |||
354 | if (*count == 0) | ||
355 | return 0; | ||
356 | |||
357 | p = xdr_inline_decode(xdr, sizeof(entries)); | ||
358 | if (unlikely(p == NULL)) | ||
359 | return -EIO; | ||
360 | entries = ntohl(*p); | ||
361 | dprintk("NFS: received %u auth flavors\n", entries); | ||
362 | if (entries > NFS_MAX_SECFLAVORS) | ||
363 | entries = NFS_MAX_SECFLAVORS; | ||
364 | |||
365 | p = xdr_inline_decode(xdr, sizeof(u32) * entries); | ||
366 | if (unlikely(p == NULL)) | ||
367 | return -EIO; | ||
368 | |||
369 | if (entries > *count) | ||
370 | entries = *count; | ||
371 | |||
372 | for (i = 0; i < entries; i++) { | ||
373 | flavors[i] = ntohl(*p++); | ||
374 | dprintk("NFS:\tflavor %u: %d\n", i, flavors[i]); | ||
139 | } | 375 | } |
376 | *count = i; | ||
377 | |||
140 | return 0; | 378 | return 0; |
141 | } | 379 | } |
142 | 380 | ||
143 | #define MNT_dirpath_sz (1 + 256) | 381 | static int mnt_dec_mountres3(struct rpc_rqst *req, __be32 *p, |
144 | #define MNT_fhstatus_sz (1 + 8) | 382 | struct mountres *res) |
145 | #define MNT_fhstatus3_sz (1 + 16) | 383 | { |
384 | struct xdr_stream xdr; | ||
385 | int status; | ||
386 | |||
387 | xdr_init_decode(&xdr, &req->rq_rcv_buf, p); | ||
388 | |||
389 | status = decode_fhs_status(&xdr, res); | ||
390 | if (unlikely(status != 0 || res->errno != 0)) | ||
391 | return status; | ||
392 | status = decode_fhandle3(&xdr, res); | ||
393 | if (unlikely(status != 0)) { | ||
394 | res->errno = -EBADHANDLE; | ||
395 | return 0; | ||
396 | } | ||
397 | return decode_auth_flavors(&xdr, res); | ||
398 | } | ||
146 | 399 | ||
147 | static struct rpc_procinfo mnt_procedures[] = { | 400 | static struct rpc_procinfo mnt_procedures[] = { |
148 | [MNTPROC_MNT] = { | 401 | [MOUNTPROC_MNT] = { |
149 | .p_proc = MNTPROC_MNT, | 402 | .p_proc = MOUNTPROC_MNT, |
150 | .p_encode = (kxdrproc_t) xdr_encode_dirpath, | 403 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, |
151 | .p_decode = (kxdrproc_t) xdr_decode_fhstatus, | 404 | .p_decode = (kxdrproc_t)mnt_dec_mountres, |
152 | .p_arglen = MNT_dirpath_sz, | 405 | .p_arglen = MNT_enc_dirpath_sz, |
153 | .p_replen = MNT_fhstatus_sz, | 406 | .p_replen = MNT_dec_mountres_sz, |
154 | .p_statidx = MNTPROC_MNT, | 407 | .p_statidx = MOUNTPROC_MNT, |
155 | .p_name = "MOUNT", | 408 | .p_name = "MOUNT", |
156 | }, | 409 | }, |
157 | }; | 410 | }; |
@@ -159,10 +412,10 @@ static struct rpc_procinfo mnt_procedures[] = { | |||
159 | static struct rpc_procinfo mnt3_procedures[] = { | 412 | static struct rpc_procinfo mnt3_procedures[] = { |
160 | [MOUNTPROC3_MNT] = { | 413 | [MOUNTPROC3_MNT] = { |
161 | .p_proc = MOUNTPROC3_MNT, | 414 | .p_proc = MOUNTPROC3_MNT, |
162 | .p_encode = (kxdrproc_t) xdr_encode_dirpath, | 415 | .p_encode = (kxdrproc_t)mnt_enc_dirpath, |
163 | .p_decode = (kxdrproc_t) xdr_decode_fhstatus3, | 416 | .p_decode = (kxdrproc_t)mnt_dec_mountres3, |
164 | .p_arglen = MNT_dirpath_sz, | 417 | .p_arglen = MNT_enc_dirpath_sz, |
165 | .p_replen = MNT_fhstatus3_sz, | 418 | .p_replen = MNT_dec_mountres3_sz, |
166 | .p_statidx = MOUNTPROC3_MNT, | 419 | .p_statidx = MOUNTPROC3_MNT, |
167 | .p_name = "MOUNT", | 420 | .p_name = "MOUNT", |
168 | }, | 421 | }, |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 6bbf0e6daad2..bac60515a4b3 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -207,8 +207,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
207 | status = nfs_revalidate_inode(server, inode); | 207 | status = nfs_revalidate_inode(server, inode); |
208 | if (status < 0) | 208 | if (status < 0) |
209 | return ERR_PTR(status); | 209 | return ERR_PTR(status); |
210 | if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) | ||
211 | nfs_zap_acl_cache(inode); | ||
212 | acl = nfs3_get_cached_acl(inode, type); | 210 | acl = nfs3_get_cached_acl(inode, type); |
213 | if (acl != ERR_PTR(-EAGAIN)) | 211 | if (acl != ERR_PTR(-EAGAIN)) |
214 | return acl; | 212 | return acl; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 57dabb8a048e..7a750f061c26 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1173,16 +1173,30 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1173 | err = _nfs4_open_delegation_recall(ctx, state, stateid); | 1173 | err = _nfs4_open_delegation_recall(ctx, state, stateid); |
1174 | switch (err) { | 1174 | switch (err) { |
1175 | case 0: | 1175 | case 0: |
1176 | return err; | 1176 | case -ENOENT: |
1177 | case -ESTALE: | ||
1178 | goto out; | ||
1177 | case -NFS4ERR_STALE_CLIENTID: | 1179 | case -NFS4ERR_STALE_CLIENTID: |
1178 | case -NFS4ERR_STALE_STATEID: | 1180 | case -NFS4ERR_STALE_STATEID: |
1179 | case -NFS4ERR_EXPIRED: | 1181 | case -NFS4ERR_EXPIRED: |
1180 | /* Don't recall a delegation if it was lost */ | 1182 | /* Don't recall a delegation if it was lost */ |
1181 | nfs4_schedule_state_recovery(server->nfs_client); | 1183 | nfs4_schedule_state_recovery(server->nfs_client); |
1182 | return err; | 1184 | goto out; |
1185 | case -ERESTARTSYS: | ||
1186 | /* | ||
1187 | * The show must go on: exit, but mark the | ||
1188 | * stateid as needing recovery. | ||
1189 | */ | ||
1190 | case -NFS4ERR_ADMIN_REVOKED: | ||
1191 | case -NFS4ERR_BAD_STATEID: | ||
1192 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | ||
1193 | case -ENOMEM: | ||
1194 | err = 0; | ||
1195 | goto out; | ||
1183 | } | 1196 | } |
1184 | err = nfs4_handle_exception(server, err, &exception); | 1197 | err = nfs4_handle_exception(server, err, &exception); |
1185 | } while (exception.retry); | 1198 | } while (exception.retry); |
1199 | out: | ||
1186 | return err; | 1200 | return err; |
1187 | } | 1201 | } |
1188 | 1202 | ||
@@ -3238,8 +3252,6 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | |||
3238 | ret = nfs_revalidate_inode(server, inode); | 3252 | ret = nfs_revalidate_inode(server, inode); |
3239 | if (ret < 0) | 3253 | if (ret < 0) |
3240 | return ret; | 3254 | return ret; |
3241 | if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) | ||
3242 | nfs_zap_acl_cache(inode); | ||
3243 | ret = nfs4_read_cached_acl(inode, buf, buflen); | 3255 | ret = nfs4_read_cached_acl(inode, buf, buflen); |
3244 | if (ret != -ENOENT) | 3256 | if (ret != -ENOENT) |
3245 | return ret; | 3257 | return ret; |
@@ -3977,8 +3989,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3977 | ret = nfs4_wait_for_completion_rpc_task(task); | 3989 | ret = nfs4_wait_for_completion_rpc_task(task); |
3978 | if (ret == 0) { | 3990 | if (ret == 0) { |
3979 | ret = data->rpc_status; | 3991 | ret = data->rpc_status; |
3980 | if (ret == -NFS4ERR_DENIED) | ||
3981 | ret = -EAGAIN; | ||
3982 | } else | 3992 | } else |
3983 | data->cancelled = 1; | 3993 | data->cancelled = 1; |
3984 | rpc_put_task(task); | 3994 | rpc_put_task(task); |
@@ -4066,9 +4076,11 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock * | |||
4066 | int err; | 4076 | int err; |
4067 | 4077 | ||
4068 | do { | 4078 | do { |
4079 | err = _nfs4_proc_setlk(state, cmd, request); | ||
4080 | if (err == -NFS4ERR_DENIED) | ||
4081 | err = -EAGAIN; | ||
4069 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | 4082 | err = nfs4_handle_exception(NFS_SERVER(state->inode), |
4070 | _nfs4_proc_setlk(state, cmd, request), | 4083 | err, &exception); |
4071 | &exception); | ||
4072 | } while (exception.retry); | 4084 | } while (exception.retry); |
4073 | return err; | 4085 | return err; |
4074 | } | 4086 | } |
@@ -4120,8 +4132,37 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4120 | goto out; | 4132 | goto out; |
4121 | do { | 4133 | do { |
4122 | err = _nfs4_do_setlk(state, F_SETLK, fl, 0); | 4134 | err = _nfs4_do_setlk(state, F_SETLK, fl, 0); |
4123 | if (err != -NFS4ERR_DELAY) | 4135 | switch (err) { |
4124 | break; | 4136 | default: |
4137 | printk(KERN_ERR "%s: unhandled error %d.\n", | ||
4138 | __func__, err); | ||
4139 | case 0: | ||
4140 | case -ESTALE: | ||
4141 | goto out; | ||
4142 | case -NFS4ERR_EXPIRED: | ||
4143 | case -NFS4ERR_STALE_CLIENTID: | ||
4144 | case -NFS4ERR_STALE_STATEID: | ||
4145 | nfs4_schedule_state_recovery(server->nfs_client); | ||
4146 | goto out; | ||
4147 | case -ERESTARTSYS: | ||
4148 | /* | ||
4149 | * The show must go on: exit, but mark the | ||
4150 | * stateid as needing recovery. | ||
4151 | */ | ||
4152 | case -NFS4ERR_ADMIN_REVOKED: | ||
4153 | case -NFS4ERR_BAD_STATEID: | ||
4154 | case -NFS4ERR_OPENMODE: | ||
4155 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | ||
4156 | err = 0; | ||
4157 | goto out; | ||
4158 | case -ENOMEM: | ||
4159 | case -NFS4ERR_DENIED: | ||
4160 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | ||
4161 | err = 0; | ||
4162 | goto out; | ||
4163 | case -NFS4ERR_DELAY: | ||
4164 | break; | ||
4165 | } | ||
4125 | err = nfs4_handle_exception(server, err, &exception); | 4166 | err = nfs4_handle_exception(server, err, &exception); |
4126 | } while (exception.retry); | 4167 | } while (exception.retry); |
4127 | out: | 4168 | out: |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 2cfca9929c9a..b73c5a728655 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -853,32 +853,45 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ | |||
853 | struct file_lock *fl; | 853 | struct file_lock *fl; |
854 | int status = 0; | 854 | int status = 0; |
855 | 855 | ||
856 | if (inode->i_flock == NULL) | ||
857 | return 0; | ||
858 | |||
859 | /* Guard against delegation returns and new lock/unlock calls */ | ||
856 | down_write(&nfsi->rwsem); | 860 | down_write(&nfsi->rwsem); |
861 | /* Protect inode->i_flock using the BKL */ | ||
862 | lock_kernel(); | ||
857 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 863 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { |
858 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 864 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) |
859 | continue; | 865 | continue; |
860 | if (nfs_file_open_context(fl->fl_file)->state != state) | 866 | if (nfs_file_open_context(fl->fl_file)->state != state) |
861 | continue; | 867 | continue; |
868 | unlock_kernel(); | ||
862 | status = ops->recover_lock(state, fl); | 869 | status = ops->recover_lock(state, fl); |
863 | if (status >= 0) | ||
864 | continue; | ||
865 | switch (status) { | 870 | switch (status) { |
871 | case 0: | ||
872 | break; | ||
873 | case -ESTALE: | ||
874 | case -NFS4ERR_ADMIN_REVOKED: | ||
875 | case -NFS4ERR_STALE_STATEID: | ||
876 | case -NFS4ERR_BAD_STATEID: | ||
877 | case -NFS4ERR_EXPIRED: | ||
878 | case -NFS4ERR_NO_GRACE: | ||
879 | case -NFS4ERR_STALE_CLIENTID: | ||
880 | goto out; | ||
866 | default: | 881 | default: |
867 | printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", | 882 | printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", |
868 | __func__, status); | 883 | __func__, status); |
869 | case -NFS4ERR_EXPIRED: | 884 | case -ENOMEM: |
870 | case -NFS4ERR_NO_GRACE: | 885 | case -NFS4ERR_DENIED: |
871 | case -NFS4ERR_RECLAIM_BAD: | 886 | case -NFS4ERR_RECLAIM_BAD: |
872 | case -NFS4ERR_RECLAIM_CONFLICT: | 887 | case -NFS4ERR_RECLAIM_CONFLICT: |
873 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | 888 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
874 | break; | 889 | status = 0; |
875 | case -NFS4ERR_STALE_CLIENTID: | ||
876 | goto out_err; | ||
877 | } | 890 | } |
891 | lock_kernel(); | ||
878 | } | 892 | } |
879 | up_write(&nfsi->rwsem); | 893 | unlock_kernel(); |
880 | return 0; | 894 | out: |
881 | out_err: | ||
882 | up_write(&nfsi->rwsem); | 895 | up_write(&nfsi->rwsem); |
883 | return status; | 896 | return status; |
884 | } | 897 | } |
@@ -924,6 +937,7 @@ restart: | |||
924 | printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", | 937 | printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", |
925 | __func__, status); | 938 | __func__, status); |
926 | case -ENOENT: | 939 | case -ENOENT: |
940 | case -ENOMEM: | ||
927 | case -ESTALE: | 941 | case -ESTALE: |
928 | /* | 942 | /* |
929 | * Open state on this file cannot be recovered | 943 | * Open state on this file cannot be recovered |
@@ -934,6 +948,9 @@ restart: | |||
934 | /* Mark the file as being 'closed' */ | 948 | /* Mark the file as being 'closed' */ |
935 | state->state = 0; | 949 | state->state = 0; |
936 | break; | 950 | break; |
951 | case -NFS4ERR_ADMIN_REVOKED: | ||
952 | case -NFS4ERR_STALE_STATEID: | ||
953 | case -NFS4ERR_BAD_STATEID: | ||
937 | case -NFS4ERR_RECLAIM_BAD: | 954 | case -NFS4ERR_RECLAIM_BAD: |
938 | case -NFS4ERR_RECLAIM_CONFLICT: | 955 | case -NFS4ERR_RECLAIM_CONFLICT: |
939 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); | 956 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index e3ed5908820b..8c55b27c0de4 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -92,6 +92,9 @@ | |||
92 | #undef NFSROOT_DEBUG | 92 | #undef NFSROOT_DEBUG |
93 | #define NFSDBG_FACILITY NFSDBG_ROOT | 93 | #define NFSDBG_FACILITY NFSDBG_ROOT |
94 | 94 | ||
95 | /* Default port to use if server is not running a portmapper */ | ||
96 | #define NFS_MNT_PORT 627 | ||
97 | |||
95 | /* Default path we try to mount. "%s" gets replaced by our IP address */ | 98 | /* Default path we try to mount. "%s" gets replaced by our IP address */ |
96 | #define NFS_ROOT "/tftpboot/%s" | 99 | #define NFS_ROOT "/tftpboot/%s" |
97 | 100 | ||
@@ -487,6 +490,7 @@ static int __init root_nfs_get_handle(void) | |||
487 | { | 490 | { |
488 | struct nfs_fh fh; | 491 | struct nfs_fh fh; |
489 | struct sockaddr_in sin; | 492 | struct sockaddr_in sin; |
493 | unsigned int auth_flav_len = 0; | ||
490 | struct nfs_mount_request request = { | 494 | struct nfs_mount_request request = { |
491 | .sap = (struct sockaddr *)&sin, | 495 | .sap = (struct sockaddr *)&sin, |
492 | .salen = sizeof(sin), | 496 | .salen = sizeof(sin), |
@@ -496,6 +500,7 @@ static int __init root_nfs_get_handle(void) | |||
496 | .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? | 500 | .protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? |
497 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP, | 501 | XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP, |
498 | .fh = &fh, | 502 | .fh = &fh, |
503 | .auth_flav_len = &auth_flav_len, | ||
499 | }; | 504 | }; |
500 | int status; | 505 | int status; |
501 | 506 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 6063054455f8..3d460527daab 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -140,22 +140,22 @@ static const match_table_t nfs_mount_option_tokens = { | |||
140 | { Opt_fscache_uniq, "fsc=%s" }, | 140 | { Opt_fscache_uniq, "fsc=%s" }, |
141 | { Opt_nofscache, "nofsc" }, | 141 | { Opt_nofscache, "nofsc" }, |
142 | 142 | ||
143 | { Opt_port, "port=%u" }, | 143 | { Opt_port, "port=%s" }, |
144 | { Opt_rsize, "rsize=%u" }, | 144 | { Opt_rsize, "rsize=%s" }, |
145 | { Opt_wsize, "wsize=%u" }, | 145 | { Opt_wsize, "wsize=%s" }, |
146 | { Opt_bsize, "bsize=%u" }, | 146 | { Opt_bsize, "bsize=%s" }, |
147 | { Opt_timeo, "timeo=%u" }, | 147 | { Opt_timeo, "timeo=%s" }, |
148 | { Opt_retrans, "retrans=%u" }, | 148 | { Opt_retrans, "retrans=%s" }, |
149 | { Opt_acregmin, "acregmin=%u" }, | 149 | { Opt_acregmin, "acregmin=%s" }, |
150 | { Opt_acregmax, "acregmax=%u" }, | 150 | { Opt_acregmax, "acregmax=%s" }, |
151 | { Opt_acdirmin, "acdirmin=%u" }, | 151 | { Opt_acdirmin, "acdirmin=%s" }, |
152 | { Opt_acdirmax, "acdirmax=%u" }, | 152 | { Opt_acdirmax, "acdirmax=%s" }, |
153 | { Opt_actimeo, "actimeo=%u" }, | 153 | { Opt_actimeo, "actimeo=%s" }, |
154 | { Opt_namelen, "namlen=%u" }, | 154 | { Opt_namelen, "namlen=%s" }, |
155 | { Opt_mountport, "mountport=%u" }, | 155 | { Opt_mountport, "mountport=%s" }, |
156 | { Opt_mountvers, "mountvers=%u" }, | 156 | { Opt_mountvers, "mountvers=%s" }, |
157 | { Opt_nfsvers, "nfsvers=%u" }, | 157 | { Opt_nfsvers, "nfsvers=%s" }, |
158 | { Opt_nfsvers, "vers=%u" }, | 158 | { Opt_nfsvers, "vers=%s" }, |
159 | { Opt_minorversion, "minorversion=%u" }, | 159 | { Opt_minorversion, "minorversion=%u" }, |
160 | 160 | ||
161 | { Opt_sec, "sec=%s" }, | 161 | { Opt_sec, "sec=%s" }, |
@@ -516,7 +516,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
516 | const char *nostr; | 516 | const char *nostr; |
517 | } nfs_info[] = { | 517 | } nfs_info[] = { |
518 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 518 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
519 | { NFS_MOUNT_INTR, ",intr", ",nointr" }, | ||
520 | { NFS_MOUNT_POSIX, ",posix", "" }, | 519 | { NFS_MOUNT_POSIX, ",posix", "" }, |
521 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 520 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
522 | { NFS_MOUNT_NOAC, ",noac", "" }, | 521 | { NFS_MOUNT_NOAC, ",noac", "" }, |
@@ -945,11 +944,6 @@ static int nfs_parse_security_flavors(char *value, | |||
945 | return 1; | 944 | return 1; |
946 | } | 945 | } |
947 | 946 | ||
948 | static void nfs_parse_invalid_value(const char *option) | ||
949 | { | ||
950 | dfprintk(MOUNT, "NFS: bad value specified for %s option\n", option); | ||
951 | } | ||
952 | |||
953 | /* | 947 | /* |
954 | * Error-check and convert a string of mount options from user space into | 948 | * Error-check and convert a string of mount options from user space into |
955 | * a data structure. The whole mount string is processed; bad options are | 949 | * a data structure. The whole mount string is processed; bad options are |
@@ -960,7 +954,7 @@ static int nfs_parse_mount_options(char *raw, | |||
960 | struct nfs_parsed_mount_data *mnt) | 954 | struct nfs_parsed_mount_data *mnt) |
961 | { | 955 | { |
962 | char *p, *string, *secdata; | 956 | char *p, *string, *secdata; |
963 | int rc, sloppy = 0, errors = 0; | 957 | int rc, sloppy = 0, invalid_option = 0; |
964 | 958 | ||
965 | if (!raw) { | 959 | if (!raw) { |
966 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 960 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -984,7 +978,9 @@ static int nfs_parse_mount_options(char *raw, | |||
984 | 978 | ||
985 | while ((p = strsep(&raw, ",")) != NULL) { | 979 | while ((p = strsep(&raw, ",")) != NULL) { |
986 | substring_t args[MAX_OPT_ARGS]; | 980 | substring_t args[MAX_OPT_ARGS]; |
987 | int option, token; | 981 | unsigned long option; |
982 | int int_option; | ||
983 | int token; | ||
988 | 984 | ||
989 | if (!*p) | 985 | if (!*p) |
990 | continue; | 986 | continue; |
@@ -1093,114 +1089,156 @@ static int nfs_parse_mount_options(char *raw, | |||
1093 | * options that take numeric values | 1089 | * options that take numeric values |
1094 | */ | 1090 | */ |
1095 | case Opt_port: | 1091 | case Opt_port: |
1096 | if (match_int(args, &option) || | 1092 | string = match_strdup(args); |
1097 | option < 0 || option > USHORT_MAX) { | 1093 | if (string == NULL) |
1098 | errors++; | 1094 | goto out_nomem; |
1099 | nfs_parse_invalid_value("port"); | 1095 | rc = strict_strtoul(string, 10, &option); |
1100 | } else | 1096 | kfree(string); |
1101 | mnt->nfs_server.port = option; | 1097 | if (rc != 0 || option > USHORT_MAX) |
1098 | goto out_invalid_value; | ||
1099 | mnt->nfs_server.port = option; | ||
1102 | break; | 1100 | break; |
1103 | case Opt_rsize: | 1101 | case Opt_rsize: |
1104 | if (match_int(args, &option) || option < 0) { | 1102 | string = match_strdup(args); |
1105 | errors++; | 1103 | if (string == NULL) |
1106 | nfs_parse_invalid_value("rsize"); | 1104 | goto out_nomem; |
1107 | } else | 1105 | rc = strict_strtoul(string, 10, &option); |
1108 | mnt->rsize = option; | 1106 | kfree(string); |
1107 | if (rc != 0) | ||
1108 | goto out_invalid_value; | ||
1109 | mnt->rsize = option; | ||
1109 | break; | 1110 | break; |
1110 | case Opt_wsize: | 1111 | case Opt_wsize: |
1111 | if (match_int(args, &option) || option < 0) { | 1112 | string = match_strdup(args); |
1112 | errors++; | 1113 | if (string == NULL) |
1113 | nfs_parse_invalid_value("wsize"); | 1114 | goto out_nomem; |
1114 | } else | 1115 | rc = strict_strtoul(string, 10, &option); |
1115 | mnt->wsize = option; | 1116 | kfree(string); |
1117 | if (rc != 0) | ||
1118 | goto out_invalid_value; | ||
1119 | mnt->wsize = option; | ||
1116 | break; | 1120 | break; |
1117 | case Opt_bsize: | 1121 | case Opt_bsize: |
1118 | if (match_int(args, &option) || option < 0) { | 1122 | string = match_strdup(args); |
1119 | errors++; | 1123 | if (string == NULL) |
1120 | nfs_parse_invalid_value("bsize"); | 1124 | goto out_nomem; |
1121 | } else | 1125 | rc = strict_strtoul(string, 10, &option); |
1122 | mnt->bsize = option; | 1126 | kfree(string); |
1127 | if (rc != 0) | ||
1128 | goto out_invalid_value; | ||
1129 | mnt->bsize = option; | ||
1123 | break; | 1130 | break; |
1124 | case Opt_timeo: | 1131 | case Opt_timeo: |
1125 | if (match_int(args, &option) || option <= 0) { | 1132 | string = match_strdup(args); |
1126 | errors++; | 1133 | if (string == NULL) |
1127 | nfs_parse_invalid_value("timeo"); | 1134 | goto out_nomem; |
1128 | } else | 1135 | rc = strict_strtoul(string, 10, &option); |
1129 | mnt->timeo = option; | 1136 | kfree(string); |
1137 | if (rc != 0 || option == 0) | ||
1138 | goto out_invalid_value; | ||
1139 | mnt->timeo = option; | ||
1130 | break; | 1140 | break; |
1131 | case Opt_retrans: | 1141 | case Opt_retrans: |
1132 | if (match_int(args, &option) || option <= 0) { | 1142 | string = match_strdup(args); |
1133 | errors++; | 1143 | if (string == NULL) |
1134 | nfs_parse_invalid_value("retrans"); | 1144 | goto out_nomem; |
1135 | } else | 1145 | rc = strict_strtoul(string, 10, &option); |
1136 | mnt->retrans = option; | 1146 | kfree(string); |
1147 | if (rc != 0 || option == 0) | ||
1148 | goto out_invalid_value; | ||
1149 | mnt->retrans = option; | ||
1137 | break; | 1150 | break; |
1138 | case Opt_acregmin: | 1151 | case Opt_acregmin: |
1139 | if (match_int(args, &option) || option < 0) { | 1152 | string = match_strdup(args); |
1140 | errors++; | 1153 | if (string == NULL) |
1141 | nfs_parse_invalid_value("acregmin"); | 1154 | goto out_nomem; |
1142 | } else | 1155 | rc = strict_strtoul(string, 10, &option); |
1143 | mnt->acregmin = option; | 1156 | kfree(string); |
1157 | if (rc != 0) | ||
1158 | goto out_invalid_value; | ||
1159 | mnt->acregmin = option; | ||
1144 | break; | 1160 | break; |
1145 | case Opt_acregmax: | 1161 | case Opt_acregmax: |
1146 | if (match_int(args, &option) || option < 0) { | 1162 | string = match_strdup(args); |
1147 | errors++; | 1163 | if (string == NULL) |
1148 | nfs_parse_invalid_value("acregmax"); | 1164 | goto out_nomem; |
1149 | } else | 1165 | rc = strict_strtoul(string, 10, &option); |
1150 | mnt->acregmax = option; | 1166 | kfree(string); |
1167 | if (rc != 0) | ||
1168 | goto out_invalid_value; | ||
1169 | mnt->acregmax = option; | ||
1151 | break; | 1170 | break; |
1152 | case Opt_acdirmin: | 1171 | case Opt_acdirmin: |
1153 | if (match_int(args, &option) || option < 0) { | 1172 | string = match_strdup(args); |
1154 | errors++; | 1173 | if (string == NULL) |
1155 | nfs_parse_invalid_value("acdirmin"); | 1174 | goto out_nomem; |
1156 | } else | 1175 | rc = strict_strtoul(string, 10, &option); |
1157 | mnt->acdirmin = option; | 1176 | kfree(string); |
1177 | if (rc != 0) | ||
1178 | goto out_invalid_value; | ||
1179 | mnt->acdirmin = option; | ||
1158 | break; | 1180 | break; |
1159 | case Opt_acdirmax: | 1181 | case Opt_acdirmax: |
1160 | if (match_int(args, &option) || option < 0) { | 1182 | string = match_strdup(args); |
1161 | errors++; | 1183 | if (string == NULL) |
1162 | nfs_parse_invalid_value("acdirmax"); | 1184 | goto out_nomem; |
1163 | } else | 1185 | rc = strict_strtoul(string, 10, &option); |
1164 | mnt->acdirmax = option; | 1186 | kfree(string); |
1187 | if (rc != 0) | ||
1188 | goto out_invalid_value; | ||
1189 | mnt->acdirmax = option; | ||
1165 | break; | 1190 | break; |
1166 | case Opt_actimeo: | 1191 | case Opt_actimeo: |
1167 | if (match_int(args, &option) || option < 0) { | 1192 | string = match_strdup(args); |
1168 | errors++; | 1193 | if (string == NULL) |
1169 | nfs_parse_invalid_value("actimeo"); | 1194 | goto out_nomem; |
1170 | } else | 1195 | rc = strict_strtoul(string, 10, &option); |
1171 | mnt->acregmin = mnt->acregmax = | 1196 | kfree(string); |
1172 | mnt->acdirmin = mnt->acdirmax = option; | 1197 | if (rc != 0) |
1198 | goto out_invalid_value; | ||
1199 | mnt->acregmin = mnt->acregmax = | ||
1200 | mnt->acdirmin = mnt->acdirmax = option; | ||
1173 | break; | 1201 | break; |
1174 | case Opt_namelen: | 1202 | case Opt_namelen: |
1175 | if (match_int(args, &option) || option < 0) { | 1203 | string = match_strdup(args); |
1176 | errors++; | 1204 | if (string == NULL) |
1177 | nfs_parse_invalid_value("namlen"); | 1205 | goto out_nomem; |
1178 | } else | 1206 | rc = strict_strtoul(string, 10, &option); |
1179 | mnt->namlen = option; | 1207 | kfree(string); |
1208 | if (rc != 0) | ||
1209 | goto out_invalid_value; | ||
1210 | mnt->namlen = option; | ||
1180 | break; | 1211 | break; |
1181 | case Opt_mountport: | 1212 | case Opt_mountport: |
1182 | if (match_int(args, &option) || | 1213 | string = match_strdup(args); |
1183 | option < 0 || option > USHORT_MAX) { | 1214 | if (string == NULL) |
1184 | errors++; | 1215 | goto out_nomem; |
1185 | nfs_parse_invalid_value("mountport"); | 1216 | rc = strict_strtoul(string, 10, &option); |
1186 | } else | 1217 | kfree(string); |
1187 | mnt->mount_server.port = option; | 1218 | if (rc != 0 || option > USHORT_MAX) |
1219 | goto out_invalid_value; | ||
1220 | mnt->mount_server.port = option; | ||
1188 | break; | 1221 | break; |
1189 | case Opt_mountvers: | 1222 | case Opt_mountvers: |
1190 | if (match_int(args, &option) || | 1223 | string = match_strdup(args); |
1224 | if (string == NULL) | ||
1225 | goto out_nomem; | ||
1226 | rc = strict_strtoul(string, 10, &option); | ||
1227 | kfree(string); | ||
1228 | if (rc != 0 || | ||
1191 | option < NFS_MNT_VERSION || | 1229 | option < NFS_MNT_VERSION || |
1192 | option > NFS_MNT3_VERSION) { | 1230 | option > NFS_MNT3_VERSION) |
1193 | errors++; | 1231 | goto out_invalid_value; |
1194 | nfs_parse_invalid_value("mountvers"); | 1232 | mnt->mount_server.version = option; |
1195 | } else | ||
1196 | mnt->mount_server.version = option; | ||
1197 | break; | 1233 | break; |
1198 | case Opt_nfsvers: | 1234 | case Opt_nfsvers: |
1199 | if (match_int(args, &option)) { | 1235 | string = match_strdup(args); |
1200 | errors++; | 1236 | if (string == NULL) |
1201 | nfs_parse_invalid_value("nfsvers"); | 1237 | goto out_nomem; |
1202 | break; | 1238 | rc = strict_strtoul(string, 10, &option); |
1203 | } | 1239 | kfree(string); |
1240 | if (rc != 0) | ||
1241 | goto out_invalid_value; | ||
1204 | switch (option) { | 1242 | switch (option) { |
1205 | case NFS2_VERSION: | 1243 | case NFS2_VERSION: |
1206 | mnt->flags &= ~NFS_MOUNT_VER3; | 1244 | mnt->flags &= ~NFS_MOUNT_VER3; |
@@ -1209,16 +1247,15 @@ static int nfs_parse_mount_options(char *raw, | |||
1209 | mnt->flags |= NFS_MOUNT_VER3; | 1247 | mnt->flags |= NFS_MOUNT_VER3; |
1210 | break; | 1248 | break; |
1211 | default: | 1249 | default: |
1212 | errors++; | 1250 | goto out_invalid_value; |
1213 | nfs_parse_invalid_value("nfsvers"); | ||
1214 | } | 1251 | } |
1215 | break; | 1252 | break; |
1216 | case Opt_minorversion: | 1253 | case Opt_minorversion: |
1217 | if (match_int(args, &option)) | 1254 | if (match_int(args, &int_option)) |
1218 | return 0; | 1255 | return 0; |
1219 | if (option < 0 || option > NFS4_MAX_MINOR_VERSION) | 1256 | if (int_option < 0 || int_option > NFS4_MAX_MINOR_VERSION) |
1220 | return 0; | 1257 | return 0; |
1221 | mnt->minorversion = option; | 1258 | mnt->minorversion = int_option; |
1222 | break; | 1259 | break; |
1223 | 1260 | ||
1224 | /* | 1261 | /* |
@@ -1231,9 +1268,9 @@ static int nfs_parse_mount_options(char *raw, | |||
1231 | rc = nfs_parse_security_flavors(string, mnt); | 1268 | rc = nfs_parse_security_flavors(string, mnt); |
1232 | kfree(string); | 1269 | kfree(string); |
1233 | if (!rc) { | 1270 | if (!rc) { |
1234 | errors++; | ||
1235 | dfprintk(MOUNT, "NFS: unrecognized " | 1271 | dfprintk(MOUNT, "NFS: unrecognized " |
1236 | "security flavor\n"); | 1272 | "security flavor\n"); |
1273 | return 0; | ||
1237 | } | 1274 | } |
1238 | break; | 1275 | break; |
1239 | case Opt_proto: | 1276 | case Opt_proto: |
@@ -1247,23 +1284,25 @@ static int nfs_parse_mount_options(char *raw, | |||
1247 | case Opt_xprt_udp: | 1284 | case Opt_xprt_udp: |
1248 | mnt->flags &= ~NFS_MOUNT_TCP; | 1285 | mnt->flags &= ~NFS_MOUNT_TCP; |
1249 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; | 1286 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
1287 | kfree(string); | ||
1250 | break; | 1288 | break; |
1251 | case Opt_xprt_tcp: | 1289 | case Opt_xprt_tcp: |
1252 | mnt->flags |= NFS_MOUNT_TCP; | 1290 | mnt->flags |= NFS_MOUNT_TCP; |
1253 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; | 1291 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
1292 | kfree(string); | ||
1254 | break; | 1293 | break; |
1255 | case Opt_xprt_rdma: | 1294 | case Opt_xprt_rdma: |
1256 | /* vector side protocols to TCP */ | 1295 | /* vector side protocols to TCP */ |
1257 | mnt->flags |= NFS_MOUNT_TCP; | 1296 | mnt->flags |= NFS_MOUNT_TCP; |
1258 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | 1297 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; |
1259 | xprt_load_transport(string); | 1298 | xprt_load_transport(string); |
1299 | kfree(string); | ||
1260 | break; | 1300 | break; |
1261 | default: | 1301 | default: |
1262 | errors++; | ||
1263 | dfprintk(MOUNT, "NFS: unrecognized " | 1302 | dfprintk(MOUNT, "NFS: unrecognized " |
1264 | "transport protocol\n"); | 1303 | "transport protocol\n"); |
1304 | return 0; | ||
1265 | } | 1305 | } |
1266 | kfree(string); | ||
1267 | break; | 1306 | break; |
1268 | case Opt_mountproto: | 1307 | case Opt_mountproto: |
1269 | string = match_strdup(args); | 1308 | string = match_strdup(args); |
@@ -1282,9 +1321,9 @@ static int nfs_parse_mount_options(char *raw, | |||
1282 | break; | 1321 | break; |
1283 | case Opt_xprt_rdma: /* not used for side protocols */ | 1322 | case Opt_xprt_rdma: /* not used for side protocols */ |
1284 | default: | 1323 | default: |
1285 | errors++; | ||
1286 | dfprintk(MOUNT, "NFS: unrecognized " | 1324 | dfprintk(MOUNT, "NFS: unrecognized " |
1287 | "transport protocol\n"); | 1325 | "transport protocol\n"); |
1326 | return 0; | ||
1288 | } | 1327 | } |
1289 | break; | 1328 | break; |
1290 | case Opt_addr: | 1329 | case Opt_addr: |
@@ -1340,9 +1379,9 @@ static int nfs_parse_mount_options(char *raw, | |||
1340 | mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE; | 1379 | mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE; |
1341 | break; | 1380 | break; |
1342 | default: | 1381 | default: |
1343 | errors++; | ||
1344 | dfprintk(MOUNT, "NFS: invalid " | 1382 | dfprintk(MOUNT, "NFS: invalid " |
1345 | "lookupcache argument\n"); | 1383 | "lookupcache argument\n"); |
1384 | return 0; | ||
1346 | }; | 1385 | }; |
1347 | break; | 1386 | break; |
1348 | 1387 | ||
@@ -1360,20 +1399,20 @@ static int nfs_parse_mount_options(char *raw, | |||
1360 | break; | 1399 | break; |
1361 | 1400 | ||
1362 | default: | 1401 | default: |
1363 | errors++; | 1402 | invalid_option = 1; |
1364 | dfprintk(MOUNT, "NFS: unrecognized mount option " | 1403 | dfprintk(MOUNT, "NFS: unrecognized mount option " |
1365 | "'%s'\n", p); | 1404 | "'%s'\n", p); |
1366 | } | 1405 | } |
1367 | } | 1406 | } |
1368 | 1407 | ||
1369 | if (errors > 0) { | 1408 | if (!sloppy && invalid_option) |
1370 | dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n", | 1409 | return 0; |
1371 | errors, (errors == 1 ? "" : "s")); | 1410 | |
1372 | if (!sloppy) | ||
1373 | return 0; | ||
1374 | } | ||
1375 | return 1; | 1411 | return 1; |
1376 | 1412 | ||
1413 | out_invalid_value: | ||
1414 | printk(KERN_INFO "NFS: bad mount option value specified: %s \n", p); | ||
1415 | return 0; | ||
1377 | out_nomem: | 1416 | out_nomem: |
1378 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); | 1417 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); |
1379 | return 0; | 1418 | return 0; |
@@ -1390,6 +1429,7 @@ out_security_failure: | |||
1390 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, | 1429 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, |
1391 | struct nfs_fh *root_fh) | 1430 | struct nfs_fh *root_fh) |
1392 | { | 1431 | { |
1432 | unsigned int auth_flavor_len = 0; | ||
1393 | struct nfs_mount_request request = { | 1433 | struct nfs_mount_request request = { |
1394 | .sap = (struct sockaddr *) | 1434 | .sap = (struct sockaddr *) |
1395 | &args->mount_server.address, | 1435 | &args->mount_server.address, |
@@ -1397,6 +1437,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1397 | .protocol = args->mount_server.protocol, | 1437 | .protocol = args->mount_server.protocol, |
1398 | .fh = root_fh, | 1438 | .fh = root_fh, |
1399 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, | 1439 | .noresvport = args->flags & NFS_MOUNT_NORESVPORT, |
1440 | .auth_flav_len = &auth_flavor_len, | ||
1400 | }; | 1441 | }; |
1401 | int status; | 1442 | int status; |
1402 | 1443 | ||
@@ -2249,6 +2290,11 @@ static void nfs4_fill_super(struct super_block *sb) | |||
2249 | nfs_initialise_sb(sb); | 2290 | nfs_initialise_sb(sb); |
2250 | } | 2291 | } |
2251 | 2292 | ||
2293 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) | ||
2294 | { | ||
2295 | args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3); | ||
2296 | } | ||
2297 | |||
2252 | /* | 2298 | /* |
2253 | * Validate NFSv4 mount options | 2299 | * Validate NFSv4 mount options |
2254 | */ | 2300 | */ |
@@ -2346,6 +2392,8 @@ static int nfs4_validate_mount_data(void *options, | |||
2346 | 2392 | ||
2347 | nfs_validate_transport_protocol(args); | 2393 | nfs_validate_transport_protocol(args); |
2348 | 2394 | ||
2395 | nfs4_validate_mount_flags(args); | ||
2396 | |||
2349 | if (args->auth_flavor_len > 1) | 2397 | if (args->auth_flavor_len > 1) |
2350 | goto out_inval_auth; | 2398 | goto out_inval_auth; |
2351 | 2399 | ||