aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2016-12-02 22:53:30 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-12-09 23:47:10 -0500
commitdff25ddb48086afcb434770caa3d6849a4489b85 (patch)
tree5072c5bf9d907cabcfa354e7c100d0302b10cb36
parentd9152114f7c9abb096275b72db8527c004d57bf9 (diff)
nfs: add support for the umask attribute
Clients can set the umask attribute when creating files to cause the server to apply it always except when inheriting permissions from the parent directory. That way, the new files will end up with the same permissions as files created locally. See https://tools.ietf.org/html/draft-ietf-nfsv4-umask-02 for more details. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r--fs/nfs/dir.c7
-rw-r--r--fs/nfs/nfs4proc.c16
-rw-r--r--fs/nfs/nfs4xdr.c36
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h2
5 files changed, 45 insertions, 17 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 7483722162fa..cb22a9f9ae7e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1529,8 +1529,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
1529 return -ENAMETOOLONG; 1529 return -ENAMETOOLONG;
1530 1530
1531 if (open_flags & O_CREAT) { 1531 if (open_flags & O_CREAT) {
1532 struct nfs_server *server = NFS_SERVER(dir);
1533
1534 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
1535 mode &= ~current_umask();
1536
1532 attr.ia_valid |= ATTR_MODE; 1537 attr.ia_valid |= ATTR_MODE;
1533 attr.ia_mode = mode & ~current_umask(); 1538 attr.ia_mode = mode;
1534 } 1539 }
1535 if (open_flags & O_TRUNC) { 1540 if (open_flags & O_TRUNC) {
1536 attr.ia_valid |= ATTR_SIZE; 1541 attr.ia_valid |= ATTR_SIZE;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c5a508669655..d33242c8d95d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1224,6 +1224,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
1224 atomic_inc(&sp->so_count); 1224 atomic_inc(&sp->so_count);
1225 p->o_arg.open_flags = flags; 1225 p->o_arg.open_flags = flags;
1226 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); 1226 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
1227 p->o_arg.umask = current_umask();
1227 p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); 1228 p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
1228 p->o_arg.share_access = nfs4_map_atomic_open_share(server, 1229 p->o_arg.share_access = nfs4_map_atomic_open_share(server,
1229 fmode, flags); 1230 fmode, flags);
@@ -3337,7 +3338,7 @@ static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
3337 3338
3338#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL) 3339#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL)
3339#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL) 3340#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL)
3340#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_SECURITY_LABEL - 1UL) 3341#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_MODE_UMASK - 1UL)
3341 3342
3342static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) 3343static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
3343{ 3344{
@@ -4010,6 +4011,7 @@ static int
4010nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 4011nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
4011 int flags) 4012 int flags)
4012{ 4013{
4014 struct nfs_server *server = NFS_SERVER(dir);
4013 struct nfs4_label l, *ilabel = NULL; 4015 struct nfs4_label l, *ilabel = NULL;
4014 struct nfs_open_context *ctx; 4016 struct nfs_open_context *ctx;
4015 struct nfs4_state *state; 4017 struct nfs4_state *state;
@@ -4021,7 +4023,8 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
4021 4023
4022 ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); 4024 ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);
4023 4025
4024 sattr->ia_mode &= ~current_umask(); 4026 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
4027 sattr->ia_mode &= ~current_umask();
4025 state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL); 4028 state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL);
4026 if (IS_ERR(state)) { 4029 if (IS_ERR(state)) {
4027 status = PTR_ERR(state); 4030 status = PTR_ERR(state);
@@ -4229,6 +4232,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
4229 data->arg.attrs = sattr; 4232 data->arg.attrs = sattr;
4230 data->arg.ftype = ftype; 4233 data->arg.ftype = ftype;
4231 data->arg.bitmask = nfs4_bitmask(server, data->label); 4234 data->arg.bitmask = nfs4_bitmask(server, data->label);
4235 data->arg.umask = current_umask();
4232 data->res.server = server; 4236 data->res.server = server;
4233 data->res.fh = &data->fh; 4237 data->res.fh = &data->fh;
4234 data->res.fattr = &data->fattr; 4238 data->res.fattr = &data->fattr;
@@ -4326,13 +4330,15 @@ out:
4326static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, 4330static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
4327 struct iattr *sattr) 4331 struct iattr *sattr)
4328{ 4332{
4333 struct nfs_server *server = NFS_SERVER(dir);
4329 struct nfs4_exception exception = { }; 4334 struct nfs4_exception exception = { };
4330 struct nfs4_label l, *label = NULL; 4335 struct nfs4_label l, *label = NULL;
4331 int err; 4336 int err;
4332 4337
4333 label = nfs4_label_init_security(dir, dentry, sattr, &l); 4338 label = nfs4_label_init_security(dir, dentry, sattr, &l);
4334 4339
4335 sattr->ia_mode &= ~current_umask(); 4340 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
4341 sattr->ia_mode &= ~current_umask();
4336 do { 4342 do {
4337 err = _nfs4_proc_mkdir(dir, dentry, sattr, label); 4343 err = _nfs4_proc_mkdir(dir, dentry, sattr, label);
4338 trace_nfs4_mkdir(dir, &dentry->d_name, err); 4344 trace_nfs4_mkdir(dir, &dentry->d_name, err);
@@ -4435,13 +4441,15 @@ out:
4435static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, 4441static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
4436 struct iattr *sattr, dev_t rdev) 4442 struct iattr *sattr, dev_t rdev)
4437{ 4443{
4444 struct nfs_server *server = NFS_SERVER(dir);
4438 struct nfs4_exception exception = { }; 4445 struct nfs4_exception exception = { };
4439 struct nfs4_label l, *label = NULL; 4446 struct nfs4_label l, *label = NULL;
4440 int err; 4447 int err;
4441 4448
4442 label = nfs4_label_init_security(dir, dentry, sattr, &l); 4449 label = nfs4_label_init_security(dir, dentry, sattr, &l);
4443 4450
4444 sattr->ia_mode &= ~current_umask(); 4451 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
4452 sattr->ia_mode &= ~current_umask();
4445 do { 4453 do {
4446 err = _nfs4_proc_mknod(dir, dentry, sattr, label, rdev); 4454 err = _nfs4_proc_mknod(dir, dentry, sattr, label, rdev);
4447 trace_nfs4_mknod(dir, &dentry->d_name, err); 4455 trace_nfs4_mknod(dir, &dentry->d_name, err);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1c1768a8fcd1..1af6268a7d8c 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -52,6 +52,7 @@
52#include <linux/nfs.h> 52#include <linux/nfs.h>
53#include <linux/nfs4.h> 53#include <linux/nfs4.h>
54#include <linux/nfs_fs.h> 54#include <linux/nfs_fs.h>
55#include <linux/fs_struct.h>
55 56
56#include "nfs4_fs.h" 57#include "nfs4_fs.h"
57#include "internal.h" 58#include "internal.h"
@@ -1008,7 +1009,7 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
1008static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, 1009static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1009 const struct nfs4_label *label, 1010 const struct nfs4_label *label,
1010 const struct nfs_server *server, 1011 const struct nfs_server *server,
1011 bool excl_check) 1012 bool excl_check, const umode_t *umask)
1012{ 1013{
1013 char owner_name[IDMAP_NAMESZ]; 1014 char owner_name[IDMAP_NAMESZ];
1014 char owner_group[IDMAP_NAMESZ]; 1015 char owner_group[IDMAP_NAMESZ];
@@ -1022,18 +1023,21 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1022 1023
1023 /* 1024 /*
1024 * We reserve enough space to write the entire attribute buffer at once. 1025 * We reserve enough space to write the entire attribute buffer at once.
1025 * In the worst-case, this would be
1026 * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
1027 * = 40 bytes, plus any contribution from variable-length fields
1028 * such as owner/group.
1029 */ 1026 */
1030 if (iap->ia_valid & ATTR_SIZE) { 1027 if (iap->ia_valid & ATTR_SIZE) {
1031 bmval[0] |= FATTR4_WORD0_SIZE; 1028 bmval[0] |= FATTR4_WORD0_SIZE;
1032 len += 8; 1029 len += 8;
1033 } 1030 }
1031 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
1032 umask = NULL;
1034 if (iap->ia_valid & ATTR_MODE) { 1033 if (iap->ia_valid & ATTR_MODE) {
1035 bmval[1] |= FATTR4_WORD1_MODE; 1034 if (umask) {
1036 len += 4; 1035 bmval[2] |= FATTR4_WORD2_MODE_UMASK;
1036 len += 8;
1037 } else {
1038 bmval[1] |= FATTR4_WORD1_MODE;
1039 len += 4;
1040 }
1037 } 1041 }
1038 if (iap->ia_valid & ATTR_UID) { 1042 if (iap->ia_valid & ATTR_UID) {
1039 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 1043 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,
1134 *p++ = cpu_to_be32(label->len); 1138 *p++ = cpu_to_be32(label->len);
1135 p = xdr_encode_opaque_fixed(p, label->label, label->len); 1139 p = xdr_encode_opaque_fixed(p, label->label, label->len);
1136 } 1140 }
1141 if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
1142 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
1143 *p++ = cpu_to_be32(*umask);
1144 }
1137 1145
1138/* out: */ 1146/* out: */
1139} 1147}
@@ -1188,7 +1196,8 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
1188 } 1196 }
1189 1197
1190 encode_string(xdr, create->name->len, create->name->name); 1198 encode_string(xdr, create->name->len, create->name->name);
1191 encode_attrs(xdr, create->attrs, create->label, create->server, false); 1199 encode_attrs(xdr, create->attrs, create->label, create->server, false,
1200 &create->umask);
1192} 1201}
1193 1202
1194static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) 1203static 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
1408 switch(arg->createmode) { 1417 switch(arg->createmode) {
1409 case NFS4_CREATE_UNCHECKED: 1418 case NFS4_CREATE_UNCHECKED:
1410 *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); 1419 *p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
1411 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false); 1420 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
1421 &arg->umask);
1412 break; 1422 break;
1413 case NFS4_CREATE_GUARDED: 1423 case NFS4_CREATE_GUARDED:
1414 *p = cpu_to_be32(NFS4_CREATE_GUARDED); 1424 *p = cpu_to_be32(NFS4_CREATE_GUARDED);
1415 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false); 1425 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
1426 &arg->umask);
1416 break; 1427 break;
1417 case NFS4_CREATE_EXCLUSIVE: 1428 case NFS4_CREATE_EXCLUSIVE:
1418 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); 1429 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
@@ -1421,7 +1432,8 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
1421 case NFS4_CREATE_EXCLUSIVE4_1: 1432 case NFS4_CREATE_EXCLUSIVE4_1:
1422 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); 1433 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
1423 encode_nfs4_verifier(xdr, &arg->u.verifier); 1434 encode_nfs4_verifier(xdr, &arg->u.verifier);
1424 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true); 1435 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true,
1436 &arg->umask);
1425 } 1437 }
1426} 1438}
1427 1439
@@ -1677,7 +1689,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
1677{ 1689{
1678 encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); 1690 encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
1679 encode_nfs4_stateid(xdr, &arg->stateid); 1691 encode_nfs4_stateid(xdr, &arg->stateid);
1680 encode_attrs(xdr, arg->iap, arg->label, server, false); 1692 encode_attrs(xdr, arg->iap, arg->label, server, false, NULL);
1681} 1693}
1682 1694
1683static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) 1695static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 9094faf0699d..bca536341d1a 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -440,6 +440,7 @@ enum lock_type4 {
440#define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4) 440#define FATTR4_WORD2_MDSTHRESHOLD (1UL << 4)
441#define FATTR4_WORD2_CLONE_BLKSIZE (1UL << 13) 441#define FATTR4_WORD2_CLONE_BLKSIZE (1UL << 13)
442#define FATTR4_WORD2_SECURITY_LABEL (1UL << 16) 442#define FATTR4_WORD2_SECURITY_LABEL (1UL << 16)
443#define FATTR4_WORD2_MODE_UMASK (1UL << 17)
443 444
444/* MDS threshold bitmap bits */ 445/* MDS threshold bitmap bits */
445#define THRESHOLD_RD (1UL << 0) 446#define THRESHOLD_RD (1UL << 0)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 617cfaa20ffc..348f7c158084 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -433,6 +433,7 @@ struct nfs_openargs {
433 enum open_claim_type4 claim; 433 enum open_claim_type4 claim;
434 enum createmode4 createmode; 434 enum createmode4 createmode;
435 const struct nfs4_label *label; 435 const struct nfs4_label *label;
436 umode_t umask;
436}; 437};
437 438
438struct nfs_openres { 439struct nfs_openres {
@@ -958,6 +959,7 @@ struct nfs4_create_arg {
958 const struct nfs_fh * dir_fh; 959 const struct nfs_fh * dir_fh;
959 const u32 * bitmask; 960 const u32 * bitmask;
960 const struct nfs4_label *label; 961 const struct nfs4_label *label;
962 umode_t umask;
961}; 963};
962 964
963struct nfs4_create_res { 965struct nfs4_create_res {