|
@@ -52,6 +52,7 @@
|
|
|
#include <linux/nfs.h>
|
|
|
#include <linux/nfs4.h>
|
|
|
#include <linux/nfs_fs.h>
|
|
|
+#include <linux/fs_struct.h>
|
|
|
|
|
|
#include "nfs4_fs.h"
|
|
|
#include "internal.h"
|
|
@@ -1008,7 +1009,7 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
|
|
|
static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
|
|
|
const struct nfs4_label *label,
|
|
|
const struct nfs_server *server,
|
|
|
- bool excl_check)
|
|
|
+ bool excl_check, const umode_t *umask)
|
|
|
{
|
|
|
char owner_name[IDMAP_NAMESZ];
|
|
|
char owner_group[IDMAP_NAMESZ];
|
|
@@ -1022,18 +1023,21 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
|
|
|
|
|
|
/*
|
|
|
* We reserve enough space to write the entire attribute buffer at once.
|
|
|
- * In the worst-case, this would be
|
|
|
- * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
|
|
|
- * = 40 bytes, plus any contribution from variable-length fields
|
|
|
- * such as owner/group.
|
|
|
*/
|
|
|
if (iap->ia_valid & ATTR_SIZE) {
|
|
|
bmval[0] |= FATTR4_WORD0_SIZE;
|
|
|
len += 8;
|
|
|
}
|
|
|
+ if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
|
|
|
+ umask = NULL;
|
|
|
if (iap->ia_valid & ATTR_MODE) {
|
|
|
- bmval[1] |= FATTR4_WORD1_MODE;
|
|
|
- len += 4;
|
|
|
+ if (umask) {
|
|
|
+ bmval[2] |= FATTR4_WORD2_MODE_UMASK;
|
|
|
+ len += 8;
|
|
|
+ } else {
|
|
|
+ bmval[1] |= FATTR4_WORD1_MODE;
|
|
|
+ len += 4;
|
|
|
+ }
|
|
|
}
|
|
|
if (iap->ia_valid & ATTR_UID) {
|
|
|
owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
|
|
@@ -1134,6 +1138,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
|
|
|
*p++ = cpu_to_be32(label->len);
|
|
|
p = xdr_encode_opaque_fixed(p, label->label, label->len);
|
|
|
}
|
|
|
+ if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
|
|
|
+ *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
|
|
|
+ *p++ = cpu_to_be32(*umask);
|
|
|
+ }
|
|
|
|
|
|
/* out: */
|
|
|
}
|
|
@@ -1188,7 +1196,8 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
|
|
|
}
|
|
|
|
|
|
encode_string(xdr, create->name->len, create->name->name);
|
|
|
- encode_attrs(xdr, create->attrs, create->label, create->server, false);
|
|
|
+ encode_attrs(xdr, create->attrs, create->label, create->server, false,
|
|
|
+ &create->umask);
|
|
|
}
|
|
|
|
|
|
static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
|
|
@@ -1408,11 +1417,13 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
|
|
|
switch(arg->createmode) {
|
|
|
case NFS4_CREATE_UNCHECKED:
|
|
|
*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
|
|
|
- encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false);
|
|
|
+ encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
|
|
|
+ &arg->umask);
|
|
|
break;
|
|
|
case NFS4_CREATE_GUARDED:
|
|
|
*p = cpu_to_be32(NFS4_CREATE_GUARDED);
|
|
|
- encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false);
|
|
|
+ encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
|
|
|
+ &arg->umask);
|
|
|
break;
|
|
|
case NFS4_CREATE_EXCLUSIVE:
|
|
|
*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
|
|
@@ -1421,7 +1432,8 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
|
|
|
case NFS4_CREATE_EXCLUSIVE4_1:
|
|
|
*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
|
|
|
encode_nfs4_verifier(xdr, &arg->u.verifier);
|
|
|
- encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true);
|
|
|
+ encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true,
|
|
|
+ &arg->umask);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1677,7 +1689,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
|
|
|
{
|
|
|
encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
|
|
|
encode_nfs4_stateid(xdr, &arg->stateid);
|
|
|
- encode_attrs(xdr, arg->iap, arg->label, server, false);
|
|
|
+ encode_attrs(xdr, arg->iap, arg->label, server, false, NULL);
|
|
|
}
|
|
|
|
|
|
static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
|