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

Changed files
+37 -31
fs
include
linux
trace
events
+7 -4
fs/nfs/delegation.c
··· 659 659 660 660 rcu_read_lock(); 661 661 delegation = rcu_dereference(NFS_I(inode)->delegation); 662 + if (delegation == NULL) 663 + goto out_enoent; 662 664 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; 667 667 nfs_mark_return_delegation(server, delegation); 668 668 rcu_read_unlock(); 669 669 670 670 nfs_delegation_run_state_manager(clp); 671 671 return 0; 672 + out_enoent: 673 + rcu_read_unlock(); 674 + return -ENOENT; 672 675 } 673 676 674 677 static struct inode *
+6 -4
fs/nfs/nfs4filelayout.c
··· 324 324 &rdata->res.seq_res, 325 325 task)) 326 326 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 */ 329 330 } 330 331 331 332 static void filelayout_read_call_done(struct rpc_task *task, void *data) ··· 436 435 &wdata->res.seq_res, 437 436 task)) 438 437 return; 439 - nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, 440 - wdata->args.lock_context, FMODE_WRITE); 438 + if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, 439 + wdata->args.lock_context, FMODE_WRITE) == -EIO) 440 + rpc_exit(task, -EIO); /* lost lock, terminate I/O */ 441 441 } 442 442 443 443 static void filelayout_write_call_done(struct rpc_task *task, void *data)
+14 -10
fs/nfs/nfs4proc.c
··· 2398 2398 2399 2399 if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) { 2400 2400 /* Use that stateid */ 2401 - } else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) { 2401 + } else if (truncate && state != NULL) { 2402 2402 struct nfs_lockowner lockowner = { 2403 2403 .l_owner = current->files, 2404 2404 .l_pid = current->tgid, 2405 2405 }; 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; 2408 2411 } else 2409 2412 nfs4_stateid_copy(&arg.stateid, &zero_stateid); 2410 2413 ··· 4014 4011 { 4015 4012 nfs4_stateid current_stateid; 4016 4013 4017 - if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode)) 4018 - return false; 4014 + /* If the current stateid represents a lost lock, then exit */ 4015 + if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode) == -EIO) 4016 + return true; 4019 4017 return nfs4_stateid_match(stateid, &current_stateid); 4020 4018 } 4021 4019 ··· 5832 5828 struct nfs4_lock_state *lsp; 5833 5829 struct nfs_server *server; 5834 5830 struct nfs_release_lockowner_args args; 5835 - struct nfs4_sequence_args seq_args; 5836 - struct nfs4_sequence_res seq_res; 5831 + struct nfs_release_lockowner_res res; 5837 5832 unsigned long timestamp; 5838 5833 }; 5839 5834 ··· 5840 5837 { 5841 5838 struct nfs_release_lockowner_data *data = calldata; 5842 5839 nfs40_setup_sequence(data->server, 5843 - &data->seq_args, &data->seq_res, task); 5840 + &data->args.seq_args, &data->res.seq_res, task); 5844 5841 data->timestamp = jiffies; 5845 5842 } 5846 5843 ··· 5849 5846 struct nfs_release_lockowner_data *data = calldata; 5850 5847 struct nfs_server *server = data->server; 5851 5848 5852 - nfs40_sequence_done(task, &data->seq_res); 5849 + nfs40_sequence_done(task, &data->res.seq_res); 5853 5850 5854 5851 switch (task->tk_status) { 5855 5852 case 0: ··· 5890 5887 data = kmalloc(sizeof(*data), GFP_NOFS); 5891 5888 if (!data) 5892 5889 return -ENOMEM; 5893 - nfs4_init_sequence(&data->seq_args, &data->seq_res, 0); 5894 5890 data->lsp = lsp; 5895 5891 data->server = server; 5896 5892 data->args.lock_owner.clientid = server->nfs_client->cl_clientid; ··· 5897 5895 data->args.lock_owner.s_dev = server->s_dev; 5898 5896 5899 5897 msg.rpc_argp = &data->args; 5898 + msg.rpc_resp = &data->res; 5899 + nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); 5900 5900 rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); 5901 5901 return 0; 5902 5902 }
+3 -11
fs/nfs/nfs4state.c
··· 974 974 else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { 975 975 nfs4_stateid_copy(dst, &lsp->ls_stateid); 976 976 ret = 0; 977 - smp_rmb(); 978 - if (!list_empty(&lsp->ls_seqid.list)) 979 - ret = -EWOULDBLOCK; 980 977 } 981 978 spin_unlock(&state->state_lock); 982 979 nfs4_put_lock_state(lsp); ··· 981 984 return ret; 982 985 } 983 986 984 - static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) 987 + static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) 985 988 { 986 989 const nfs4_stateid *src; 987 - int ret; 988 990 int seq; 989 991 990 992 do { ··· 992 996 if (test_bit(NFS_OPEN_STATE, &state->flags)) 993 997 src = &state->open_stateid; 994 998 nfs4_stateid_copy(dst, src); 995 - ret = 0; 996 - smp_rmb(); 997 - if (!list_empty(&state->owner->so_seqid.list)) 998 - ret = -EWOULDBLOCK; 999 999 } while (read_seqretry(&state->seqlock, seq)); 1000 - return ret; 1001 1000 } 1002 1001 1003 1002 /* ··· 1017 1026 * choose to use. 1018 1027 */ 1019 1028 goto out; 1020 - ret = nfs4_copy_open_stateid(dst, state); 1029 + nfs4_copy_open_stateid(dst, state); 1030 + ret = 0; 1021 1031 out: 1022 1032 if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) 1023 1033 dst->seqid = 0;
+5
include/linux/nfs_xdr.h
··· 467 467 }; 468 468 469 469 struct nfs_release_lockowner_args { 470 + struct nfs4_sequence_args seq_args; 470 471 struct nfs_lowner lock_owner; 472 + }; 473 + 474 + struct nfs_release_lockowner_res { 475 + struct nfs4_sequence_res seq_res; 471 476 }; 472 477 473 478 struct nfs4_delegreturnargs {
+2 -2
include/trace/events/sunrpc.h
··· 83 83 ), 84 84 85 85 TP_fast_assign( 86 - __entry->client_id = clnt->cl_clid; 86 + __entry->client_id = clnt ? clnt->cl_clid : -1; 87 87 __entry->task_id = task->tk_pid; 88 88 __entry->action = action; 89 89 __entry->runstate = task->tk_runstate; ··· 91 91 __entry->flags = task->tk_flags; 92 92 ), 93 93 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", 95 95 __entry->task_id, __entry->client_id, 96 96 __entry->flags, 97 97 __entry->runstate,