diff options
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 7c8801769a3c..d781658e8084 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -123,6 +123,35 @@ nfsd4_check_open_attributes(struct svc_rqst *rqstp, | |||
123 | return status; | 123 | return status; |
124 | } | 124 | } |
125 | 125 | ||
126 | static int | ||
127 | is_create_with_attrs(struct nfsd4_open *open) | ||
128 | { | ||
129 | return open->op_create == NFS4_OPEN_CREATE | ||
130 | && (open->op_createmode == NFS4_CREATE_UNCHECKED | ||
131 | || open->op_createmode == NFS4_CREATE_GUARDED | ||
132 | || open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * if error occurs when setting the acl, just clear the acl bit | ||
137 | * in the returned attr bitmap. | ||
138 | */ | ||
139 | static void | ||
140 | do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | ||
141 | struct nfs4_acl *acl, u32 *bmval) | ||
142 | { | ||
143 | __be32 status; | ||
144 | |||
145 | status = nfsd4_set_nfs4_acl(rqstp, fhp, acl); | ||
146 | if (status) | ||
147 | /* | ||
148 | * We should probably fail the whole open at this point, | ||
149 | * but we've already created the file, so it's too late; | ||
150 | * So this seems the least of evils: | ||
151 | */ | ||
152 | bmval[0] &= ~FATTR4_WORD0_ACL; | ||
153 | } | ||
154 | |||
126 | static inline void | 155 | static inline void |
127 | fh_dup2(struct svc_fh *dst, struct svc_fh *src) | 156 | fh_dup2(struct svc_fh *dst, struct svc_fh *src) |
128 | { | 157 | { |
@@ -206,6 +235,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o | |||
206 | if (status) | 235 | if (status) |
207 | goto out; | 236 | goto out; |
208 | 237 | ||
238 | if (is_create_with_attrs(open) && open->op_acl != NULL) | ||
239 | do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval); | ||
240 | |||
209 | set_change_info(&open->op_cinfo, current_fh); | 241 | set_change_info(&open->op_cinfo, current_fh); |
210 | fh_dup2(current_fh, &resfh); | 242 | fh_dup2(current_fh, &resfh); |
211 | 243 | ||
@@ -536,12 +568,17 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
536 | status = nfserr_badtype; | 568 | status = nfserr_badtype; |
537 | } | 569 | } |
538 | 570 | ||
539 | if (!status) { | 571 | if (status) |
540 | fh_unlock(&cstate->current_fh); | 572 | goto out; |
541 | set_change_info(&create->cr_cinfo, &cstate->current_fh); | ||
542 | fh_dup2(&cstate->current_fh, &resfh); | ||
543 | } | ||
544 | 573 | ||
574 | if (create->cr_acl != NULL) | ||
575 | do_set_nfs4_acl(rqstp, &resfh, create->cr_acl, | ||
576 | create->cr_bmval); | ||
577 | |||
578 | fh_unlock(&cstate->current_fh); | ||
579 | set_change_info(&create->cr_cinfo, &cstate->current_fh); | ||
580 | fh_dup2(&cstate->current_fh, &resfh); | ||
581 | out: | ||
545 | fh_put(&resfh); | 582 | fh_put(&resfh); |
546 | return status; | 583 | return status; |
547 | } | 584 | } |