Skip to content

Commit 873b779

Browse files
committed
Merge tag 'nfs-for-3.5-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: - Fix a couple of mount regressions due to the recent cleanups. - Fix an Oops in the open recovery code - Fix an rpc_pipefs upcall hang that results from some of the net namespace work from 3.4.x (stable kernel candidate). - Fix a couple of write and o_direct regressions that were found at last weeks Bakeathon testing event in Ann Arbor." * tag 'nfs-for-3.5-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: add an endian notation for sparse NFSv4.1: integer overflow in decode_cb_sequence_args() rpc_pipefs: allow rpc_purge_list to take a NULL waitq pointer NFSv4 do not send an empty SETATTR compound NFSv2: EOF incorrectly set on short read NFS: Use the NFS_DEFAULT_VERSION for v2 and v3 mounts NFS: fix directio refcount bug on commit NFSv4: Fix unnecessary delegation returns in nfs4_do_open NFSv4.1: Convert another trivial printk into a dprintk NFS4: Fix open bug when pnfs module blacklisted NFS: Remove incorrect BUG_ON in nfs_found_client NFS: Map minor mismatch error to protocol not support error. NFS: Fix a commit bug NFS4: Set parsed mount data version to 4 NFSv4.1: Ensure we clear session state flags after a session creation NFSv4.1: Convert a trivial printk into a dprintk NFSv4: Fix up decode_attr_mdsthreshold NFSv4: Fix an Oops in the open recovery code NFSv4.1: Fix a request leak on the back channel
2 parents 56b880e + e216c8c commit 873b779

File tree

14 files changed

+85
-46
lines changed

14 files changed

+85
-46
lines changed

fs/nfs/callback_xdr.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
455455
args->csa_nrclists = ntohl(*p++);
456456
args->csa_rclists = NULL;
457457
if (args->csa_nrclists) {
458-
args->csa_rclists = kmalloc(args->csa_nrclists *
459-
sizeof(*args->csa_rclists),
460-
GFP_KERNEL);
458+
args->csa_rclists = kmalloc_array(args->csa_nrclists,
459+
sizeof(*args->csa_rclists),
460+
GFP_KERNEL);
461461
if (unlikely(args->csa_rclists == NULL))
462462
goto out;
463463

@@ -696,7 +696,7 @@ static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
696696
const struct cb_sequenceres *res)
697697
{
698698
__be32 *p;
699-
unsigned status = res->csr_status;
699+
__be32 status = res->csr_status;
700700

701701
if (unlikely(status != 0))
702702
goto out;

fs/nfs/client.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,8 +544,6 @@ nfs_found_client(const struct nfs_client_initdata *cl_init,
544544

545545
smp_rmb();
546546

547-
BUG_ON(clp->cl_cons_state != NFS_CS_READY);
548-
549547
dprintk("<-- %s found nfs_client %p for %s\n",
550548
__func__, clp, cl_init->hostname ?: "");
551549
return clp;

fs/nfs/direct.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,9 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
523523
nfs_list_remove_request(req);
524524
if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) {
525525
/* Note the rewrite will go through mds */
526-
kref_get(&req->wb_kref);
527526
nfs_mark_request_commit(req, NULL, &cinfo);
528-
}
527+
} else
528+
nfs_release_request(req);
529529
nfs_unlock_and_release_request(req);
530530
}
531531

@@ -716,12 +716,12 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
716716
if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
717717
bit = NFS_IOHDR_NEED_RESCHED;
718718
else if (dreq->flags == 0) {
719-
memcpy(&dreq->verf, &req->wb_verf,
719+
memcpy(&dreq->verf, hdr->verf,
720720
sizeof(dreq->verf));
721721
bit = NFS_IOHDR_NEED_COMMIT;
722722
dreq->flags = NFS_ODIRECT_DO_COMMIT;
723723
} else if (dreq->flags == NFS_ODIRECT_DO_COMMIT) {
724-
if (memcmp(&dreq->verf, &req->wb_verf, sizeof(dreq->verf))) {
724+
if (memcmp(&dreq->verf, hdr->verf, sizeof(dreq->verf))) {
725725
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
726726
bit = NFS_IOHDR_NEED_RESCHED;
727727
} else

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ is_ds_client(struct nfs_client *clp)
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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ static int nfs4_map_errors(int err)
105105
return -EINVAL;
106106
case -NFS4ERR_SHARE_DENIED:
107107
return -EACCES;
108+
case -NFS4ERR_MINOR_VERS_MISMATCH:
109+
return -EPROTONOSUPPORT;
108110
default:
109111
dprintk("%s could not handle NFSv4 error %d\n",
110112
__func__, -err);
@@ -116,7 +118,7 @@ static int nfs4_map_errors(int err)
116118
/*
117119
* This is our standard bitmap for GETATTR requests.
118120
*/
119-
const u32 nfs4_fattr_bitmap[2] = {
121+
const u32 nfs4_fattr_bitmap[3] = {
120122
FATTR4_WORD0_TYPE
121123
| FATTR4_WORD0_CHANGE
122124
| FATTR4_WORD0_SIZE
@@ -133,6 +135,24 @@ const u32 nfs4_fattr_bitmap[2] = {
133135
| FATTR4_WORD1_TIME_MODIFY
134136
};
135137

138+
static const u32 nfs4_pnfs_open_bitmap[3] = {
139+
FATTR4_WORD0_TYPE
140+
| FATTR4_WORD0_CHANGE
141+
| FATTR4_WORD0_SIZE
142+
| FATTR4_WORD0_FSID
143+
| FATTR4_WORD0_FILEID,
144+
FATTR4_WORD1_MODE
145+
| FATTR4_WORD1_NUMLINKS
146+
| FATTR4_WORD1_OWNER
147+
| FATTR4_WORD1_OWNER_GROUP
148+
| FATTR4_WORD1_RAWDEV
149+
| FATTR4_WORD1_SPACE_USED
150+
| FATTR4_WORD1_TIME_ACCESS
151+
| FATTR4_WORD1_TIME_METADATA
152+
| FATTR4_WORD1_TIME_MODIFY,
153+
FATTR4_WORD2_MDSTHRESHOLD
154+
};
155+
136156
const u32 nfs4_statfs_bitmap[2] = {
137157
FATTR4_WORD0_FILES_AVAIL
138158
| FATTR4_WORD0_FILES_FREE
@@ -844,6 +864,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
844864
p->o_arg.name = &dentry->d_name;
845865
p->o_arg.server = server;
846866
p->o_arg.bitmask = server->attr_bitmask;
867+
p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
847868
p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
848869
if (attrs != NULL && attrs->ia_valid != 0) {
849870
__be32 verf[2];
@@ -1820,6 +1841,7 @@ static int _nfs4_do_open(struct inode *dir,
18201841
opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
18211842
if (!opendata->f_attr.mdsthreshold)
18221843
goto err_opendata_put;
1844+
opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
18231845
}
18241846
if (dentry->d_inode != NULL)
18251847
opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
@@ -1880,6 +1902,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
18801902
struct nfs4_state *res;
18811903
int status;
18821904

1905+
fmode &= FMODE_READ|FMODE_WRITE;
18831906
do {
18841907
status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
18851908
&res, ctx_th);
@@ -2526,6 +2549,14 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
25262549

25272550
nfs_fattr_init(fattr);
25282551

2552+
/* Deal with open(O_TRUNC) */
2553+
if (sattr->ia_valid & ATTR_OPEN)
2554+
sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
2555+
2556+
/* Optimization: if the end result is no change, don't RPC */
2557+
if ((sattr->ia_valid & ~(ATTR_FILE)) == 0)
2558+
return 0;
2559+
25292560
/* Search for an existing open(O_WRITE) file */
25302561
if (sattr->ia_valid & ATTR_FILE) {
25312562
struct nfs_open_context *ctx;
@@ -2537,10 +2568,6 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
25372568
}
25382569
}
25392570

2540-
/* Deal with open(O_TRUNC) */
2541-
if (sattr->ia_valid & ATTR_OPEN)
2542-
sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
2543-
25442571
status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
25452572
if (status == 0)
25462573
nfs_setattr_update_inode(inode, sattr);
@@ -5275,7 +5302,7 @@ static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
52755302

52765303
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
52775304
if (status)
5278-
pr_warn("NFS: Got error %d from the server %s on "
5305+
dprintk("NFS: Got error %d from the server %s on "
52795306
"DESTROY_CLIENTID.", status, clp->cl_hostname);
52805307
return status;
52815308
}
@@ -5746,8 +5773,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session,
57465773
status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
57475774

57485775
if (status)
5749-
printk(KERN_WARNING
5750-
"NFS: Got error %d from the server on DESTROY_SESSION. "
5776+
dprintk("NFS: Got error %d from the server on DESTROY_SESSION. "
57515777
"Session has been destroyed regardless...\n", status);
57525778

57535779
dprintk("<-- nfs4_proc_destroy_session\n");

fs/nfs/nfs4state.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,16 @@ static int nfs4_begin_drain_session(struct nfs_client *clp)
244244
return nfs4_wait_on_slot_tbl(&ses->fc_slot_table);
245245
}
246246

247+
static void nfs41_finish_session_reset(struct nfs_client *clp)
248+
{
249+
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
250+
clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
251+
/* create_session negotiated new slot table */
252+
clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
253+
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
254+
nfs41_setup_state_renewal(clp);
255+
}
256+
247257
int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
248258
{
249259
int status;
@@ -259,8 +269,7 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
259269
status = nfs4_proc_create_session(clp, cred);
260270
if (status != 0)
261271
goto out;
262-
clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
263-
nfs41_setup_state_renewal(clp);
272+
nfs41_finish_session_reset(clp);
264273
nfs_mark_client_ready(clp, NFS_CS_READY);
265274
out:
266275
return status;
@@ -1772,16 +1781,9 @@ static int nfs4_reset_session(struct nfs_client *clp)
17721781
status = nfs4_handle_reclaim_lease_error(clp, status);
17731782
goto out;
17741783
}
1775-
clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
1776-
/* create_session negotiated new slot table */
1777-
clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1778-
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
1784+
nfs41_finish_session_reset(clp);
17791785
dprintk("%s: session reset was successful for server %s!\n",
17801786
__func__, clp->cl_hostname);
1781-
1782-
/* Let the state manager reestablish state */
1783-
if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1784-
nfs41_setup_state_renewal(clp);
17851787
out:
17861788
if (cred)
17871789
put_rpccred(cred);

fs/nfs/nfs4xdr.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,12 +1198,13 @@ static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct c
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,
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

@@ -4359,7 +4360,10 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
43594360

43604361
if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
43614362
return -EIO;
4362-
if (likely(bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD)) {
4363+
if (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;
@@ -4372,6 +4376,7 @@ static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
43724376
__func__);
43734377

43744378
status = decode_first_threshold_item4(xdr, res);
4379+
bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD;
43754380
}
43764381
return status;
43774382
out_overflow:

fs/nfs/pnfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static inline bool
365365
pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src,
366366
struct nfs_server *nfss)
367367
{
368-
return (dst && src && src->bm != 0 &&
368+
return (dst && src && src->bm != 0 && nfss->pnfs_curr_ld &&
369369
nfss->pnfs_curr_ld->id == src->l_type);
370370
}
371371

fs/nfs/proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
651651
/* Emulate the eof flag, which isn't normally needed in NFSv2
652652
* as it is guaranteed to always return the file attributes
653653
*/
654-
if (data->args.offset + data->args.count >= data->res.fattr->size)
654+
if (data->args.offset + data->res.count >= data->res.fattr->size)
655655
data->res.eof = 1;
656656
}
657657
return 0;

fs/nfs/super.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options,
18671867
if (data == NULL)
18681868
goto out_no_data;
18691869

1870+
args->version = NFS_DEFAULT_VERSION;
18701871
switch (data->version) {
18711872
case 1:
18721873
data->namlen = 0;
@@ -2637,6 +2638,8 @@ static int nfs4_validate_mount_data(void *options,
26372638
if (data == NULL)
26382639
goto out_no_data;
26392640

2641+
args->version = 4;
2642+
26402643
switch (data->version) {
26412644
case 1:
26422645
if (data->host_addrlen > sizeof(args->nfs_server.address))

0 commit comments

Comments
 (0)