aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c114
-rw-r--r--include/linux/nfs_xdr.h3
2 files changed, 44 insertions, 73 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4b1635ce658d..38a709d78594 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -490,11 +490,17 @@ static void nfs41_init_sequence(struct nfs4_sequence_args *args,
490{ 490{
491 args->sa_slot = NULL; 491 args->sa_slot = NULL;
492 args->sa_cache_this = 0; 492 args->sa_cache_this = 0;
493 args->sa_privileged = 0;
493 if (cache_reply) 494 if (cache_reply)
494 args->sa_cache_this = 1; 495 args->sa_cache_this = 1;
495 res->sr_slot = NULL; 496 res->sr_slot = NULL;
496} 497}
497 498
499static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
500{
501 args->sa_privileged = 1;
502}
503
498int nfs41_setup_sequence(struct nfs4_session *session, 504int nfs41_setup_sequence(struct nfs4_session *session,
499 struct nfs4_sequence_args *args, 505 struct nfs4_sequence_args *args,
500 struct nfs4_sequence_res *res, 506 struct nfs4_sequence_res *res,
@@ -514,7 +520,7 @@ int nfs41_setup_sequence(struct nfs4_session *session,
514 520
515 spin_lock(&tbl->slot_tbl_lock); 521 spin_lock(&tbl->slot_tbl_lock);
516 if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && 522 if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) &&
517 !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { 523 !args->sa_privileged) {
518 /* The state manager will wait until the slot table is empty */ 524 /* The state manager will wait until the slot table is empty */
519 dprintk("%s session is draining\n", __func__); 525 dprintk("%s session is draining\n", __func__);
520 goto out_sleep; 526 goto out_sleep;
@@ -548,6 +554,9 @@ out_success:
548 rpc_call_start(task); 554 rpc_call_start(task);
549 return 0; 555 return 0;
550out_sleep: 556out_sleep:
557 /* Privileged tasks are queued with top priority */
558 if (args->sa_privileged)
559 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
551 rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); 560 rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
552 spin_unlock(&tbl->slot_tbl_lock); 561 spin_unlock(&tbl->slot_tbl_lock);
553 return -EAGAIN; 562 return -EAGAIN;
@@ -593,12 +602,6 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
593 nfs41_setup_sequence(session, data->seq_args, data->seq_res, task); 602 nfs41_setup_sequence(session, data->seq_args, data->seq_res, task);
594} 603}
595 604
596static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata)
597{
598 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
599 nfs41_call_sync_prepare(task, calldata);
600}
601
602static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) 605static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
603{ 606{
604 struct nfs41_call_sync_data *data = calldata; 607 struct nfs41_call_sync_data *data = calldata;
@@ -611,17 +614,11 @@ static const struct rpc_call_ops nfs41_call_sync_ops = {
611 .rpc_call_done = nfs41_call_sync_done, 614 .rpc_call_done = nfs41_call_sync_done,
612}; 615};
613 616
614static const struct rpc_call_ops nfs41_call_priv_sync_ops = {
615 .rpc_call_prepare = nfs41_call_priv_sync_prepare,
616 .rpc_call_done = nfs41_call_sync_done,
617};
618
619static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, 617static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
620 struct nfs_server *server, 618 struct nfs_server *server,
621 struct rpc_message *msg, 619 struct rpc_message *msg,
622 struct nfs4_sequence_args *args, 620 struct nfs4_sequence_args *args,
623 struct nfs4_sequence_res *res, 621 struct nfs4_sequence_res *res)
624 int privileged)
625{ 622{
626 int ret; 623 int ret;
627 struct rpc_task *task; 624 struct rpc_task *task;
@@ -637,8 +634,6 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
637 .callback_data = &data 634 .callback_data = &data
638 }; 635 };
639 636
640 if (privileged)
641 task_setup.callback_ops = &nfs41_call_priv_sync_ops;
642 task = rpc_run_task(&task_setup); 637 task = rpc_run_task(&task_setup);
643 if (IS_ERR(task)) 638 if (IS_ERR(task))
644 ret = PTR_ERR(task); 639 ret = PTR_ERR(task);
@@ -656,16 +651,21 @@ int _nfs4_call_sync_session(struct rpc_clnt *clnt,
656 struct nfs4_sequence_args *args, 651 struct nfs4_sequence_args *args,
657 struct nfs4_sequence_res *res) 652 struct nfs4_sequence_res *res)
658{ 653{
659 return nfs4_call_sync_sequence(clnt, server, msg, args, res, 0); 654 return nfs4_call_sync_sequence(clnt, server, msg, args, res);
660} 655}
661 656
662#else 657#else
663static inline 658static
664void nfs41_init_sequence(struct nfs4_sequence_args *args, 659void nfs41_init_sequence(struct nfs4_sequence_args *args,
665 struct nfs4_sequence_res *res, int cache_reply) 660 struct nfs4_sequence_res *res, int cache_reply)
666{ 661{
667} 662}
668 663
664static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
665{
666}
667
668
669static int nfs4_sequence_done(struct rpc_task *task, 669static int nfs4_sequence_done(struct rpc_task *task,
670 struct nfs4_sequence_res *res) 670 struct nfs4_sequence_res *res)
671{ 671{
@@ -1475,13 +1475,6 @@ unlock_no_action:
1475 rcu_read_unlock(); 1475 rcu_read_unlock();
1476out_no_action: 1476out_no_action:
1477 task->tk_action = NULL; 1477 task->tk_action = NULL;
1478
1479}
1480
1481static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata)
1482{
1483 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
1484 nfs4_open_prepare(task, calldata);
1485} 1478}
1486 1479
1487static void nfs4_open_done(struct rpc_task *task, void *calldata) 1480static void nfs4_open_done(struct rpc_task *task, void *calldata)
@@ -1542,12 +1535,6 @@ static const struct rpc_call_ops nfs4_open_ops = {
1542 .rpc_release = nfs4_open_release, 1535 .rpc_release = nfs4_open_release,
1543}; 1536};
1544 1537
1545static const struct rpc_call_ops nfs4_recover_open_ops = {
1546 .rpc_call_prepare = nfs4_recover_open_prepare,
1547 .rpc_call_done = nfs4_open_done,
1548 .rpc_release = nfs4_open_release,
1549};
1550
1551static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) 1538static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
1552{ 1539{
1553 struct inode *dir = data->dir->d_inode; 1540 struct inode *dir = data->dir->d_inode;
@@ -1577,7 +1564,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
1577 data->rpc_status = 0; 1564 data->rpc_status = 0;
1578 data->cancelled = 0; 1565 data->cancelled = 0;
1579 if (isrecover) 1566 if (isrecover)
1580 task_setup_data.callback_ops = &nfs4_recover_open_ops; 1567 nfs4_set_sequence_privileged(&o_arg->seq_args);
1581 task = rpc_run_task(&task_setup_data); 1568 task = rpc_run_task(&task_setup_data);
1582 if (IS_ERR(task)) 1569 if (IS_ERR(task))
1583 return PTR_ERR(task); 1570 return PTR_ERR(task);
@@ -4558,8 +4545,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
4558 return; 4545 return;
4559 /* Do we need to do an open_to_lock_owner? */ 4546 /* Do we need to do an open_to_lock_owner? */
4560 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { 4547 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
4561 if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) 4548 if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
4562 goto out_release_lock_seqid; 4549 goto out_release_lock_seqid;
4550 }
4563 data->arg.open_stateid = &state->stateid; 4551 data->arg.open_stateid = &state->stateid;
4564 data->arg.new_lock_owner = 1; 4552 data->arg.new_lock_owner = 1;
4565 data->res.open_seqid = data->arg.open_seqid; 4553 data->res.open_seqid = data->arg.open_seqid;
@@ -4574,13 +4562,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
4574 nfs_release_seqid(data->arg.open_seqid); 4562 nfs_release_seqid(data->arg.open_seqid);
4575out_release_lock_seqid: 4563out_release_lock_seqid:
4576 nfs_release_seqid(data->arg.lock_seqid); 4564 nfs_release_seqid(data->arg.lock_seqid);
4577 dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); 4565 dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
4578}
4579
4580static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
4581{
4582 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
4583 nfs4_lock_prepare(task, calldata);
4584} 4566}
4585 4567
4586static void nfs4_lock_done(struct rpc_task *task, void *calldata) 4568static void nfs4_lock_done(struct rpc_task *task, void *calldata)
@@ -4635,12 +4617,6 @@ static const struct rpc_call_ops nfs4_lock_ops = {
4635 .rpc_release = nfs4_lock_release, 4617 .rpc_release = nfs4_lock_release,
4636}; 4618};
4637 4619
4638static const struct rpc_call_ops nfs4_recover_lock_ops = {
4639 .rpc_call_prepare = nfs4_recover_lock_prepare,
4640 .rpc_call_done = nfs4_lock_done,
4641 .rpc_release = nfs4_lock_release,
4642};
4643
4644static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) 4620static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
4645{ 4621{
4646 switch (error) { 4622 switch (error) {
@@ -4683,15 +4659,15 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
4683 return -ENOMEM; 4659 return -ENOMEM;
4684 if (IS_SETLKW(cmd)) 4660 if (IS_SETLKW(cmd))
4685 data->arg.block = 1; 4661 data->arg.block = 1;
4686 if (recovery_type > NFS_LOCK_NEW) {
4687 if (recovery_type == NFS_LOCK_RECLAIM)
4688 data->arg.reclaim = NFS_LOCK_RECLAIM;
4689 task_setup_data.callback_ops = &nfs4_recover_lock_ops;
4690 }
4691 nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1); 4662 nfs41_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
4692 msg.rpc_argp = &data->arg; 4663 msg.rpc_argp = &data->arg;
4693 msg.rpc_resp = &data->res; 4664 msg.rpc_resp = &data->res;
4694 task_setup_data.callback_data = data; 4665 task_setup_data.callback_data = data;
4666 if (recovery_type > NFS_LOCK_NEW) {
4667 if (recovery_type == NFS_LOCK_RECLAIM)
4668 data->arg.reclaim = NFS_LOCK_RECLAIM;
4669 nfs4_set_sequence_privileged(&data->arg.seq_args);
4670 }
4695 task = rpc_run_task(&task_setup_data); 4671 task = rpc_run_task(&task_setup_data);
4696 if (IS_ERR(task)) 4672 if (IS_ERR(task))
4697 return PTR_ERR(task); 4673 return PTR_ERR(task);
@@ -5432,7 +5408,6 @@ static void nfs4_get_lease_time_prepare(struct rpc_task *task,
5432 (struct nfs4_get_lease_time_data *)calldata; 5408 (struct nfs4_get_lease_time_data *)calldata;
5433 5409
5434 dprintk("--> %s\n", __func__); 5410 dprintk("--> %s\n", __func__);
5435 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
5436 /* just setup sequence, do not trigger session recovery 5411 /* just setup sequence, do not trigger session recovery
5437 since we're invoked within one */ 5412 since we're invoked within one */
5438 nfs41_setup_sequence(data->clp->cl_session, 5413 nfs41_setup_sequence(data->clp->cl_session,
@@ -5500,6 +5475,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
5500 int status; 5475 int status;
5501 5476
5502 nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0); 5477 nfs41_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
5478 nfs4_set_sequence_privileged(&args.la_seq_args);
5503 dprintk("--> %s\n", __func__); 5479 dprintk("--> %s\n", __func__);
5504 task = rpc_run_task(&task_setup); 5480 task = rpc_run_task(&task_setup);
5505 5481
@@ -5775,26 +5751,15 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
5775 nfs41_setup_sequence(clp->cl_session, args, res, task); 5751 nfs41_setup_sequence(clp->cl_session, args, res, task);
5776} 5752}
5777 5753
5778static void nfs41_sequence_prepare_privileged(struct rpc_task *task, void *data)
5779{
5780 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
5781 nfs41_sequence_prepare(task, data);
5782}
5783
5784static const struct rpc_call_ops nfs41_sequence_ops = { 5754static const struct rpc_call_ops nfs41_sequence_ops = {
5785 .rpc_call_done = nfs41_sequence_call_done, 5755 .rpc_call_done = nfs41_sequence_call_done,
5786 .rpc_call_prepare = nfs41_sequence_prepare, 5756 .rpc_call_prepare = nfs41_sequence_prepare,
5787 .rpc_release = nfs41_sequence_release, 5757 .rpc_release = nfs41_sequence_release,
5788}; 5758};
5789 5759
5790static const struct rpc_call_ops nfs41_sequence_privileged_ops = { 5760static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
5791 .rpc_call_done = nfs41_sequence_call_done, 5761 struct rpc_cred *cred,
5792 .rpc_call_prepare = nfs41_sequence_prepare_privileged, 5762 bool is_privileged)
5793 .rpc_release = nfs41_sequence_release,
5794};
5795
5796static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred,
5797 const struct rpc_call_ops *seq_ops)
5798{ 5763{
5799 struct nfs4_sequence_data *calldata; 5764 struct nfs4_sequence_data *calldata;
5800 struct rpc_message msg = { 5765 struct rpc_message msg = {
@@ -5804,7 +5769,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
5804 struct rpc_task_setup task_setup_data = { 5769 struct rpc_task_setup task_setup_data = {
5805 .rpc_client = clp->cl_rpcclient, 5770 .rpc_client = clp->cl_rpcclient,
5806 .rpc_message = &msg, 5771 .rpc_message = &msg,
5807 .callback_ops = seq_ops, 5772 .callback_ops = &nfs41_sequence_ops,
5808 .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT, 5773 .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT,
5809 }; 5774 };
5810 5775
@@ -5816,6 +5781,8 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
5816 return ERR_PTR(-ENOMEM); 5781 return ERR_PTR(-ENOMEM);
5817 } 5782 }
5818 nfs41_init_sequence(&calldata->args, &calldata->res, 0); 5783 nfs41_init_sequence(&calldata->args, &calldata->res, 0);
5784 if (is_privileged)
5785 nfs4_set_sequence_privileged(&calldata->args);
5819 msg.rpc_argp = &calldata->args; 5786 msg.rpc_argp = &calldata->args;
5820 msg.rpc_resp = &calldata->res; 5787 msg.rpc_resp = &calldata->res;
5821 calldata->clp = clp; 5788 calldata->clp = clp;
@@ -5831,7 +5798,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr
5831 5798
5832 if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) 5799 if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
5833 return 0; 5800 return 0;
5834 task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_ops); 5801 task = _nfs41_proc_sequence(clp, cred, false);
5835 if (IS_ERR(task)) 5802 if (IS_ERR(task))
5836 ret = PTR_ERR(task); 5803 ret = PTR_ERR(task);
5837 else 5804 else
@@ -5845,7 +5812,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
5845 struct rpc_task *task; 5812 struct rpc_task *task;
5846 int ret; 5813 int ret;
5847 5814
5848 task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_privileged_ops); 5815 task = _nfs41_proc_sequence(clp, cred, true);
5849 if (IS_ERR(task)) { 5816 if (IS_ERR(task)) {
5850 ret = PTR_ERR(task); 5817 ret = PTR_ERR(task);
5851 goto out; 5818 goto out;
@@ -5874,7 +5841,6 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
5874{ 5841{
5875 struct nfs4_reclaim_complete_data *calldata = data; 5842 struct nfs4_reclaim_complete_data *calldata = data;
5876 5843
5877 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
5878 nfs41_setup_sequence(calldata->clp->cl_session, 5844 nfs41_setup_sequence(calldata->clp->cl_session,
5879 &calldata->arg.seq_args, 5845 &calldata->arg.seq_args,
5880 &calldata->res.seq_res, 5846 &calldata->res.seq_res,
@@ -5955,6 +5921,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
5955 calldata->arg.one_fs = 0; 5921 calldata->arg.one_fs = 0;
5956 5922
5957 nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0); 5923 nfs41_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
5924 nfs4_set_sequence_privileged(&calldata->arg.seq_args);
5958 msg.rpc_argp = &calldata->arg; 5925 msg.rpc_argp = &calldata->arg;
5959 msg.rpc_resp = &calldata->res; 5926 msg.rpc_resp = &calldata->res;
5960 task_setup_data.callback_data = calldata; 5927 task_setup_data.callback_data = calldata;
@@ -6521,7 +6488,9 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid)
6521 6488
6522 dprintk("NFS call test_stateid %p\n", stateid); 6489 dprintk("NFS call test_stateid %p\n", stateid);
6523 nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); 6490 nfs41_init_sequence(&args.seq_args, &res.seq_res, 0);
6524 status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); 6491 nfs4_set_sequence_privileged(&args.seq_args);
6492 status = nfs4_call_sync_sequence(server->client, server, &msg,
6493 &args.seq_args, &res.seq_res);
6525 if (status != NFS_OK) { 6494 if (status != NFS_OK) {
6526 dprintk("NFS reply test_stateid: failed, %d\n", status); 6495 dprintk("NFS reply test_stateid: failed, %d\n", status);
6527 return status; 6496 return status;
@@ -6568,8 +6537,9 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid)
6568 6537
6569 dprintk("NFS call free_stateid %p\n", stateid); 6538 dprintk("NFS call free_stateid %p\n", stateid);
6570 nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); 6539 nfs41_init_sequence(&args.seq_args, &res.seq_res, 0);
6540 nfs4_set_sequence_privileged(&args.seq_args);
6571 status = nfs4_call_sync_sequence(server->client, server, &msg, 6541 status = nfs4_call_sync_sequence(server->client, server, &msg,
6572 &args.seq_args, &res.seq_res, 1); 6542 &args.seq_args, &res.seq_res);
6573 dprintk("NFS reply free_stateid: %d\n", status); 6543 dprintk("NFS reply free_stateid: %d\n", status);
6574 return status; 6544 return status;
6575} 6545}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 2076149db1a4..baa673edb597 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -188,7 +188,8 @@ struct nfs4_channel_attrs {
188struct nfs4_slot; 188struct nfs4_slot;
189struct nfs4_sequence_args { 189struct nfs4_sequence_args {
190 struct nfs4_slot *sa_slot; 190 struct nfs4_slot *sa_slot;
191 u8 sa_cache_this; 191 u8 sa_cache_this : 1,
192 sa_privileged : 1;
192}; 193};
193 194
194struct nfs4_sequence_res { 195struct nfs4_sequence_res {