diff options
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 7c8801769a3..bebc0c2e1b0 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -68,7 +68,6 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 68 | u32 *bmval, u32 *writable) | 68 | u32 *bmval, u32 *writable) |
| 69 | { | 69 | { |
| 70 | struct dentry *dentry = cstate->current_fh.fh_dentry; | 70 | struct dentry *dentry = cstate->current_fh.fh_dentry; |
| 71 | struct svc_export *exp = cstate->current_fh.fh_export; | ||
| 72 | 71 | ||
| 73 | /* | 72 | /* |
| 74 | * Check about attributes are supported by the NFSv4 server or not. | 73 | * Check about attributes are supported by the NFSv4 server or not. |
| @@ -80,17 +79,13 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 80 | return nfserr_attrnotsupp; | 79 | return nfserr_attrnotsupp; |
| 81 | 80 | ||
| 82 | /* | 81 | /* |
| 83 | * Check FATTR4_WORD0_ACL & FATTR4_WORD0_FS_LOCATIONS can be supported | 82 | * Check FATTR4_WORD0_ACL can be supported |
| 84 | * in current environment or not. | 83 | * in current environment or not. |
| 85 | */ | 84 | */ |
| 86 | if (bmval[0] & FATTR4_WORD0_ACL) { | 85 | if (bmval[0] & FATTR4_WORD0_ACL) { |
| 87 | if (!IS_POSIXACL(dentry->d_inode)) | 86 | if (!IS_POSIXACL(dentry->d_inode)) |
| 88 | return nfserr_attrnotsupp; | 87 | return nfserr_attrnotsupp; |
| 89 | } | 88 | } |
| 90 | if (bmval[0] & FATTR4_WORD0_FS_LOCATIONS) { | ||
| 91 | if (exp->ex_fslocs.locations == NULL) | ||
| 92 | return nfserr_attrnotsupp; | ||
| 93 | } | ||
| 94 | 89 | ||
| 95 | /* | 90 | /* |
| 96 | * According to spec, read-only attributes return ERR_INVAL. | 91 | * According to spec, read-only attributes return ERR_INVAL. |
| @@ -123,6 +118,35 @@ nfsd4_check_open_attributes(struct svc_rqst *rqstp, | |||
| 123 | return status; | 118 | return status; |
| 124 | } | 119 | } |
| 125 | 120 | ||
| 121 | static int | ||
| 122 | is_create_with_attrs(struct nfsd4_open *open) | ||
| 123 | { | ||
| 124 | return open->op_create == NFS4_OPEN_CREATE | ||
| 125 | && (open->op_createmode == NFS4_CREATE_UNCHECKED | ||
| 126 | || open->op_createmode == NFS4_CREATE_GUARDED | ||
| 127 | || open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* | ||
| 131 | * if error occurs when setting the acl, just clear the acl bit | ||
| 132 | * in the returned attr bitmap. | ||
| 133 | */ | ||
| 134 | static void | ||
| 135 | do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | ||
| 136 | struct nfs4_acl *acl, u32 *bmval) | ||
| 137 | { | ||
| 138 | __be32 status; | ||
| 139 | |||
| 140 | status = nfsd4_set_nfs4_acl(rqstp, fhp, acl); | ||
| 141 | if (status) | ||
| 142 | /* | ||
| 143 | * We should probably fail the whole open at this point, | ||
| 144 | * but we've already created the file, so it's too late; | ||
| 145 | * So this seems the least of evils: | ||
| 146 | */ | ||
| 147 | bmval[0] &= ~FATTR4_WORD0_ACL; | ||
| 148 | } | ||
| 149 | |||
| 126 | static inline void | 150 | static inline void |
| 127 | fh_dup2(struct svc_fh *dst, struct svc_fh *src) | 151 | fh_dup2(struct svc_fh *dst, struct svc_fh *src) |
| 128 | { | 152 | { |
| @@ -206,6 +230,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o | |||
| 206 | if (status) | 230 | if (status) |
| 207 | goto out; | 231 | goto out; |
| 208 | 232 | ||
| 233 | if (is_create_with_attrs(open) && open->op_acl != NULL) | ||
| 234 | do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval); | ||
| 235 | |||
| 209 | set_change_info(&open->op_cinfo, current_fh); | 236 | set_change_info(&open->op_cinfo, current_fh); |
| 210 | fh_dup2(current_fh, &resfh); | 237 | fh_dup2(current_fh, &resfh); |
| 211 | 238 | ||
| @@ -536,12 +563,17 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 536 | status = nfserr_badtype; | 563 | status = nfserr_badtype; |
| 537 | } | 564 | } |
| 538 | 565 | ||
| 539 | if (!status) { | 566 | if (status) |
| 540 | fh_unlock(&cstate->current_fh); | 567 | goto out; |
| 541 | set_change_info(&create->cr_cinfo, &cstate->current_fh); | 568 | |
| 542 | fh_dup2(&cstate->current_fh, &resfh); | 569 | if (create->cr_acl != NULL) |
| 543 | } | 570 | do_set_nfs4_acl(rqstp, &resfh, create->cr_acl, |
| 571 | create->cr_bmval); | ||
| 544 | 572 | ||
| 573 | fh_unlock(&cstate->current_fh); | ||
| 574 | set_change_info(&create->cr_cinfo, &cstate->current_fh); | ||
| 575 | fh_dup2(&cstate->current_fh, &resfh); | ||
| 576 | out: | ||
| 545 | fh_put(&resfh); | 577 | fh_put(&resfh); |
| 546 | return status; | 578 | return status; |
| 547 | } | 579 | } |
| @@ -947,34 +979,6 @@ static struct nfsd4_operation nfsd4_ops[]; | |||
| 947 | static const char *nfsd4_op_name(unsigned opnum); | 979 | static const char *nfsd4_op_name(unsigned opnum); |
| 948 | 980 | ||
| 949 | /* | 981 | /* |
| 950 | * This is a replay of a compound for which no cache entry pages | ||
| 951 | * were used. Encode the sequence operation, and if cachethis is FALSE | ||
| 952 | * encode the uncache rep error on the next operation. | ||
| 953 | */ | ||
| 954 | static __be32 | ||
| 955 | nfsd4_enc_uncached_replay(struct nfsd4_compoundargs *args, | ||
| 956 | struct nfsd4_compoundres *resp) | ||
| 957 | { | ||
| 958 | struct nfsd4_op *op; | ||
| 959 | |||
| 960 | dprintk("--> %s resp->opcnt %d ce_cachethis %u \n", __func__, | ||
| 961 | resp->opcnt, resp->cstate.slot->sl_cache_entry.ce_cachethis); | ||
| 962 | |||
| 963 | /* Encode the replayed sequence operation */ | ||
| 964 | BUG_ON(resp->opcnt != 1); | ||
| 965 | op = &args->ops[resp->opcnt - 1]; | ||
| 966 | nfsd4_encode_operation(resp, op); | ||
| 967 | |||
| 968 | /*return nfserr_retry_uncached_rep in next operation. */ | ||
| 969 | if (resp->cstate.slot->sl_cache_entry.ce_cachethis == 0) { | ||
| 970 | op = &args->ops[resp->opcnt++]; | ||
| 971 | op->status = nfserr_retry_uncached_rep; | ||
| 972 | nfsd4_encode_operation(resp, op); | ||
| 973 | } | ||
| 974 | return op->status; | ||
| 975 | } | ||
| 976 | |||
| 977 | /* | ||
| 978 | * Enforce NFSv4.1 COMPOUND ordering rules. | 982 | * Enforce NFSv4.1 COMPOUND ordering rules. |
| 979 | * | 983 | * |
| 980 | * TODO: | 984 | * TODO: |
| @@ -1083,13 +1087,10 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
| 1083 | BUG_ON(op->status == nfs_ok); | 1087 | BUG_ON(op->status == nfs_ok); |
| 1084 | 1088 | ||
| 1085 | encode_op: | 1089 | encode_op: |
| 1086 | /* Only from SEQUENCE or CREATE_SESSION */ | 1090 | /* Only from SEQUENCE */ |
| 1087 | if (resp->cstate.status == nfserr_replay_cache) { | 1091 | if (resp->cstate.status == nfserr_replay_cache) { |
| 1088 | dprintk("%s NFS4.1 replay from cache\n", __func__); | 1092 | dprintk("%s NFS4.1 replay from cache\n", __func__); |
| 1089 | if (nfsd4_not_cached(resp)) | 1093 | status = op->status; |
| 1090 | status = nfsd4_enc_uncached_replay(args, resp); | ||
| 1091 | else | ||
| 1092 | status = op->status; | ||
| 1093 | goto out; | 1094 | goto out; |
| 1094 | } | 1095 | } |
| 1095 | if (op->status == nfserr_replay_me) { | 1096 | if (op->status == nfserr_replay_me) { |
