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).
Unified · Split
| @@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp) · 294 unmodified lines | ||
| 295 | 295 | |
| 296 | 296 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; |
| 297 | 297 | |
| 298 | −extern const u32 nfs4_fattr_bitmap[2]; | |
| 298 | +extern const u32 nfs4_fattr_bitmap[3]; | |
| 299 | 299 | extern const u32 nfs4_statfs_bitmap[2]; |
| 300 | 300 | extern const u32 nfs4_pathconf_bitmap[2]; |
| 301 | 301 | extern const u32 nfs4_fsinfo_bitmap[3]; |
| @@ -116,7 +116,7 @@ static int nfs4_map_errors(int err) · 115 unmodified lines | ||
| 116 | 116 | /* |
| 117 | 117 | * This is our standard bitmap for GETATTR requests. |
| 118 | 118 | */ |
| 119 | −const u32 nfs4_fattr_bitmap[2] = { | |
| 119 | +const u32 nfs4_fattr_bitmap[3] = { | |
| 120 | 120 | FATTR4_WORD0_TYPE |
| 121 | 121 | | FATTR4_WORD0_CHANGE |
| 122 | 122 | | FATTR4_WORD0_SIZE |
| @@ -133,6 +133,24 @@ const u32 nfs4_fattr_bitmap[2] = { · 10 unmodified lines | ||
| 133 | 133 | | FATTR4_WORD1_TIME_MODIFY |
| 134 | 134 | }; |
| 135 | 135 | |
| 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 | + | |
| 136 | 154 | const u32 nfs4_statfs_bitmap[2] = { |
| 137 | 155 | FATTR4_WORD0_FILES_AVAIL |
| 138 | 156 | | FATTR4_WORD0_FILES_FREE |
| @@ -844,6 +862,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, · 705 unmodified lines | ||
| 844 | 862 | p->o_arg.name = &dentry->d_name; |
| 845 | 863 | p->o_arg.server = server; |
| 846 | 864 | p->o_arg.bitmask = server->attr_bitmask; |
| 865 | + p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; | |
| 847 | 866 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; |
| 848 | 867 | if (attrs != NULL && attrs->ia_valid != 0) { |
| 849 | 868 | __be32 verf[2]; |
| @@ -1820,6 +1839,7 @@ static int _nfs4_do_open(struct inode *dir, · 970 unmodified lines | ||
| 1820 | 1839 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); |
| 1821 | 1840 | if (!opendata->f_attr.mdsthreshold) |
| 1822 | 1841 | goto err_opendata_put; |
| 1842 | + opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; | |
| 1823 | 1843 | } |
| 1824 | 1844 | if (dentry->d_inode != NULL) |
| 1825 | 1845 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); |
| @@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c · 1197 unmodified lines | ||
| 1198 | 1198 | } |
| 1199 | 1199 | |
| 1200 | 1200 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, |
| 1201 | + const u32 *open_bitmap, | |
| 1201 | 1202 | struct compound_hdr *hdr) |
| 1202 | 1203 | { |
| 1203 | 1204 | 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], | |
| 1207 | 1208 | hdr); |
| 1208 | 1209 | } |
| 1209 | 1210 | |
| @@ -2221,7 +2222,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr, · 1011 unmodified lines | ||
| 2221 | 2222 | encode_putfh(xdr, args->fh, &hdr); |
| 2222 | 2223 | encode_open(xdr, args, &hdr); |
| 2223 | 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 | 2226 | encode_nops(&hdr); |
| 2226 | 2227 | } |
| 2227 | 2228 | |
| @@ -4360,6 +4361,9 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr, · 2132 unmodified lines | ||
| 4360 | 4361 | if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U))) |
| 4361 | 4362 | return -EIO; |
| 4362 | 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 | 4367 | p = xdr_inline_decode(xdr, 4); |
| 4364 | 4368 | if (unlikely(!p)) |
| 4365 | 4369 | goto out_overflow; |
| @@ -348,6 +348,7 @@ struct nfs_openargs { · 347 unmodified lines | ||
| 348 | 348 | const struct qstr * name; |
| 349 | 349 | const struct nfs_server *server; /* Needed for ID mapping */ |
| 350 | 350 | const u32 * bitmask; |
| 351 | + const u32 * open_bitmap; | |
| 351 | 352 | __u32 claim; |
| 352 | 353 | struct nfs4_sequence_args seq_args; |
| 353 | 354 | }; |