aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-07 17:24:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-07 17:24:41 -0400
commit0d9f9e122c74583de15a86d1c660c08dc298f2c8 (patch)
treea04ad387e231db43db112753fa2eae23754189a9 /fs/nfsd
parentdf44f9f4f9b5d362b5a2d1c8444fe7e6d4c42653 (diff)
parent998db52c03cd293d16a457f1b396cea932244147 (diff)
Merge branch 'for-2.6.36' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.36' of git://linux-nfs.org/~bfields/linux: (34 commits) nfsd4: fix file open accounting for RDWR opens nfsd: don't allow setting maxblksize after svc created nfsd: initialize nfsd versions before creating svc net: sunrpc: removed duplicated #include nfsd41: Fix a crash when a callback is retried nfsd: fix startup/shutdown order bug nfsd: minor nfsd read api cleanup gcc-4.6: nfsd: fix initialized but not read warnings nfsd4: share file descriptors between stateid's nfsd4: fix openmode checking on IO using lock stateid nfsd4: miscellaneous process_open2 cleanup nfsd4: don't pretend to support write delegations nfsd: bypass readahead cache when have struct file nfsd: minor nfsd_svc() cleanup nfsd: move more into nfsd_startup() nfsd: just keep single lockd reference for nfsd nfsd: clean up nfsd_create_serv error handling nfsd: fix error handling in __write_ports_addxprt nfsd: fix error handling when starting nfsd with rpcbind down nfsd4: fix v4 state shutdown error paths ...
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs3proc.c8
-rw-r--r--fs/nfsd/nfs4callback.c57
-rw-r--r--fs/nfsd/nfs4state.c381
-rw-r--r--fs/nfsd/nfs4xdr.c3
-rw-r--r--fs/nfsd/nfsctl.c24
-rw-r--r--fs/nfsd/nfsd.h1
-rw-r--r--fs/nfsd/nfsproc.c4
-rw-r--r--fs/nfsd/nfssvc.c151
-rw-r--r--fs/nfsd/state.h40
-rw-r--r--fs/nfsd/vfs.c79
-rw-r--r--fs/nfsd/vfs.h4
11 files changed, 465 insertions, 287 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 3d68f45a37b9..5b7e3021e06b 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -168,7 +168,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
168 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); 168 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
169 169
170 fh_copy(&resp->fh, &argp->fh); 170 fh_copy(&resp->fh, &argp->fh);
171 nfserr = nfsd_read(rqstp, &resp->fh, NULL, 171 nfserr = nfsd_read(rqstp, &resp->fh,
172 argp->offset, 172 argp->offset,
173 rqstp->rq_vec, argp->vlen, 173 rqstp->rq_vec, argp->vlen,
174 &resp->count); 174 &resp->count);
@@ -271,7 +271,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
271 fh_init(&resp->fh, NFS3_FHSIZE); 271 fh_init(&resp->fh, NFS3_FHSIZE);
272 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, 272 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
273 &argp->attrs, S_IFDIR, 0, &resp->fh); 273 &argp->attrs, S_IFDIR, 0, &resp->fh);
274 274 fh_unlock(&resp->dirfh);
275 RETURN_STATUS(nfserr); 275 RETURN_STATUS(nfserr);
276} 276}
277 277
@@ -327,7 +327,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
327 type = nfs3_ftypes[argp->ftype]; 327 type = nfs3_ftypes[argp->ftype];
328 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, 328 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
329 &argp->attrs, type, rdev, &resp->fh); 329 &argp->attrs, type, rdev, &resp->fh);
330 330 fh_unlock(&resp->dirfh);
331 RETURN_STATUS(nfserr); 331 RETURN_STATUS(nfserr);
332} 332}
333 333
@@ -348,6 +348,7 @@ nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
348 /* Unlink. -S_IFDIR means file must not be a directory */ 348 /* Unlink. -S_IFDIR means file must not be a directory */
349 fh_copy(&resp->fh, &argp->fh); 349 fh_copy(&resp->fh, &argp->fh);
350 nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len); 350 nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
351 fh_unlock(&resp->fh);
351 RETURN_STATUS(nfserr); 352 RETURN_STATUS(nfserr);
352} 353}
353 354
@@ -367,6 +368,7 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
367 368
368 fh_copy(&resp->fh, &argp->fh); 369 fh_copy(&resp->fh, &argp->fh);
369 nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len); 370 nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
371 fh_unlock(&resp->fh);
370 RETURN_STATUS(nfserr); 372 RETURN_STATUS(nfserr);
371} 373}
372 374
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index eb78e7e22077..988cbb3a19b6 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -143,8 +143,6 @@ struct nfs4_cb_compound_hdr {
143 u32 minorversion; 143 u32 minorversion;
144 /* res */ 144 /* res */
145 int status; 145 int status;
146 u32 taglen;
147 char *tag;
148}; 146};
149 147
150static struct { 148static struct {
@@ -205,6 +203,16 @@ nfs_cb_stat_to_errno(int stat)
205 */ 203 */
206 204
207static void 205static void
206encode_stateid(struct xdr_stream *xdr, stateid_t *sid)
207{
208 __be32 *p;
209
210 RESERVE_SPACE(sizeof(stateid_t));
211 WRITE32(sid->si_generation);
212 WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
213}
214
215static void
208encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) 216encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
209{ 217{
210 __be32 * p; 218 __be32 * p;
@@ -229,10 +237,10 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
229 __be32 *p; 237 __be32 *p;
230 int len = dp->dl_fh.fh_size; 238 int len = dp->dl_fh.fh_size;
231 239
232 RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len); 240 RESERVE_SPACE(4);
233 WRITE32(OP_CB_RECALL); 241 WRITE32(OP_CB_RECALL);
234 WRITE32(dp->dl_stateid.si_generation); 242 encode_stateid(xdr, &dp->dl_stateid);
235 WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t)); 243 RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2));
236 WRITE32(0); /* truncate optimization not implemented */ 244 WRITE32(0); /* truncate optimization not implemented */
237 WRITE32(len); 245 WRITE32(len);
238 WRITEMEM(&dp->dl_fh.fh_base, len); 246 WRITEMEM(&dp->dl_fh.fh_base, len);
@@ -293,13 +301,14 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
293static int 301static int
294decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ 302decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){
295 __be32 *p; 303 __be32 *p;
304 u32 taglen;
296 305
297 READ_BUF(8); 306 READ_BUF(8);
298 READ32(hdr->status); 307 READ32(hdr->status);
299 READ32(hdr->taglen); 308 /* We've got no use for the tag; ignore it: */
300 READ_BUF(hdr->taglen + 4); 309 READ32(taglen);
301 hdr->tag = (char *)p; 310 READ_BUF(taglen + 4);
302 p += XDR_QUADLEN(hdr->taglen); 311 p += XDR_QUADLEN(taglen);
303 READ32(hdr->nops); 312 READ32(hdr->nops);
304 return 0; 313 return 0;
305} 314}
@@ -667,28 +676,28 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
667 } 676 }
668 677
669 switch (task->tk_status) { 678 switch (task->tk_status) {
670 case -EIO: 679 case 0:
680 return;
681 case -EBADHANDLE:
682 case -NFS4ERR_BAD_STATEID:
683 /* Race: client probably got cb_recall
684 * before open reply granting delegation */
685 break;
686 default:
671 /* Network partition? */ 687 /* Network partition? */
672 atomic_set(&clp->cl_cb_set, 0); 688 atomic_set(&clp->cl_cb_set, 0);
673 warn_no_callback_path(clp, task->tk_status); 689 warn_no_callback_path(clp, task->tk_status);
674 if (current_rpc_client != task->tk_client) { 690 if (current_rpc_client != task->tk_client) {
675 /* queue a callback on the new connection: */ 691 /* queue a callback on the new connection: */
692 atomic_inc(&dp->dl_count);
676 nfsd4_cb_recall(dp); 693 nfsd4_cb_recall(dp);
677 return; 694 return;
678 } 695 }
679 case -EBADHANDLE:
680 case -NFS4ERR_BAD_STATEID:
681 /* Race: client probably got cb_recall
682 * before open reply granting delegation */
683 break;
684 default:
685 /* success, or error we can't handle */
686 return;
687 } 696 }
688 if (dp->dl_retries--) { 697 if (dp->dl_retries--) {
689 rpc_delay(task, 2*HZ); 698 rpc_delay(task, 2*HZ);
690 task->tk_status = 0; 699 task->tk_status = 0;
691 rpc_restart_call(task); 700 rpc_restart_call_prepare(task);
692 return; 701 return;
693 } else { 702 } else {
694 atomic_set(&clp->cl_cb_set, 0); 703 atomic_set(&clp->cl_cb_set, 0);
@@ -752,18 +761,16 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
752 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], 761 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
753 .rpc_cred = callback_cred 762 .rpc_cred = callback_cred
754 }; 763 };
755 int status;
756 764
757 if (clnt == NULL) 765 if (clnt == NULL) {
766 nfs4_put_delegation(dp);
758 return; /* Client is shutting down; give up. */ 767 return; /* Client is shutting down; give up. */
768 }
759 769
760 args->args_op = dp; 770 args->args_op = dp;
761 msg.rpc_argp = args; 771 msg.rpc_argp = args;
762 dp->dl_retries = 1; 772 dp->dl_retries = 1;
763 status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT, 773 rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp);
764 &nfsd4_cb_recall_ops, dp);
765 if (status)
766 nfs4_put_delegation(dp);
767} 774}
768 775
769void nfsd4_do_callback_rpc(struct work_struct *w) 776void nfsd4_do_callback_rpc(struct work_struct *w)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4a2734758778..2e7357104cfd 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -51,7 +51,6 @@ static time_t boot_time;
51static u32 current_ownerid = 1; 51static u32 current_ownerid = 1;
52static u32 current_fileid = 1; 52static u32 current_fileid = 1;
53static u32 current_delegid = 1; 53static u32 current_delegid = 1;
54static u32 nfs4_init;
55static stateid_t zerostateid; /* bits all 0 */ 54static stateid_t zerostateid; /* bits all 0 */
56static stateid_t onestateid; /* bits all 1 */ 55static stateid_t onestateid; /* bits all 1 */
57static u64 current_sessionid = 1; 56static u64 current_sessionid = 1;
@@ -163,6 +162,46 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
163static struct list_head file_hashtbl[FILE_HASH_SIZE]; 162static struct list_head file_hashtbl[FILE_HASH_SIZE];
164static struct list_head stateid_hashtbl[STATEID_HASH_SIZE]; 163static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
165 164
165static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag)
166{
167 BUG_ON(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR]));
168 atomic_inc(&fp->fi_access[oflag]);
169}
170
171static void nfs4_file_get_access(struct nfs4_file *fp, int oflag)
172{
173 if (oflag == O_RDWR) {
174 __nfs4_file_get_access(fp, O_RDONLY);
175 __nfs4_file_get_access(fp, O_WRONLY);
176 } else
177 __nfs4_file_get_access(fp, oflag);
178}
179
180static void nfs4_file_put_fd(struct nfs4_file *fp, int oflag)
181{
182 if (fp->fi_fds[oflag]) {
183 fput(fp->fi_fds[oflag]);
184 fp->fi_fds[oflag] = NULL;
185 }
186}
187
188static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
189{
190 if (atomic_dec_and_test(&fp->fi_access[oflag])) {
191 nfs4_file_put_fd(fp, O_RDWR);
192 nfs4_file_put_fd(fp, oflag);
193 }
194}
195
196static void nfs4_file_put_access(struct nfs4_file *fp, int oflag)
197{
198 if (oflag == O_RDWR) {
199 __nfs4_file_put_access(fp, O_RDONLY);
200 __nfs4_file_put_access(fp, O_WRONLY);
201 } else
202 __nfs4_file_put_access(fp, oflag);
203}
204
166static struct nfs4_delegation * 205static struct nfs4_delegation *
167alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) 206alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
168{ 207{
@@ -171,6 +210,13 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
171 struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn; 210 struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
172 211
173 dprintk("NFSD alloc_init_deleg\n"); 212 dprintk("NFSD alloc_init_deleg\n");
213 /*
214 * Major work on the lease subsystem (for example, to support
215 * calbacks on stat) will be required before we can support
216 * write delegations properly.
217 */
218 if (type != NFS4_OPEN_DELEGATE_READ)
219 return NULL;
174 if (fp->fi_had_conflict) 220 if (fp->fi_had_conflict)
175 return NULL; 221 return NULL;
176 if (num_delegations > max_delegations) 222 if (num_delegations > max_delegations)
@@ -185,9 +231,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
185 dp->dl_client = clp; 231 dp->dl_client = clp;
186 get_nfs4_file(fp); 232 get_nfs4_file(fp);
187 dp->dl_file = fp; 233 dp->dl_file = fp;
234 nfs4_file_get_access(fp, O_RDONLY);
188 dp->dl_flock = NULL; 235 dp->dl_flock = NULL;
189 get_file(stp->st_vfs_file);
190 dp->dl_vfs_file = stp->st_vfs_file;
191 dp->dl_type = type; 236 dp->dl_type = type;
192 dp->dl_ident = cb->cb_ident; 237 dp->dl_ident = cb->cb_ident;
193 dp->dl_stateid.si_boot = boot_time; 238 dp->dl_stateid.si_boot = boot_time;
@@ -222,15 +267,12 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
222static void 267static void
223nfs4_close_delegation(struct nfs4_delegation *dp) 268nfs4_close_delegation(struct nfs4_delegation *dp)
224{ 269{
225 struct file *filp = dp->dl_vfs_file; 270 struct file *filp = find_readable_file(dp->dl_file);
226 271
227 dprintk("NFSD: close_delegation dp %p\n",dp); 272 dprintk("NFSD: close_delegation dp %p\n",dp);
228 dp->dl_vfs_file = NULL;
229 /* The following nfsd_close may not actually close the file,
230 * but we want to remove the lease in any case. */
231 if (dp->dl_flock) 273 if (dp->dl_flock)
232 vfs_setlease(filp, F_UNLCK, &dp->dl_flock); 274 vfs_setlease(filp, F_UNLCK, &dp->dl_flock);
233 nfsd_close(filp); 275 nfs4_file_put_access(dp->dl_file, O_RDONLY);
234} 276}
235 277
236/* Called under the state lock. */ 278/* Called under the state lock. */
@@ -302,8 +344,12 @@ static void free_generic_stateid(struct nfs4_stateid *stp)
302 344
303static void release_lock_stateid(struct nfs4_stateid *stp) 345static void release_lock_stateid(struct nfs4_stateid *stp)
304{ 346{
347 struct file *file;
348
305 unhash_generic_stateid(stp); 349 unhash_generic_stateid(stp);
306 locks_remove_posix(stp->st_vfs_file, (fl_owner_t)stp->st_stateowner); 350 file = find_any_file(stp->st_file);
351 if (file)
352 locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
307 free_generic_stateid(stp); 353 free_generic_stateid(stp);
308} 354}
309 355
@@ -341,11 +387,85 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
341 } 387 }
342} 388}
343 389
390/*
391 * We store the NONE, READ, WRITE, and BOTH bits separately in the
392 * st_{access,deny}_bmap field of the stateid, in order to track not
393 * only what share bits are currently in force, but also what
394 * combinations of share bits previous opens have used. This allows us
395 * to enforce the recommendation of rfc 3530 14.2.19 that the server
396 * return an error if the client attempt to downgrade to a combination
397 * of share bits not explicable by closing some of its previous opens.
398 *
399 * XXX: This enforcement is actually incomplete, since we don't keep
400 * track of access/deny bit combinations; so, e.g., we allow:
401 *
402 * OPEN allow read, deny write
403 * OPEN allow both, deny none
404 * DOWNGRADE allow read, deny none
405 *
406 * which we should reject.
407 */
408static void
409set_access(unsigned int *access, unsigned long bmap) {
410 int i;
411
412 *access = 0;
413 for (i = 1; i < 4; i++) {
414 if (test_bit(i, &bmap))
415 *access |= i;
416 }
417}
418
419static void
420set_deny(unsigned int *deny, unsigned long bmap) {
421 int i;
422
423 *deny = 0;
424 for (i = 0; i < 4; i++) {
425 if (test_bit(i, &bmap))
426 *deny |= i ;
427 }
428}
429
430static int
431test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
432 unsigned int access, deny;
433
434 set_access(&access, stp->st_access_bmap);
435 set_deny(&deny, stp->st_deny_bmap);
436 if ((access & open->op_share_deny) || (deny & open->op_share_access))
437 return 0;
438 return 1;
439}
440
441static int nfs4_access_to_omode(u32 access)
442{
443 switch (access) {
444 case NFS4_SHARE_ACCESS_READ:
445 return O_RDONLY;
446 case NFS4_SHARE_ACCESS_WRITE:
447 return O_WRONLY;
448 case NFS4_SHARE_ACCESS_BOTH:
449 return O_RDWR;
450 }
451 BUG();
452}
453
454static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
455{
456 unsigned int access;
457
458 set_access(&access, stp->st_access_bmap);
459 return nfs4_access_to_omode(access);
460}
461
344static void release_open_stateid(struct nfs4_stateid *stp) 462static void release_open_stateid(struct nfs4_stateid *stp)
345{ 463{
464 int oflag = nfs4_access_bmap_to_omode(stp);
465
346 unhash_generic_stateid(stp); 466 unhash_generic_stateid(stp);
347 release_stateid_lockowners(stp); 467 release_stateid_lockowners(stp);
348 nfsd_close(stp->st_vfs_file); 468 nfs4_file_put_access(stp->st_file, oflag);
349 free_generic_stateid(stp); 469 free_generic_stateid(stp);
350} 470}
351 471
@@ -457,7 +577,7 @@ static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan)
457 spin_unlock(&nfsd_drc_lock); 577 spin_unlock(&nfsd_drc_lock);
458 578
459 if (fchan->maxreqs == 0) 579 if (fchan->maxreqs == 0)
460 return nfserr_serverfault; 580 return nfserr_jukebox;
461 581
462 fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ; 582 fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ;
463 return 0; 583 return 0;
@@ -542,7 +662,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
542 BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot) 662 BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot)
543 + sizeof(struct nfsd4_session) > PAGE_SIZE); 663 + sizeof(struct nfsd4_session) > PAGE_SIZE);
544 664
545 status = nfserr_serverfault; 665 status = nfserr_jukebox;
546 /* allocate struct nfsd4_session and slot table pointers in one piece */ 666 /* allocate struct nfsd4_session and slot table pointers in one piece */
547 slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *); 667 slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *);
548 new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL); 668 new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
@@ -591,10 +711,8 @@ find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
591 711
592 dump_sessionid(__func__, sessionid); 712 dump_sessionid(__func__, sessionid);
593 idx = hash_sessionid(sessionid); 713 idx = hash_sessionid(sessionid);
594 dprintk("%s: idx is %d\n", __func__, idx);
595 /* Search in the appropriate list */ 714 /* Search in the appropriate list */
596 list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) { 715 list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
597 dump_sessionid("list traversal", &elem->se_sessionid);
598 if (!memcmp(elem->se_sessionid.data, sessionid->data, 716 if (!memcmp(elem->se_sessionid.data, sessionid->data,
599 NFS4_MAX_SESSIONID_LEN)) { 717 NFS4_MAX_SESSIONID_LEN)) {
600 return elem; 718 return elem;
@@ -714,7 +832,6 @@ release_session_client(struct nfsd4_session *session)
714 } else 832 } else
715 renew_client_locked(clp); 833 renew_client_locked(clp);
716 spin_unlock(&client_lock); 834 spin_unlock(&client_lock);
717 nfsd4_put_session(session);
718} 835}
719 836
720/* must be called under the client_lock */ 837/* must be called under the client_lock */
@@ -1220,7 +1337,7 @@ out_new:
1220 /* Normal case */ 1337 /* Normal case */
1221 new = create_client(exid->clname, dname, rqstp, &verf); 1338 new = create_client(exid->clname, dname, rqstp, &verf);
1222 if (new == NULL) { 1339 if (new == NULL) {
1223 status = nfserr_serverfault; 1340 status = nfserr_jukebox;
1224 goto out; 1341 goto out;
1225 } 1342 }
1226 1343
@@ -1760,6 +1877,8 @@ alloc_init_file(struct inode *ino)
1760 fp->fi_inode = igrab(ino); 1877 fp->fi_inode = igrab(ino);
1761 fp->fi_id = current_fileid++; 1878 fp->fi_id = current_fileid++;
1762 fp->fi_had_conflict = false; 1879 fp->fi_had_conflict = false;
1880 memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
1881 memset(fp->fi_access, 0, sizeof(fp->fi_access));
1763 spin_lock(&recall_lock); 1882 spin_lock(&recall_lock);
1764 list_add(&fp->fi_hash, &file_hashtbl[hashval]); 1883 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
1765 spin_unlock(&recall_lock); 1884 spin_unlock(&recall_lock);
@@ -1971,57 +2090,6 @@ static inline int deny_valid(u32 x)
1971} 2090}
1972 2091
1973/* 2092/*
1974 * We store the NONE, READ, WRITE, and BOTH bits separately in the
1975 * st_{access,deny}_bmap field of the stateid, in order to track not
1976 * only what share bits are currently in force, but also what
1977 * combinations of share bits previous opens have used. This allows us
1978 * to enforce the recommendation of rfc 3530 14.2.19 that the server
1979 * return an error if the client attempt to downgrade to a combination
1980 * of share bits not explicable by closing some of its previous opens.
1981 *
1982 * XXX: This enforcement is actually incomplete, since we don't keep
1983 * track of access/deny bit combinations; so, e.g., we allow:
1984 *
1985 * OPEN allow read, deny write
1986 * OPEN allow both, deny none
1987 * DOWNGRADE allow read, deny none
1988 *
1989 * which we should reject.
1990 */
1991static void
1992set_access(unsigned int *access, unsigned long bmap) {
1993 int i;
1994
1995 *access = 0;
1996 for (i = 1; i < 4; i++) {
1997 if (test_bit(i, &bmap))
1998 *access |= i;
1999 }
2000}
2001
2002static void
2003set_deny(unsigned int *deny, unsigned long bmap) {
2004 int i;
2005
2006 *deny = 0;
2007 for (i = 0; i < 4; i++) {
2008 if (test_bit(i, &bmap))
2009 *deny |= i ;
2010 }
2011}
2012
2013static int
2014test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
2015 unsigned int access, deny;
2016
2017 set_access(&access, stp->st_access_bmap);
2018 set_deny(&deny, stp->st_deny_bmap);
2019 if ((access & open->op_share_deny) || (deny & open->op_share_access))
2020 return 0;
2021 return 1;
2022}
2023
2024/*
2025 * Called to check deny when READ with all zero stateid or 2093 * Called to check deny when READ with all zero stateid or
2026 * WRITE with all zero or all one stateid 2094 * WRITE with all zero or all one stateid
2027 */ 2095 */
@@ -2052,14 +2120,12 @@ out:
2052} 2120}
2053 2121
2054static inline void 2122static inline void
2055nfs4_file_downgrade(struct file *filp, unsigned int share_access) 2123nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access)
2056{ 2124{
2057 if (share_access & NFS4_SHARE_ACCESS_WRITE) { 2125 if (share_access & NFS4_SHARE_ACCESS_WRITE)
2058 drop_file_write_access(filp); 2126 nfs4_file_put_access(fp, O_WRONLY);
2059 spin_lock(&filp->f_lock); 2127 if (share_access & NFS4_SHARE_ACCESS_READ)
2060 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; 2128 nfs4_file_put_access(fp, O_RDONLY);
2061 spin_unlock(&filp->f_lock);
2062 }
2063} 2129}
2064 2130
2065/* 2131/*
@@ -2255,6 +2321,13 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
2255 return NULL; 2321 return NULL;
2256} 2322}
2257 2323
2324int share_access_to_flags(u32 share_access)
2325{
2326 share_access &= ~NFS4_SHARE_WANT_MASK;
2327
2328 return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE;
2329}
2330
2258static __be32 2331static __be32
2259nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, 2332nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
2260 struct nfs4_delegation **dp) 2333 struct nfs4_delegation **dp)
@@ -2265,8 +2338,7 @@ nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
2265 *dp = find_delegation_file(fp, &open->op_delegate_stateid); 2338 *dp = find_delegation_file(fp, &open->op_delegate_stateid);
2266 if (*dp == NULL) 2339 if (*dp == NULL)
2267 goto out; 2340 goto out;
2268 flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ? 2341 flags = share_access_to_flags(open->op_share_access);
2269 RD_STATE : WR_STATE;
2270 status = nfs4_check_delegmode(*dp, flags); 2342 status = nfs4_check_delegmode(*dp, flags);
2271 if (status) 2343 if (status)
2272 *dp = NULL; 2344 *dp = NULL;
@@ -2308,30 +2380,53 @@ nfs4_alloc_stateid(void)
2308 return kmem_cache_alloc(stateid_slab, GFP_KERNEL); 2380 return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
2309} 2381}
2310 2382
2383static inline int nfs4_access_to_access(u32 nfs4_access)
2384{
2385 int flags = 0;
2386
2387 if (nfs4_access & NFS4_SHARE_ACCESS_READ)
2388 flags |= NFSD_MAY_READ;
2389 if (nfs4_access & NFS4_SHARE_ACCESS_WRITE)
2390 flags |= NFSD_MAY_WRITE;
2391 return flags;
2392}
2393
2394static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file
2395*fp, struct svc_fh *cur_fh, u32 nfs4_access)
2396{
2397 __be32 status;
2398 int oflag = nfs4_access_to_omode(nfs4_access);
2399 int access = nfs4_access_to_access(nfs4_access);
2400
2401 if (!fp->fi_fds[oflag]) {
2402 status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
2403 &fp->fi_fds[oflag]);
2404 if (status == nfserr_dropit)
2405 status = nfserr_jukebox;
2406 if (status)
2407 return status;
2408 }
2409 nfs4_file_get_access(fp, oflag);
2410
2411 return nfs_ok;
2412}
2413
2311static __be32 2414static __be32
2312nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, 2415nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
2313 struct nfs4_delegation *dp, 2416 struct nfs4_file *fp, struct svc_fh *cur_fh,
2314 struct svc_fh *cur_fh, int flags) 2417 struct nfsd4_open *open)
2315{ 2418{
2316 struct nfs4_stateid *stp; 2419 struct nfs4_stateid *stp;
2420 __be32 status;
2317 2421
2318 stp = nfs4_alloc_stateid(); 2422 stp = nfs4_alloc_stateid();
2319 if (stp == NULL) 2423 if (stp == NULL)
2320 return nfserr_resource; 2424 return nfserr_resource;
2321 2425
2322 if (dp) { 2426 status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access);
2323 get_file(dp->dl_vfs_file); 2427 if (status) {
2324 stp->st_vfs_file = dp->dl_vfs_file; 2428 kmem_cache_free(stateid_slab, stp);
2325 } else { 2429 return status;
2326 __be32 status;
2327 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
2328 &stp->st_vfs_file);
2329 if (status) {
2330 if (status == nfserr_dropit)
2331 status = nfserr_jukebox;
2332 kmem_cache_free(stateid_slab, stp);
2333 return status;
2334 }
2335 } 2430 }
2336 *stpp = stp; 2431 *stpp = stp;
2337 return 0; 2432 return 0;
@@ -2353,35 +2448,30 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
2353} 2448}
2354 2449
2355static __be32 2450static __be32
2356nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) 2451nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
2357{ 2452{
2358 struct file *filp = stp->st_vfs_file; 2453 u32 op_share_access, new_access;
2359 struct inode *inode = filp->f_path.dentry->d_inode;
2360 unsigned int share_access, new_writer;
2361 __be32 status; 2454 __be32 status;
2362 2455
2363 set_access(&share_access, stp->st_access_bmap); 2456 set_access(&new_access, stp->st_access_bmap);
2364 new_writer = (~share_access) & open->op_share_access 2457 new_access = (~new_access) & open->op_share_access & ~NFS4_SHARE_WANT_MASK;
2365 & NFS4_SHARE_ACCESS_WRITE; 2458
2366 2459 if (new_access) {
2367 if (new_writer) { 2460 status = nfs4_get_vfs_file(rqstp, fp, cur_fh, new_access);
2368 int err = get_write_access(inode); 2461 if (status)
2369 if (err) 2462 return status;
2370 return nfserrno(err);
2371 err = mnt_want_write(cur_fh->fh_export->ex_path.mnt);
2372 if (err)
2373 return nfserrno(err);
2374 file_take_write(filp);
2375 } 2463 }
2376 status = nfsd4_truncate(rqstp, cur_fh, open); 2464 status = nfsd4_truncate(rqstp, cur_fh, open);
2377 if (status) { 2465 if (status) {
2378 if (new_writer) 2466 if (new_access) {
2379 put_write_access(inode); 2467 int oflag = nfs4_access_to_omode(new_access);
2468 nfs4_file_put_access(fp, oflag);
2469 }
2380 return status; 2470 return status;
2381 } 2471 }
2382 /* remember the open */ 2472 /* remember the open */
2383 filp->f_mode |= open->op_share_access; 2473 op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK;
2384 __set_bit(open->op_share_access, &stp->st_access_bmap); 2474 __set_bit(op_share_access, &stp->st_access_bmap);
2385 __set_bit(open->op_share_deny, &stp->st_deny_bmap); 2475 __set_bit(open->op_share_deny, &stp->st_deny_bmap);
2386 2476
2387 return nfs_ok; 2477 return nfs_ok;
@@ -2444,13 +2534,14 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2444 fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; 2534 fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
2445 fl.fl_end = OFFSET_MAX; 2535 fl.fl_end = OFFSET_MAX;
2446 fl.fl_owner = (fl_owner_t)dp; 2536 fl.fl_owner = (fl_owner_t)dp;
2447 fl.fl_file = stp->st_vfs_file; 2537 fl.fl_file = find_readable_file(stp->st_file);
2538 BUG_ON(!fl.fl_file);
2448 fl.fl_pid = current->tgid; 2539 fl.fl_pid = current->tgid;
2449 2540
2450 /* vfs_setlease checks to see if delegation should be handed out. 2541 /* vfs_setlease checks to see if delegation should be handed out.
2451 * the lock_manager callbacks fl_mylease and fl_change are used 2542 * the lock_manager callbacks fl_mylease and fl_change are used
2452 */ 2543 */
2453 if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) { 2544 if ((status = vfs_setlease(fl.fl_file, fl.fl_type, &flp))) {
2454 dprintk("NFSD: setlease failed [%d], no delegation\n", status); 2545 dprintk("NFSD: setlease failed [%d], no delegation\n", status);
2455 unhash_delegation(dp); 2546 unhash_delegation(dp);
2456 flag = NFS4_OPEN_DELEGATE_NONE; 2547 flag = NFS4_OPEN_DELEGATE_NONE;
@@ -2514,18 +2605,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2514 */ 2605 */
2515 if (stp) { 2606 if (stp) {
2516 /* Stateid was found, this is an OPEN upgrade */ 2607 /* Stateid was found, this is an OPEN upgrade */
2517 status = nfs4_upgrade_open(rqstp, current_fh, stp, open); 2608 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
2518 if (status) 2609 if (status)
2519 goto out; 2610 goto out;
2520 update_stateid(&stp->st_stateid); 2611 update_stateid(&stp->st_stateid);
2521 } else { 2612 } else {
2522 /* Stateid was not found, this is a new OPEN */ 2613 status = nfs4_new_open(rqstp, &stp, fp, current_fh, open);
2523 int flags = 0;
2524 if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
2525 flags |= NFSD_MAY_READ;
2526 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
2527 flags |= NFSD_MAY_WRITE;
2528 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
2529 if (status) 2614 if (status)
2530 goto out; 2615 goto out;
2531 init_stateid(stp, fp, open); 2616 init_stateid(stp, fp, open);
@@ -2727,7 +2812,7 @@ search_close_lru(u32 st_id, int flags)
2727static inline int 2812static inline int
2728nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) 2813nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
2729{ 2814{
2730 return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode; 2815 return fhp->fh_dentry->d_inode != stp->st_file->fi_inode;
2731} 2816}
2732 2817
2733static int 2818static int
@@ -2760,6 +2845,9 @@ __be32 nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
2760{ 2845{
2761 __be32 status = nfserr_openmode; 2846 __be32 status = nfserr_openmode;
2762 2847
2848 /* For lock stateid's, we test the parent open, not the lock: */
2849 if (stp->st_openstp)
2850 stp = stp->st_openstp;
2763 if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap))) 2851 if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap)))
2764 goto out; 2852 goto out;
2765 if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap))) 2853 if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap)))
@@ -2872,7 +2960,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2872 goto out; 2960 goto out;
2873 renew_client(dp->dl_client); 2961 renew_client(dp->dl_client);
2874 if (filpp) 2962 if (filpp)
2875 *filpp = dp->dl_vfs_file; 2963 *filpp = find_readable_file(dp->dl_file);
2964 BUG_ON(!*filpp);
2876 } else { /* open or lock stateid */ 2965 } else { /* open or lock stateid */
2877 stp = find_stateid(stateid, flags); 2966 stp = find_stateid(stateid, flags);
2878 if (!stp) 2967 if (!stp)
@@ -2889,8 +2978,13 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2889 if (status) 2978 if (status)
2890 goto out; 2979 goto out;
2891 renew_client(stp->st_stateowner->so_client); 2980 renew_client(stp->st_stateowner->so_client);
2892 if (filpp) 2981 if (filpp) {
2893 *filpp = stp->st_vfs_file; 2982 if (flags & RD_STATE)
2983 *filpp = find_readable_file(stp->st_file);
2984 else
2985 *filpp = find_writeable_file(stp->st_file);
2986 BUG_ON(!*filpp); /* assured by check_openmode */
2987 }
2894 } 2988 }
2895 status = nfs_ok; 2989 status = nfs_ok;
2896out: 2990out:
@@ -3126,8 +3220,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3126 goto out; 3220 goto out;
3127 } 3221 }
3128 set_access(&share_access, stp->st_access_bmap); 3222 set_access(&share_access, stp->st_access_bmap);
3129 nfs4_file_downgrade(stp->st_vfs_file, 3223 nfs4_file_downgrade(stp->st_file, share_access & ~od->od_share_access);
3130 share_access & ~od->od_share_access);
3131 3224
3132 reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap); 3225 reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
3133 reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap); 3226 reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
@@ -3346,11 +3439,9 @@ static inline void
3346nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) 3439nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
3347{ 3440{
3348 struct nfs4_stateowner *sop; 3441 struct nfs4_stateowner *sop;
3349 unsigned int hval;
3350 3442
3351 if (fl->fl_lmops == &nfsd_posix_mng_ops) { 3443 if (fl->fl_lmops == &nfsd_posix_mng_ops) {
3352 sop = (struct nfs4_stateowner *) fl->fl_owner; 3444 sop = (struct nfs4_stateowner *) fl->fl_owner;
3353 hval = lockownerid_hashval(sop->so_id);
3354 kref_get(&sop->so_ref); 3445 kref_get(&sop->so_ref);
3355 deny->ld_sop = sop; 3446 deny->ld_sop = sop;
3356 deny->ld_clientid = sop->so_client->cl_clientid; 3447 deny->ld_clientid = sop->so_client->cl_clientid;
@@ -3446,8 +3537,6 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
3446 stp->st_stateid.si_stateownerid = sop->so_id; 3537 stp->st_stateid.si_stateownerid = sop->so_id;
3447 stp->st_stateid.si_fileid = fp->fi_id; 3538 stp->st_stateid.si_fileid = fp->fi_id;
3448 stp->st_stateid.si_generation = 0; 3539 stp->st_stateid.si_generation = 0;
3449 stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
3450 stp->st_access_bmap = open_stp->st_access_bmap;
3451 stp->st_deny_bmap = open_stp->st_deny_bmap; 3540 stp->st_deny_bmap = open_stp->st_deny_bmap;
3452 stp->st_openstp = open_stp; 3541 stp->st_openstp = open_stp;
3453 3542
@@ -3547,7 +3636,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3547 lock_sop = lock->lk_replay_owner; 3636 lock_sop = lock->lk_replay_owner;
3548 } 3637 }
3549 /* lock->lk_replay_owner and lock_stp have been created or found */ 3638 /* lock->lk_replay_owner and lock_stp have been created or found */
3550 filp = lock_stp->st_vfs_file;
3551 3639
3552 status = nfserr_grace; 3640 status = nfserr_grace;
3553 if (locks_in_grace() && !lock->lk_reclaim) 3641 if (locks_in_grace() && !lock->lk_reclaim)
@@ -3560,11 +3648,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3560 switch (lock->lk_type) { 3648 switch (lock->lk_type) {
3561 case NFS4_READ_LT: 3649 case NFS4_READ_LT:
3562 case NFS4_READW_LT: 3650 case NFS4_READW_LT:
3651 filp = find_readable_file(lock_stp->st_file);
3563 file_lock.fl_type = F_RDLCK; 3652 file_lock.fl_type = F_RDLCK;
3564 cmd = F_SETLK; 3653 cmd = F_SETLK;
3565 break; 3654 break;
3566 case NFS4_WRITE_LT: 3655 case NFS4_WRITE_LT:
3567 case NFS4_WRITEW_LT: 3656 case NFS4_WRITEW_LT:
3657 filp = find_writeable_file(lock_stp->st_file);
3568 file_lock.fl_type = F_WRLCK; 3658 file_lock.fl_type = F_WRLCK;
3569 cmd = F_SETLK; 3659 cmd = F_SETLK;
3570 break; 3660 break;
@@ -3572,6 +3662,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3572 status = nfserr_inval; 3662 status = nfserr_inval;
3573 goto out; 3663 goto out;
3574 } 3664 }
3665 if (!filp) {
3666 status = nfserr_openmode;
3667 goto out;
3668 }
3575 file_lock.fl_owner = (fl_owner_t)lock_sop; 3669 file_lock.fl_owner = (fl_owner_t)lock_sop;
3576 file_lock.fl_pid = current->tgid; 3670 file_lock.fl_pid = current->tgid;
3577 file_lock.fl_file = filp; 3671 file_lock.fl_file = filp;
@@ -3740,7 +3834,11 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3740 &locku->lu_stateowner, &stp, NULL))) 3834 &locku->lu_stateowner, &stp, NULL)))
3741 goto out; 3835 goto out;
3742 3836
3743 filp = stp->st_vfs_file; 3837 filp = find_any_file(stp->st_file);
3838 if (!filp) {
3839 status = nfserr_lock_range;
3840 goto out;
3841 }
3744 BUG_ON(!filp); 3842 BUG_ON(!filp);
3745 locks_init_lock(&file_lock); 3843 locks_init_lock(&file_lock);
3746 file_lock.fl_type = F_UNLCK; 3844 file_lock.fl_type = F_UNLCK;
@@ -3787,10 +3885,10 @@ out_nfserr:
3787 * 0: no locks held by lockowner 3885 * 0: no locks held by lockowner
3788 */ 3886 */
3789static int 3887static int
3790check_for_locks(struct file *filp, struct nfs4_stateowner *lowner) 3888check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner)
3791{ 3889{
3792 struct file_lock **flpp; 3890 struct file_lock **flpp;
3793 struct inode *inode = filp->f_path.dentry->d_inode; 3891 struct inode *inode = filp->fi_inode;
3794 int status = 0; 3892 int status = 0;
3795 3893
3796 lock_kernel(); 3894 lock_kernel();
@@ -3841,7 +3939,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
3841 continue; 3939 continue;
3842 list_for_each_entry(stp, &sop->so_stateids, 3940 list_for_each_entry(stp, &sop->so_stateids,
3843 st_perstateowner) { 3941 st_perstateowner) {
3844 if (check_for_locks(stp->st_vfs_file, sop)) 3942 if (check_for_locks(stp->st_file, sop))
3845 goto out; 3943 goto out;
3846 /* Note: so_perclient unused for lockowners, 3944 /* Note: so_perclient unused for lockowners,
3847 * so it's OK to fool with here. */ 3945 * so it's OK to fool with here. */
@@ -4066,16 +4164,8 @@ out_free_laundry:
4066int 4164int
4067nfs4_state_start(void) 4165nfs4_state_start(void)
4068{ 4166{
4069 int ret;
4070
4071 if (nfs4_init)
4072 return 0;
4073 nfsd4_load_reboot_recovery_data(); 4167 nfsd4_load_reboot_recovery_data();
4074 ret = __nfs4_state_start(); 4168 return __nfs4_state_start();
4075 if (ret)
4076 return ret;
4077 nfs4_init = 1;
4078 return 0;
4079} 4169}
4080 4170
4081static void 4171static void
@@ -4110,7 +4200,6 @@ __nfs4_state_shutdown(void)
4110 } 4200 }
4111 4201
4112 nfsd4_shutdown_recdir(); 4202 nfsd4_shutdown_recdir();
4113 nfs4_init = 0;
4114} 4203}
4115 4204
4116void 4205void
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ac17a7080239..f8931acb05f3 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2630,7 +2630,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2630 } 2630 }
2631 read->rd_vlen = v; 2631 read->rd_vlen = v;
2632 2632
2633 nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, 2633 nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp,
2634 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, 2634 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen,
2635 &maxcount); 2635 &maxcount);
2636 2636
@@ -3325,6 +3325,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
3325 } 3325 }
3326 /* Renew the clientid on success and on replay */ 3326 /* Renew the clientid on success and on replay */
3327 release_session_client(cs->session); 3327 release_session_client(cs->session);
3328 nfsd4_put_session(cs->session);
3328 } 3329 }
3329 return 1; 3330 return 1;
3330} 3331}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 508941c23af7..b53b1d042f1f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -949,15 +949,12 @@ static ssize_t __write_ports_addfd(char *buf)
949 if (err != 0) 949 if (err != 0)
950 return err; 950 return err;
951 951
952 err = lockd_up();
953 if (err != 0)
954 goto out;
955
956 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 952 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
957 if (err < 0) 953 if (err < 0) {
958 lockd_down(); 954 svc_destroy(nfsd_serv);
955 return err;
956 }
959 957
960out:
961 /* Decrease the count, but don't shut down the service */ 958 /* Decrease the count, but don't shut down the service */
962 nfsd_serv->sv_nrthreads--; 959 nfsd_serv->sv_nrthreads--;
963 return err; 960 return err;
@@ -978,9 +975,6 @@ static ssize_t __write_ports_delfd(char *buf)
978 if (nfsd_serv != NULL) 975 if (nfsd_serv != NULL)
979 len = svc_sock_names(nfsd_serv, buf, 976 len = svc_sock_names(nfsd_serv, buf,
980 SIMPLE_TRANSACTION_LIMIT, toclose); 977 SIMPLE_TRANSACTION_LIMIT, toclose);
981 if (len >= 0)
982 lockd_down();
983
984 kfree(toclose); 978 kfree(toclose);
985 return len; 979 return len;
986} 980}
@@ -1014,6 +1008,9 @@ static ssize_t __write_ports_addxprt(char *buf)
1014 PF_INET6, port, SVC_SOCK_ANONYMOUS); 1008 PF_INET6, port, SVC_SOCK_ANONYMOUS);
1015 if (err < 0 && err != -EAFNOSUPPORT) 1009 if (err < 0 && err != -EAFNOSUPPORT)
1016 goto out_close; 1010 goto out_close;
1011
1012 /* Decrease the count, but don't shut down the service */
1013 nfsd_serv->sv_nrthreads--;
1017 return 0; 1014 return 0;
1018out_close: 1015out_close:
1019 xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port); 1016 xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
@@ -1022,8 +1019,7 @@ out_close:
1022 svc_xprt_put(xprt); 1019 svc_xprt_put(xprt);
1023 } 1020 }
1024out_err: 1021out_err:
1025 /* Decrease the count, but don't shut down the service */ 1022 svc_destroy(nfsd_serv);
1026 nfsd_serv->sv_nrthreads--;
1027 return err; 1023 return err;
1028} 1024}
1029 1025
@@ -1194,7 +1190,7 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
1194 bsize = NFSSVC_MAXBLKSIZE; 1190 bsize = NFSSVC_MAXBLKSIZE;
1195 bsize &= ~(1024-1); 1191 bsize &= ~(1024-1);
1196 mutex_lock(&nfsd_mutex); 1192 mutex_lock(&nfsd_mutex);
1197 if (nfsd_serv && nfsd_serv->sv_nrthreads) { 1193 if (nfsd_serv) {
1198 mutex_unlock(&nfsd_mutex); 1194 mutex_unlock(&nfsd_mutex);
1199 return -EBUSY; 1195 return -EBUSY;
1200 } 1196 }
@@ -1310,6 +1306,8 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
1310 return -EINVAL; 1306 return -EINVAL;
1311 1307
1312 status = nfs4_reset_recoverydir(recdir); 1308 status = nfs4_reset_recoverydir(recdir);
1309 if (status)
1310 return status;
1313 } 1311 }
1314 1312
1315 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n", 1313 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 72377761270e..b76ac3a82e39 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -153,6 +153,7 @@ void nfsd_lockd_shutdown(void);
153#define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID) 153#define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID)
154#define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK) 154#define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK)
155#define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME) 155#define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME)
156#define nfserr_lock_range cpu_to_be32(NFSERR_LOCK_RANGE)
156#define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH) 157#define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH)
157#define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP) 158#define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP)
158#define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR) 159#define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR)
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index a047ad6111ef..08e17264784b 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -144,7 +144,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
144 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); 144 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
145 145
146 resp->count = argp->count; 146 resp->count = argp->count;
147 nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL, 147 nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
148 argp->offset, 148 argp->offset,
149 rqstp->rq_vec, argp->vlen, 149 rqstp->rq_vec, argp->vlen,
150 &resp->count); 150 &resp->count);
@@ -290,7 +290,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
290 * gospel of sun micro 290 * gospel of sun micro
291 */ 291 */
292 if (type != S_IFREG) { 292 if (type != S_IFREG) {
293 int is_borc = 0;
294 if (type != S_IFBLK && type != S_IFCHR) { 293 if (type != S_IFBLK && type != S_IFCHR) {
295 rdev = 0; 294 rdev = 0;
296 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { 295 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
@@ -298,7 +297,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
298 type = S_IFIFO; 297 type = S_IFIFO;
299 } else { 298 } else {
300 /* Okay, char or block special */ 299 /* Okay, char or block special */
301 is_borc = 1;
302 if (!rdev) 300 if (!rdev)
303 rdev = wanted; 301 rdev = wanted;
304 } 302 }
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 06b2a26edfe0..e2c43464f237 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -180,15 +180,80 @@ int nfsd_nrthreads(void)
180 return rv; 180 return rv;
181} 181}
182 182
183static int nfsd_init_socks(int port)
184{
185 int error;
186 if (!list_empty(&nfsd_serv->sv_permsocks))
187 return 0;
188
189 error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port,
190 SVC_SOCK_DEFAULTS);
191 if (error < 0)
192 return error;
193
194 error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port,
195 SVC_SOCK_DEFAULTS);
196 if (error < 0)
197 return error;
198
199 return 0;
200}
201
202static bool nfsd_up = false;
203
204static int nfsd_startup(unsigned short port, int nrservs)
205{
206 int ret;
207
208 if (nfsd_up)
209 return 0;
210 /*
211 * Readahead param cache - will no-op if it already exists.
212 * (Note therefore results will be suboptimal if number of
213 * threads is modified after nfsd start.)
214 */
215 ret = nfsd_racache_init(2*nrservs);
216 if (ret)
217 return ret;
218 ret = nfsd_init_socks(port);
219 if (ret)
220 goto out_racache;
221 ret = lockd_up();
222 if (ret)
223 goto out_racache;
224 ret = nfs4_state_start();
225 if (ret)
226 goto out_lockd;
227 nfsd_up = true;
228 return 0;
229out_lockd:
230 lockd_down();
231out_racache:
232 nfsd_racache_shutdown();
233 return ret;
234}
235
236static void nfsd_shutdown(void)
237{
238 /*
239 * write_ports can create the server without actually starting
240 * any threads--if we get shut down before any threads are
241 * started, then nfsd_last_thread will be run before any of this
242 * other initialization has been done.
243 */
244 if (!nfsd_up)
245 return;
246 nfs4_state_shutdown();
247 lockd_down();
248 nfsd_racache_shutdown();
249 nfsd_up = false;
250}
251
183static void nfsd_last_thread(struct svc_serv *serv) 252static void nfsd_last_thread(struct svc_serv *serv)
184{ 253{
185 /* When last nfsd thread exits we need to do some clean-up */ 254 /* When last nfsd thread exits we need to do some clean-up */
186 struct svc_xprt *xprt;
187 list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list)
188 lockd_down();
189 nfsd_serv = NULL; 255 nfsd_serv = NULL;
190 nfsd_racache_shutdown(); 256 nfsd_shutdown();
191 nfs4_state_shutdown();
192 257
193 printk(KERN_WARNING "nfsd: last server has exited, flushing export " 258 printk(KERN_WARNING "nfsd: last server has exited, flushing export "
194 "cache\n"); 259 "cache\n");
@@ -263,45 +328,18 @@ int nfsd_create_serv(void)
263 nfsd_max_blksize >= 8*1024*2) 328 nfsd_max_blksize >= 8*1024*2)
264 nfsd_max_blksize /= 2; 329 nfsd_max_blksize /= 2;
265 } 330 }
331 nfsd_reset_versions();
266 332
267 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 333 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
268 nfsd_last_thread, nfsd, THIS_MODULE); 334 nfsd_last_thread, nfsd, THIS_MODULE);
269 if (nfsd_serv == NULL) 335 if (nfsd_serv == NULL)
270 err = -ENOMEM; 336 return -ENOMEM;
271 else
272 set_max_drc();
273 337
338 set_max_drc();
274 do_gettimeofday(&nfssvc_boot); /* record boot time */ 339 do_gettimeofday(&nfssvc_boot); /* record boot time */
275 return err; 340 return err;
276} 341}
277 342
278static int nfsd_init_socks(int port)
279{
280 int error;
281 if (!list_empty(&nfsd_serv->sv_permsocks))
282 return 0;
283
284 error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port,
285 SVC_SOCK_DEFAULTS);
286 if (error < 0)
287 return error;
288
289 error = lockd_up();
290 if (error < 0)
291 return error;
292
293 error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port,
294 SVC_SOCK_DEFAULTS);
295 if (error < 0)
296 return error;
297
298 error = lockd_up();
299 if (error < 0)
300 return error;
301
302 return 0;
303}
304
305int nfsd_nrpools(void) 343int nfsd_nrpools(void)
306{ 344{
307 if (nfsd_serv == NULL) 345 if (nfsd_serv == NULL)
@@ -376,10 +414,16 @@ int nfsd_set_nrthreads(int n, int *nthreads)
376 return err; 414 return err;
377} 415}
378 416
417/*
418 * Adjust the number of threads and return the new number of threads.
419 * This is also the function that starts the server if necessary, if
420 * this is the first time nrservs is nonzero.
421 */
379int 422int
380nfsd_svc(unsigned short port, int nrservs) 423nfsd_svc(unsigned short port, int nrservs)
381{ 424{
382 int error; 425 int error;
426 bool nfsd_up_before;
383 427
384 mutex_lock(&nfsd_mutex); 428 mutex_lock(&nfsd_mutex);
385 dprintk("nfsd: creating service\n"); 429 dprintk("nfsd: creating service\n");
@@ -391,34 +435,29 @@ nfsd_svc(unsigned short port, int nrservs)
391 if (nrservs == 0 && nfsd_serv == NULL) 435 if (nrservs == 0 && nfsd_serv == NULL)
392 goto out; 436 goto out;
393 437
394 /* Readahead param cache - will no-op if it already exists */ 438 error = nfsd_create_serv();
395 error = nfsd_racache_init(2*nrservs);
396 if (error<0)
397 goto out;
398 error = nfs4_state_start();
399 if (error) 439 if (error)
400 goto out; 440 goto out;
401 441
402 nfsd_reset_versions(); 442 nfsd_up_before = nfsd_up;
403
404 error = nfsd_create_serv();
405 443
444 error = nfsd_startup(port, nrservs);
406 if (error) 445 if (error)
407 goto out; 446 goto out_destroy;
408 error = nfsd_init_socks(port);
409 if (error)
410 goto failure;
411
412 error = svc_set_num_threads(nfsd_serv, NULL, nrservs); 447 error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
413 if (error == 0) 448 if (error)
414 /* We are holding a reference to nfsd_serv which 449 goto out_shutdown;
415 * we don't want to count in the return value, 450 /* We are holding a reference to nfsd_serv which
416 * so subtract 1 451 * we don't want to count in the return value,
417 */ 452 * so subtract 1
418 error = nfsd_serv->sv_nrthreads - 1; 453 */
419 failure: 454 error = nfsd_serv->sv_nrthreads - 1;
455out_shutdown:
456 if (error < 0 && !nfsd_up_before)
457 nfsd_shutdown();
458out_destroy:
420 svc_destroy(nfsd_serv); /* Release server */ 459 svc_destroy(nfsd_serv); /* Release server */
421 out: 460out:
422 mutex_unlock(&nfsd_mutex); 461 mutex_unlock(&nfsd_mutex);
423 return error; 462 return error;
424} 463}
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 006c84230c7c..7731a75971dd 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -88,7 +88,6 @@ struct nfs4_delegation {
88 struct nfs4_client *dl_client; 88 struct nfs4_client *dl_client;
89 struct nfs4_file *dl_file; 89 struct nfs4_file *dl_file;
90 struct file_lock *dl_flock; 90 struct file_lock *dl_flock;
91 struct file *dl_vfs_file;
92 u32 dl_type; 91 u32 dl_type;
93 time_t dl_time; 92 time_t dl_time;
94/* For recall: */ 93/* For recall: */
@@ -342,12 +341,50 @@ struct nfs4_file {
342 struct list_head fi_hash; /* hash by "struct inode *" */ 341 struct list_head fi_hash; /* hash by "struct inode *" */
343 struct list_head fi_stateids; 342 struct list_head fi_stateids;
344 struct list_head fi_delegations; 343 struct list_head fi_delegations;
344 /* One each for O_RDONLY, O_WRONLY, O_RDWR: */
345 struct file * fi_fds[3];
346 /* One each for O_RDONLY, O_WRONLY: */
347 atomic_t fi_access[2];
348 /*
349 * Each open stateid contributes 1 to either fi_readers or
350 * fi_writers, or both, depending on the open mode. A
351 * delegation also takes an fi_readers reference. Lock
352 * stateid's take none.
353 */
354 atomic_t fi_readers;
355 atomic_t fi_writers;
345 struct inode *fi_inode; 356 struct inode *fi_inode;
346 u32 fi_id; /* used with stateowner->so_id 357 u32 fi_id; /* used with stateowner->so_id
347 * for stateid_hashtbl hash */ 358 * for stateid_hashtbl hash */
348 bool fi_had_conflict; 359 bool fi_had_conflict;
349}; 360};
350 361
362/* XXX: for first cut may fall back on returning file that doesn't work
363 * at all? */
364static inline struct file *find_writeable_file(struct nfs4_file *f)
365{
366 if (f->fi_fds[O_RDWR])
367 return f->fi_fds[O_RDWR];
368 return f->fi_fds[O_WRONLY];
369}
370
371static inline struct file *find_readable_file(struct nfs4_file *f)
372{
373 if (f->fi_fds[O_RDWR])
374 return f->fi_fds[O_RDWR];
375 return f->fi_fds[O_RDONLY];
376}
377
378static inline struct file *find_any_file(struct nfs4_file *f)
379{
380 if (f->fi_fds[O_RDWR])
381 return f->fi_fds[O_RDWR];
382 else if (f->fi_fds[O_RDWR])
383 return f->fi_fds[O_WRONLY];
384 else
385 return f->fi_fds[O_RDONLY];
386}
387
351/* 388/*
352* nfs4_stateid can either be an open stateid or (eventually) a lock stateid 389* nfs4_stateid can either be an open stateid or (eventually) a lock stateid
353* 390*
@@ -373,7 +410,6 @@ struct nfs4_stateid {
373 struct nfs4_stateowner * st_stateowner; 410 struct nfs4_stateowner * st_stateowner;
374 struct nfs4_file * st_file; 411 struct nfs4_file * st_file;
375 stateid_t st_stateid; 412 stateid_t st_stateid;
376 struct file * st_vfs_file;
377 unsigned long st_access_bmap; 413 unsigned long st_access_bmap;
378 unsigned long st_deny_bmap; 414 unsigned long st_deny_bmap;
379 struct nfs4_stateid * st_openstp; 415 struct nfs4_stateid * st_openstp;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 3c111120b619..9df85a13af28 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -604,7 +604,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
604 return error; 604 return error;
605} 605}
606 606
607#endif /* defined(CONFIG_NFS_V4) */ 607#endif /* defined(CONFIG_NFSD_V4) */
608 608
609#ifdef CONFIG_NFSD_V3 609#ifdef CONFIG_NFSD_V3
610/* 610/*
@@ -903,7 +903,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
903 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 903 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
904{ 904{
905 struct inode *inode; 905 struct inode *inode;
906 struct raparms *ra;
907 mm_segment_t oldfs; 906 mm_segment_t oldfs;
908 __be32 err; 907 __be32 err;
909 int host_err; 908 int host_err;
@@ -914,12 +913,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
914 if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) 913 if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
915 goto out; 914 goto out;
916 915
917 /* Get readahead parameters */
918 ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
919
920 if (ra && ra->p_set)
921 file->f_ra = ra->p_ra;
922
923 if (file->f_op->splice_read && rqstp->rq_splice_ok) { 916 if (file->f_op->splice_read && rqstp->rq_splice_ok) {
924 struct splice_desc sd = { 917 struct splice_desc sd = {
925 .len = 0, 918 .len = 0,
@@ -937,16 +930,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
937 set_fs(oldfs); 930 set_fs(oldfs);
938 } 931 }
939 932
940 /* Write back readahead params */
941 if (ra) {
942 struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex];
943 spin_lock(&rab->pb_lock);
944 ra->p_ra = file->f_ra;
945 ra->p_set = 1;
946 ra->p_count--;
947 spin_unlock(&rab->pb_lock);
948 }
949
950 if (host_err >= 0) { 933 if (host_err >= 0) {
951 nfsdstats.io_read += host_err; 934 nfsdstats.io_read += host_err;
952 *count = host_err; 935 *count = host_err;
@@ -1086,8 +1069,45 @@ out:
1086 * on entry. On return, *count contains the number of bytes actually read. 1069 * on entry. On return, *count contains the number of bytes actually read.
1087 * N.B. After this call fhp needs an fh_put 1070 * N.B. After this call fhp needs an fh_put
1088 */ 1071 */
1072__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
1073 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
1074{
1075 struct file *file;
1076 struct inode *inode;
1077 struct raparms *ra;
1078 __be32 err;
1079
1080 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
1081 if (err)
1082 return err;
1083
1084 inode = file->f_path.dentry->d_inode;
1085
1086 /* Get readahead parameters */
1087 ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
1088
1089 if (ra && ra->p_set)
1090 file->f_ra = ra->p_ra;
1091
1092 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
1093
1094 /* Write back readahead params */
1095 if (ra) {
1096 struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex];
1097 spin_lock(&rab->pb_lock);
1098 ra->p_ra = file->f_ra;
1099 ra->p_set = 1;
1100 ra->p_count--;
1101 spin_unlock(&rab->pb_lock);
1102 }
1103
1104 nfsd_close(file);
1105 return err;
1106}
1107
1108/* As above, but use the provided file descriptor. */
1089__be32 1109__be32
1090nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 1110nfsd_read_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1091 loff_t offset, struct kvec *vec, int vlen, 1111 loff_t offset, struct kvec *vec, int vlen,
1092 unsigned long *count) 1112 unsigned long *count)
1093{ 1113{
@@ -1099,13 +1119,8 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1099 if (err) 1119 if (err)
1100 goto out; 1120 goto out;
1101 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); 1121 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
1102 } else { 1122 } else /* Note file may still be NULL in NFSv4 special stateid case: */
1103 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); 1123 err = nfsd_read(rqstp, fhp, offset, vec, vlen, count);
1104 if (err)
1105 goto out;
1106 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
1107 nfsd_close(file);
1108 }
1109out: 1124out:
1110 return err; 1125 return err;
1111} 1126}
@@ -1631,7 +1646,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1631 char *name, int len, struct svc_fh *tfhp) 1646 char *name, int len, struct svc_fh *tfhp)
1632{ 1647{
1633 struct dentry *ddir, *dnew, *dold; 1648 struct dentry *ddir, *dnew, *dold;
1634 struct inode *dirp, *dest; 1649 struct inode *dirp;
1635 __be32 err; 1650 __be32 err;
1636 int host_err; 1651 int host_err;
1637 1652
@@ -1659,7 +1674,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1659 goto out_nfserr; 1674 goto out_nfserr;
1660 1675
1661 dold = tfhp->fh_dentry; 1676 dold = tfhp->fh_dentry;
1662 dest = dold->d_inode;
1663 1677
1664 host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt); 1678 host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt);
1665 if (host_err) { 1679 if (host_err) {
@@ -2038,7 +2052,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2038 struct dentry *dentry, int acc) 2052 struct dentry *dentry, int acc)
2039{ 2053{
2040 struct inode *inode = dentry->d_inode; 2054 struct inode *inode = dentry->d_inode;
2041 struct path path;
2042 int err; 2055 int err;
2043 2056
2044 if (acc == NFSD_MAY_NOP) 2057 if (acc == NFSD_MAY_NOP)
@@ -2111,15 +2124,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2111 if (err == -EACCES && S_ISREG(inode->i_mode) && 2124 if (err == -EACCES && S_ISREG(inode->i_mode) &&
2112 acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) 2125 acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE))
2113 err = inode_permission(inode, MAY_EXEC); 2126 err = inode_permission(inode, MAY_EXEC);
2114 if (err)
2115 goto nfsd_out;
2116 2127
2117 /* Do integrity (permission) checking now, but defer incrementing
2118 * IMA counts to the actual file open.
2119 */
2120 path.mnt = exp->ex_path.mnt;
2121 path.dentry = dentry;
2122nfsd_out:
2123 return err? nfserrno(err) : 0; 2128 return err? nfserrno(err) : 0;
2124} 2129}
2125 2130
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 217a62c2a357..9a370a5e36b7 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -64,7 +64,9 @@ __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *,
64__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int, 64__be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int,
65 int, struct file **); 65 int, struct file **);
66void nfsd_close(struct file *); 66void nfsd_close(struct file *);
67__be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *, 67__be32 nfsd_read(struct svc_rqst *, struct svc_fh *,
68 loff_t, struct kvec *, int, unsigned long *);
69__be32 nfsd_read_file(struct svc_rqst *, struct svc_fh *, struct file *,
68 loff_t, struct kvec *, int, unsigned long *); 70 loff_t, struct kvec *, int, unsigned long *);
69__be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, 71__be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
70 loff_t, struct kvec *,int, unsigned long *, int *); 72 loff_t, struct kvec *,int, unsigned long *, int *);