History

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).

Trond Myklebust committed 14 years ago

Commit 15492101 parent b3b02ae4 files · +31 −6Browse files

Unified · Split

4 files
  1. fs/nfs/nfs4_fs.h +1 −1
  2. fs/nfs/nfs4proc.c +21 −1
  3. fs/nfs/nfs4xdr.c +8 −4
  4. include/linux/nfs_xdr.h +1 −0
fs/nfs/nfs4_fs.h+1−1
@@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp) · 294 unmodified lines
295295
296296 extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
297297
298−extern const u32 nfs4_fattr_bitmap[2];
298+extern const u32 nfs4_fattr_bitmap[3];
299299 extern const u32 nfs4_statfs_bitmap[2];
300300 extern const u32 nfs4_pathconf_bitmap[2];
301301 extern const u32 nfs4_fsinfo_bitmap[3];
fs/nfs/nfs4proc.c+21−1
@@ -116,7 +116,7 @@ static int nfs4_map_errors(int err) · 115 unmodified lines
116116 /*
117117 * This is our standard bitmap for GETATTR requests.
118118 */
119−const u32 nfs4_fattr_bitmap[2] = {
119+const u32 nfs4_fattr_bitmap[3] = {
120120 FATTR4_WORD0_TYPE
121121 | FATTR4_WORD0_CHANGE
122122 | FATTR4_WORD0_SIZE
@@ -133,6 +133,24 @@ const u32 nfs4_fattr_bitmap[2] = { · 10 unmodified lines
133133 | FATTR4_WORD1_TIME_MODIFY
134134 };
135135
136+static 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+
136154 const u32 nfs4_statfs_bitmap[2] = {
137155 FATTR4_WORD0_FILES_AVAIL
138156 | FATTR4_WORD0_FILES_FREE
@@ -844,6 +862,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, · 705 unmodified lines
844862 p->o_arg.name = &dentry->d_name;
845863 p->o_arg.server = server;
846864 p->o_arg.bitmask = server->attr_bitmask;
865+ p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
847866 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
848867 if (attrs != NULL && attrs->ia_valid != 0) {
849868 __be32 verf[2];
@@ -1820,6 +1839,7 @@ static int _nfs4_do_open(struct inode *dir, · 970 unmodified lines
18201839 opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
18211840 if (!opendata->f_attr.mdsthreshold)
18221841 goto err_opendata_put;
1842+ opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
18231843 }
18241844 if (dentry->d_inode != NULL)
18251845 opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
fs/nfs/nfs4xdr.c+8−4
@@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c · 1197 unmodified lines
11981198 }
11991199
12001200 static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
1201+ const u32 *open_bitmap,
12011202 struct compound_hdr *hdr)
12021203 {
12031204 encode_getattr_three(xdr,
1204− bitmask[0] & nfs4_fattr_bitmap[0],
1205− bitmask[1] & nfs4_fattr_bitmap[1],
1206− bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD,
1205+ bitmask[0] & open_bitmap[0],
1206+ bitmask[1] & open_bitmap[1],
1207+ bitmask[2] & open_bitmap[2],
12071208 hdr);
12081209 }
12091210
@@ -2221,7 +2222,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, · 1011 unmodified lines
22212222 encode_putfh(xdr, args->fh, &hdr);
22222223 encode_open(xdr, args, &hdr);
22232224 encode_getfh(xdr, &hdr);
2224− encode_getfattr_open(xdr, args->bitmask, &hdr);
2225+ encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
22252226 encode_nops(&hdr);
22262227 }
22272228
@@ -4360,6 +4361,9 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, · 2132 unmodified lines
43604361 if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
43614362 return -EIO;
43624363 if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) {
4364+ /* Did the server return an unrequested attribute? */
4365+ if (unlikely(res == NULL))
4366+ return -EREMOTEIO;
43634367 p = xdr_inline_decode(xdr, 4);
43644368 if (unlikely(!p))
43654369 goto out_overflow;
include/linux/nfs_xdr.h+1−0
@@ -348,6 +348,7 @@ struct nfs_openargs { · 347 unmodified lines
348348 const struct qstr * name;
349349 const struct nfs_server *server; /* Needed for ID mapping */
350350 const u32 * bitmask;
351+ const u32 * open_bitmap;
351352 __u32 claim;
352353 struct nfs4_sequence_args seq_args;
353354 };