|
@@ -279,6 +279,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str
|
|
|
{
|
|
|
struct svc_fh *current_fh = &cstate->current_fh;
|
|
|
__be32 status;
|
|
|
+ int accmode = 0;
|
|
|
|
|
|
/* We don't know the target directory, and therefore can not
|
|
|
* set the change info
|
|
@@ -290,9 +291,19 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, str
|
|
|
|
|
|
open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
|
|
|
(open->op_iattr.ia_size == 0);
|
|
|
+ /*
|
|
|
+ * In the delegation case, the client is telling us about an
|
|
|
+ * open that it *already* performed locally, some time ago. We
|
|
|
+ * should let it succeed now if possible.
|
|
|
+ *
|
|
|
+ * In the case of a CLAIM_FH open, on the other hand, the client
|
|
|
+ * may be counting on us to enforce permissions (the Linux 4.1
|
|
|
+ * client uses this for normal opens, for example).
|
|
|
+ */
|
|
|
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH)
|
|
|
+ accmode = NFSD_MAY_OWNER_OVERRIDE;
|
|
|
|
|
|
- status = do_open_permission(rqstp, current_fh, open,
|
|
|
- NFSD_MAY_OWNER_OVERRIDE);
|
|
|
+ status = do_open_permission(rqstp, current_fh, open, accmode);
|
|
|
|
|
|
return status;
|
|
|
}
|