aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-06-05 09:16:47 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-06-05 10:00:14 -0400
commit1549210fcc17e9ae20c09ac8cd4c48a8dfd431bd (patch)
tree87db73acf11d00c1c4366e488faf86cd70ed996a
parentb3b02ae5865c2dcd506322e0fc6def59a042e72f (diff)
NFSv4: Fix an Oops in the open recovery code
The open recovery code does not need to request a new value for the mdsthreshold, and so does not allocate a struct nfs4_threshold. The problem is that encode_getfattr_open() will still request an mdsthreshold, and so we end up Oopsing in decode_attr_mdsthreshold. This patch fixes encode_getfattr_open so that it doesn't request an mdsthreshold when the caller isn't asking for one. It also fixes decode_attr_mdsthreshold so that it errors if the server returns an mdsthreshold that we didn't ask for (instead of Oopsing). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Andy Adamson <andros@netapp.com>
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c22
-rw-r--r--fs/nfs/nfs4xdr.c12
-rw-r--r--include/linux/nfs_xdr.h1
4 files changed, 31 insertions, 6 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c6827f93ab57..cc5900ac61b5 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp)
295 295
296extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; 296extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
297 297
298extern const u32 nfs4_fattr_bitmap[2]; 298extern const u32 nfs4_fattr_bitmap[3];
299extern const u32 nfs4_statfs_bitmap[2]; 299extern const u32 nfs4_statfs_bitmap[2];
300extern const u32 nfs4_pathconf_bitmap[2]; 300extern const u32 nfs4_pathconf_bitmap[2];
301extern const u32 nfs4_fsinfo_bitmap[3]; 301extern const u32 nfs4_fsinfo_bitmap[3];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d48dbefa0e71..ad1515521a6a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -116,7 +116,7 @@ static int nfs4_map_errors(int err)
116/* 116/*
117 * This is our standard bitmap for GETATTR requests. 117 * This is our standard bitmap for GETATTR requests.
118 */ 118 */
119const u32 nfs4_fattr_bitmap[2] = { 119const u32 nfs4_fattr_bitmap[3] = {
120 FATTR4_WORD0_TYPE 120 FATTR4_WORD0_TYPE
121 | FATTR4_WORD0_CHANGE 121 | FATTR4_WORD0_CHANGE
122 | FATTR4_WORD0_SIZE 122 | FATTR4_WORD0_SIZE
@@ -133,6 +133,24 @@ const u32 nfs4_fattr_bitmap[2] = {
133 | FATTR4_WORD1_TIME_MODIFY 133 | FATTR4_WORD1_TIME_MODIFY
134}; 134};
135 135
136static const u32 nfs4_pnfs_open_bitmap[3] = {
137 FATTR4_WORD0_TYPE
138 | FATTR4_WORD0_CHANGE
139 | FATTR4_WORD0_SIZE
140 | FATTR4_WORD0_FSID
141 | FATTR4_WORD0_FILEID,
142 FATTR4_WORD1_MODE
143 | FATTR4_WORD1_NUMLINKS
144 | FATTR4_WORD1_OWNER
145 | FATTR4_WORD1_OWNER_GROUP
146 | FATTR4_WORD1_RAWDEV
147 | FATTR4_WORD1_SPACE_USED
148 | FATTR4_WORD1_TIME_ACCESS
149 | FATTR4_WORD1_TIME_METADATA
150 | FATTR4_WORD1_TIME_MODIFY,
151 FATTR4_WORD2_MDSTHRESHOLD
152};
153
136const u32 nfs4_statfs_bitmap[2] = { 154const u32 nfs4_statfs_bitmap[2] = {
137 FATTR4_WORD0_FILES_AVAIL 155 FATTR4_WORD0_FILES_AVAIL
138 | FATTR4_WORD0_FILES_FREE 156 | FATTR4_WORD0_FILES_FREE
@@ -844,6 +862,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
844 p->o_arg.name = &dentry->d_name; 862 p->o_arg.name = &dentry->d_name;
845 p->o_arg.server = server; 863 p->o_arg.server = server;
846 p->o_arg.bitmask = server->attr_bitmask; 864 p->o_arg.bitmask = server->attr_bitmask;
865 p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
847 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; 866 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
848 if (attrs != NULL && attrs->ia_valid != 0) { 867 if (attrs != NULL && attrs->ia_valid != 0) {
849 __be32 verf[2]; 868 __be32 verf[2];
@@ -1820,6 +1839,7 @@ static int _nfs4_do_open(struct inode *dir,
1820 opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); 1839 opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
1821 if (!opendata->f_attr.mdsthreshold) 1840 if (!opendata->f_attr.mdsthreshold)
1822 goto err_opendata_put; 1841 goto err_opendata_put;
1842 opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
1823 } 1843 }
1824 if (dentry->d_inode != NULL) 1844 if (dentry->d_inode != NULL)
1825 opendata->state = nfs4_get_open_state(dentry->d_inode, sp); 1845 opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index ee4a74db95d0..9ca1428da9d9 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c
1198} 1198}
1199 1199
1200static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, 1200static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
1201 const u32 *open_bitmap,
1201 struct compound_hdr *hdr) 1202 struct compound_hdr *hdr)
1202{ 1203{
1203 encode_getattr_three(xdr, 1204 encode_getattr_three(xdr,
1204 bitmask[0] & nfs4_fattr_bitmap[0], 1205 bitmask[0] & open_bitmap[0],
1205 bitmask[1] & nfs4_fattr_bitmap[1], 1206 bitmask[1] & open_bitmap[1],
1206 bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD, 1207 bitmask[2] & open_bitmap[2],
1207 hdr); 1208 hdr);
1208} 1209}
1209 1210
@@ -2221,7 +2222,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
2221 encode_putfh(xdr, args->fh, &hdr); 2222 encode_putfh(xdr, args->fh, &hdr);
2222 encode_open(xdr, args, &hdr); 2223 encode_open(xdr, args, &hdr);
2223 encode_getfh(xdr, &hdr); 2224 encode_getfh(xdr, &hdr);
2224 encode_getfattr_open(xdr, args->bitmask, &hdr); 2225 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
2225 encode_nops(&hdr); 2226 encode_nops(&hdr);
2226} 2227}
2227 2228
@@ -4360,6 +4361,9 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
4360 if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) 4361 if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
4361 return -EIO; 4362 return -EIO;
4362 if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) { 4363 if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) {
4364 /* Did the server return an unrequested attribute? */
4365 if (unlikely(res == NULL))
4366 return -EREMOTEIO;
4363 p = xdr_inline_decode(xdr, 4); 4367 p = xdr_inline_decode(xdr, 4);
4364 if (unlikely(!p)) 4368 if (unlikely(!p))
4365 goto out_overflow; 4369 goto out_overflow;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index d1a7bf51c326..7519baef025b 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -348,6 +348,7 @@ struct nfs_openargs {
348 const struct qstr * name; 348 const struct qstr * name;
349 const struct nfs_server *server; /* Needed for ID mapping */ 349 const struct nfs_server *server; /* Needed for ID mapping */
350 const u32 * bitmask; 350 const u32 * bitmask;
351 const u32 * open_bitmap;
351 __u32 claim; 352 __u32 claim;
352 struct nfs4_sequence_args seq_args; 353 struct nfs4_sequence_args seq_args;
353}; 354};