Skip to content

Commit fe9ea91

Browse files
committed
Merge tag 'nfs-for-3.14-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: - Fix another nfs4_sequence corruptor in RELEASE_LOCKOWNER - Fix an Oopsable delegation callback race - Fix another bad stateid infinite loop - Fail the data server I/O is the stateid represents a lost lock - Fix an Oopsable sunrpc trace event" * tag 'nfs-for-3.14-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: SUNRPC: Fix oops when trace sunrpc_task events in nfs client NFSv4: Fail the truncate() if the lock/open stateid is invalid NFSv4.1 Fail data server I/O if stateid represents a lost lock NFSv4: Fix the return value of nfs4_select_rw_stateid NFSv4: nfs4_stateid_is_current should return 'true' for an invalid stateid NFS: Fix a delegation callback race NFSv4: Fix another nfs4_sequence corruptor
2 parents cf8bf7c + 2ca310f commit fe9ea91

File tree

6 files changed

+37
-31
lines changed

6 files changed

+37
-31
lines changed

fs/nfs/delegation.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,16 +659,19 @@ int nfs_async_inode_return_delegation(struct inode *inode,
659659

660660
rcu_read_lock();
661661
delegation = rcu_dereference(NFS_I(inode)->delegation);
662+
if (delegation == NULL)
663+
goto out_enoent;
662664

663-
if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) {
664-
rcu_read_unlock();
665-
return -ENOENT;
666-
}
665+
if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
666+
goto out_enoent;
667667
nfs_mark_return_delegation(server, delegation);
668668
rcu_read_unlock();
669669

670670
nfs_delegation_run_state_manager(clp);
671671
return 0;
672+
out_enoent:
673+
rcu_read_unlock();
674+
return -ENOENT;
672675
}
673676

674677
static struct inode *

fs/nfs/nfs4filelayout.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,9 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
324324
&rdata->res.seq_res,
325325
task))
326326
return;
327-
nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context,
328-
rdata->args.lock_context, FMODE_READ);
327+
if (nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context,
328+
rdata->args.lock_context, FMODE_READ) == -EIO)
329+
rpc_exit(task, -EIO); /* lost lock, terminate I/O */
329330
}
330331

331332
static void filelayout_read_call_done(struct rpc_task *task, void *data)
@@ -435,8 +436,9 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
435436
&wdata->res.seq_res,
436437
task))
437438
return;
438-
nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context,
439-
wdata->args.lock_context, FMODE_WRITE);
439+
if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context,
440+
wdata->args.lock_context, FMODE_WRITE) == -EIO)
441+
rpc_exit(task, -EIO); /* lost lock, terminate I/O */
440442
}
441443

442444
static void filelayout_write_call_done(struct rpc_task *task, void *data)

fs/nfs/nfs4proc.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,13 +2398,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
23982398

23992399
if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) {
24002400
/* Use that stateid */
2401-
} else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) {
2401+
} else if (truncate && state != NULL) {
24022402
struct nfs_lockowner lockowner = {
24032403
.l_owner = current->files,
24042404
.l_pid = current->tgid,
24052405
};
2406-
nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
2407-
&lockowner);
2406+
if (!nfs4_valid_open_stateid(state))
2407+
return -EBADF;
2408+
if (nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
2409+
&lockowner) == -EIO)
2410+
return -EBADF;
24082411
} else
24092412
nfs4_stateid_copy(&arg.stateid, &zero_stateid);
24102413

@@ -4011,8 +4014,9 @@ static bool nfs4_stateid_is_current(nfs4_stateid *stateid,
40114014
{
40124015
nfs4_stateid current_stateid;
40134016

4014-
if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode))
4015-
return false;
4017+
/* If the current stateid represents a lost lock, then exit */
4018+
if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode) == -EIO)
4019+
return true;
40164020
return nfs4_stateid_match(stateid, &current_stateid);
40174021
}
40184022

@@ -5828,16 +5832,15 @@ struct nfs_release_lockowner_data {
58285832
struct nfs4_lock_state *lsp;
58295833
struct nfs_server *server;
58305834
struct nfs_release_lockowner_args args;
5831-
struct nfs4_sequence_args seq_args;
5832-
struct nfs4_sequence_res seq_res;
5835+
struct nfs_release_lockowner_res res;
58335836
unsigned long timestamp;
58345837
};
58355838

58365839
static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata)
58375840
{
58385841
struct nfs_release_lockowner_data *data = calldata;
58395842
nfs40_setup_sequence(data->server,
5840-
&data->seq_args, &data->seq_res, task);
5843+
&data->args.seq_args, &data->res.seq_res, task);
58415844
data->timestamp = jiffies;
58425845
}
58435846

@@ -5846,7 +5849,7 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
58465849
struct nfs_release_lockowner_data *data = calldata;
58475850
struct nfs_server *server = data->server;
58485851

5849-
nfs40_sequence_done(task, &data->seq_res);
5852+
nfs40_sequence_done(task, &data->res.seq_res);
58505853

58515854
switch (task->tk_status) {
58525855
case 0:
@@ -5887,14 +5890,15 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
58875890
data = kmalloc(sizeof(*data), GFP_NOFS);
58885891
if (!data)
58895892
return -ENOMEM;
5890-
nfs4_init_sequence(&data->seq_args, &data->seq_res, 0);
58915893
data->lsp = lsp;
58925894
data->server = server;
58935895
data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
58945896
data->args.lock_owner.id = lsp->ls_seqid.owner_id;
58955897
data->args.lock_owner.s_dev = server->s_dev;
58965898

58975899
msg.rpc_argp = &data->args;
5900+
msg.rpc_resp = &data->res;
5901+
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
58985902
rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
58995903
return 0;
59005904
}

fs/nfs/nfs4state.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -974,20 +974,16 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst,
974974
else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
975975
nfs4_stateid_copy(dst, &lsp->ls_stateid);
976976
ret = 0;
977-
smp_rmb();
978-
if (!list_empty(&lsp->ls_seqid.list))
979-
ret = -EWOULDBLOCK;
980977
}
981978
spin_unlock(&state->state_lock);
982979
nfs4_put_lock_state(lsp);
983980
out:
984981
return ret;
985982
}
986983

987-
static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
984+
static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
988985
{
989986
const nfs4_stateid *src;
990-
int ret;
991987
int seq;
992988

993989
do {
@@ -996,12 +992,7 @@ static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
996992
if (test_bit(NFS_OPEN_STATE, &state->flags))
997993
src = &state->open_stateid;
998994
nfs4_stateid_copy(dst, src);
999-
ret = 0;
1000-
smp_rmb();
1001-
if (!list_empty(&state->owner->so_seqid.list))
1002-
ret = -EWOULDBLOCK;
1003995
} while (read_seqretry(&state->seqlock, seq));
1004-
return ret;
1005996
}
1006997

1007998
/*
@@ -1026,7 +1017,8 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
10261017
* choose to use.
10271018
*/
10281019
goto out;
1029-
ret = nfs4_copy_open_stateid(dst, state);
1020+
nfs4_copy_open_stateid(dst, state);
1021+
ret = 0;
10301022
out:
10311023
if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41))
10321024
dst->seqid = 0;

include/linux/nfs_xdr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,9 +467,14 @@ struct nfs_lockt_res {
467467
};
468468

469469
struct nfs_release_lockowner_args {
470+
struct nfs4_sequence_args seq_args;
470471
struct nfs_lowner lock_owner;
471472
};
472473

474+
struct nfs_release_lockowner_res {
475+
struct nfs4_sequence_res seq_res;
476+
};
477+
473478
struct nfs4_delegreturnargs {
474479
struct nfs4_sequence_args seq_args;
475480
const struct nfs_fh *fhandle;

include/trace/events/sunrpc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ DECLARE_EVENT_CLASS(rpc_task_running,
8383
),
8484

8585
TP_fast_assign(
86-
__entry->client_id = clnt->cl_clid;
86+
__entry->client_id = clnt ? clnt->cl_clid : -1;
8787
__entry->task_id = task->tk_pid;
8888
__entry->action = action;
8989
__entry->runstate = task->tk_runstate;
9090
__entry->status = task->tk_status;
9191
__entry->flags = task->tk_flags;
9292
),
9393

94-
TP_printk("task:%u@%u flags=%4.4x state=%4.4lx status=%d action=%pf",
94+
TP_printk("task:%u@%d flags=%4.4x state=%4.4lx status=%d action=%pf",
9595
__entry->task_id, __entry->client_id,
9696
__entry->flags,
9797
__entry->runstate,

0 commit comments

Comments
 (0)