aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/nfs4_fs.h8
-rw-r--r--fs/nfs/nfs4proc.c126
-rw-r--r--fs/nfs/nfs4state.c24
-rw-r--r--fs/nfs/nfs4xdr.c10
-rw-r--r--include/linux/nfs_fs.h4
-rw-r--r--include/linux/nfs_xdr.h3
7 files changed, 94 insertions, 83 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d22eb383e1cf..1cf39202c3ea 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -592,7 +592,7 @@ static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context
592/* 592/*
593 * Given an inode, search for an open context with the desired characteristics 593 * Given an inode, search for an open context with the desired characteristics
594 */ 594 */
595struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode) 595struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode)
596{ 596{
597 struct nfs_inode *nfsi = NFS_I(inode); 597 struct nfs_inode *nfsi = NFS_I(inode);
598 struct nfs_open_context *pos, *ctx = NULL; 598 struct nfs_open_context *pos, *ctx = NULL;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ee5f51ef696d..d5f5efaf2b26 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -161,7 +161,7 @@ struct nfs4_state {
161 unsigned int n_rdonly; /* Number of read-only references */ 161 unsigned int n_rdonly; /* Number of read-only references */
162 unsigned int n_wronly; /* Number of write-only references */ 162 unsigned int n_wronly; /* Number of write-only references */
163 unsigned int n_rdwr; /* Number of read/write references */ 163 unsigned int n_rdwr; /* Number of read/write references */
164 int state; /* State on the server (R,W, or RW) */ 164 fmode_t state; /* State on the server (R,W, or RW) */
165 atomic_t count; 165 atomic_t count;
166}; 166};
167 167
@@ -223,9 +223,9 @@ extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struc
223extern void nfs4_put_state_owner(struct nfs4_state_owner *); 223extern void nfs4_put_state_owner(struct nfs4_state_owner *);
224extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); 224extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
225extern void nfs4_put_open_state(struct nfs4_state *); 225extern void nfs4_put_open_state(struct nfs4_state *);
226extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t); 226extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t);
227extern void nfs4_close_sync(struct path *, struct nfs4_state *, mode_t); 227extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t);
228extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); 228extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
229extern void nfs4_schedule_state_recovery(struct nfs_client *); 229extern void nfs4_schedule_state_recovery(struct nfs_client *);
230extern void nfs4_schedule_state_manager(struct nfs_client *); 230extern void nfs4_schedule_state_manager(struct nfs_client *);
231extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); 231extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fc0c9d255cf7..e8df52dc2bc5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -323,7 +323,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
323} 323}
324 324
325static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, 325static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
326 struct nfs4_state_owner *sp, int flags, 326 struct nfs4_state_owner *sp, fmode_t fmode, int flags,
327 const struct iattr *attrs) 327 const struct iattr *attrs)
328{ 328{
329 struct dentry *parent = dget_parent(path->dentry); 329 struct dentry *parent = dget_parent(path->dentry);
@@ -343,7 +343,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
343 p->owner = sp; 343 p->owner = sp;
344 atomic_inc(&sp->so_count); 344 atomic_inc(&sp->so_count);
345 p->o_arg.fh = NFS_FH(dir); 345 p->o_arg.fh = NFS_FH(dir);
346 p->o_arg.open_flags = flags, 346 p->o_arg.open_flags = flags;
347 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
347 p->o_arg.clientid = server->nfs_client->cl_clientid; 348 p->o_arg.clientid = server->nfs_client->cl_clientid;
348 p->o_arg.id = sp->so_owner_id.id; 349 p->o_arg.id = sp->so_owner_id.id;
349 p->o_arg.name = &p->path.dentry->d_name; 350 p->o_arg.name = &p->path.dentry->d_name;
@@ -399,10 +400,13 @@ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
399 return ret; 400 return ret;
400} 401}
401 402
402static int can_open_cached(struct nfs4_state *state, int mode) 403static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
403{ 404{
404 int ret = 0; 405 int ret = 0;
405 switch (mode & (FMODE_READ|FMODE_WRITE|O_EXCL)) { 406
407 if (open_mode & O_EXCL)
408 goto out;
409 switch (mode & (FMODE_READ|FMODE_WRITE)) {
406 case FMODE_READ: 410 case FMODE_READ:
407 ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0; 411 ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0;
408 break; 412 break;
@@ -412,12 +416,13 @@ static int can_open_cached(struct nfs4_state *state, int mode)
412 case FMODE_READ|FMODE_WRITE: 416 case FMODE_READ|FMODE_WRITE:
413 ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0; 417 ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
414 } 418 }
419out:
415 return ret; 420 return ret;
416} 421}
417 422
418static int can_open_delegated(struct nfs_delegation *delegation, mode_t open_flags) 423static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode)
419{ 424{
420 if ((delegation->type & open_flags) != open_flags) 425 if ((delegation->type & fmode) != fmode)
421 return 0; 426 return 0;
422 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags)) 427 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
423 return 0; 428 return 0;
@@ -425,9 +430,9 @@ static int can_open_delegated(struct nfs_delegation *delegation, mode_t open_fla
425 return 1; 430 return 1;
426} 431}
427 432
428static void update_open_stateflags(struct nfs4_state *state, mode_t open_flags) 433static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
429{ 434{
430 switch (open_flags) { 435 switch (fmode) {
431 case FMODE_WRITE: 436 case FMODE_WRITE:
432 state->n_wronly++; 437 state->n_wronly++;
433 break; 438 break;
@@ -437,15 +442,15 @@ static void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
437 case FMODE_READ|FMODE_WRITE: 442 case FMODE_READ|FMODE_WRITE:
438 state->n_rdwr++; 443 state->n_rdwr++;
439 } 444 }
440 nfs4_state_set_mode_locked(state, state->state | open_flags); 445 nfs4_state_set_mode_locked(state, state->state | fmode);
441} 446}
442 447
443static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) 448static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
444{ 449{
445 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) 450 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
446 memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data)); 451 memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data));
447 memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data)); 452 memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data));
448 switch (open_flags) { 453 switch (fmode) {
449 case FMODE_READ: 454 case FMODE_READ:
450 set_bit(NFS_O_RDONLY_STATE, &state->flags); 455 set_bit(NFS_O_RDONLY_STATE, &state->flags);
451 break; 456 break;
@@ -457,14 +462,14 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *
457 } 462 }
458} 463}
459 464
460static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) 465static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode)
461{ 466{
462 write_seqlock(&state->seqlock); 467 write_seqlock(&state->seqlock);
463 nfs_set_open_stateid_locked(state, stateid, open_flags); 468 nfs_set_open_stateid_locked(state, stateid, fmode);
464 write_sequnlock(&state->seqlock); 469 write_sequnlock(&state->seqlock);
465} 470}
466 471
467static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, const nfs4_stateid *deleg_stateid, int open_flags) 472static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, const nfs4_stateid *deleg_stateid, fmode_t fmode)
468{ 473{
469 /* 474 /*
470 * Protect the call to nfs4_state_set_mode_locked and 475 * Protect the call to nfs4_state_set_mode_locked and
@@ -476,20 +481,20 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
476 set_bit(NFS_DELEGATED_STATE, &state->flags); 481 set_bit(NFS_DELEGATED_STATE, &state->flags);
477 } 482 }
478 if (open_stateid != NULL) 483 if (open_stateid != NULL)
479 nfs_set_open_stateid_locked(state, open_stateid, open_flags); 484 nfs_set_open_stateid_locked(state, open_stateid, fmode);
480 write_sequnlock(&state->seqlock); 485 write_sequnlock(&state->seqlock);
481 spin_lock(&state->owner->so_lock); 486 spin_lock(&state->owner->so_lock);
482 update_open_stateflags(state, open_flags); 487 update_open_stateflags(state, fmode);
483 spin_unlock(&state->owner->so_lock); 488 spin_unlock(&state->owner->so_lock);
484} 489}
485 490
486static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *delegation, int open_flags) 491static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *delegation, fmode_t fmode)
487{ 492{
488 struct nfs_inode *nfsi = NFS_I(state->inode); 493 struct nfs_inode *nfsi = NFS_I(state->inode);
489 struct nfs_delegation *deleg_cur; 494 struct nfs_delegation *deleg_cur;
490 int ret = 0; 495 int ret = 0;
491 496
492 open_flags &= (FMODE_READ|FMODE_WRITE); 497 fmode &= (FMODE_READ|FMODE_WRITE);
493 498
494 rcu_read_lock(); 499 rcu_read_lock();
495 deleg_cur = rcu_dereference(nfsi->delegation); 500 deleg_cur = rcu_dereference(nfsi->delegation);
@@ -498,7 +503,7 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat
498 503
499 spin_lock(&deleg_cur->lock); 504 spin_lock(&deleg_cur->lock);
500 if (nfsi->delegation != deleg_cur || 505 if (nfsi->delegation != deleg_cur ||
501 (deleg_cur->type & open_flags) != open_flags) 506 (deleg_cur->type & fmode) != fmode)
502 goto no_delegation_unlock; 507 goto no_delegation_unlock;
503 508
504 if (delegation == NULL) 509 if (delegation == NULL)
@@ -507,7 +512,7 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat
507 goto no_delegation_unlock; 512 goto no_delegation_unlock;
508 513
509 nfs_mark_delegation_referenced(deleg_cur); 514 nfs_mark_delegation_referenced(deleg_cur);
510 __update_open_stateid(state, open_stateid, &deleg_cur->stateid, open_flags); 515 __update_open_stateid(state, open_stateid, &deleg_cur->stateid, fmode);
511 ret = 1; 516 ret = 1;
512no_delegation_unlock: 517no_delegation_unlock:
513 spin_unlock(&deleg_cur->lock); 518 spin_unlock(&deleg_cur->lock);
@@ -515,7 +520,7 @@ no_delegation:
515 rcu_read_unlock(); 520 rcu_read_unlock();
516 521
517 if (!ret && open_stateid != NULL) { 522 if (!ret && open_stateid != NULL) {
518 __update_open_stateid(state, open_stateid, NULL, open_flags); 523 __update_open_stateid(state, open_stateid, NULL, fmode);
519 ret = 1; 524 ret = 1;
520 } 525 }
521 526
@@ -523,13 +528,13 @@ no_delegation:
523} 528}
524 529
525 530
526static void nfs4_return_incompatible_delegation(struct inode *inode, mode_t open_flags) 531static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmode)
527{ 532{
528 struct nfs_delegation *delegation; 533 struct nfs_delegation *delegation;
529 534
530 rcu_read_lock(); 535 rcu_read_lock();
531 delegation = rcu_dereference(NFS_I(inode)->delegation); 536 delegation = rcu_dereference(NFS_I(inode)->delegation);
532 if (delegation == NULL || (delegation->type & open_flags) == open_flags) { 537 if (delegation == NULL || (delegation->type & fmode) == fmode) {
533 rcu_read_unlock(); 538 rcu_read_unlock();
534 return; 539 return;
535 } 540 }
@@ -542,15 +547,16 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
542 struct nfs4_state *state = opendata->state; 547 struct nfs4_state *state = opendata->state;
543 struct nfs_inode *nfsi = NFS_I(state->inode); 548 struct nfs_inode *nfsi = NFS_I(state->inode);
544 struct nfs_delegation *delegation; 549 struct nfs_delegation *delegation;
545 int open_mode = opendata->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL); 550 int open_mode = opendata->o_arg.open_flags & O_EXCL;
551 fmode_t fmode = opendata->o_arg.fmode;
546 nfs4_stateid stateid; 552 nfs4_stateid stateid;
547 int ret = -EAGAIN; 553 int ret = -EAGAIN;
548 554
549 for (;;) { 555 for (;;) {
550 if (can_open_cached(state, open_mode)) { 556 if (can_open_cached(state, fmode, open_mode)) {
551 spin_lock(&state->owner->so_lock); 557 spin_lock(&state->owner->so_lock);
552 if (can_open_cached(state, open_mode)) { 558 if (can_open_cached(state, fmode, open_mode)) {
553 update_open_stateflags(state, open_mode); 559 update_open_stateflags(state, fmode);
554 spin_unlock(&state->owner->so_lock); 560 spin_unlock(&state->owner->so_lock);
555 goto out_return_state; 561 goto out_return_state;
556 } 562 }
@@ -559,7 +565,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
559 rcu_read_lock(); 565 rcu_read_lock();
560 delegation = rcu_dereference(nfsi->delegation); 566 delegation = rcu_dereference(nfsi->delegation);
561 if (delegation == NULL || 567 if (delegation == NULL ||
562 !can_open_delegated(delegation, open_mode)) { 568 !can_open_delegated(delegation, fmode)) {
563 rcu_read_unlock(); 569 rcu_read_unlock();
564 break; 570 break;
565 } 571 }
@@ -572,7 +578,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
572 ret = -EAGAIN; 578 ret = -EAGAIN;
573 579
574 /* Try to update the stateid using the delegation */ 580 /* Try to update the stateid using the delegation */
575 if (update_open_stateid(state, NULL, &stateid, open_mode)) 581 if (update_open_stateid(state, NULL, &stateid, fmode))
576 goto out_return_state; 582 goto out_return_state;
577 } 583 }
578out: 584out:
@@ -624,7 +630,7 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
624 } 630 }
625 631
626 update_open_stateid(state, &data->o_res.stateid, NULL, 632 update_open_stateid(state, &data->o_res.stateid, NULL,
627 data->o_arg.open_flags); 633 data->o_arg.fmode);
628 iput(inode); 634 iput(inode);
629out: 635out:
630 return state; 636 return state;
@@ -655,7 +661,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
655{ 661{
656 struct nfs4_opendata *opendata; 662 struct nfs4_opendata *opendata;
657 663
658 opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL); 664 opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, 0, NULL);
659 if (opendata == NULL) 665 if (opendata == NULL)
660 return ERR_PTR(-ENOMEM); 666 return ERR_PTR(-ENOMEM);
661 opendata->state = state; 667 opendata->state = state;
@@ -663,12 +669,13 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
663 return opendata; 669 return opendata;
664} 670}
665 671
666static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res) 672static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmode, struct nfs4_state **res)
667{ 673{
668 struct nfs4_state *newstate; 674 struct nfs4_state *newstate;
669 int ret; 675 int ret;
670 676
671 opendata->o_arg.open_flags = openflags; 677 opendata->o_arg.open_flags = 0;
678 opendata->o_arg.fmode = fmode;
672 memset(&opendata->o_res, 0, sizeof(opendata->o_res)); 679 memset(&opendata->o_res, 0, sizeof(opendata->o_res));
673 memset(&opendata->c_res, 0, sizeof(opendata->c_res)); 680 memset(&opendata->c_res, 0, sizeof(opendata->c_res));
674 nfs4_init_opendata_res(opendata); 681 nfs4_init_opendata_res(opendata);
@@ -678,7 +685,7 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openf
678 newstate = nfs4_opendata_to_nfs4_state(opendata); 685 newstate = nfs4_opendata_to_nfs4_state(opendata);
679 if (IS_ERR(newstate)) 686 if (IS_ERR(newstate))
680 return PTR_ERR(newstate); 687 return PTR_ERR(newstate);
681 nfs4_close_state(&opendata->path, newstate, openflags); 688 nfs4_close_state(&opendata->path, newstate, fmode);
682 *res = newstate; 689 *res = newstate;
683 return 0; 690 return 0;
684} 691}
@@ -734,7 +741,7 @@ static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
734{ 741{
735 struct nfs_delegation *delegation; 742 struct nfs_delegation *delegation;
736 struct nfs4_opendata *opendata; 743 struct nfs4_opendata *opendata;
737 int delegation_type = 0; 744 fmode_t delegation_type = 0;
738 int status; 745 int status;
739 746
740 opendata = nfs4_open_recoverdata_alloc(ctx, state); 747 opendata = nfs4_open_recoverdata_alloc(ctx, state);
@@ -847,7 +854,7 @@ static void nfs4_open_confirm_release(void *calldata)
847 goto out_free; 854 goto out_free;
848 state = nfs4_opendata_to_nfs4_state(data); 855 state = nfs4_opendata_to_nfs4_state(data);
849 if (!IS_ERR(state)) 856 if (!IS_ERR(state))
850 nfs4_close_state(&data->path, state, data->o_arg.open_flags); 857 nfs4_close_state(&data->path, state, data->o_arg.fmode);
851out_free: 858out_free:
852 nfs4_opendata_put(data); 859 nfs4_opendata_put(data);
853} 860}
@@ -911,7 +918,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
911 if (data->state != NULL) { 918 if (data->state != NULL) {
912 struct nfs_delegation *delegation; 919 struct nfs_delegation *delegation;
913 920
914 if (can_open_cached(data->state, data->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL))) 921 if (can_open_cached(data->state, data->o_arg.fmode, data->o_arg.open_flags))
915 goto out_no_action; 922 goto out_no_action;
916 rcu_read_lock(); 923 rcu_read_lock();
917 delegation = rcu_dereference(NFS_I(data->state->inode)->delegation); 924 delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
@@ -980,7 +987,7 @@ static void nfs4_open_release(void *calldata)
980 goto out_free; 987 goto out_free;
981 state = nfs4_opendata_to_nfs4_state(data); 988 state = nfs4_opendata_to_nfs4_state(data);
982 if (!IS_ERR(state)) 989 if (!IS_ERR(state))
983 nfs4_close_state(&data->path, state, data->o_arg.open_flags); 990 nfs4_close_state(&data->path, state, data->o_arg.fmode);
984out_free: 991out_free:
985 nfs4_opendata_put(data); 992 nfs4_opendata_put(data);
986} 993}
@@ -1135,7 +1142,7 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
1135/* 1142/*
1136 * Returns a referenced nfs4_state 1143 * Returns a referenced nfs4_state
1137 */ 1144 */
1138static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res) 1145static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
1139{ 1146{
1140 struct nfs4_state_owner *sp; 1147 struct nfs4_state_owner *sp;
1141 struct nfs4_state *state = NULL; 1148 struct nfs4_state *state = NULL;
@@ -1153,9 +1160,9 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
1153 if (status != 0) 1160 if (status != 0)
1154 goto err_put_state_owner; 1161 goto err_put_state_owner;
1155 if (path->dentry->d_inode != NULL) 1162 if (path->dentry->d_inode != NULL)
1156 nfs4_return_incompatible_delegation(path->dentry->d_inode, flags & (FMODE_READ|FMODE_WRITE)); 1163 nfs4_return_incompatible_delegation(path->dentry->d_inode, fmode);
1157 status = -ENOMEM; 1164 status = -ENOMEM;
1158 opendata = nfs4_opendata_alloc(path, sp, flags, sattr); 1165 opendata = nfs4_opendata_alloc(path, sp, fmode, flags, sattr);
1159 if (opendata == NULL) 1166 if (opendata == NULL)
1160 goto err_put_state_owner; 1167 goto err_put_state_owner;
1161 1168
@@ -1187,14 +1194,14 @@ out_err:
1187} 1194}
1188 1195
1189 1196
1190static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred) 1197static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred)
1191{ 1198{
1192 struct nfs4_exception exception = { }; 1199 struct nfs4_exception exception = { };
1193 struct nfs4_state *res; 1200 struct nfs4_state *res;
1194 int status; 1201 int status;
1195 1202
1196 do { 1203 do {
1197 status = _nfs4_do_open(dir, path, flags, sattr, cred, &res); 1204 status = _nfs4_do_open(dir, path, fmode, flags, sattr, cred, &res);
1198 if (status == 0) 1205 if (status == 0)
1199 break; 1206 break;
1200 /* NOTE: BAD_SEQID means the server and client disagree about the 1207 /* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1332,7 +1339,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
1332 case -NFS4ERR_OLD_STATEID: 1339 case -NFS4ERR_OLD_STATEID:
1333 case -NFS4ERR_BAD_STATEID: 1340 case -NFS4ERR_BAD_STATEID:
1334 case -NFS4ERR_EXPIRED: 1341 case -NFS4ERR_EXPIRED:
1335 if (calldata->arg.open_flags == 0) 1342 if (calldata->arg.fmode == 0)
1336 break; 1343 break;
1337 default: 1344 default:
1338 if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { 1345 if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
@@ -1374,10 +1381,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
1374 nfs_fattr_init(calldata->res.fattr); 1381 nfs_fattr_init(calldata->res.fattr);
1375 if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { 1382 if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) {
1376 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; 1383 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
1377 calldata->arg.open_flags = FMODE_READ; 1384 calldata->arg.fmode = FMODE_READ;
1378 } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { 1385 } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) {
1379 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; 1386 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
1380 calldata->arg.open_flags = FMODE_WRITE; 1387 calldata->arg.fmode = FMODE_WRITE;
1381 } 1388 }
1382 calldata->timestamp = jiffies; 1389 calldata->timestamp = jiffies;
1383 rpc_call_start(task); 1390 rpc_call_start(task);
@@ -1430,7 +1437,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
1430 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); 1437 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
1431 if (calldata->arg.seqid == NULL) 1438 if (calldata->arg.seqid == NULL)
1432 goto out_free_calldata; 1439 goto out_free_calldata;
1433 calldata->arg.open_flags = 0; 1440 calldata->arg.fmode = 0;
1434 calldata->arg.bitmask = server->attr_bitmask; 1441 calldata->arg.bitmask = server->attr_bitmask;
1435 calldata->res.fattr = &calldata->fattr; 1442 calldata->res.fattr = &calldata->fattr;
1436 calldata->res.seqid = calldata->arg.seqid; 1443 calldata->res.seqid = calldata->arg.seqid;
@@ -1457,13 +1464,13 @@ out:
1457 return status; 1464 return status;
1458} 1465}
1459 1466
1460static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state) 1467static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode)
1461{ 1468{
1462 struct file *filp; 1469 struct file *filp;
1463 int ret; 1470 int ret;
1464 1471
1465 /* If the open_intent is for execute, we have an extra check to make */ 1472 /* If the open_intent is for execute, we have an extra check to make */
1466 if (nd->intent.open.flags & FMODE_EXEC) { 1473 if (fmode & FMODE_EXEC) {
1467 ret = nfs_may_open(state->inode, 1474 ret = nfs_may_open(state->inode,
1468 state->owner->so_cred, 1475 state->owner->so_cred,
1469 nd->intent.open.flags); 1476 nd->intent.open.flags);
@@ -1479,7 +1486,7 @@ static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct
1479 } 1486 }
1480 ret = PTR_ERR(filp); 1487 ret = PTR_ERR(filp);
1481out_close: 1488out_close:
1482 nfs4_close_sync(path, state, nd->intent.open.flags); 1489 nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE));
1483 return ret; 1490 return ret;
1484} 1491}
1485 1492
@@ -1495,6 +1502,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1495 struct rpc_cred *cred; 1502 struct rpc_cred *cred;
1496 struct nfs4_state *state; 1503 struct nfs4_state *state;
1497 struct dentry *res; 1504 struct dentry *res;
1505 fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
1498 1506
1499 if (nd->flags & LOOKUP_CREATE) { 1507 if (nd->flags & LOOKUP_CREATE) {
1500 attr.ia_mode = nd->intent.open.create_mode; 1508 attr.ia_mode = nd->intent.open.create_mode;
@@ -1512,7 +1520,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1512 parent = dentry->d_parent; 1520 parent = dentry->d_parent;
1513 /* Protect against concurrent sillydeletes */ 1521 /* Protect against concurrent sillydeletes */
1514 nfs_block_sillyrename(parent); 1522 nfs_block_sillyrename(parent);
1515 state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred); 1523 state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, cred);
1516 put_rpccred(cred); 1524 put_rpccred(cred);
1517 if (IS_ERR(state)) { 1525 if (IS_ERR(state)) {
1518 if (PTR_ERR(state) == -ENOENT) { 1526 if (PTR_ERR(state) == -ENOENT) {
@@ -1527,7 +1535,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1527 path.dentry = res; 1535 path.dentry = res;
1528 nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir)); 1536 nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
1529 nfs_unblock_sillyrename(parent); 1537 nfs_unblock_sillyrename(parent);
1530 nfs4_intent_set_file(nd, &path, state); 1538 nfs4_intent_set_file(nd, &path, state, fmode);
1531 return res; 1539 return res;
1532} 1540}
1533 1541
@@ -1540,11 +1548,12 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
1540 }; 1548 };
1541 struct rpc_cred *cred; 1549 struct rpc_cred *cred;
1542 struct nfs4_state *state; 1550 struct nfs4_state *state;
1551 fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE);
1543 1552
1544 cred = rpc_lookup_cred(); 1553 cred = rpc_lookup_cred();
1545 if (IS_ERR(cred)) 1554 if (IS_ERR(cred))
1546 return PTR_ERR(cred); 1555 return PTR_ERR(cred);
1547 state = nfs4_do_open(dir, &path, openflags, NULL, cred); 1556 state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
1548 put_rpccred(cred); 1557 put_rpccred(cred);
1549 if (IS_ERR(state)) { 1558 if (IS_ERR(state)) {
1550 switch (PTR_ERR(state)) { 1559 switch (PTR_ERR(state)) {
@@ -1561,10 +1570,10 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
1561 } 1570 }
1562 if (state->inode == dentry->d_inode) { 1571 if (state->inode == dentry->d_inode) {
1563 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1572 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1564 nfs4_intent_set_file(nd, &path, state); 1573 nfs4_intent_set_file(nd, &path, state, fmode);
1565 return 1; 1574 return 1;
1566 } 1575 }
1567 nfs4_close_sync(&path, state, openflags); 1576 nfs4_close_sync(&path, state, fmode);
1568out_drop: 1577out_drop:
1569 d_drop(dentry); 1578 d_drop(dentry);
1570 return 0; 1579 return 0;
@@ -1990,6 +1999,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1990 }; 1999 };
1991 struct nfs4_state *state; 2000 struct nfs4_state *state;
1992 struct rpc_cred *cred; 2001 struct rpc_cred *cred;
2002 fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE);
1993 int status = 0; 2003 int status = 0;
1994 2004
1995 cred = rpc_lookup_cred(); 2005 cred = rpc_lookup_cred();
@@ -1997,7 +2007,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1997 status = PTR_ERR(cred); 2007 status = PTR_ERR(cred);
1998 goto out; 2008 goto out;
1999 } 2009 }
2000 state = nfs4_do_open(dir, &path, flags, sattr, cred); 2010 state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
2001 d_drop(dentry); 2011 d_drop(dentry);
2002 if (IS_ERR(state)) { 2012 if (IS_ERR(state)) {
2003 status = PTR_ERR(state); 2013 status = PTR_ERR(state);
@@ -2013,9 +2023,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
2013 nfs_post_op_update_inode(state->inode, &fattr); 2023 nfs_post_op_update_inode(state->inode, &fattr);
2014 } 2024 }
2015 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) 2025 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
2016 status = nfs4_intent_set_file(nd, &path, state); 2026 status = nfs4_intent_set_file(nd, &path, state, fmode);
2017 else 2027 else
2018 nfs4_close_sync(&path, state, flags); 2028 nfs4_close_sync(&path, state, fmode);
2019out_putcred: 2029out_putcred:
2020 put_rpccred(cred); 2030 put_rpccred(cred);
2021out: 2031out:
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index cd16b301f13c..2022fe47966f 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -363,18 +363,18 @@ nfs4_alloc_open_state(void)
363} 363}
364 364
365void 365void
366nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode) 366nfs4_state_set_mode_locked(struct nfs4_state *state, fmode_t fmode)
367{ 367{
368 if (state->state == mode) 368 if (state->state == fmode)
369 return; 369 return;
370 /* NB! List reordering - see the reclaim code for why. */ 370 /* NB! List reordering - see the reclaim code for why. */
371 if ((mode & FMODE_WRITE) != (state->state & FMODE_WRITE)) { 371 if ((fmode & FMODE_WRITE) != (state->state & FMODE_WRITE)) {
372 if (mode & FMODE_WRITE) 372 if (fmode & FMODE_WRITE)
373 list_move(&state->open_states, &state->owner->so_states); 373 list_move(&state->open_states, &state->owner->so_states);
374 else 374 else
375 list_move_tail(&state->open_states, &state->owner->so_states); 375 list_move_tail(&state->open_states, &state->owner->so_states);
376 } 376 }
377 state->state = mode; 377 state->state = fmode;
378} 378}
379 379
380static struct nfs4_state * 380static struct nfs4_state *
@@ -454,16 +454,16 @@ void nfs4_put_open_state(struct nfs4_state *state)
454/* 454/*
455 * Close the current file. 455 * Close the current file.
456 */ 456 */
457static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mode, int wait) 457static void __nfs4_close(struct path *path, struct nfs4_state *state, fmode_t fmode, int wait)
458{ 458{
459 struct nfs4_state_owner *owner = state->owner; 459 struct nfs4_state_owner *owner = state->owner;
460 int call_close = 0; 460 int call_close = 0;
461 int newstate; 461 fmode_t newstate;
462 462
463 atomic_inc(&owner->so_count); 463 atomic_inc(&owner->so_count);
464 /* Protect against nfs4_find_state() */ 464 /* Protect against nfs4_find_state() */
465 spin_lock(&owner->so_lock); 465 spin_lock(&owner->so_lock);
466 switch (mode & (FMODE_READ | FMODE_WRITE)) { 466 switch (fmode & (FMODE_READ | FMODE_WRITE)) {
467 case FMODE_READ: 467 case FMODE_READ:
468 state->n_rdonly--; 468 state->n_rdonly--;
469 break; 469 break;
@@ -498,14 +498,14 @@ static void __nfs4_close(struct path *path, struct nfs4_state *state, mode_t mod
498 nfs4_do_close(path, state, wait); 498 nfs4_do_close(path, state, wait);
499} 499}
500 500
501void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 501void nfs4_close_state(struct path *path, struct nfs4_state *state, fmode_t fmode)
502{ 502{
503 __nfs4_close(path, state, mode, 0); 503 __nfs4_close(path, state, fmode, 0);
504} 504}
505 505
506void nfs4_close_sync(struct path *path, struct nfs4_state *state, mode_t mode) 506void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode)
507{ 507{
508 __nfs4_close(path, state, mode, 1); 508 __nfs4_close(path, state, fmode, 1);
509} 509}
510 510
511/* 511/*
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 879911c99030..d8ddfc5467d6 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -953,12 +953,12 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
953 return 0; 953 return 0;
954} 954}
955 955
956static void encode_share_access(struct xdr_stream *xdr, int open_flags) 956static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
957{ 957{
958 __be32 *p; 958 __be32 *p;
959 959
960 RESERVE_SPACE(8); 960 RESERVE_SPACE(8);
961 switch (open_flags & (FMODE_READ|FMODE_WRITE)) { 961 switch (fmode & (FMODE_READ|FMODE_WRITE)) {
962 case FMODE_READ: 962 case FMODE_READ:
963 WRITE32(NFS4_SHARE_ACCESS_READ); 963 WRITE32(NFS4_SHARE_ACCESS_READ);
964 break; 964 break;
@@ -969,7 +969,7 @@ static void encode_share_access(struct xdr_stream *xdr, int open_flags)
969 WRITE32(NFS4_SHARE_ACCESS_BOTH); 969 WRITE32(NFS4_SHARE_ACCESS_BOTH);
970 break; 970 break;
971 default: 971 default:
972 BUG(); 972 WRITE32(0);
973 } 973 }
974 WRITE32(0); /* for linux, share_deny = 0 always */ 974 WRITE32(0); /* for linux, share_deny = 0 always */
975} 975}
@@ -984,7 +984,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
984 RESERVE_SPACE(8); 984 RESERVE_SPACE(8);
985 WRITE32(OP_OPEN); 985 WRITE32(OP_OPEN);
986 WRITE32(arg->seqid->sequence->counter); 986 WRITE32(arg->seqid->sequence->counter);
987 encode_share_access(xdr, arg->open_flags); 987 encode_share_access(xdr, arg->fmode);
988 RESERVE_SPACE(28); 988 RESERVE_SPACE(28);
989 WRITE64(arg->clientid); 989 WRITE64(arg->clientid);
990 WRITE32(16); 990 WRITE32(16);
@@ -1112,7 +1112,7 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea
1112 WRITE32(OP_OPEN_DOWNGRADE); 1112 WRITE32(OP_OPEN_DOWNGRADE);
1113 WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); 1113 WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
1114 WRITE32(arg->seqid->sequence->counter); 1114 WRITE32(arg->seqid->sequence->counter);
1115 encode_share_access(xdr, arg->open_flags); 1115 encode_share_access(xdr, arg->fmode);
1116 return 0; 1116 return 0;
1117} 1117}
1118 1118
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 8d71d7b7c78a..b8d9c6dd4f63 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -83,7 +83,7 @@ struct nfs_open_context {
83 struct rpc_cred *cred; 83 struct rpc_cred *cred;
84 struct nfs4_state *state; 84 struct nfs4_state *state;
85 fl_owner_t lockowner; 85 fl_owner_t lockowner;
86 int mode; 86 fmode_t mode;
87 87
88 unsigned long flags; 88 unsigned long flags;
89#define NFS_CONTEXT_ERROR_WRITE (0) 89#define NFS_CONTEXT_ERROR_WRITE (0)
@@ -342,7 +342,7 @@ extern int nfs_setattr(struct dentry *, struct iattr *);
342extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); 342extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
343extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); 343extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
344extern void put_nfs_open_context(struct nfs_open_context *ctx); 344extern void put_nfs_open_context(struct nfs_open_context *ctx);
345extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode); 345extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
346extern u64 nfs_compat_user_ino64(u64 fileid); 346extern u64 nfs_compat_user_ino64(u64 fileid);
347extern void nfs_fattr_init(struct nfs_fattr *fattr); 347extern void nfs_fattr_init(struct nfs_fattr *fattr);
348 348
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 32c1a0ecdbff..a550b528319f 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -120,6 +120,7 @@ struct nfs_openargs {
120 const struct nfs_fh * fh; 120 const struct nfs_fh * fh;
121 struct nfs_seqid * seqid; 121 struct nfs_seqid * seqid;
122 int open_flags; 122 int open_flags;
123 fmode_t fmode;
123 __u64 clientid; 124 __u64 clientid;
124 __u64 id; 125 __u64 id;
125 union { 126 union {
@@ -171,7 +172,7 @@ struct nfs_closeargs {
171 struct nfs_fh * fh; 172 struct nfs_fh * fh;
172 nfs4_stateid * stateid; 173 nfs4_stateid * stateid;
173 struct nfs_seqid * seqid; 174 struct nfs_seqid * seqid;
174 int open_flags; 175 fmode_t fmode;
175 const u32 * bitmask; 176 const u32 * bitmask;
176}; 177};
177 178