aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-07 13:22:46 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-07 13:22:46 -0500
commit6926afd1925a54a13684ebe05987868890665e2b (patch)
tree14dd0c00c757277d6f28b732c08206376e6dbf31 /fs/nfs/nfs4xdr.c
parente2fecb215b321db0e4a5b2597349a63c07bec42f (diff)
NFSv4: Save the owner/group name string when doing open
...so that we can do the uid/gid mapping outside the asynchronous RPC context. This fixes a bug in the current NFSv4 atomic open code where the client isn't able to determine what the true uid/gid fields of the file are, (because the asynchronous nature of the OPEN call denies it the ability to do an upcall) and so fills them with default values, marking the inode as needing revalidation. Unfortunately, in some cases, the VFS will do some additional sanity checks on the file, and may override the server's decision to allow the open because it sees the wrong owner/group fields. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c106
1 files changed, 47 insertions, 59 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index dcaf69309d8e..95e92e438407 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2298,7 +2298,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
2298 encode_getfh(xdr, &hdr); 2298 encode_getfh(xdr, &hdr);
2299 encode_getfattr(xdr, args->bitmask, &hdr); 2299 encode_getfattr(xdr, args->bitmask, &hdr);
2300 encode_restorefh(xdr, &hdr); 2300 encode_restorefh(xdr, &hdr);
2301 encode_getfattr(xdr, args->bitmask, &hdr); 2301 encode_getfattr(xdr, args->dir_bitmask, &hdr);
2302 encode_nops(&hdr); 2302 encode_nops(&hdr);
2303} 2303}
2304 2304
@@ -3792,7 +3792,8 @@ out_overflow:
3792} 3792}
3793 3793
3794static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, 3794static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
3795 const struct nfs_server *server, uint32_t *uid, int may_sleep) 3795 const struct nfs_server *server, uint32_t *uid,
3796 struct nfs4_string *owner_name)
3796{ 3797{
3797 uint32_t len; 3798 uint32_t len;
3798 __be32 *p; 3799 __be32 *p;
@@ -3809,8 +3810,12 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
3809 p = xdr_inline_decode(xdr, len); 3810 p = xdr_inline_decode(xdr, len);
3810 if (unlikely(!p)) 3811 if (unlikely(!p))
3811 goto out_overflow; 3812 goto out_overflow;
3812 if (!may_sleep) { 3813 if (owner_name != NULL) {
3813 /* do nothing */ 3814 owner_name->data = kmemdup(p, len, GFP_NOWAIT);
3815 if (owner_name->data != NULL) {
3816 owner_name->len = len;
3817 ret = NFS_ATTR_FATTR_OWNER_NAME;
3818 }
3814 } else if (len < XDR_MAX_NETOBJ) { 3819 } else if (len < XDR_MAX_NETOBJ) {
3815 if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) 3820 if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0)
3816 ret = NFS_ATTR_FATTR_OWNER; 3821 ret = NFS_ATTR_FATTR_OWNER;
@@ -3830,7 +3835,8 @@ out_overflow:
3830} 3835}
3831 3836
3832static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, 3837static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
3833 const struct nfs_server *server, uint32_t *gid, int may_sleep) 3838 const struct nfs_server *server, uint32_t *gid,
3839 struct nfs4_string *group_name)
3834{ 3840{
3835 uint32_t len; 3841 uint32_t len;
3836 __be32 *p; 3842 __be32 *p;
@@ -3847,8 +3853,12 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
3847 p = xdr_inline_decode(xdr, len); 3853 p = xdr_inline_decode(xdr, len);
3848 if (unlikely(!p)) 3854 if (unlikely(!p))
3849 goto out_overflow; 3855 goto out_overflow;
3850 if (!may_sleep) { 3856 if (group_name != NULL) {
3851 /* do nothing */ 3857 group_name->data = kmemdup(p, len, GFP_NOWAIT);
3858 if (group_name->data != NULL) {
3859 group_name->len = len;
3860 ret = NFS_ATTR_FATTR_GROUP_NAME;
3861 }
3852 } else if (len < XDR_MAX_NETOBJ) { 3862 } else if (len < XDR_MAX_NETOBJ) {
3853 if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) 3863 if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0)
3854 ret = NFS_ATTR_FATTR_GROUP; 3864 ret = NFS_ATTR_FATTR_GROUP;
@@ -4285,7 +4295,7 @@ xdr_error:
4285 4295
4286static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, 4296static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
4287 struct nfs_fattr *fattr, struct nfs_fh *fh, 4297 struct nfs_fattr *fattr, struct nfs_fh *fh,
4288 const struct nfs_server *server, int may_sleep) 4298 const struct nfs_server *server)
4289{ 4299{
4290 int status; 4300 int status;
4291 umode_t fmode = 0; 4301 umode_t fmode = 0;
@@ -4352,12 +4362,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
4352 goto xdr_error; 4362 goto xdr_error;
4353 fattr->valid |= status; 4363 fattr->valid |= status;
4354 4364
4355 status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); 4365 status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name);
4356 if (status < 0) 4366 if (status < 0)
4357 goto xdr_error; 4367 goto xdr_error;
4358 fattr->valid |= status; 4368 fattr->valid |= status;
4359 4369
4360 status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); 4370 status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name);
4361 if (status < 0) 4371 if (status < 0)
4362 goto xdr_error; 4372 goto xdr_error;
4363 fattr->valid |= status; 4373 fattr->valid |= status;
@@ -4398,7 +4408,7 @@ xdr_error:
4398} 4408}
4399 4409
4400static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4410static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
4401 struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) 4411 struct nfs_fh *fh, const struct nfs_server *server)
4402{ 4412{
4403 __be32 *savep; 4413 __be32 *savep;
4404 uint32_t attrlen, 4414 uint32_t attrlen,
@@ -4417,7 +4427,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat
4417 if (status < 0) 4427 if (status < 0)
4418 goto xdr_error; 4428 goto xdr_error;
4419 4429
4420 status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); 4430 status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server);
4421 if (status < 0) 4431 if (status < 0)
4422 goto xdr_error; 4432 goto xdr_error;
4423 4433
@@ -4428,9 +4438,9 @@ xdr_error:
4428} 4438}
4429 4439
4430static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4440static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
4431 const struct nfs_server *server, int may_sleep) 4441 const struct nfs_server *server)
4432{ 4442{
4433 return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); 4443 return decode_getfattr_generic(xdr, fattr, NULL, server);
4434} 4444}
4435 4445
4436/* 4446/*
@@ -5711,8 +5721,7 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp,
5711 status = decode_open_downgrade(xdr, res); 5721 status = decode_open_downgrade(xdr, res);
5712 if (status != 0) 5722 if (status != 0)
5713 goto out; 5723 goto out;
5714 decode_getfattr(xdr, res->fattr, res->server, 5724 decode_getfattr(xdr, res->fattr, res->server);
5715 !RPC_IS_ASYNC(rqstp->rq_task));
5716out: 5725out:
5717 return status; 5726 return status;
5718} 5727}
@@ -5738,8 +5747,7 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5738 status = decode_access(xdr, res); 5747 status = decode_access(xdr, res);
5739 if (status != 0) 5748 if (status != 0)
5740 goto out; 5749 goto out;
5741 decode_getfattr(xdr, res->fattr, res->server, 5750 decode_getfattr(xdr, res->fattr, res->server);
5742 !RPC_IS_ASYNC(rqstp->rq_task));
5743out: 5751out:
5744 return status; 5752 return status;
5745} 5753}
@@ -5768,8 +5776,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5768 status = decode_getfh(xdr, res->fh); 5776 status = decode_getfh(xdr, res->fh);
5769 if (status) 5777 if (status)
5770 goto out; 5778 goto out;
5771 status = decode_getfattr(xdr, res->fattr, res->server 5779 status = decode_getfattr(xdr, res->fattr, res->server);
5772 ,!RPC_IS_ASYNC(rqstp->rq_task));
5773out: 5780out:
5774 return status; 5781 return status;
5775} 5782}
@@ -5795,8 +5802,7 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp,
5795 goto out; 5802 goto out;
5796 status = decode_getfh(xdr, res->fh); 5803 status = decode_getfh(xdr, res->fh);
5797 if (status == 0) 5804 if (status == 0)
5798 status = decode_getfattr(xdr, res->fattr, res->server, 5805 status = decode_getfattr(xdr, res->fattr, res->server);
5799 !RPC_IS_ASYNC(rqstp->rq_task));
5800out: 5806out:
5801 return status; 5807 return status;
5802} 5808}
@@ -5822,8 +5828,7 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5822 status = decode_remove(xdr, &res->cinfo); 5828 status = decode_remove(xdr, &res->cinfo);
5823 if (status) 5829 if (status)
5824 goto out; 5830 goto out;
5825 decode_getfattr(xdr, res->dir_attr, res->server, 5831 decode_getfattr(xdr, res->dir_attr, res->server);
5826 !RPC_IS_ASYNC(rqstp->rq_task));
5827out: 5832out:
5828 return status; 5833 return status;
5829} 5834}
@@ -5856,14 +5861,12 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5856 if (status) 5861 if (status)
5857 goto out; 5862 goto out;
5858 /* Current FH is target directory */ 5863 /* Current FH is target directory */
5859 if (decode_getfattr(xdr, res->new_fattr, res->server, 5864 if (decode_getfattr(xdr, res->new_fattr, res->server))
5860 !RPC_IS_ASYNC(rqstp->rq_task)) != 0)
5861 goto out; 5865 goto out;
5862 status = decode_restorefh(xdr); 5866 status = decode_restorefh(xdr);
5863 if (status) 5867 if (status)
5864 goto out; 5868 goto out;
5865 decode_getfattr(xdr, res->old_fattr, res->server, 5869 decode_getfattr(xdr, res->old_fattr, res->server);
5866 !RPC_IS_ASYNC(rqstp->rq_task));
5867out: 5870out:
5868 return status; 5871 return status;
5869} 5872}
@@ -5899,14 +5902,12 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5899 * Note order: OP_LINK leaves the directory as the current 5902 * Note order: OP_LINK leaves the directory as the current
5900 * filehandle. 5903 * filehandle.
5901 */ 5904 */
5902 if (decode_getfattr(xdr, res->dir_attr, res->server, 5905 if (decode_getfattr(xdr, res->dir_attr, res->server))
5903 !RPC_IS_ASYNC(rqstp->rq_task)) != 0)
5904 goto out; 5906 goto out;
5905 status = decode_restorefh(xdr); 5907 status = decode_restorefh(xdr);
5906 if (status) 5908 if (status)
5907 goto out; 5909 goto out;
5908 decode_getfattr(xdr, res->fattr, res->server, 5910 decode_getfattr(xdr, res->fattr, res->server);
5909 !RPC_IS_ASYNC(rqstp->rq_task));
5910out: 5911out:
5911 return status; 5912 return status;
5912} 5913}
@@ -5938,14 +5939,12 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5938 status = decode_getfh(xdr, res->fh); 5939 status = decode_getfh(xdr, res->fh);
5939 if (status) 5940 if (status)
5940 goto out; 5941 goto out;
5941 if (decode_getfattr(xdr, res->fattr, res->server, 5942 if (decode_getfattr(xdr, res->fattr, res->server))
5942 !RPC_IS_ASYNC(rqstp->rq_task)) != 0)
5943 goto out; 5943 goto out;
5944 status = decode_restorefh(xdr); 5944 status = decode_restorefh(xdr);
5945 if (status) 5945 if (status)
5946 goto out; 5946 goto out;
5947 decode_getfattr(xdr, res->dir_fattr, res->server, 5947 decode_getfattr(xdr, res->dir_fattr, res->server);
5948 !RPC_IS_ASYNC(rqstp->rq_task));
5949out: 5948out:
5950 return status; 5949 return status;
5951} 5950}
@@ -5977,8 +5976,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5977 status = decode_putfh(xdr); 5976 status = decode_putfh(xdr);
5978 if (status) 5977 if (status)
5979 goto out; 5978 goto out;
5980 status = decode_getfattr(xdr, res->fattr, res->server, 5979 status = decode_getfattr(xdr, res->fattr, res->server);
5981 !RPC_IS_ASYNC(rqstp->rq_task));
5982out: 5980out:
5983 return status; 5981 return status;
5984} 5982}
@@ -6076,8 +6074,7 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6076 * an ESTALE error. Shouldn't be a problem, 6074 * an ESTALE error. Shouldn't be a problem,
6077 * though, since fattr->valid will remain unset. 6075 * though, since fattr->valid will remain unset.
6078 */ 6076 */
6079 decode_getfattr(xdr, res->fattr, res->server, 6077 decode_getfattr(xdr, res->fattr, res->server);
6080 !RPC_IS_ASYNC(rqstp->rq_task));
6081out: 6078out:
6082 return status; 6079 return status;
6083} 6080}
@@ -6108,13 +6105,11 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6108 goto out; 6105 goto out;
6109 if (decode_getfh(xdr, &res->fh) != 0) 6106 if (decode_getfh(xdr, &res->fh) != 0)
6110 goto out; 6107 goto out;
6111 if (decode_getfattr(xdr, res->f_attr, res->server, 6108 if (decode_getfattr(xdr, res->f_attr, res->server) != 0)
6112 !RPC_IS_ASYNC(rqstp->rq_task)) != 0)
6113 goto out; 6109 goto out;
6114 if (decode_restorefh(xdr) != 0) 6110 if (decode_restorefh(xdr) != 0)
6115 goto out; 6111 goto out;
6116 decode_getfattr(xdr, res->dir_attr, res->server, 6112 decode_getfattr(xdr, res->dir_attr, res->server);
6117 !RPC_IS_ASYNC(rqstp->rq_task));
6118out: 6113out:
6119 return status; 6114 return status;
6120} 6115}
@@ -6162,8 +6157,7 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
6162 status = decode_open(xdr, res); 6157 status = decode_open(xdr, res);
6163 if (status) 6158 if (status)
6164 goto out; 6159 goto out;
6165 decode_getfattr(xdr, res->f_attr, res->server, 6160 decode_getfattr(xdr, res->f_attr, res->server);
6166 !RPC_IS_ASYNC(rqstp->rq_task));
6167out: 6161out:
6168 return status; 6162 return status;
6169} 6163}
@@ -6190,8 +6184,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp,
6190 status = decode_setattr(xdr); 6184 status = decode_setattr(xdr);
6191 if (status) 6185 if (status)
6192 goto out; 6186 goto out;
6193 decode_getfattr(xdr, res->fattr, res->server, 6187 decode_getfattr(xdr, res->fattr, res->server);
6194 !RPC_IS_ASYNC(rqstp->rq_task));
6195out: 6188out:
6196 return status; 6189 return status;
6197} 6190}
@@ -6371,8 +6364,7 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6371 if (status) 6364 if (status)
6372 goto out; 6365 goto out;
6373 if (res->fattr) 6366 if (res->fattr)
6374 decode_getfattr(xdr, res->fattr, res->server, 6367 decode_getfattr(xdr, res->fattr, res->server);
6375 !RPC_IS_ASYNC(rqstp->rq_task));
6376 if (!status) 6368 if (!status)
6377 status = res->count; 6369 status = res->count;
6378out: 6370out:
@@ -6401,8 +6393,7 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6401 if (status) 6393 if (status)
6402 goto out; 6394 goto out;
6403 if (res->fattr) 6395 if (res->fattr)
6404 decode_getfattr(xdr, res->fattr, res->server, 6396 decode_getfattr(xdr, res->fattr, res->server);
6405 !RPC_IS_ASYNC(rqstp->rq_task));
6406out: 6397out:
6407 return status; 6398 return status;
6408} 6399}
@@ -6561,8 +6552,7 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp,
6561 status = decode_delegreturn(xdr); 6552 status = decode_delegreturn(xdr);
6562 if (status != 0) 6553 if (status != 0)
6563 goto out; 6554 goto out;
6564 decode_getfattr(xdr, res->fattr, res->server, 6555 decode_getfattr(xdr, res->fattr, res->server);
6565 !RPC_IS_ASYNC(rqstp->rq_task));
6566out: 6556out:
6567 return status; 6557 return status;
6568} 6558}
@@ -6591,8 +6581,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req,
6591 goto out; 6581 goto out;
6592 xdr_enter_page(xdr, PAGE_SIZE); 6582 xdr_enter_page(xdr, PAGE_SIZE);
6593 status = decode_getfattr(xdr, &res->fs_locations->fattr, 6583 status = decode_getfattr(xdr, &res->fs_locations->fattr,
6594 res->fs_locations->server, 6584 res->fs_locations->server);
6595 !RPC_IS_ASYNC(req->rq_task));
6596out: 6585out:
6597 return status; 6586 return status;
6598} 6587}
@@ -6841,8 +6830,7 @@ static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
6841 status = decode_layoutcommit(xdr, rqstp, res); 6830 status = decode_layoutcommit(xdr, rqstp, res);
6842 if (status) 6831 if (status)
6843 goto out; 6832 goto out;
6844 decode_getfattr(xdr, res->fattr, res->server, 6833 decode_getfattr(xdr, res->fattr, res->server);
6845 !RPC_IS_ASYNC(rqstp->rq_task));
6846out: 6834out:
6847 return status; 6835 return status;
6848} 6836}
@@ -6973,7 +6961,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6973 goto out_overflow; 6961 goto out_overflow;
6974 6962
6975 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, 6963 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
6976 entry->server, 1) < 0) 6964 entry->server) < 0)
6977 goto out_overflow; 6965 goto out_overflow;
6978 if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) 6966 if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
6979 entry->ino = entry->fattr->mounted_on_fileid; 6967 entry->ino = entry->fattr->mounted_on_fileid;