diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 257 |
1 files changed, 96 insertions, 161 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 31673cd251c3..f6744bc03dae 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -61,7 +61,6 @@ static time_t lease_time = 90; /* default lease time */ | |||
61 | static time_t user_lease_time = 90; | 61 | static time_t user_lease_time = 90; |
62 | static time_t boot_time; | 62 | static time_t boot_time; |
63 | static int in_grace = 1; | 63 | static int in_grace = 1; |
64 | static u32 current_clientid = 1; | ||
65 | static u32 current_ownerid = 1; | 64 | static u32 current_ownerid = 1; |
66 | static u32 current_fileid = 1; | 65 | static u32 current_fileid = 1; |
67 | static u32 current_delegid = 1; | 66 | static u32 current_delegid = 1; |
@@ -340,21 +339,20 @@ STALE_CLIENTID(clientid_t *clid) | |||
340 | * This type of memory management is somewhat inefficient, but we use it | 339 | * This type of memory management is somewhat inefficient, but we use it |
341 | * anyway since SETCLIENTID is not a common operation. | 340 | * anyway since SETCLIENTID is not a common operation. |
342 | */ | 341 | */ |
343 | static inline struct nfs4_client * | 342 | static struct nfs4_client *alloc_client(struct xdr_netobj name) |
344 | alloc_client(struct xdr_netobj name) | ||
345 | { | 343 | { |
346 | struct nfs4_client *clp; | 344 | struct nfs4_client *clp; |
347 | 345 | ||
348 | if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) { | 346 | clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL); |
349 | if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) { | 347 | if (clp == NULL) |
350 | memcpy(clp->cl_name.data, name.data, name.len); | 348 | return NULL; |
351 | clp->cl_name.len = name.len; | 349 | clp->cl_name.data = kmalloc(name.len, GFP_KERNEL); |
352 | } | 350 | if (clp->cl_name.data == NULL) { |
353 | else { | 351 | kfree(clp); |
354 | kfree(clp); | 352 | return NULL; |
355 | clp = NULL; | ||
356 | } | ||
357 | } | 353 | } |
354 | memcpy(clp->cl_name.data, name.data, name.len); | ||
355 | clp->cl_name.len = name.len; | ||
358 | return clp; | 356 | return clp; |
359 | } | 357 | } |
360 | 358 | ||
@@ -363,8 +361,11 @@ shutdown_callback_client(struct nfs4_client *clp) | |||
363 | { | 361 | { |
364 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; | 362 | struct rpc_clnt *clnt = clp->cl_callback.cb_client; |
365 | 363 | ||
366 | /* shutdown rpc client, ending any outstanding recall rpcs */ | ||
367 | if (clnt) { | 364 | if (clnt) { |
365 | /* | ||
366 | * Callback threads take a reference on the client, so there | ||
367 | * should be no outstanding callbacks at this point. | ||
368 | */ | ||
368 | clp->cl_callback.cb_client = NULL; | 369 | clp->cl_callback.cb_client = NULL; |
369 | rpc_shutdown_client(clnt); | 370 | rpc_shutdown_client(clnt); |
370 | } | 371 | } |
@@ -422,12 +423,13 @@ expire_client(struct nfs4_client *clp) | |||
422 | put_nfs4_client(clp); | 423 | put_nfs4_client(clp); |
423 | } | 424 | } |
424 | 425 | ||
425 | static struct nfs4_client * | 426 | static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir) |
426 | create_client(struct xdr_netobj name, char *recdir) { | 427 | { |
427 | struct nfs4_client *clp; | 428 | struct nfs4_client *clp; |
428 | 429 | ||
429 | if (!(clp = alloc_client(name))) | 430 | clp = alloc_client(name); |
430 | goto out; | 431 | if (clp == NULL) |
432 | return NULL; | ||
431 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); | 433 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); |
432 | atomic_set(&clp->cl_count, 1); | 434 | atomic_set(&clp->cl_count, 1); |
433 | atomic_set(&clp->cl_callback.cb_set, 0); | 435 | atomic_set(&clp->cl_callback.cb_set, 0); |
@@ -436,32 +438,30 @@ create_client(struct xdr_netobj name, char *recdir) { | |||
436 | INIT_LIST_HEAD(&clp->cl_openowners); | 438 | INIT_LIST_HEAD(&clp->cl_openowners); |
437 | INIT_LIST_HEAD(&clp->cl_delegations); | 439 | INIT_LIST_HEAD(&clp->cl_delegations); |
438 | INIT_LIST_HEAD(&clp->cl_lru); | 440 | INIT_LIST_HEAD(&clp->cl_lru); |
439 | out: | ||
440 | return clp; | 441 | return clp; |
441 | } | 442 | } |
442 | 443 | ||
443 | static void | 444 | static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) |
444 | copy_verf(struct nfs4_client *target, nfs4_verifier *source) { | 445 | { |
445 | memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data)); | 446 | memcpy(target->cl_verifier.data, source->data, |
447 | sizeof(target->cl_verifier.data)); | ||
446 | } | 448 | } |
447 | 449 | ||
448 | static void | 450 | static void copy_clid(struct nfs4_client *target, struct nfs4_client *source) |
449 | copy_clid(struct nfs4_client *target, struct nfs4_client *source) { | 451 | { |
450 | target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; | 452 | target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; |
451 | target->cl_clientid.cl_id = source->cl_clientid.cl_id; | 453 | target->cl_clientid.cl_id = source->cl_clientid.cl_id; |
452 | } | 454 | } |
453 | 455 | ||
454 | static void | 456 | static void copy_cred(struct svc_cred *target, struct svc_cred *source) |
455 | copy_cred(struct svc_cred *target, struct svc_cred *source) { | 457 | { |
456 | |||
457 | target->cr_uid = source->cr_uid; | 458 | target->cr_uid = source->cr_uid; |
458 | target->cr_gid = source->cr_gid; | 459 | target->cr_gid = source->cr_gid; |
459 | target->cr_group_info = source->cr_group_info; | 460 | target->cr_group_info = source->cr_group_info; |
460 | get_group_info(target->cr_group_info); | 461 | get_group_info(target->cr_group_info); |
461 | } | 462 | } |
462 | 463 | ||
463 | static inline int | 464 | static int same_name(const char *n1, const char *n2) |
464 | same_name(const char *n1, const char *n2) | ||
465 | { | 465 | { |
466 | return 0 == memcmp(n1, n2, HEXDIR_LEN); | 466 | return 0 == memcmp(n1, n2, HEXDIR_LEN); |
467 | } | 467 | } |
@@ -485,26 +485,26 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2) | |||
485 | return cr1->cr_uid == cr2->cr_uid; | 485 | return cr1->cr_uid == cr2->cr_uid; |
486 | } | 486 | } |
487 | 487 | ||
488 | static void | 488 | static void gen_clid(struct nfs4_client *clp) |
489 | gen_clid(struct nfs4_client *clp) { | 489 | { |
490 | static u32 current_clientid = 1; | ||
491 | |||
490 | clp->cl_clientid.cl_boot = boot_time; | 492 | clp->cl_clientid.cl_boot = boot_time; |
491 | clp->cl_clientid.cl_id = current_clientid++; | 493 | clp->cl_clientid.cl_id = current_clientid++; |
492 | } | 494 | } |
493 | 495 | ||
494 | static void | 496 | static void gen_confirm(struct nfs4_client *clp) |
495 | gen_confirm(struct nfs4_client *clp) { | 497 | { |
496 | struct timespec tv; | 498 | static u32 i; |
497 | u32 * p; | 499 | u32 *p; |
498 | 500 | ||
499 | tv = CURRENT_TIME; | ||
500 | p = (u32 *)clp->cl_confirm.data; | 501 | p = (u32 *)clp->cl_confirm.data; |
501 | *p++ = tv.tv_sec; | 502 | *p++ = get_seconds(); |
502 | *p++ = tv.tv_nsec; | 503 | *p++ = i++; |
503 | } | 504 | } |
504 | 505 | ||
505 | static int | 506 | static int check_name(struct xdr_netobj name) |
506 | check_name(struct xdr_netobj name) { | 507 | { |
507 | |||
508 | if (name.len == 0) | 508 | if (name.len == 0) |
509 | return 0; | 509 | return 0; |
510 | if (name.len > NFS4_OPAQUE_LIMIT) { | 510 | if (name.len > NFS4_OPAQUE_LIMIT) { |
@@ -683,39 +683,6 @@ out_err: | |||
683 | return; | 683 | return; |
684 | } | 684 | } |
685 | 685 | ||
686 | /* | ||
687 | * RFC 3010 has a complex implmentation description of processing a | ||
688 | * SETCLIENTID request consisting of 5 bullets, labeled as | ||
689 | * CASE0 - CASE4 below. | ||
690 | * | ||
691 | * NOTES: | ||
692 | * callback information will be processed in a future patch | ||
693 | * | ||
694 | * an unconfirmed record is added when: | ||
695 | * NORMAL (part of CASE 4): there is no confirmed nor unconfirmed record. | ||
696 | * CASE 1: confirmed record found with matching name, principal, | ||
697 | * verifier, and clientid. | ||
698 | * CASE 2: confirmed record found with matching name, principal, | ||
699 | * and there is no unconfirmed record with matching | ||
700 | * name and principal | ||
701 | * | ||
702 | * an unconfirmed record is replaced when: | ||
703 | * CASE 3: confirmed record found with matching name, principal, | ||
704 | * and an unconfirmed record is found with matching | ||
705 | * name, principal, and with clientid and | ||
706 | * confirm that does not match the confirmed record. | ||
707 | * CASE 4: there is no confirmed record with matching name and | ||
708 | * principal. there is an unconfirmed record with | ||
709 | * matching name, principal. | ||
710 | * | ||
711 | * an unconfirmed record is deleted when: | ||
712 | * CASE 1: an unconfirmed record that matches input name, verifier, | ||
713 | * and confirmed clientid. | ||
714 | * CASE 4: any unconfirmed records with matching name and principal | ||
715 | * that exist after an unconfirmed record has been replaced | ||
716 | * as described above. | ||
717 | * | ||
718 | */ | ||
719 | __be32 | 686 | __be32 |
720 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 687 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
721 | struct nfsd4_setclientid *setclid) | 688 | struct nfsd4_setclientid *setclid) |
@@ -748,11 +715,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
748 | nfs4_lock_state(); | 715 | nfs4_lock_state(); |
749 | conf = find_confirmed_client_by_str(dname, strhashval); | 716 | conf = find_confirmed_client_by_str(dname, strhashval); |
750 | if (conf) { | 717 | if (conf) { |
751 | /* | 718 | /* RFC 3530 14.2.33 CASE 0: */ |
752 | * CASE 0: | ||
753 | * clname match, confirmed, different principal | ||
754 | * or different ip_address | ||
755 | */ | ||
756 | status = nfserr_clid_inuse; | 719 | status = nfserr_clid_inuse; |
757 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) | 720 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) |
758 | || conf->cl_addr != sin->sin_addr.s_addr) { | 721 | || conf->cl_addr != sin->sin_addr.s_addr) { |
@@ -761,12 +724,17 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
761 | goto out; | 724 | goto out; |
762 | } | 725 | } |
763 | } | 726 | } |
727 | /* | ||
728 | * section 14.2.33 of RFC 3530 (under the heading "IMPLEMENTATION") | ||
729 | * has a description of SETCLIENTID request processing consisting | ||
730 | * of 5 bullet points, labeled as CASE0 - CASE4 below. | ||
731 | */ | ||
764 | unconf = find_unconfirmed_client_by_str(dname, strhashval); | 732 | unconf = find_unconfirmed_client_by_str(dname, strhashval); |
765 | status = nfserr_resource; | 733 | status = nfserr_resource; |
766 | if (!conf) { | 734 | if (!conf) { |
767 | /* | 735 | /* |
768 | * CASE 4: | 736 | * RFC 3530 14.2.33 CASE 4: |
769 | * placed first, because it is the normal case. | 737 | * placed first, because it is the normal case |
770 | */ | 738 | */ |
771 | if (unconf) | 739 | if (unconf) |
772 | expire_client(unconf); | 740 | expire_client(unconf); |
@@ -776,17 +744,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
776 | gen_clid(new); | 744 | gen_clid(new); |
777 | } else if (same_verf(&conf->cl_verifier, &clverifier)) { | 745 | } else if (same_verf(&conf->cl_verifier, &clverifier)) { |
778 | /* | 746 | /* |
779 | * CASE 1: | 747 | * RFC 3530 14.2.33 CASE 1: |
780 | * cl_name match, confirmed, principal match | 748 | * probable callback update |
781 | * verifier match: probable callback update | ||
782 | * | ||
783 | * remove any unconfirmed nfs4_client with | ||
784 | * matching cl_name, cl_verifier, and cl_clientid | ||
785 | * | ||
786 | * create and insert an unconfirmed nfs4_client with same | ||
787 | * cl_name, cl_verifier, and cl_clientid as existing | ||
788 | * nfs4_client, but with the new callback info and a | ||
789 | * new cl_confirm | ||
790 | */ | 749 | */ |
791 | if (unconf) { | 750 | if (unconf) { |
792 | /* Note this is removing unconfirmed {*x***}, | 751 | /* Note this is removing unconfirmed {*x***}, |
@@ -802,43 +761,25 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
802 | copy_clid(new, conf); | 761 | copy_clid(new, conf); |
803 | } else if (!unconf) { | 762 | } else if (!unconf) { |
804 | /* | 763 | /* |
805 | * CASE 2: | 764 | * RFC 3530 14.2.33 CASE 2: |
806 | * clname match, confirmed, principal match | 765 | * probable client reboot; state will be removed if |
807 | * verfier does not match | 766 | * confirmed. |
808 | * no unconfirmed. create a new unconfirmed nfs4_client | ||
809 | * using input clverifier, clname, and callback info | ||
810 | * and generate a new cl_clientid and cl_confirm. | ||
811 | */ | 767 | */ |
812 | new = create_client(clname, dname); | 768 | new = create_client(clname, dname); |
813 | if (new == NULL) | 769 | if (new == NULL) |
814 | goto out; | 770 | goto out; |
815 | gen_clid(new); | 771 | gen_clid(new); |
816 | } else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) { | 772 | } else { |
817 | /* | 773 | /* |
818 | * CASE3: | 774 | * RFC 3530 14.2.33 CASE 3: |
819 | * confirmed found (name, principal match) | 775 | * probable client reboot; state will be removed if |
820 | * confirmed verifier does not match input clverifier | 776 | * confirmed. |
821 | * | ||
822 | * unconfirmed found (name match) | ||
823 | * confirmed->cl_confirm != unconfirmed->cl_confirm | ||
824 | * | ||
825 | * remove unconfirmed. | ||
826 | * | ||
827 | * create an unconfirmed nfs4_client | ||
828 | * with same cl_name as existing confirmed nfs4_client, | ||
829 | * but with new callback info, new cl_clientid, | ||
830 | * new cl_verifier and a new cl_confirm | ||
831 | */ | 777 | */ |
832 | expire_client(unconf); | 778 | expire_client(unconf); |
833 | new = create_client(clname, dname); | 779 | new = create_client(clname, dname); |
834 | if (new == NULL) | 780 | if (new == NULL) |
835 | goto out; | 781 | goto out; |
836 | gen_clid(new); | 782 | gen_clid(new); |
837 | } else { | ||
838 | /* No cases hit !!! */ | ||
839 | status = nfserr_inval; | ||
840 | goto out; | ||
841 | |||
842 | } | 783 | } |
843 | copy_verf(new, &clverifier); | 784 | copy_verf(new, &clverifier); |
844 | new->cl_addr = sin->sin_addr.s_addr; | 785 | new->cl_addr = sin->sin_addr.s_addr; |
@@ -857,11 +798,9 @@ out: | |||
857 | 798 | ||
858 | 799 | ||
859 | /* | 800 | /* |
860 | * RFC 3010 has a complex implmentation description of processing a | 801 | * Section 14.2.34 of RFC 3530 (under the heading "IMPLEMENTATION") has |
861 | * SETCLIENTID_CONFIRM request consisting of 4 bullets describing | 802 | * a description of SETCLIENTID_CONFIRM request processing consisting of 4 |
862 | * processing on a DRC miss, labeled as CASE1 - CASE4 below. | 803 | * bullets, labeled as CASE1 - CASE4 below. |
863 | * | ||
864 | * NOTE: callback information will be processed here in a future patch | ||
865 | */ | 804 | */ |
866 | __be32 | 805 | __be32 |
867 | nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | 806 | nfsd4_setclientid_confirm(struct svc_rqst *rqstp, |
@@ -892,16 +831,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
892 | if (unconf && unconf->cl_addr != sin->sin_addr.s_addr) | 831 | if (unconf && unconf->cl_addr != sin->sin_addr.s_addr) |
893 | goto out; | 832 | goto out; |
894 | 833 | ||
895 | if ((conf && unconf) && | 834 | /* |
896 | (same_verf(&unconf->cl_confirm, &confirm)) && | 835 | * section 14.2.34 of RFC 3530 has a description of |
897 | (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) && | 836 | * SETCLIENTID_CONFIRM request processing consisting |
898 | (same_name(conf->cl_recdir,unconf->cl_recdir)) && | 837 | * of 4 bullet points, labeled as CASE1 - CASE4 below. |
899 | (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) { | 838 | */ |
900 | /* CASE 1: | 839 | if (conf && unconf && same_verf(&confirm, &unconf->cl_confirm)) { |
901 | * unconf record that matches input clientid and input confirm. | 840 | /* |
902 | * conf record that matches input clientid. | 841 | * RFC 3530 14.2.34 CASE 1: |
903 | * conf and unconf records match names, verifiers | 842 | * callback update |
904 | */ | 843 | */ |
905 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) | 844 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) |
906 | status = nfserr_clid_inuse; | 845 | status = nfserr_clid_inuse; |
907 | else { | 846 | else { |
@@ -914,15 +853,11 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
914 | status = nfs_ok; | 853 | status = nfs_ok; |
915 | 854 | ||
916 | } | 855 | } |
917 | } else if ((conf && !unconf) || | 856 | } else if (conf && !unconf) { |
918 | ((conf && unconf) && | 857 | /* |
919 | (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) || | 858 | * RFC 3530 14.2.34 CASE 2: |
920 | !same_name(conf->cl_recdir, unconf->cl_recdir)))) { | 859 | * probable retransmitted request; play it safe and |
921 | /* CASE 2: | 860 | * do nothing. |
922 | * conf record that matches input clientid. | ||
923 | * if unconf record matches input clientid, then | ||
924 | * unconf->cl_name or unconf->cl_verifier don't match the | ||
925 | * conf record. | ||
926 | */ | 861 | */ |
927 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) | 862 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) |
928 | status = nfserr_clid_inuse; | 863 | status = nfserr_clid_inuse; |
@@ -930,10 +865,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
930 | status = nfs_ok; | 865 | status = nfs_ok; |
931 | } else if (!conf && unconf | 866 | } else if (!conf && unconf |
932 | && same_verf(&unconf->cl_confirm, &confirm)) { | 867 | && same_verf(&unconf->cl_confirm, &confirm)) { |
933 | /* CASE 3: | 868 | /* |
934 | * conf record not found. | 869 | * RFC 3530 14.2.34 CASE 3: |
935 | * unconf record found. | 870 | * Normal case; new or rebooted client: |
936 | * unconf->cl_confirm matches input confirm | ||
937 | */ | 871 | */ |
938 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { | 872 | if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { |
939 | status = nfserr_clid_inuse; | 873 | status = nfserr_clid_inuse; |
@@ -948,16 +882,15 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
948 | } | 882 | } |
949 | move_to_confirmed(unconf); | 883 | move_to_confirmed(unconf); |
950 | conf = unconf; | 884 | conf = unconf; |
885 | nfsd4_probe_callback(conf); | ||
951 | status = nfs_ok; | 886 | status = nfs_ok; |
952 | } | 887 | } |
953 | } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) | 888 | } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) |
954 | && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, | 889 | && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, |
955 | &confirm)))) { | 890 | &confirm)))) { |
956 | /* CASE 4: | 891 | /* |
957 | * conf record not found, or if conf, conf->cl_confirm does not | 892 | * RFC 3530 14.2.34 CASE 4: |
958 | * match input confirm. | 893 | * Client probably hasn't noticed that we rebooted yet. |
959 | * unconf record not found, or if unconf, unconf->cl_confirm | ||
960 | * does not match input confirm. | ||
961 | */ | 894 | */ |
962 | status = nfserr_stale_clientid; | 895 | status = nfserr_stale_clientid; |
963 | } else { | 896 | } else { |
@@ -965,8 +898,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
965 | status = nfserr_clid_inuse; | 898 | status = nfserr_clid_inuse; |
966 | } | 899 | } |
967 | out: | 900 | out: |
968 | if (!status) | ||
969 | nfsd4_probe_callback(conf); | ||
970 | nfs4_unlock_state(); | 901 | nfs4_unlock_state(); |
971 | return status; | 902 | return status; |
972 | } | 903 | } |
@@ -1226,14 +1157,19 @@ find_file(struct inode *ino) | |||
1226 | return NULL; | 1157 | return NULL; |
1227 | } | 1158 | } |
1228 | 1159 | ||
1229 | static int access_valid(u32 x) | 1160 | static inline int access_valid(u32 x) |
1230 | { | 1161 | { |
1231 | return (x > 0 && x < 4); | 1162 | if (x < NFS4_SHARE_ACCESS_READ) |
1163 | return 0; | ||
1164 | if (x > NFS4_SHARE_ACCESS_BOTH) | ||
1165 | return 0; | ||
1166 | return 1; | ||
1232 | } | 1167 | } |
1233 | 1168 | ||
1234 | static int deny_valid(u32 x) | 1169 | static inline int deny_valid(u32 x) |
1235 | { | 1170 | { |
1236 | return (x >= 0 && x < 5); | 1171 | /* Note: unlike access bits, deny bits may be zero. */ |
1172 | return x <= NFS4_SHARE_DENY_BOTH; | ||
1237 | } | 1173 | } |
1238 | 1174 | ||
1239 | static void | 1175 | static void |
@@ -2162,8 +2098,10 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2162 | goto check_replay; | 2098 | goto check_replay; |
2163 | } | 2099 | } |
2164 | 2100 | ||
2101 | *stpp = stp; | ||
2102 | *sopp = sop = stp->st_stateowner; | ||
2103 | |||
2165 | if (lock) { | 2104 | if (lock) { |
2166 | struct nfs4_stateowner *sop = stp->st_stateowner; | ||
2167 | clientid_t *lockclid = &lock->v.new.clientid; | 2105 | clientid_t *lockclid = &lock->v.new.clientid; |
2168 | struct nfs4_client *clp = sop->so_client; | 2106 | struct nfs4_client *clp = sop->so_client; |
2169 | int lkflg = 0; | 2107 | int lkflg = 0; |
@@ -2193,9 +2131,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2193 | return nfserr_bad_stateid; | 2131 | return nfserr_bad_stateid; |
2194 | } | 2132 | } |
2195 | 2133 | ||
2196 | *stpp = stp; | ||
2197 | *sopp = sop = stp->st_stateowner; | ||
2198 | |||
2199 | /* | 2134 | /* |
2200 | * We now validate the seqid and stateid generation numbers. | 2135 | * We now validate the seqid and stateid generation numbers. |
2201 | * For the moment, we ignore the possibility of | 2136 | * For the moment, we ignore the possibility of |