aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/svc.c33
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs2acl.c7
-rw-r--r--fs/nfsd/nfs3acl.c5
-rw-r--r--fs/nfsd/nfs3proc.c8
-rw-r--r--fs/nfsd/nfs4proc.c76
-rw-r--r--fs/nfsd/nfs4state.c27
-rw-r--r--fs/nfsd/nfs4xdr.c185
-rw-r--r--fs/nfsd/nfsctl.c103
-rw-r--r--fs/nfsd/nfsfh.c31
-rw-r--r--fs/nfsd/nfsproc.c9
-rw-r--r--fs/nfsd/nfssvc.c148
-rw-r--r--fs/nfsd/vfs.c140
13 files changed, 433 insertions, 341 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 2169af4d5455..5bd9bf0fa9df 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -50,7 +50,7 @@ EXPORT_SYMBOL(nlmsvc_ops);
50static DEFINE_MUTEX(nlmsvc_mutex); 50static DEFINE_MUTEX(nlmsvc_mutex);
51static unsigned int nlmsvc_users; 51static unsigned int nlmsvc_users;
52static struct task_struct *nlmsvc_task; 52static struct task_struct *nlmsvc_task;
53static struct svc_serv *nlmsvc_serv; 53static struct svc_rqst *nlmsvc_rqst;
54int nlmsvc_grace_period; 54int nlmsvc_grace_period;
55unsigned long nlmsvc_timeout; 55unsigned long nlmsvc_timeout;
56 56
@@ -194,20 +194,11 @@ lockd(void *vrqstp)
194 194
195 svc_process(rqstp); 195 svc_process(rqstp);
196 } 196 }
197
198 flush_signals(current); 197 flush_signals(current);
199 if (nlmsvc_ops) 198 if (nlmsvc_ops)
200 nlmsvc_invalidate_all(); 199 nlmsvc_invalidate_all();
201 nlm_shutdown_hosts(); 200 nlm_shutdown_hosts();
202
203 unlock_kernel(); 201 unlock_kernel();
204
205 nlmsvc_task = NULL;
206 nlmsvc_serv = NULL;
207
208 /* Exit the RPC thread */
209 svc_exit_thread(rqstp);
210
211 return 0; 202 return 0;
212} 203}
213 204
@@ -254,16 +245,15 @@ int
254lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */ 245lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
255{ 246{
256 struct svc_serv *serv; 247 struct svc_serv *serv;
257 struct svc_rqst *rqstp;
258 int error = 0; 248 int error = 0;
259 249
260 mutex_lock(&nlmsvc_mutex); 250 mutex_lock(&nlmsvc_mutex);
261 /* 251 /*
262 * Check whether we're already up and running. 252 * Check whether we're already up and running.
263 */ 253 */
264 if (nlmsvc_serv) { 254 if (nlmsvc_rqst) {
265 if (proto) 255 if (proto)
266 error = make_socks(nlmsvc_serv, proto); 256 error = make_socks(nlmsvc_rqst->rq_server, proto);
267 goto out; 257 goto out;
268 } 258 }
269 259
@@ -288,9 +278,10 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
288 /* 278 /*
289 * Create the kernel thread and wait for it to start. 279 * Create the kernel thread and wait for it to start.
290 */ 280 */
291 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]); 281 nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
292 if (IS_ERR(rqstp)) { 282 if (IS_ERR(nlmsvc_rqst)) {
293 error = PTR_ERR(rqstp); 283 error = PTR_ERR(nlmsvc_rqst);
284 nlmsvc_rqst = NULL;
294 printk(KERN_WARNING 285 printk(KERN_WARNING
295 "lockd_up: svc_rqst allocation failed, error=%d\n", 286 "lockd_up: svc_rqst allocation failed, error=%d\n",
296 error); 287 error);
@@ -298,16 +289,15 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
298 } 289 }
299 290
300 svc_sock_update_bufs(serv); 291 svc_sock_update_bufs(serv);
301 nlmsvc_serv = rqstp->rq_server;
302 292
303 nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name); 293 nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
304 if (IS_ERR(nlmsvc_task)) { 294 if (IS_ERR(nlmsvc_task)) {
305 error = PTR_ERR(nlmsvc_task); 295 error = PTR_ERR(nlmsvc_task);
296 svc_exit_thread(nlmsvc_rqst);
306 nlmsvc_task = NULL; 297 nlmsvc_task = NULL;
307 nlmsvc_serv = NULL; 298 nlmsvc_rqst = NULL;
308 printk(KERN_WARNING 299 printk(KERN_WARNING
309 "lockd_up: kthread_run failed, error=%d\n", error); 300 "lockd_up: kthread_run failed, error=%d\n", error);
310 svc_exit_thread(rqstp);
311 goto destroy_and_out; 301 goto destroy_and_out;
312 } 302 }
313 303
@@ -346,6 +336,9 @@ lockd_down(void)
346 BUG(); 336 BUG();
347 } 337 }
348 kthread_stop(nlmsvc_task); 338 kthread_stop(nlmsvc_task);
339 svc_exit_thread(nlmsvc_rqst);
340 nlmsvc_task = NULL;
341 nlmsvc_rqst = NULL;
349out: 342out:
350 mutex_unlock(&nlmsvc_mutex); 343 mutex_unlock(&nlmsvc_mutex);
351} 344}
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 9e4a568a5013..6b6225ac4926 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -35,7 +35,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
35 fh.fh_export = NULL; 35 fh.fh_export = NULL;
36 36
37 exp_readlock(); 37 exp_readlock();
38 nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp); 38 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
39 fh_put(&fh); 39 fh_put(&fh);
40 rqstp->rq_client = NULL; 40 rqstp->rq_client = NULL;
41 exp_readunlock(); 41 exp_readunlock();
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 1c3b7654e966..4e3219e84116 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -40,7 +40,8 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
40 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); 40 dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
41 41
42 fh = fh_copy(&resp->fh, &argp->fh); 42 fh = fh_copy(&resp->fh, &argp->fh);
43 if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) 43 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
44 if (nfserr)
44 RETURN_STATUS(nfserr); 45 RETURN_STATUS(nfserr);
45 46
46 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 47 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
@@ -107,7 +108,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
107 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh)); 108 dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
108 109
109 fh = fh_copy(&resp->fh, &argp->fh); 110 fh = fh_copy(&resp->fh, &argp->fh);
110 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR); 111 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
111 112
112 if (!nfserr) { 113 if (!nfserr) {
113 nfserr = nfserrno( nfsd_set_posix_acl( 114 nfserr = nfserrno( nfsd_set_posix_acl(
@@ -134,7 +135,7 @@ static __be32 nfsacld_proc_getattr(struct svc_rqst * rqstp,
134 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); 135 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
135 136
136 fh_copy(&resp->fh, &argp->fh); 137 fh_copy(&resp->fh, &argp->fh);
137 return fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 138 return fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
138} 139}
139 140
140/* 141/*
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index b647f2f872dc..9981dbb377a3 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -36,7 +36,8 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
36 __be32 nfserr = 0; 36 __be32 nfserr = 0;
37 37
38 fh = fh_copy(&resp->fh, &argp->fh); 38 fh = fh_copy(&resp->fh, &argp->fh);
39 if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) 39 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
40 if (nfserr)
40 RETURN_STATUS(nfserr); 41 RETURN_STATUS(nfserr);
41 42
42 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 43 if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
@@ -101,7 +102,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
101 __be32 nfserr = 0; 102 __be32 nfserr = 0;
102 103
103 fh = fh_copy(&resp->fh, &argp->fh); 104 fh = fh_copy(&resp->fh, &argp->fh);
104 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_SATTR); 105 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
105 106
106 if (!nfserr) { 107 if (!nfserr) {
107 nfserr = nfserrno( nfsd_set_posix_acl( 108 nfserr = nfserrno( nfsd_set_posix_acl(
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index c721a1e6e9dd..4d617ea28cfc 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -63,7 +63,7 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
63 SVCFH_fmt(&argp->fh)); 63 SVCFH_fmt(&argp->fh));
64 64
65 fh_copy(&resp->fh, &argp->fh); 65 fh_copy(&resp->fh, &argp->fh);
66 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 66 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
67 if (nfserr) 67 if (nfserr)
68 RETURN_STATUS(nfserr); 68 RETURN_STATUS(nfserr);
69 69
@@ -242,7 +242,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
242 attr = &argp->attrs; 242 attr = &argp->attrs;
243 243
244 /* Get the directory inode */ 244 /* Get the directory inode */
245 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE); 245 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_CREATE);
246 if (nfserr) 246 if (nfserr)
247 RETURN_STATUS(nfserr); 247 RETURN_STATUS(nfserr);
248 248
@@ -558,7 +558,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
558 resp->f_maxfilesize = ~(u32) 0; 558 resp->f_maxfilesize = ~(u32) 0;
559 resp->f_properties = NFS3_FSF_DEFAULT; 559 resp->f_properties = NFS3_FSF_DEFAULT;
560 560
561 nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP); 561 nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
562 562
563 /* Check special features of the file system. May request 563 /* Check special features of the file system. May request
564 * different read/write sizes for file systems known to have 564 * different read/write sizes for file systems known to have
@@ -597,7 +597,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
597 resp->p_case_insensitive = 0; 597 resp->p_case_insensitive = 0;
598 resp->p_case_preserving = 1; 598 resp->p_case_preserving = 1;
599 599
600 nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP); 600 nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
601 601
602 if (nfserr == 0) { 602 if (nfserr == 0) {
603 struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb; 603 struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index c309c881bd4e..eef1629806f5 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -71,11 +71,11 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
71 return nfserr_inval; 71 return nfserr_inval;
72 72
73 if (open->op_share_access & NFS4_SHARE_ACCESS_READ) 73 if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
74 accmode |= MAY_READ; 74 accmode |= NFSD_MAY_READ;
75 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 75 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
76 accmode |= (MAY_WRITE | MAY_TRUNC); 76 accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
77 if (open->op_share_deny & NFS4_SHARE_DENY_WRITE) 77 if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
78 accmode |= MAY_WRITE; 78 accmode |= NFSD_MAY_WRITE;
79 79
80 status = fh_verify(rqstp, current_fh, S_IFREG, accmode); 80 status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
81 81
@@ -126,7 +126,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
126 &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size); 126 &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size);
127 127
128 if (!created) 128 if (!created)
129 status = do_open_permission(rqstp, current_fh, open, MAY_NOP); 129 status = do_open_permission(rqstp, current_fh, open,
130 NFSD_MAY_NOP);
130 131
131out: 132out:
132 fh_put(&resfh); 133 fh_put(&resfh);
@@ -157,7 +158,8 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
157 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && 158 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
158 (open->op_iattr.ia_size == 0); 159 (open->op_iattr.ia_size == 0);
159 160
160 status = do_open_permission(rqstp, current_fh, open, MAY_OWNER_OVERRIDE); 161 status = do_open_permission(rqstp, current_fh, open,
162 NFSD_MAY_OWNER_OVERRIDE);
161 163
162 return status; 164 return status;
163} 165}
@@ -186,7 +188,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
186 cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len; 188 cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
187 memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh, 189 memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
188 rp->rp_openfh_len); 190 rp->rp_openfh_len);
189 status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); 191 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
190 if (status) 192 if (status)
191 dprintk("nfsd4_open: replay failed" 193 dprintk("nfsd4_open: replay failed"
192 " restoring previous filehandle\n"); 194 " restoring previous filehandle\n");
@@ -285,7 +287,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
285 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; 287 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
286 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, 288 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
287 putfh->pf_fhlen); 289 putfh->pf_fhlen);
288 return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); 290 return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
289} 291}
290 292
291static __be32 293static __be32
@@ -363,7 +365,8 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
363 365
364 fh_init(&resfh, NFS4_FHSIZE); 366 fh_init(&resfh, NFS4_FHSIZE);
365 367
366 status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE); 368 status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
369 NFSD_MAY_CREATE);
367 if (status == nfserr_symlink) 370 if (status == nfserr_symlink)
368 status = nfserr_notdir; 371 status = nfserr_notdir;
369 if (status) 372 if (status)
@@ -445,7 +448,7 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
445{ 448{
446 __be32 status; 449 __be32 status;
447 450
448 status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); 451 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
449 if (status) 452 if (status)
450 return status; 453 return status;
451 454
@@ -730,7 +733,7 @@ _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
730 int count; 733 int count;
731 __be32 status; 734 __be32 status;
732 735
733 status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); 736 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
734 if (status) 737 if (status)
735 return status; 738 return status;
736 739
@@ -843,10 +846,13 @@ struct nfsd4_operation {
843#define ALLOWED_WITHOUT_FH 1 846#define ALLOWED_WITHOUT_FH 1
844/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */ 847/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
845#define ALLOWED_ON_ABSENT_FS 2 848#define ALLOWED_ON_ABSENT_FS 2
849 char *op_name;
846}; 850};
847 851
848static struct nfsd4_operation nfsd4_ops[]; 852static struct nfsd4_operation nfsd4_ops[];
849 853
854static inline char *nfsd4_op_name(unsigned opnum);
855
850/* 856/*
851 * COMPOUND call. 857 * COMPOUND call.
852 */ 858 */
@@ -888,7 +894,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
888 while (!status && resp->opcnt < args->opcnt) { 894 while (!status && resp->opcnt < args->opcnt) {
889 op = &args->ops[resp->opcnt++]; 895 op = &args->ops[resp->opcnt++];
890 896
891 dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum); 897 dprintk("nfsv4 compound op #%d/%d: %d (%s)\n",
898 resp->opcnt, args->opcnt, op->opnum,
899 nfsd4_op_name(op->opnum));
892 900
893 /* 901 /*
894 * The XDR decode routines may have pre-set op->status; 902 * The XDR decode routines may have pre-set op->status;
@@ -952,126 +960,170 @@ encode_op:
952out: 960out:
953 nfsd4_release_compoundargs(args); 961 nfsd4_release_compoundargs(args);
954 cstate_free(cstate); 962 cstate_free(cstate);
963 dprintk("nfsv4 compound returned %d\n", ntohl(status));
955 return status; 964 return status;
956} 965}
957 966
958static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = { 967static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
959 [OP_ACCESS] = { 968 [OP_ACCESS] = {
960 .op_func = (nfsd4op_func)nfsd4_access, 969 .op_func = (nfsd4op_func)nfsd4_access,
970 .op_name = "OP_ACCESS",
961 }, 971 },
962 [OP_CLOSE] = { 972 [OP_CLOSE] = {
963 .op_func = (nfsd4op_func)nfsd4_close, 973 .op_func = (nfsd4op_func)nfsd4_close,
974 .op_name = "OP_CLOSE",
964 }, 975 },
965 [OP_COMMIT] = { 976 [OP_COMMIT] = {
966 .op_func = (nfsd4op_func)nfsd4_commit, 977 .op_func = (nfsd4op_func)nfsd4_commit,
978 .op_name = "OP_COMMIT",
967 }, 979 },
968 [OP_CREATE] = { 980 [OP_CREATE] = {
969 .op_func = (nfsd4op_func)nfsd4_create, 981 .op_func = (nfsd4op_func)nfsd4_create,
982 .op_name = "OP_CREATE",
970 }, 983 },
971 [OP_DELEGRETURN] = { 984 [OP_DELEGRETURN] = {
972 .op_func = (nfsd4op_func)nfsd4_delegreturn, 985 .op_func = (nfsd4op_func)nfsd4_delegreturn,
986 .op_name = "OP_DELEGRETURN",
973 }, 987 },
974 [OP_GETATTR] = { 988 [OP_GETATTR] = {
975 .op_func = (nfsd4op_func)nfsd4_getattr, 989 .op_func = (nfsd4op_func)nfsd4_getattr,
976 .op_flags = ALLOWED_ON_ABSENT_FS, 990 .op_flags = ALLOWED_ON_ABSENT_FS,
991 .op_name = "OP_GETATTR",
977 }, 992 },
978 [OP_GETFH] = { 993 [OP_GETFH] = {
979 .op_func = (nfsd4op_func)nfsd4_getfh, 994 .op_func = (nfsd4op_func)nfsd4_getfh,
995 .op_name = "OP_GETFH",
980 }, 996 },
981 [OP_LINK] = { 997 [OP_LINK] = {
982 .op_func = (nfsd4op_func)nfsd4_link, 998 .op_func = (nfsd4op_func)nfsd4_link,
999 .op_name = "OP_LINK",
983 }, 1000 },
984 [OP_LOCK] = { 1001 [OP_LOCK] = {
985 .op_func = (nfsd4op_func)nfsd4_lock, 1002 .op_func = (nfsd4op_func)nfsd4_lock,
1003 .op_name = "OP_LOCK",
986 }, 1004 },
987 [OP_LOCKT] = { 1005 [OP_LOCKT] = {
988 .op_func = (nfsd4op_func)nfsd4_lockt, 1006 .op_func = (nfsd4op_func)nfsd4_lockt,
1007 .op_name = "OP_LOCKT",
989 }, 1008 },
990 [OP_LOCKU] = { 1009 [OP_LOCKU] = {
991 .op_func = (nfsd4op_func)nfsd4_locku, 1010 .op_func = (nfsd4op_func)nfsd4_locku,
1011 .op_name = "OP_LOCKU",
992 }, 1012 },
993 [OP_LOOKUP] = { 1013 [OP_LOOKUP] = {
994 .op_func = (nfsd4op_func)nfsd4_lookup, 1014 .op_func = (nfsd4op_func)nfsd4_lookup,
1015 .op_name = "OP_LOOKUP",
995 }, 1016 },
996 [OP_LOOKUPP] = { 1017 [OP_LOOKUPP] = {
997 .op_func = (nfsd4op_func)nfsd4_lookupp, 1018 .op_func = (nfsd4op_func)nfsd4_lookupp,
1019 .op_name = "OP_LOOKUPP",
998 }, 1020 },
999 [OP_NVERIFY] = { 1021 [OP_NVERIFY] = {
1000 .op_func = (nfsd4op_func)nfsd4_nverify, 1022 .op_func = (nfsd4op_func)nfsd4_nverify,
1023 .op_name = "OP_NVERIFY",
1001 }, 1024 },
1002 [OP_OPEN] = { 1025 [OP_OPEN] = {
1003 .op_func = (nfsd4op_func)nfsd4_open, 1026 .op_func = (nfsd4op_func)nfsd4_open,
1027 .op_name = "OP_OPEN",
1004 }, 1028 },
1005 [OP_OPEN_CONFIRM] = { 1029 [OP_OPEN_CONFIRM] = {
1006 .op_func = (nfsd4op_func)nfsd4_open_confirm, 1030 .op_func = (nfsd4op_func)nfsd4_open_confirm,
1031 .op_name = "OP_OPEN_CONFIRM",
1007 }, 1032 },
1008 [OP_OPEN_DOWNGRADE] = { 1033 [OP_OPEN_DOWNGRADE] = {
1009 .op_func = (nfsd4op_func)nfsd4_open_downgrade, 1034 .op_func = (nfsd4op_func)nfsd4_open_downgrade,
1035 .op_name = "OP_OPEN_DOWNGRADE",
1010 }, 1036 },
1011 [OP_PUTFH] = { 1037 [OP_PUTFH] = {
1012 .op_func = (nfsd4op_func)nfsd4_putfh, 1038 .op_func = (nfsd4op_func)nfsd4_putfh,
1013 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1039 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1040 .op_name = "OP_PUTFH",
1014 }, 1041 },
1015 [OP_PUTPUBFH] = { 1042 [OP_PUTPUBFH] = {
1016 /* unsupported; just for future reference: */ 1043 /* unsupported, just for future reference: */
1017 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1044 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1045 .op_name = "OP_PUTPUBFH",
1018 }, 1046 },
1019 [OP_PUTROOTFH] = { 1047 [OP_PUTROOTFH] = {
1020 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1048 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1021 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1049 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1050 .op_name = "OP_PUTROOTFH",
1022 }, 1051 },
1023 [OP_READ] = { 1052 [OP_READ] = {
1024 .op_func = (nfsd4op_func)nfsd4_read, 1053 .op_func = (nfsd4op_func)nfsd4_read,
1054 .op_name = "OP_READ",
1025 }, 1055 },
1026 [OP_READDIR] = { 1056 [OP_READDIR] = {
1027 .op_func = (nfsd4op_func)nfsd4_readdir, 1057 .op_func = (nfsd4op_func)nfsd4_readdir,
1058 .op_name = "OP_READDIR",
1028 }, 1059 },
1029 [OP_READLINK] = { 1060 [OP_READLINK] = {
1030 .op_func = (nfsd4op_func)nfsd4_readlink, 1061 .op_func = (nfsd4op_func)nfsd4_readlink,
1062 .op_name = "OP_READLINK",
1031 }, 1063 },
1032 [OP_REMOVE] = { 1064 [OP_REMOVE] = {
1033 .op_func = (nfsd4op_func)nfsd4_remove, 1065 .op_func = (nfsd4op_func)nfsd4_remove,
1066 .op_name = "OP_REMOVE",
1034 }, 1067 },
1035 [OP_RENAME] = { 1068 [OP_RENAME] = {
1069 .op_name = "OP_RENAME",
1036 .op_func = (nfsd4op_func)nfsd4_rename, 1070 .op_func = (nfsd4op_func)nfsd4_rename,
1037 }, 1071 },
1038 [OP_RENEW] = { 1072 [OP_RENEW] = {
1039 .op_func = (nfsd4op_func)nfsd4_renew, 1073 .op_func = (nfsd4op_func)nfsd4_renew,
1040 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1074 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1075 .op_name = "OP_RENEW",
1041 }, 1076 },
1042 [OP_RESTOREFH] = { 1077 [OP_RESTOREFH] = {
1043 .op_func = (nfsd4op_func)nfsd4_restorefh, 1078 .op_func = (nfsd4op_func)nfsd4_restorefh,
1044 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1079 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1080 .op_name = "OP_RESTOREFH",
1045 }, 1081 },
1046 [OP_SAVEFH] = { 1082 [OP_SAVEFH] = {
1047 .op_func = (nfsd4op_func)nfsd4_savefh, 1083 .op_func = (nfsd4op_func)nfsd4_savefh,
1084 .op_name = "OP_SAVEFH",
1048 }, 1085 },
1049 [OP_SECINFO] = { 1086 [OP_SECINFO] = {
1050 .op_func = (nfsd4op_func)nfsd4_secinfo, 1087 .op_func = (nfsd4op_func)nfsd4_secinfo,
1088 .op_name = "OP_SECINFO",
1051 }, 1089 },
1052 [OP_SETATTR] = { 1090 [OP_SETATTR] = {
1053 .op_func = (nfsd4op_func)nfsd4_setattr, 1091 .op_func = (nfsd4op_func)nfsd4_setattr,
1092 .op_name = "OP_SETATTR",
1054 }, 1093 },
1055 [OP_SETCLIENTID] = { 1094 [OP_SETCLIENTID] = {
1056 .op_func = (nfsd4op_func)nfsd4_setclientid, 1095 .op_func = (nfsd4op_func)nfsd4_setclientid,
1057 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1096 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1097 .op_name = "OP_SETCLIENTID",
1058 }, 1098 },
1059 [OP_SETCLIENTID_CONFIRM] = { 1099 [OP_SETCLIENTID_CONFIRM] = {
1060 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm, 1100 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
1061 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1101 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1102 .op_name = "OP_SETCLIENTID_CONFIRM",
1062 }, 1103 },
1063 [OP_VERIFY] = { 1104 [OP_VERIFY] = {
1064 .op_func = (nfsd4op_func)nfsd4_verify, 1105 .op_func = (nfsd4op_func)nfsd4_verify,
1106 .op_name = "OP_VERIFY",
1065 }, 1107 },
1066 [OP_WRITE] = { 1108 [OP_WRITE] = {
1067 .op_func = (nfsd4op_func)nfsd4_write, 1109 .op_func = (nfsd4op_func)nfsd4_write,
1110 .op_name = "OP_WRITE",
1068 }, 1111 },
1069 [OP_RELEASE_LOCKOWNER] = { 1112 [OP_RELEASE_LOCKOWNER] = {
1070 .op_func = (nfsd4op_func)nfsd4_release_lockowner, 1113 .op_func = (nfsd4op_func)nfsd4_release_lockowner,
1071 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1114 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1115 .op_name = "OP_RELEASE_LOCKOWNER",
1072 }, 1116 },
1073}; 1117};
1074 1118
1119static inline char *
1120nfsd4_op_name(unsigned opnum)
1121{
1122 if (opnum < ARRAY_SIZE(nfsd4_ops))
1123 return nfsd4_ops[opnum].op_name;
1124 return "unknown_operation";
1125}
1126
1075#define nfs4svc_decode_voidargs NULL 1127#define nfs4svc_decode_voidargs NULL
1076#define nfs4svc_release_void NULL 1128#define nfs4svc_release_void NULL
1077#define nfsd4_voidres nfsd4_voidargs 1129#define nfsd4_voidres nfsd4_voidargs
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 8799b8708188..eca8aaa450f1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1579,8 +1579,8 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
1579 } 1579 }
1580 /* remember the open */ 1580 /* remember the open */
1581 filp->f_mode |= open->op_share_access; 1581 filp->f_mode |= open->op_share_access;
1582 set_bit(open->op_share_access, &stp->st_access_bmap); 1582 __set_bit(open->op_share_access, &stp->st_access_bmap);
1583 set_bit(open->op_share_deny, &stp->st_deny_bmap); 1583 __set_bit(open->op_share_deny, &stp->st_deny_bmap);
1584 1584
1585 return nfs_ok; 1585 return nfs_ok;
1586} 1586}
@@ -1722,9 +1722,9 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1722 /* Stateid was not found, this is a new OPEN */ 1722 /* Stateid was not found, this is a new OPEN */
1723 int flags = 0; 1723 int flags = 0;
1724 if (open->op_share_access & NFS4_SHARE_ACCESS_READ) 1724 if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
1725 flags |= MAY_READ; 1725 flags |= NFSD_MAY_READ;
1726 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 1726 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1727 flags |= MAY_WRITE; 1727 flags |= NFSD_MAY_WRITE;
1728 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); 1728 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
1729 if (status) 1729 if (status)
1730 goto out; 1730 goto out;
@@ -2610,7 +2610,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2610 return nfserr_inval; 2610 return nfserr_inval;
2611 2611
2612 if ((status = fh_verify(rqstp, &cstate->current_fh, 2612 if ((status = fh_verify(rqstp, &cstate->current_fh,
2613 S_IFREG, MAY_LOCK))) { 2613 S_IFREG, NFSD_MAY_LOCK))) {
2614 dprintk("NFSD: nfsd4_lock: permission denied!\n"); 2614 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2615 return status; 2615 return status;
2616 } 2616 }
@@ -3249,12 +3249,14 @@ nfs4_state_shutdown(void)
3249 nfs4_unlock_state(); 3249 nfs4_unlock_state();
3250} 3250}
3251 3251
3252/*
3253 * user_recovery_dirname is protected by the nfsd_mutex since it's only
3254 * accessed when nfsd is starting.
3255 */
3252static void 3256static void
3253nfs4_set_recdir(char *recdir) 3257nfs4_set_recdir(char *recdir)
3254{ 3258{
3255 nfs4_lock_state();
3256 strcpy(user_recovery_dirname, recdir); 3259 strcpy(user_recovery_dirname, recdir);
3257 nfs4_unlock_state();
3258} 3260}
3259 3261
3260/* 3262/*
@@ -3278,6 +3280,12 @@ nfs4_reset_recoverydir(char *recdir)
3278 return status; 3280 return status;
3279} 3281}
3280 3282
3283char *
3284nfs4_recoverydir(void)
3285{
3286 return user_recovery_dirname;
3287}
3288
3281/* 3289/*
3282 * Called when leasetime is changed. 3290 * Called when leasetime is changed.
3283 * 3291 *
@@ -3286,11 +3294,12 @@ nfs4_reset_recoverydir(char *recdir)
3286 * we start to register any changes in lease time. If the administrator 3294 * we start to register any changes in lease time. If the administrator
3287 * really wants to change the lease time *now*, they can go ahead and bring 3295 * really wants to change the lease time *now*, they can go ahead and bring
3288 * nfsd down and then back up again after changing the lease time. 3296 * nfsd down and then back up again after changing the lease time.
3297 *
3298 * user_lease_time is protected by nfsd_mutex since it's only really accessed
3299 * when nfsd is starting
3289 */ 3300 */
3290void 3301void
3291nfs4_reset_lease(time_t leasetime) 3302nfs4_reset_lease(time_t leasetime)
3292{ 3303{
3293 lock_kernel();
3294 user_lease_time = leasetime; 3304 user_lease_time = leasetime;
3295 unlock_kernel();
3296} 3305}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index c513bbdf2d36..a40bec53fa66 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -986,10 +986,74 @@ nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_rel
986} 986}
987 987
988static __be32 988static __be32
989nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
990{
991 return nfs_ok;
992}
993
994static __be32
995nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
996{
997 return nfserr_opnotsupp;
998}
999
1000typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
1001
1002static nfsd4_dec nfsd4_dec_ops[] = {
1003 [OP_ACCESS] (nfsd4_dec)nfsd4_decode_access,
1004 [OP_CLOSE] (nfsd4_dec)nfsd4_decode_close,
1005 [OP_COMMIT] (nfsd4_dec)nfsd4_decode_commit,
1006 [OP_CREATE] (nfsd4_dec)nfsd4_decode_create,
1007 [OP_DELEGPURGE] (nfsd4_dec)nfsd4_decode_notsupp,
1008 [OP_DELEGRETURN] (nfsd4_dec)nfsd4_decode_delegreturn,
1009 [OP_GETATTR] (nfsd4_dec)nfsd4_decode_getattr,
1010 [OP_GETFH] (nfsd4_dec)nfsd4_decode_noop,
1011 [OP_LINK] (nfsd4_dec)nfsd4_decode_link,
1012 [OP_LOCK] (nfsd4_dec)nfsd4_decode_lock,
1013 [OP_LOCKT] (nfsd4_dec)nfsd4_decode_lockt,
1014 [OP_LOCKU] (nfsd4_dec)nfsd4_decode_locku,
1015 [OP_LOOKUP] (nfsd4_dec)nfsd4_decode_lookup,
1016 [OP_LOOKUPP] (nfsd4_dec)nfsd4_decode_noop,
1017 [OP_NVERIFY] (nfsd4_dec)nfsd4_decode_verify,
1018 [OP_OPEN] (nfsd4_dec)nfsd4_decode_open,
1019 [OP_OPENATTR] (nfsd4_dec)nfsd4_decode_notsupp,
1020 [OP_OPEN_CONFIRM] (nfsd4_dec)nfsd4_decode_open_confirm,
1021 [OP_OPEN_DOWNGRADE] (nfsd4_dec)nfsd4_decode_open_downgrade,
1022 [OP_PUTFH] (nfsd4_dec)nfsd4_decode_putfh,
1023 [OP_PUTPUBFH] (nfsd4_dec)nfsd4_decode_notsupp,
1024 [OP_PUTROOTFH] (nfsd4_dec)nfsd4_decode_noop,
1025 [OP_READ] (nfsd4_dec)nfsd4_decode_read,
1026 [OP_READDIR] (nfsd4_dec)nfsd4_decode_readdir,
1027 [OP_READLINK] (nfsd4_dec)nfsd4_decode_noop,
1028 [OP_REMOVE] (nfsd4_dec)nfsd4_decode_remove,
1029 [OP_RENAME] (nfsd4_dec)nfsd4_decode_rename,
1030 [OP_RENEW] (nfsd4_dec)nfsd4_decode_renew,
1031 [OP_RESTOREFH] (nfsd4_dec)nfsd4_decode_noop,
1032 [OP_SAVEFH] (nfsd4_dec)nfsd4_decode_noop,
1033 [OP_SECINFO] (nfsd4_dec)nfsd4_decode_secinfo,
1034 [OP_SETATTR] (nfsd4_dec)nfsd4_decode_setattr,
1035 [OP_SETCLIENTID] (nfsd4_dec)nfsd4_decode_setclientid,
1036 [OP_SETCLIENTID_CONFIRM](nfsd4_dec)nfsd4_decode_setclientid_confirm,
1037 [OP_VERIFY] (nfsd4_dec)nfsd4_decode_verify,
1038 [OP_WRITE] (nfsd4_dec)nfsd4_decode_write,
1039 [OP_RELEASE_LOCKOWNER] (nfsd4_dec)nfsd4_decode_release_lockowner,
1040};
1041
1042struct nfsd4_minorversion_ops {
1043 nfsd4_dec *decoders;
1044 int nops;
1045};
1046
1047static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
1048 [0] { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
1049};
1050
1051static __be32
989nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 1052nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
990{ 1053{
991 DECODE_HEAD; 1054 DECODE_HEAD;
992 struct nfsd4_op *op; 1055 struct nfsd4_op *op;
1056 struct nfsd4_minorversion_ops *ops;
993 int i; 1057 int i;
994 1058
995 /* 1059 /*
@@ -1019,6 +1083,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1019 } 1083 }
1020 } 1084 }
1021 1085
1086 if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion))
1087 argp->opcnt = 0;
1088
1089 ops = &nfsd4_minorversion[argp->minorversion];
1022 for (i = 0; i < argp->opcnt; i++) { 1090 for (i = 0; i < argp->opcnt; i++) {
1023 op = &argp->ops[i]; 1091 op = &argp->ops[i];
1024 op->replay = NULL; 1092 op->replay = NULL;
@@ -1056,120 +1124,11 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1056 } 1124 }
1057 op->opnum = ntohl(*argp->p++); 1125 op->opnum = ntohl(*argp->p++);
1058 1126
1059 switch (op->opnum) { 1127 if (op->opnum >= OP_ACCESS && op->opnum < ops->nops)
1060 case 2: /* Reserved operation */ 1128 op->status = ops->decoders[op->opnum](argp, &op->u);
1061 op->opnum = OP_ILLEGAL; 1129 else {
1062 if (argp->minorversion == 0)
1063 op->status = nfserr_op_illegal;
1064 else
1065 op->status = nfserr_minor_vers_mismatch;
1066 break;
1067 case OP_ACCESS:
1068 op->status = nfsd4_decode_access(argp, &op->u.access);
1069 break;
1070 case OP_CLOSE:
1071 op->status = nfsd4_decode_close(argp, &op->u.close);
1072 break;
1073 case OP_COMMIT:
1074 op->status = nfsd4_decode_commit(argp, &op->u.commit);
1075 break;
1076 case OP_CREATE:
1077 op->status = nfsd4_decode_create(argp, &op->u.create);
1078 break;
1079 case OP_DELEGRETURN:
1080 op->status = nfsd4_decode_delegreturn(argp, &op->u.delegreturn);
1081 break;
1082 case OP_GETATTR:
1083 op->status = nfsd4_decode_getattr(argp, &op->u.getattr);
1084 break;
1085 case OP_GETFH:
1086 op->status = nfs_ok;
1087 break;
1088 case OP_LINK:
1089 op->status = nfsd4_decode_link(argp, &op->u.link);
1090 break;
1091 case OP_LOCK:
1092 op->status = nfsd4_decode_lock(argp, &op->u.lock);
1093 break;
1094 case OP_LOCKT:
1095 op->status = nfsd4_decode_lockt(argp, &op->u.lockt);
1096 break;
1097 case OP_LOCKU:
1098 op->status = nfsd4_decode_locku(argp, &op->u.locku);
1099 break;
1100 case OP_LOOKUP:
1101 op->status = nfsd4_decode_lookup(argp, &op->u.lookup);
1102 break;
1103 case OP_LOOKUPP:
1104 op->status = nfs_ok;
1105 break;
1106 case OP_NVERIFY:
1107 op->status = nfsd4_decode_verify(argp, &op->u.nverify);
1108 break;
1109 case OP_OPEN:
1110 op->status = nfsd4_decode_open(argp, &op->u.open);
1111 break;
1112 case OP_OPEN_CONFIRM:
1113 op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm);
1114 break;
1115 case OP_OPEN_DOWNGRADE:
1116 op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade);
1117 break;
1118 case OP_PUTFH:
1119 op->status = nfsd4_decode_putfh(argp, &op->u.putfh);
1120 break;
1121 case OP_PUTROOTFH:
1122 op->status = nfs_ok;
1123 break;
1124 case OP_READ:
1125 op->status = nfsd4_decode_read(argp, &op->u.read);
1126 break;
1127 case OP_READDIR:
1128 op->status = nfsd4_decode_readdir(argp, &op->u.readdir);
1129 break;
1130 case OP_READLINK:
1131 op->status = nfs_ok;
1132 break;
1133 case OP_REMOVE:
1134 op->status = nfsd4_decode_remove(argp, &op->u.remove);
1135 break;
1136 case OP_RENAME:
1137 op->status = nfsd4_decode_rename(argp, &op->u.rename);
1138 break;
1139 case OP_RESTOREFH:
1140 op->status = nfs_ok;
1141 break;
1142 case OP_RENEW:
1143 op->status = nfsd4_decode_renew(argp, &op->u.renew);
1144 break;
1145 case OP_SAVEFH:
1146 op->status = nfs_ok;
1147 break;
1148 case OP_SECINFO:
1149 op->status = nfsd4_decode_secinfo(argp, &op->u.secinfo);
1150 break;
1151 case OP_SETATTR:
1152 op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
1153 break;
1154 case OP_SETCLIENTID:
1155 op->status = nfsd4_decode_setclientid(argp, &op->u.setclientid);
1156 break;
1157 case OP_SETCLIENTID_CONFIRM:
1158 op->status = nfsd4_decode_setclientid_confirm(argp, &op->u.setclientid_confirm);
1159 break;
1160 case OP_VERIFY:
1161 op->status = nfsd4_decode_verify(argp, &op->u.verify);
1162 break;
1163 case OP_WRITE:
1164 op->status = nfsd4_decode_write(argp, &op->u.write);
1165 break;
1166 case OP_RELEASE_LOCKOWNER:
1167 op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
1168 break;
1169 default:
1170 op->opnum = OP_ILLEGAL; 1130 op->opnum = OP_ILLEGAL;
1171 op->status = nfserr_op_illegal; 1131 op->status = nfserr_op_illegal;
1172 break;
1173 } 1132 }
1174 1133
1175 if (op->status) { 1134 if (op->status) {
@@ -1201,7 +1160,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1201 *p++ = htonl((u32)((n) >> 32)); \ 1160 *p++ = htonl((u32)((n) >> 32)); \
1202 *p++ = htonl((u32)(n)); \ 1161 *p++ = htonl((u32)(n)); \
1203} while (0) 1162} while (0)
1204#define WRITEMEM(ptr,nbytes) do { \ 1163#define WRITEMEM(ptr,nbytes) do if (nbytes > 0) { \
1205 *(p + XDR_QUADLEN(nbytes) -1) = 0; \ 1164 *(p + XDR_QUADLEN(nbytes) -1) = 0; \
1206 memcpy(p, ptr, nbytes); \ 1165 memcpy(p, ptr, nbytes); \
1207 p += XDR_QUADLEN(nbytes); \ 1166 p += XDR_QUADLEN(nbytes); \
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 5ac00c4fee91..2c2eb8796c10 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -450,22 +450,26 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
450 int i; 450 int i;
451 int rv; 451 int rv;
452 int len; 452 int len;
453 int npools = nfsd_nrpools(); 453 int npools;
454 int *nthreads; 454 int *nthreads;
455 455
456 mutex_lock(&nfsd_mutex);
457 npools = nfsd_nrpools();
456 if (npools == 0) { 458 if (npools == 0) {
457 /* 459 /*
458 * NFS is shut down. The admin can start it by 460 * NFS is shut down. The admin can start it by
459 * writing to the threads file but NOT the pool_threads 461 * writing to the threads file but NOT the pool_threads
460 * file, sorry. Report zero threads. 462 * file, sorry. Report zero threads.
461 */ 463 */
464 mutex_unlock(&nfsd_mutex);
462 strcpy(buf, "0\n"); 465 strcpy(buf, "0\n");
463 return strlen(buf); 466 return strlen(buf);
464 } 467 }
465 468
466 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); 469 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
470 rv = -ENOMEM;
467 if (nthreads == NULL) 471 if (nthreads == NULL)
468 return -ENOMEM; 472 goto out_free;
469 473
470 if (size > 0) { 474 if (size > 0) {
471 for (i = 0; i < npools; i++) { 475 for (i = 0; i < npools; i++) {
@@ -496,14 +500,16 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
496 mesg += len; 500 mesg += len;
497 } 501 }
498 502
503 mutex_unlock(&nfsd_mutex);
499 return (mesg-buf); 504 return (mesg-buf);
500 505
501out_free: 506out_free:
502 kfree(nthreads); 507 kfree(nthreads);
508 mutex_unlock(&nfsd_mutex);
503 return rv; 509 return rv;
504} 510}
505 511
506static ssize_t write_versions(struct file *file, char *buf, size_t size) 512static ssize_t __write_versions(struct file *file, char *buf, size_t size)
507{ 513{
508 /* 514 /*
509 * Format: 515 * Format:
@@ -566,14 +572,23 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
566 return len; 572 return len;
567} 573}
568 574
569static ssize_t write_ports(struct file *file, char *buf, size_t size) 575static ssize_t write_versions(struct file *file, char *buf, size_t size)
576{
577 ssize_t rv;
578
579 mutex_lock(&nfsd_mutex);
580 rv = __write_versions(file, buf, size);
581 mutex_unlock(&nfsd_mutex);
582 return rv;
583}
584
585static ssize_t __write_ports(struct file *file, char *buf, size_t size)
570{ 586{
571 if (size == 0) { 587 if (size == 0) {
572 int len = 0; 588 int len = 0;
573 lock_kernel(); 589
574 if (nfsd_serv) 590 if (nfsd_serv)
575 len = svc_xprt_names(nfsd_serv, buf, 0); 591 len = svc_xprt_names(nfsd_serv, buf, 0);
576 unlock_kernel();
577 return len; 592 return len;
578 } 593 }
579 /* Either a single 'fd' number is written, in which 594 /* Either a single 'fd' number is written, in which
@@ -603,9 +618,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size)
603 /* Decrease the count, but don't shutdown the 618 /* Decrease the count, but don't shutdown the
604 * the service 619 * the service
605 */ 620 */
606 lock_kernel();
607 nfsd_serv->sv_nrthreads--; 621 nfsd_serv->sv_nrthreads--;
608 unlock_kernel();
609 } 622 }
610 return err < 0 ? err : 0; 623 return err < 0 ? err : 0;
611 } 624 }
@@ -614,10 +627,8 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size)
614 int len = 0; 627 int len = 0;
615 if (!toclose) 628 if (!toclose)
616 return -ENOMEM; 629 return -ENOMEM;
617 lock_kernel();
618 if (nfsd_serv) 630 if (nfsd_serv)
619 len = svc_sock_names(buf, nfsd_serv, toclose); 631 len = svc_sock_names(buf, nfsd_serv, toclose);
620 unlock_kernel();
621 if (len >= 0) 632 if (len >= 0)
622 lockd_down(); 633 lockd_down();
623 kfree(toclose); 634 kfree(toclose);
@@ -655,7 +666,6 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size)
655 if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { 666 if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) {
656 if (port == 0) 667 if (port == 0)
657 return -EINVAL; 668 return -EINVAL;
658 lock_kernel();
659 if (nfsd_serv) { 669 if (nfsd_serv) {
660 xprt = svc_find_xprt(nfsd_serv, transport, 670 xprt = svc_find_xprt(nfsd_serv, transport,
661 AF_UNSPEC, port); 671 AF_UNSPEC, port);
@@ -666,13 +676,23 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size)
666 } else 676 } else
667 err = -ENOTCONN; 677 err = -ENOTCONN;
668 } 678 }
669 unlock_kernel();
670 return err < 0 ? err : 0; 679 return err < 0 ? err : 0;
671 } 680 }
672 } 681 }
673 return -EINVAL; 682 return -EINVAL;
674} 683}
675 684
685static ssize_t write_ports(struct file *file, char *buf, size_t size)
686{
687 ssize_t rv;
688
689 mutex_lock(&nfsd_mutex);
690 rv = __write_ports(file, buf, size);
691 mutex_unlock(&nfsd_mutex);
692 return rv;
693}
694
695
676int nfsd_max_blksize; 696int nfsd_max_blksize;
677 697
678static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 698static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
@@ -691,13 +711,13 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
691 if (bsize > NFSSVC_MAXBLKSIZE) 711 if (bsize > NFSSVC_MAXBLKSIZE)
692 bsize = NFSSVC_MAXBLKSIZE; 712 bsize = NFSSVC_MAXBLKSIZE;
693 bsize &= ~(1024-1); 713 bsize &= ~(1024-1);
694 lock_kernel(); 714 mutex_lock(&nfsd_mutex);
695 if (nfsd_serv && nfsd_serv->sv_nrthreads) { 715 if (nfsd_serv && nfsd_serv->sv_nrthreads) {
696 unlock_kernel(); 716 mutex_unlock(&nfsd_mutex);
697 return -EBUSY; 717 return -EBUSY;
698 } 718 }
699 nfsd_max_blksize = bsize; 719 nfsd_max_blksize = bsize;
700 unlock_kernel(); 720 mutex_unlock(&nfsd_mutex);
701 } 721 }
702 return sprintf(buf, "%d\n", nfsd_max_blksize); 722 return sprintf(buf, "%d\n", nfsd_max_blksize);
703} 723}
@@ -705,16 +725,17 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
705#ifdef CONFIG_NFSD_V4 725#ifdef CONFIG_NFSD_V4
706extern time_t nfs4_leasetime(void); 726extern time_t nfs4_leasetime(void);
707 727
708static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 728static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
709{ 729{
710 /* if size > 10 seconds, call 730 /* if size > 10 seconds, call
711 * nfs4_reset_lease() then write out the new lease (seconds) as reply 731 * nfs4_reset_lease() then write out the new lease (seconds) as reply
712 */ 732 */
713 char *mesg = buf; 733 char *mesg = buf;
714 int rv; 734 int rv, lease;
715 735
716 if (size > 0) { 736 if (size > 0) {
717 int lease; 737 if (nfsd_serv)
738 return -EBUSY;
718 rv = get_int(&mesg, &lease); 739 rv = get_int(&mesg, &lease);
719 if (rv) 740 if (rv)
720 return rv; 741 return rv;
@@ -726,24 +747,52 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
726 return strlen(buf); 747 return strlen(buf);
727} 748}
728 749
729static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 750static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
751{
752 ssize_t rv;
753
754 mutex_lock(&nfsd_mutex);
755 rv = __write_leasetime(file, buf, size);
756 mutex_unlock(&nfsd_mutex);
757 return rv;
758}
759
760extern char *nfs4_recoverydir(void);
761
762static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
730{ 763{
731 char *mesg = buf; 764 char *mesg = buf;
732 char *recdir; 765 char *recdir;
733 int len, status; 766 int len, status;
734 767
735 if (size == 0 || size > PATH_MAX || buf[size-1] != '\n') 768 if (size > 0) {
736 return -EINVAL; 769 if (nfsd_serv)
737 buf[size-1] = 0; 770 return -EBUSY;
771 if (size > PATH_MAX || buf[size-1] != '\n')
772 return -EINVAL;
773 buf[size-1] = 0;
738 774
739 recdir = mesg; 775 recdir = mesg;
740 len = qword_get(&mesg, recdir, size); 776 len = qword_get(&mesg, recdir, size);
741 if (len <= 0) 777 if (len <= 0)
742 return -EINVAL; 778 return -EINVAL;
743 779
744 status = nfs4_reset_recoverydir(recdir); 780 status = nfs4_reset_recoverydir(recdir);
781 }
782 sprintf(buf, "%s\n", nfs4_recoverydir());
745 return strlen(buf); 783 return strlen(buf);
746} 784}
785
786static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
787{
788 ssize_t rv;
789
790 mutex_lock(&nfsd_mutex);
791 rv = __write_recoverydir(file, buf, size);
792 mutex_unlock(&nfsd_mutex);
793 return rv;
794}
795
747#endif 796#endif
748 797
749/*----------------------------------------------------------------------------*/ 798/*----------------------------------------------------------------------------*/
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 100ae5641162..f45451eb1e38 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -176,9 +176,24 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
176 if (IS_ERR(exp)) 176 if (IS_ERR(exp))
177 return nfserrno(PTR_ERR(exp)); 177 return nfserrno(PTR_ERR(exp));
178 178
179 error = nfsd_setuser_and_check_port(rqstp, exp); 179 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) {
180 if (error) 180 /* Elevate privileges so that the lack of 'r' or 'x'
181 goto out; 181 * permission on some parent directory will
182 * not stop exportfs_decode_fh from being able
183 * to reconnect a directory into the dentry cache.
184 * The same problem can affect "SUBTREECHECK" exports,
185 * but as nfsd_acceptable depends on correct
186 * access control settings being in effect, we cannot
187 * fix that case easily.
188 */
189 current->cap_effective =
190 cap_raise_nfsd_set(current->cap_effective,
191 current->cap_permitted);
192 } else {
193 error = nfsd_setuser_and_check_port(rqstp, exp);
194 if (error)
195 goto out;
196 }
182 197
183 /* 198 /*
184 * Look up the dentry using the NFS file handle. 199 * Look up the dentry using the NFS file handle.
@@ -215,6 +230,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
215 goto out; 230 goto out;
216 } 231 }
217 232
233 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) {
234 error = nfsd_setuser_and_check_port(rqstp, exp);
235 if (error) {
236 dput(dentry);
237 goto out;
238 }
239 }
240
218 if (S_ISDIR(dentry->d_inode->i_mode) && 241 if (S_ISDIR(dentry->d_inode->i_mode) &&
219 (dentry->d_flags & DCACHE_DISCONNECTED)) { 242 (dentry->d_flags & DCACHE_DISCONNECTED)) {
220 printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n", 243 printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
@@ -279,7 +302,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
279 if (error) 302 if (error)
280 goto out; 303 goto out;
281 304
282 if (!(access & MAY_LOCK)) { 305 if (!(access & NFSD_MAY_LOCK)) {
283 /* 306 /*
284 * pseudoflavor restrictions are not enforced on NLM, 307 * pseudoflavor restrictions are not enforced on NLM,
285 * which clients virtually always use auth_sys for, 308 * which clients virtually always use auth_sys for,
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 6cfc96a12483..0766f95d236a 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -65,7 +65,7 @@ nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
65 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); 65 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
66 66
67 fh_copy(&resp->fh, &argp->fh); 67 fh_copy(&resp->fh, &argp->fh);
68 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); 68 nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
69 return nfsd_return_attrs(nfserr, resp); 69 return nfsd_return_attrs(nfserr, resp);
70} 70}
71 71
@@ -215,11 +215,11 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
215 SVCFH_fmt(dirfhp), argp->len, argp->name); 215 SVCFH_fmt(dirfhp), argp->len, argp->name);
216 216
217 /* First verify the parent file handle */ 217 /* First verify the parent file handle */
218 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC); 218 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
219 if (nfserr) 219 if (nfserr)
220 goto done; /* must fh_put dirfhp even on error */ 220 goto done; /* must fh_put dirfhp even on error */
221 221
222 /* Check for MAY_WRITE in nfsd_create if necessary */ 222 /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
223 223
224 nfserr = nfserr_acces; 224 nfserr = nfserr_acces;
225 if (!argp->len) 225 if (!argp->len)
@@ -281,7 +281,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
281 nfserr = nfsd_permission(rqstp, 281 nfserr = nfsd_permission(rqstp,
282 newfhp->fh_export, 282 newfhp->fh_export,
283 newfhp->fh_dentry, 283 newfhp->fh_dentry,
284 MAY_WRITE|MAY_LOCAL_ACCESS); 284 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
285 if (nfserr && nfserr != nfserr_rofs) 285 if (nfserr && nfserr != nfserr_rofs)
286 goto out_unlock; 286 goto out_unlock;
287 } 287 }
@@ -614,6 +614,7 @@ nfserrno (int errno)
614#endif 614#endif
615 { nfserr_stale, -ESTALE }, 615 { nfserr_stale, -ESTALE },
616 { nfserr_jukebox, -ETIMEDOUT }, 616 { nfserr_jukebox, -ETIMEDOUT },
617 { nfserr_jukebox, -ERESTARTSYS },
617 { nfserr_dropit, -EAGAIN }, 618 { nfserr_dropit, -EAGAIN },
618 { nfserr_dropit, -ENOMEM }, 619 { nfserr_dropit, -ENOMEM },
619 { nfserr_badname, -ESRCH }, 620 { nfserr_badname, -ESRCH },
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 941041f4b136..80292ff5e924 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -21,6 +21,7 @@
21#include <linux/smp_lock.h> 21#include <linux/smp_lock.h>
22#include <linux/freezer.h> 22#include <linux/freezer.h>
23#include <linux/fs_struct.h> 23#include <linux/fs_struct.h>
24#include <linux/kthread.h>
24 25
25#include <linux/sunrpc/types.h> 26#include <linux/sunrpc/types.h>
26#include <linux/sunrpc/stats.h> 27#include <linux/sunrpc/stats.h>
@@ -36,28 +37,38 @@
36 37
37#define NFSDDBG_FACILITY NFSDDBG_SVC 38#define NFSDDBG_FACILITY NFSDDBG_SVC
38 39
39/* these signals will be delivered to an nfsd thread
40 * when handling a request
41 */
42#define ALLOWED_SIGS (sigmask(SIGKILL))
43/* these signals will be delivered to an nfsd thread
44 * when not handling a request. i.e. when waiting
45 */
46#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT))
47/* if the last thread dies with SIGHUP, then the exports table is
48 * left unchanged ( like 2.4-{0-9} ). Any other signal will clear
49 * the exports table (like 2.2).
50 */
51#define SIG_NOCLEAN SIGHUP
52
53extern struct svc_program nfsd_program; 40extern struct svc_program nfsd_program;
54static void nfsd(struct svc_rqst *rqstp); 41static int nfsd(void *vrqstp);
55struct timeval nfssvc_boot; 42struct timeval nfssvc_boot;
56 struct svc_serv *nfsd_serv;
57static atomic_t nfsd_busy; 43static atomic_t nfsd_busy;
58static unsigned long nfsd_last_call; 44static unsigned long nfsd_last_call;
59static DEFINE_SPINLOCK(nfsd_call_lock); 45static DEFINE_SPINLOCK(nfsd_call_lock);
60 46
47/*
48 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
49 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
50 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
51 *
52 * If (out side the lock) nfsd_serv is non-NULL, then it must point to a
53 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
54 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
55 * entry of ->sv_pools[].
56 *
57 * Transitions of the thread count between zero and non-zero are of particular
58 * interest since the svc_serv needs to be created and initialized at that
59 * point, or freed.
60 *
61 * Finally, the nfsd_mutex also protects some of the global variables that are
62 * accessed when nfsd starts and that are settable via the write_* routines in
63 * nfsctl.c. In particular:
64 *
65 * user_recovery_dirname
66 * user_lease_time
67 * nfsd_versions
68 */
69DEFINE_MUTEX(nfsd_mutex);
70struct svc_serv *nfsd_serv;
71
61#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 72#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
62static struct svc_stat nfsd_acl_svcstats; 73static struct svc_stat nfsd_acl_svcstats;
63static struct svc_version * nfsd_acl_version[] = { 74static struct svc_version * nfsd_acl_version[] = {
@@ -145,13 +156,14 @@ int nfsd_vers(int vers, enum vers_op change)
145 156
146int nfsd_nrthreads(void) 157int nfsd_nrthreads(void)
147{ 158{
148 if (nfsd_serv == NULL) 159 int rv = 0;
149 return 0; 160 mutex_lock(&nfsd_mutex);
150 else 161 if (nfsd_serv)
151 return nfsd_serv->sv_nrthreads; 162 rv = nfsd_serv->sv_nrthreads;
163 mutex_unlock(&nfsd_mutex);
164 return rv;
152} 165}
153 166
154static int killsig; /* signal that was used to kill last nfsd */
155static void nfsd_last_thread(struct svc_serv *serv) 167static void nfsd_last_thread(struct svc_serv *serv)
156{ 168{
157 /* When last nfsd thread exits we need to do some clean-up */ 169 /* When last nfsd thread exits we need to do some clean-up */
@@ -162,11 +174,9 @@ static void nfsd_last_thread(struct svc_serv *serv)
162 nfsd_racache_shutdown(); 174 nfsd_racache_shutdown();
163 nfs4_state_shutdown(); 175 nfs4_state_shutdown();
164 176
165 printk(KERN_WARNING "nfsd: last server has exited\n"); 177 printk(KERN_WARNING "nfsd: last server has exited, flushing export "
166 if (killsig != SIG_NOCLEAN) { 178 "cache\n");
167 printk(KERN_WARNING "nfsd: unexporting all filesystems\n"); 179 nfsd_export_flush();
168 nfsd_export_flush();
169 }
170} 180}
171 181
172void nfsd_reset_versions(void) 182void nfsd_reset_versions(void)
@@ -190,13 +200,14 @@ void nfsd_reset_versions(void)
190 } 200 }
191} 201}
192 202
203
193int nfsd_create_serv(void) 204int nfsd_create_serv(void)
194{ 205{
195 int err = 0; 206 int err = 0;
196 lock_kernel(); 207
208 WARN_ON(!mutex_is_locked(&nfsd_mutex));
197 if (nfsd_serv) { 209 if (nfsd_serv) {
198 svc_get(nfsd_serv); 210 svc_get(nfsd_serv);
199 unlock_kernel();
200 return 0; 211 return 0;
201 } 212 }
202 if (nfsd_max_blksize == 0) { 213 if (nfsd_max_blksize == 0) {
@@ -217,13 +228,11 @@ int nfsd_create_serv(void)
217 } 228 }
218 229
219 atomic_set(&nfsd_busy, 0); 230 atomic_set(&nfsd_busy, 0);
220 nfsd_serv = svc_create_pooled(&nfsd_program, 231 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
221 nfsd_max_blksize, 232 nfsd_last_thread, nfsd, THIS_MODULE);
222 nfsd_last_thread,
223 nfsd, SIG_NOCLEAN, THIS_MODULE);
224 if (nfsd_serv == NULL) 233 if (nfsd_serv == NULL)
225 err = -ENOMEM; 234 err = -ENOMEM;
226 unlock_kernel(); 235
227 do_gettimeofday(&nfssvc_boot); /* record boot time */ 236 do_gettimeofday(&nfssvc_boot); /* record boot time */
228 return err; 237 return err;
229} 238}
@@ -282,6 +291,8 @@ int nfsd_set_nrthreads(int n, int *nthreads)
282 int tot = 0; 291 int tot = 0;
283 int err = 0; 292 int err = 0;
284 293
294 WARN_ON(!mutex_is_locked(&nfsd_mutex));
295
285 if (nfsd_serv == NULL || n <= 0) 296 if (nfsd_serv == NULL || n <= 0)
286 return 0; 297 return 0;
287 298
@@ -316,7 +327,6 @@ int nfsd_set_nrthreads(int n, int *nthreads)
316 nthreads[0] = 1; 327 nthreads[0] = 1;
317 328
318 /* apply the new numbers */ 329 /* apply the new numbers */
319 lock_kernel();
320 svc_get(nfsd_serv); 330 svc_get(nfsd_serv);
321 for (i = 0; i < n; i++) { 331 for (i = 0; i < n; i++) {
322 err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i], 332 err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i],
@@ -325,7 +335,6 @@ int nfsd_set_nrthreads(int n, int *nthreads)
325 break; 335 break;
326 } 336 }
327 svc_destroy(nfsd_serv); 337 svc_destroy(nfsd_serv);
328 unlock_kernel();
329 338
330 return err; 339 return err;
331} 340}
@@ -334,8 +343,8 @@ int
334nfsd_svc(unsigned short port, int nrservs) 343nfsd_svc(unsigned short port, int nrservs)
335{ 344{
336 int error; 345 int error;
337 346
338 lock_kernel(); 347 mutex_lock(&nfsd_mutex);
339 dprintk("nfsd: creating service\n"); 348 dprintk("nfsd: creating service\n");
340 error = -EINVAL; 349 error = -EINVAL;
341 if (nrservs <= 0) 350 if (nrservs <= 0)
@@ -363,7 +372,7 @@ nfsd_svc(unsigned short port, int nrservs)
363 failure: 372 failure:
364 svc_destroy(nfsd_serv); /* Release server */ 373 svc_destroy(nfsd_serv); /* Release server */
365 out: 374 out:
366 unlock_kernel(); 375 mutex_unlock(&nfsd_mutex);
367 return error; 376 return error;
368} 377}
369 378
@@ -391,18 +400,17 @@ update_thread_usage(int busy_threads)
391/* 400/*
392 * This is the NFS server kernel thread 401 * This is the NFS server kernel thread
393 */ 402 */
394static void 403static int
395nfsd(struct svc_rqst *rqstp) 404nfsd(void *vrqstp)
396{ 405{
406 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
397 struct fs_struct *fsp; 407 struct fs_struct *fsp;
398 int err; 408 int err, preverr = 0;
399 sigset_t shutdown_mask, allowed_mask;
400 409
401 /* Lock module and set up kernel thread */ 410 /* Lock module and set up kernel thread */
402 lock_kernel(); 411 mutex_lock(&nfsd_mutex);
403 daemonize("nfsd");
404 412
405 /* After daemonize() this kernel thread shares current->fs 413 /* At this point, the thread shares current->fs
406 * with the init process. We need to create files with a 414 * with the init process. We need to create files with a
407 * umask of 0 instead of init's umask. */ 415 * umask of 0 instead of init's umask. */
408 fsp = copy_fs_struct(current->fs); 416 fsp = copy_fs_struct(current->fs);
@@ -414,14 +422,17 @@ nfsd(struct svc_rqst *rqstp)
414 current->fs = fsp; 422 current->fs = fsp;
415 current->fs->umask = 0; 423 current->fs->umask = 0;
416 424
417 siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS); 425 /*
418 siginitsetinv(&allowed_mask, ALLOWED_SIGS); 426 * thread is spawned with all signals set to SIG_IGN, re-enable
427 * the ones that will bring down the thread
428 */
429 allow_signal(SIGKILL);
430 allow_signal(SIGHUP);
431 allow_signal(SIGINT);
432 allow_signal(SIGQUIT);
419 433
420 nfsdstats.th_cnt++; 434 nfsdstats.th_cnt++;
421 435 mutex_unlock(&nfsd_mutex);
422 rqstp->rq_task = current;
423
424 unlock_kernel();
425 436
426 /* 437 /*
427 * We want less throttling in balance_dirty_pages() so that nfs to 438 * We want less throttling in balance_dirty_pages() so that nfs to
@@ -435,26 +446,30 @@ nfsd(struct svc_rqst *rqstp)
435 * The main request loop 446 * The main request loop
436 */ 447 */
437 for (;;) { 448 for (;;) {
438 /* Block all but the shutdown signals */
439 sigprocmask(SIG_SETMASK, &shutdown_mask, NULL);
440
441 /* 449 /*
442 * Find a socket with data available and call its 450 * Find a socket with data available and call its
443 * recvfrom routine. 451 * recvfrom routine.
444 */ 452 */
445 while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN) 453 while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN)
446 ; 454 ;
447 if (err < 0) 455 if (err == -EINTR)
448 break; 456 break;
457 else if (err < 0) {
458 if (err != preverr) {
459 printk(KERN_WARNING "%s: unexpected error "
460 "from svc_recv (%d)\n", __func__, -err);
461 preverr = err;
462 }
463 schedule_timeout_uninterruptible(HZ);
464 continue;
465 }
466
449 update_thread_usage(atomic_read(&nfsd_busy)); 467 update_thread_usage(atomic_read(&nfsd_busy));
450 atomic_inc(&nfsd_busy); 468 atomic_inc(&nfsd_busy);
451 469
452 /* Lock the export hash tables for reading. */ 470 /* Lock the export hash tables for reading. */
453 exp_readlock(); 471 exp_readlock();
454 472
455 /* Process request with signals blocked. */
456 sigprocmask(SIG_SETMASK, &allowed_mask, NULL);
457
458 svc_process(rqstp); 473 svc_process(rqstp);
459 474
460 /* Unlock export hash tables */ 475 /* Unlock export hash tables */
@@ -463,22 +478,10 @@ nfsd(struct svc_rqst *rqstp)
463 atomic_dec(&nfsd_busy); 478 atomic_dec(&nfsd_busy);
464 } 479 }
465 480
466 if (err != -EINTR) {
467 printk(KERN_WARNING "nfsd: terminating on error %d\n", -err);
468 } else {
469 unsigned int signo;
470
471 for (signo = 1; signo <= _NSIG; signo++)
472 if (sigismember(&current->pending.signal, signo) &&
473 !sigismember(&current->blocked, signo))
474 break;
475 killsig = signo;
476 }
477 /* Clear signals before calling svc_exit_thread() */ 481 /* Clear signals before calling svc_exit_thread() */
478 flush_signals(current); 482 flush_signals(current);
479 483
480 lock_kernel(); 484 mutex_lock(&nfsd_mutex);
481
482 nfsdstats.th_cnt --; 485 nfsdstats.th_cnt --;
483 486
484out: 487out:
@@ -486,8 +489,9 @@ out:
486 svc_exit_thread(rqstp); 489 svc_exit_thread(rqstp);
487 490
488 /* Release module */ 491 /* Release module */
489 unlock_kernel(); 492 mutex_unlock(&nfsd_mutex);
490 module_put_and_exit(0); 493 module_put_and_exit(0);
494 return 0;
491} 495}
492 496
493static __be32 map_new_errors(u32 vers, __be32 nfserr) 497static __be32 map_new_errors(u32 vers, __be32 nfserr)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a3a291f771f4..0f4481e0502d 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -144,7 +144,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
144 dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); 144 dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name);
145 145
146 /* Obtain dentry and export. */ 146 /* Obtain dentry and export. */
147 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC); 147 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
148 if (err) 148 if (err)
149 return err; 149 return err;
150 150
@@ -262,14 +262,14 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
262{ 262{
263 struct dentry *dentry; 263 struct dentry *dentry;
264 struct inode *inode; 264 struct inode *inode;
265 int accmode = MAY_SATTR; 265 int accmode = NFSD_MAY_SATTR;
266 int ftype = 0; 266 int ftype = 0;
267 __be32 err; 267 __be32 err;
268 int host_err; 268 int host_err;
269 int size_change = 0; 269 int size_change = 0;
270 270
271 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) 271 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
272 accmode |= MAY_WRITE|MAY_OWNER_OVERRIDE; 272 accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
273 if (iap->ia_valid & ATTR_SIZE) 273 if (iap->ia_valid & ATTR_SIZE)
274 ftype = S_IFREG; 274 ftype = S_IFREG;
275 275
@@ -331,7 +331,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
331 */ 331 */
332 if (iap->ia_valid & ATTR_SIZE) { 332 if (iap->ia_valid & ATTR_SIZE) {
333 if (iap->ia_size < inode->i_size) { 333 if (iap->ia_size < inode->i_size) {
334 err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE); 334 err = nfsd_permission(rqstp, fhp->fh_export, dentry,
335 NFSD_MAY_TRUNC|NFSD_MAY_OWNER_OVERRIDE);
335 if (err) 336 if (err)
336 goto out; 337 goto out;
337 } 338 }
@@ -462,7 +463,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
462 unsigned int flags = 0; 463 unsigned int flags = 0;
463 464
464 /* Get inode */ 465 /* Get inode */
465 error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR); 466 error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
466 if (error) 467 if (error)
467 return error; 468 return error;
468 469
@@ -563,20 +564,20 @@ struct accessmap {
563 int how; 564 int how;
564}; 565};
565static struct accessmap nfs3_regaccess[] = { 566static struct accessmap nfs3_regaccess[] = {
566 { NFS3_ACCESS_READ, MAY_READ }, 567 { NFS3_ACCESS_READ, NFSD_MAY_READ },
567 { NFS3_ACCESS_EXECUTE, MAY_EXEC }, 568 { NFS3_ACCESS_EXECUTE, NFSD_MAY_EXEC },
568 { NFS3_ACCESS_MODIFY, MAY_WRITE|MAY_TRUNC }, 569 { NFS3_ACCESS_MODIFY, NFSD_MAY_WRITE|NFSD_MAY_TRUNC },
569 { NFS3_ACCESS_EXTEND, MAY_WRITE }, 570 { NFS3_ACCESS_EXTEND, NFSD_MAY_WRITE },
570 571
571 { 0, 0 } 572 { 0, 0 }
572}; 573};
573 574
574static struct accessmap nfs3_diraccess[] = { 575static struct accessmap nfs3_diraccess[] = {
575 { NFS3_ACCESS_READ, MAY_READ }, 576 { NFS3_ACCESS_READ, NFSD_MAY_READ },
576 { NFS3_ACCESS_LOOKUP, MAY_EXEC }, 577 { NFS3_ACCESS_LOOKUP, NFSD_MAY_EXEC },
577 { NFS3_ACCESS_MODIFY, MAY_EXEC|MAY_WRITE|MAY_TRUNC }, 578 { NFS3_ACCESS_MODIFY, NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC},
578 { NFS3_ACCESS_EXTEND, MAY_EXEC|MAY_WRITE }, 579 { NFS3_ACCESS_EXTEND, NFSD_MAY_EXEC|NFSD_MAY_WRITE },
579 { NFS3_ACCESS_DELETE, MAY_REMOVE }, 580 { NFS3_ACCESS_DELETE, NFSD_MAY_REMOVE },
580 581
581 { 0, 0 } 582 { 0, 0 }
582}; 583};
@@ -589,10 +590,10 @@ static struct accessmap nfs3_anyaccess[] = {
589 * mainly at mode bits, and we make sure to ignore read-only 590 * mainly at mode bits, and we make sure to ignore read-only
590 * filesystem checks 591 * filesystem checks
591 */ 592 */
592 { NFS3_ACCESS_READ, MAY_READ }, 593 { NFS3_ACCESS_READ, NFSD_MAY_READ },
593 { NFS3_ACCESS_EXECUTE, MAY_EXEC }, 594 { NFS3_ACCESS_EXECUTE, NFSD_MAY_EXEC },
594 { NFS3_ACCESS_MODIFY, MAY_WRITE|MAY_LOCAL_ACCESS }, 595 { NFS3_ACCESS_MODIFY, NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS },
595 { NFS3_ACCESS_EXTEND, MAY_WRITE|MAY_LOCAL_ACCESS }, 596 { NFS3_ACCESS_EXTEND, NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS },
596 597
597 { 0, 0 } 598 { 0, 0 }
598}; 599};
@@ -606,7 +607,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
606 u32 query, result = 0, sresult = 0; 607 u32 query, result = 0, sresult = 0;
607 __be32 error; 608 __be32 error;
608 609
609 error = fh_verify(rqstp, fhp, 0, MAY_NOP); 610 error = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
610 if (error) 611 if (error)
611 goto out; 612 goto out;
612 613
@@ -678,7 +679,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
678 * and (hopefully) checked permission - so allow OWNER_OVERRIDE 679 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
679 * in case a chmod has now revoked permission. 680 * in case a chmod has now revoked permission.
680 */ 681 */
681 err = fh_verify(rqstp, fhp, type, access | MAY_OWNER_OVERRIDE); 682 err = fh_verify(rqstp, fhp, type, access | NFSD_MAY_OWNER_OVERRIDE);
682 if (err) 683 if (err)
683 goto out; 684 goto out;
684 685
@@ -689,7 +690,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
689 * or any access when mandatory locking enabled 690 * or any access when mandatory locking enabled
690 */ 691 */
691 err = nfserr_perm; 692 err = nfserr_perm;
692 if (IS_APPEND(inode) && (access & MAY_WRITE)) 693 if (IS_APPEND(inode) && (access & NFSD_MAY_WRITE))
693 goto out; 694 goto out;
694 /* 695 /*
695 * We must ignore files (but only files) which might have mandatory 696 * We must ignore files (but only files) which might have mandatory
@@ -706,14 +707,14 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
706 * Check to see if there are any leases on this file. 707 * Check to see if there are any leases on this file.
707 * This may block while leases are broken. 708 * This may block while leases are broken.
708 */ 709 */
709 host_err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0)); 710 host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? FMODE_WRITE : 0));
710 if (host_err == -EWOULDBLOCK) 711 if (host_err == -EWOULDBLOCK)
711 host_err = -ETIMEDOUT; 712 host_err = -ETIMEDOUT;
712 if (host_err) /* NOMEM or WOULDBLOCK */ 713 if (host_err) /* NOMEM or WOULDBLOCK */
713 goto out_nfserr; 714 goto out_nfserr;
714 715
715 if (access & MAY_WRITE) { 716 if (access & NFSD_MAY_WRITE) {
716 if (access & MAY_READ) 717 if (access & NFSD_MAY_READ)
717 flags = O_RDWR|O_LARGEFILE; 718 flags = O_RDWR|O_LARGEFILE;
718 else 719 else
719 flags = O_WRONLY|O_LARGEFILE; 720 flags = O_WRONLY|O_LARGEFILE;
@@ -1069,12 +1070,12 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1069 1070
1070 if (file) { 1071 if (file) {
1071 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, 1072 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
1072 MAY_READ|MAY_OWNER_OVERRIDE); 1073 NFSD_MAY_READ|NFSD_MAY_OWNER_OVERRIDE);
1073 if (err) 1074 if (err)
1074 goto out; 1075 goto out;
1075 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); 1076 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
1076 } else { 1077 } else {
1077 err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file); 1078 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
1078 if (err) 1079 if (err)
1079 goto out; 1080 goto out;
1080 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); 1081 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
@@ -1098,13 +1099,13 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1098 1099
1099 if (file) { 1100 if (file) {
1100 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, 1101 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
1101 MAY_WRITE|MAY_OWNER_OVERRIDE); 1102 NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE);
1102 if (err) 1103 if (err)
1103 goto out; 1104 goto out;
1104 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, 1105 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
1105 stablep); 1106 stablep);
1106 } else { 1107 } else {
1107 err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file); 1108 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1108 if (err) 1109 if (err)
1109 goto out; 1110 goto out;
1110 1111
@@ -1136,7 +1137,8 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1136 if ((u64)count > ~(u64)offset) 1137 if ((u64)count > ~(u64)offset)
1137 return nfserr_inval; 1138 return nfserr_inval;
1138 1139
1139 if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0) 1140 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1141 if (err)
1140 return err; 1142 return err;
1141 if (EX_ISSYNC(fhp->fh_export)) { 1143 if (EX_ISSYNC(fhp->fh_export)) {
1142 if (file->f_op && file->f_op->fsync) { 1144 if (file->f_op && file->f_op->fsync) {
@@ -1197,7 +1199,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1197 if (isdotent(fname, flen)) 1199 if (isdotent(fname, flen))
1198 goto out; 1200 goto out;
1199 1201
1200 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE); 1202 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
1201 if (err) 1203 if (err)
1202 goto out; 1204 goto out;
1203 1205
@@ -1248,36 +1250,34 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1248 iap->ia_mode = 0; 1250 iap->ia_mode = 0;
1249 iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type; 1251 iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
1250 1252
1253 err = nfserr_inval;
1254 if (!S_ISREG(type) && !S_ISDIR(type) && !special_file(type)) {
1255 printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n",
1256 type);
1257 goto out;
1258 }
1259
1260 host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
1261 if (host_err)
1262 goto out_nfserr;
1263
1251 /* 1264 /*
1252 * Get the dir op function pointer. 1265 * Get the dir op function pointer.
1253 */ 1266 */
1254 err = 0; 1267 err = 0;
1255 switch (type) { 1268 switch (type) {
1256 case S_IFREG: 1269 case S_IFREG:
1257 host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
1258 if (host_err)
1259 goto out_nfserr;
1260 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); 1270 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1261 break; 1271 break;
1262 case S_IFDIR: 1272 case S_IFDIR:
1263 host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
1264 if (host_err)
1265 goto out_nfserr;
1266 host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); 1273 host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
1267 break; 1274 break;
1268 case S_IFCHR: 1275 case S_IFCHR:
1269 case S_IFBLK: 1276 case S_IFBLK:
1270 case S_IFIFO: 1277 case S_IFIFO:
1271 case S_IFSOCK: 1278 case S_IFSOCK:
1272 host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
1273 if (host_err)
1274 goto out_nfserr;
1275 host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); 1279 host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
1276 break; 1280 break;
1277 default:
1278 printk("nfsd: bad file type %o in nfsd_create\n", type);
1279 host_err = -EINVAL;
1280 goto out_nfserr;
1281 } 1281 }
1282 if (host_err < 0) { 1282 if (host_err < 0) {
1283 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1283 mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1289,7 +1289,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1289 write_inode_now(dchild->d_inode, 1); 1289 write_inode_now(dchild->d_inode, 1);
1290 } 1290 }
1291 1291
1292
1293 err2 = nfsd_create_setattr(rqstp, resfhp, iap); 1292 err2 = nfsd_create_setattr(rqstp, resfhp, iap);
1294 if (err2) 1293 if (err2)
1295 err = err2; 1294 err = err2;
@@ -1334,7 +1333,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1334 goto out; 1333 goto out;
1335 if (!(iap->ia_valid & ATTR_MODE)) 1334 if (!(iap->ia_valid & ATTR_MODE))
1336 iap->ia_mode = 0; 1335 iap->ia_mode = 0;
1337 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE); 1336 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
1338 if (err) 1337 if (err)
1339 goto out; 1338 goto out;
1340 1339
@@ -1471,7 +1470,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
1471 __be32 err; 1470 __be32 err;
1472 int host_err; 1471 int host_err;
1473 1472
1474 err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP); 1473 err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP);
1475 if (err) 1474 if (err)
1476 goto out; 1475 goto out;
1477 1476
@@ -1526,7 +1525,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1526 if (isdotent(fname, flen)) 1525 if (isdotent(fname, flen))
1527 goto out; 1526 goto out;
1528 1527
1529 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE); 1528 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
1530 if (err) 1529 if (err)
1531 goto out; 1530 goto out;
1532 fh_lock(fhp); 1531 fh_lock(fhp);
@@ -1591,10 +1590,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1591 __be32 err; 1590 __be32 err;
1592 int host_err; 1591 int host_err;
1593 1592
1594 err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE); 1593 err = fh_verify(rqstp, ffhp, S_IFDIR, NFSD_MAY_CREATE);
1595 if (err) 1594 if (err)
1596 goto out; 1595 goto out;
1597 err = fh_verify(rqstp, tfhp, -S_IFDIR, MAY_NOP); 1596 err = fh_verify(rqstp, tfhp, -S_IFDIR, NFSD_MAY_NOP);
1598 if (err) 1597 if (err)
1599 goto out; 1598 goto out;
1600 1599
@@ -1661,10 +1660,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1661 __be32 err; 1660 __be32 err;
1662 int host_err; 1661 int host_err;
1663 1662
1664 err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE); 1663 err = fh_verify(rqstp, ffhp, S_IFDIR, NFSD_MAY_REMOVE);
1665 if (err) 1664 if (err)
1666 goto out; 1665 goto out;
1667 err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE); 1666 err = fh_verify(rqstp, tfhp, S_IFDIR, NFSD_MAY_CREATE);
1668 if (err) 1667 if (err)
1669 goto out; 1668 goto out;
1670 1669
@@ -1768,7 +1767,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1768 err = nfserr_acces; 1767 err = nfserr_acces;
1769 if (!flen || isdotent(fname, flen)) 1768 if (!flen || isdotent(fname, flen))
1770 goto out; 1769 goto out;
1771 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE); 1770 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_REMOVE);
1772 if (err) 1771 if (err)
1773 goto out; 1772 goto out;
1774 1773
@@ -1834,7 +1833,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
1834 struct file *file; 1833 struct file *file;
1835 loff_t offset = *offsetp; 1834 loff_t offset = *offsetp;
1836 1835
1837 err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file); 1836 err = nfsd_open(rqstp, fhp, S_IFDIR, NFSD_MAY_READ, &file);
1838 if (err) 1837 if (err)
1839 goto out; 1838 goto out;
1840 1839
@@ -1875,7 +1874,7 @@ out:
1875__be32 1874__be32
1876nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) 1875nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
1877{ 1876{
1878 __be32 err = fh_verify(rqstp, fhp, 0, MAY_NOP); 1877 __be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
1879 if (!err && vfs_statfs(fhp->fh_dentry,stat)) 1878 if (!err && vfs_statfs(fhp->fh_dentry,stat))
1880 err = nfserr_io; 1879 err = nfserr_io;
1881 return err; 1880 return err;
@@ -1896,18 +1895,18 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
1896 struct inode *inode = dentry->d_inode; 1895 struct inode *inode = dentry->d_inode;
1897 int err; 1896 int err;
1898 1897
1899 if (acc == MAY_NOP) 1898 if (acc == NFSD_MAY_NOP)
1900 return 0; 1899 return 0;
1901#if 0 1900#if 0
1902 dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n", 1901 dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
1903 acc, 1902 acc,
1904 (acc & MAY_READ)? " read" : "", 1903 (acc & NFSD_MAY_READ)? " read" : "",
1905 (acc & MAY_WRITE)? " write" : "", 1904 (acc & NFSD_MAY_WRITE)? " write" : "",
1906 (acc & MAY_EXEC)? " exec" : "", 1905 (acc & NFSD_MAY_EXEC)? " exec" : "",
1907 (acc & MAY_SATTR)? " sattr" : "", 1906 (acc & NFSD_MAY_SATTR)? " sattr" : "",
1908 (acc & MAY_TRUNC)? " trunc" : "", 1907 (acc & NFSD_MAY_TRUNC)? " trunc" : "",
1909 (acc & MAY_LOCK)? " lock" : "", 1908 (acc & NFSD_MAY_LOCK)? " lock" : "",
1910 (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "", 1909 (acc & NFSD_MAY_OWNER_OVERRIDE)? " owneroverride" : "",
1911 inode->i_mode, 1910 inode->i_mode,
1912 IS_IMMUTABLE(inode)? " immut" : "", 1911 IS_IMMUTABLE(inode)? " immut" : "",
1913 IS_APPEND(inode)? " append" : "", 1912 IS_APPEND(inode)? " append" : "",
@@ -1920,18 +1919,18 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
1920 * system. But if it is IRIX doing check on write-access for a 1919 * system. But if it is IRIX doing check on write-access for a
1921 * device special file, we ignore rofs. 1920 * device special file, we ignore rofs.
1922 */ 1921 */
1923 if (!(acc & MAY_LOCAL_ACCESS)) 1922 if (!(acc & NFSD_MAY_LOCAL_ACCESS))
1924 if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { 1923 if (acc & (NFSD_MAY_WRITE | NFSD_MAY_SATTR | NFSD_MAY_TRUNC)) {
1925 if (exp_rdonly(rqstp, exp) || 1924 if (exp_rdonly(rqstp, exp) ||
1926 __mnt_is_readonly(exp->ex_path.mnt)) 1925 __mnt_is_readonly(exp->ex_path.mnt))
1927 return nfserr_rofs; 1926 return nfserr_rofs;
1928 if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) 1927 if (/* (acc & NFSD_MAY_WRITE) && */ IS_IMMUTABLE(inode))
1929 return nfserr_perm; 1928 return nfserr_perm;
1930 } 1929 }
1931 if ((acc & MAY_TRUNC) && IS_APPEND(inode)) 1930 if ((acc & NFSD_MAY_TRUNC) && IS_APPEND(inode))
1932 return nfserr_perm; 1931 return nfserr_perm;
1933 1932
1934 if (acc & MAY_LOCK) { 1933 if (acc & NFSD_MAY_LOCK) {
1935 /* If we cannot rely on authentication in NLM requests, 1934 /* If we cannot rely on authentication in NLM requests,
1936 * just allow locks, otherwise require read permission, or 1935 * just allow locks, otherwise require read permission, or
1937 * ownership 1936 * ownership
@@ -1939,7 +1938,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
1939 if (exp->ex_flags & NFSEXP_NOAUTHNLM) 1938 if (exp->ex_flags & NFSEXP_NOAUTHNLM)
1940 return 0; 1939 return 0;
1941 else 1940 else
1942 acc = MAY_READ | MAY_OWNER_OVERRIDE; 1941 acc = NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE;
1943 } 1942 }
1944 /* 1943 /*
1945 * The file owner always gets access permission for accesses that 1944 * The file owner always gets access permission for accesses that
@@ -1955,15 +1954,16 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
1955 * We must trust the client to do permission checking - using "ACCESS" 1954 * We must trust the client to do permission checking - using "ACCESS"
1956 * with NFSv3. 1955 * with NFSv3.
1957 */ 1956 */
1958 if ((acc & MAY_OWNER_OVERRIDE) && 1957 if ((acc & NFSD_MAY_OWNER_OVERRIDE) &&
1959 inode->i_uid == current->fsuid) 1958 inode->i_uid == current->fsuid)
1960 return 0; 1959 return 0;
1961 1960
1961 /* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */
1962 err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL); 1962 err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
1963 1963
1964 /* Allow read access to binaries even when mode 111 */ 1964 /* Allow read access to binaries even when mode 111 */
1965 if (err == -EACCES && S_ISREG(inode->i_mode) && 1965 if (err == -EACCES && S_ISREG(inode->i_mode) &&
1966 acc == (MAY_READ | MAY_OWNER_OVERRIDE)) 1966 acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE))
1967 err = permission(inode, MAY_EXEC, NULL); 1967 err = permission(inode, MAY_EXEC, NULL);
1968 1968
1969 return err? nfserrno(err) : 0; 1969 return err? nfserrno(err) : 0;