aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorAlexandros Batsakis <batsakis@netapp.com>2009-12-15 00:27:57 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-12-15 13:58:07 -0500
commitb257957e502a2c467c3c75005215a3f45ecb7f25 (patch)
tree261271f8f3d6c30a0b6c2eb7f3680a23b93eec6f /fs/nfs
parent689cf5c15baf603a8041565ff0bd0d65d1634fd7 (diff)
nfs: make recovery state manager operations privileged
Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c115
1 files changed, 97 insertions, 18 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 02513da9a016..18cce76867ce 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -64,6 +64,7 @@
64 64
65struct nfs4_opendata; 65struct nfs4_opendata;
66static int _nfs4_proc_open(struct nfs4_opendata *data); 66static int _nfs4_proc_open(struct nfs4_opendata *data);
67static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
67static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); 68static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
68static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); 69static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
69static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); 70static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
@@ -567,6 +568,12 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
567 rpc_call_start(task); 568 rpc_call_start(task);
568} 569}
569 570
571static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata)
572{
573 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
574 nfs41_call_sync_prepare(task, calldata);
575}
576
570static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) 577static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
571{ 578{
572 struct nfs41_call_sync_data *data = calldata; 579 struct nfs41_call_sync_data *data = calldata;
@@ -579,12 +586,18 @@ struct rpc_call_ops nfs41_call_sync_ops = {
579 .rpc_call_done = nfs41_call_sync_done, 586 .rpc_call_done = nfs41_call_sync_done,
580}; 587};
581 588
589struct rpc_call_ops nfs41_call_priv_sync_ops = {
590 .rpc_call_prepare = nfs41_call_priv_sync_prepare,
591 .rpc_call_done = nfs41_call_sync_done,
592};
593
582static int nfs4_call_sync_sequence(struct nfs_client *clp, 594static int nfs4_call_sync_sequence(struct nfs_client *clp,
583 struct rpc_clnt *clnt, 595 struct rpc_clnt *clnt,
584 struct rpc_message *msg, 596 struct rpc_message *msg,
585 struct nfs4_sequence_args *args, 597 struct nfs4_sequence_args *args,
586 struct nfs4_sequence_res *res, 598 struct nfs4_sequence_res *res,
587 int cache_reply) 599 int cache_reply,
600 int privileged)
588{ 601{
589 int ret; 602 int ret;
590 struct rpc_task *task; 603 struct rpc_task *task;
@@ -602,6 +615,8 @@ static int nfs4_call_sync_sequence(struct nfs_client *clp,
602 }; 615 };
603 616
604 res->sr_slotid = NFS4_MAX_SLOT_TABLE; 617 res->sr_slotid = NFS4_MAX_SLOT_TABLE;
618 if (privileged)
619 task_setup.callback_ops = &nfs41_call_priv_sync_ops;
605 task = rpc_run_task(&task_setup); 620 task = rpc_run_task(&task_setup);
606 if (IS_ERR(task)) 621 if (IS_ERR(task))
607 ret = PTR_ERR(task); 622 ret = PTR_ERR(task);
@@ -619,7 +634,7 @@ int _nfs4_call_sync_session(struct nfs_server *server,
619 int cache_reply) 634 int cache_reply)
620{ 635{
621 return nfs4_call_sync_sequence(server->nfs_client, server->client, 636 return nfs4_call_sync_sequence(server->nfs_client, server->client,
622 msg, args, res, cache_reply); 637 msg, args, res, cache_reply, 0);
623} 638}
624 639
625#endif /* CONFIG_NFS_V4_1 */ 640#endif /* CONFIG_NFS_V4_1 */
@@ -1057,7 +1072,7 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod
1057 memset(&opendata->o_res, 0, sizeof(opendata->o_res)); 1072 memset(&opendata->o_res, 0, sizeof(opendata->o_res));
1058 memset(&opendata->c_res, 0, sizeof(opendata->c_res)); 1073 memset(&opendata->c_res, 0, sizeof(opendata->c_res));
1059 nfs4_init_opendata_res(opendata); 1074 nfs4_init_opendata_res(opendata);
1060 ret = _nfs4_proc_open(opendata); 1075 ret = _nfs4_recover_proc_open(opendata);
1061 if (ret != 0) 1076 if (ret != 0)
1062 return ret; 1077 return ret;
1063 newstate = nfs4_opendata_to_nfs4_state(opendata); 1078 newstate = nfs4_opendata_to_nfs4_state(opendata);
@@ -1348,6 +1363,12 @@ out_no_action:
1348 1363
1349} 1364}
1350 1365
1366static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata)
1367{
1368 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
1369 nfs4_open_prepare(task, calldata);
1370}
1371
1351static void nfs4_open_done(struct rpc_task *task, void *calldata) 1372static void nfs4_open_done(struct rpc_task *task, void *calldata)
1352{ 1373{
1353 struct nfs4_opendata *data = calldata; 1374 struct nfs4_opendata *data = calldata;
@@ -1406,10 +1427,13 @@ static const struct rpc_call_ops nfs4_open_ops = {
1406 .rpc_release = nfs4_open_release, 1427 .rpc_release = nfs4_open_release,
1407}; 1428};
1408 1429
1409/* 1430static const struct rpc_call_ops nfs4_recover_open_ops = {
1410 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata 1431 .rpc_call_prepare = nfs4_recover_open_prepare,
1411 */ 1432 .rpc_call_done = nfs4_open_done,
1412static int _nfs4_proc_open(struct nfs4_opendata *data) 1433 .rpc_release = nfs4_open_release,
1434};
1435
1436static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
1413{ 1437{
1414 struct inode *dir = data->dir->d_inode; 1438 struct inode *dir = data->dir->d_inode;
1415 struct nfs_server *server = NFS_SERVER(dir); 1439 struct nfs_server *server = NFS_SERVER(dir);
@@ -1436,16 +1460,55 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
1436 data->rpc_done = 0; 1460 data->rpc_done = 0;
1437 data->rpc_status = 0; 1461 data->rpc_status = 0;
1438 data->cancelled = 0; 1462 data->cancelled = 0;
1463 if (isrecover)
1464 task_setup_data.callback_ops = &nfs4_recover_open_ops;
1439 task = rpc_run_task(&task_setup_data); 1465 task = rpc_run_task(&task_setup_data);
1440 if (IS_ERR(task)) 1466 if (IS_ERR(task))
1441 return PTR_ERR(task); 1467 return PTR_ERR(task);
1442 status = nfs4_wait_for_completion_rpc_task(task); 1468 status = nfs4_wait_for_completion_rpc_task(task);
1443 if (status != 0) { 1469 if (status != 0) {
1444 data->cancelled = 1; 1470 data->cancelled = 1;
1445 smp_wmb(); 1471 smp_wmb();
1446 } else 1472 } else
1447 status = data->rpc_status; 1473 status = data->rpc_status;
1448 rpc_put_task(task); 1474 rpc_put_task(task);
1475
1476 return status;
1477}
1478
1479static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
1480{
1481 struct inode *dir = data->dir->d_inode;
1482 struct nfs_openres *o_res = &data->o_res;
1483 int status;
1484
1485 status = nfs4_run_open_task(data, 1);
1486 if (status != 0 || !data->rpc_done)
1487 return status;
1488
1489 nfs_refresh_inode(dir, o_res->dir_attr);
1490
1491 if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
1492 status = _nfs4_proc_open_confirm(data);
1493 if (status != 0)
1494 return status;
1495 }
1496
1497 return status;
1498}
1499
1500/*
1501 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
1502 */
1503static int _nfs4_proc_open(struct nfs4_opendata *data)
1504{
1505 struct inode *dir = data->dir->d_inode;
1506 struct nfs_server *server = NFS_SERVER(dir);
1507 struct nfs_openargs *o_arg = &data->o_arg;
1508 struct nfs_openres *o_res = &data->o_res;
1509 int status;
1510
1511 status = nfs4_run_open_task(data, 0);
1449 if (status != 0 || !data->rpc_done) 1512 if (status != 0 || !data->rpc_done)
1450 return status; 1513 return status;
1451 1514
@@ -3960,6 +4023,12 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
3960 dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); 4023 dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
3961} 4024}
3962 4025
4026static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
4027{
4028 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
4029 nfs4_lock_prepare(task, calldata);
4030}
4031
3963static void nfs4_lock_done(struct rpc_task *task, void *calldata) 4032static void nfs4_lock_done(struct rpc_task *task, void *calldata)
3964{ 4033{
3965 struct nfs4_lockdata *data = calldata; 4034 struct nfs4_lockdata *data = calldata;
@@ -4015,6 +4084,12 @@ static const struct rpc_call_ops nfs4_lock_ops = {
4015 .rpc_release = nfs4_lock_release, 4084 .rpc_release = nfs4_lock_release,
4016}; 4085};
4017 4086
4087static const struct rpc_call_ops nfs4_recover_lock_ops = {
4088 .rpc_call_prepare = nfs4_recover_lock_prepare,
4089 .rpc_call_done = nfs4_lock_done,
4090 .rpc_release = nfs4_lock_release,
4091};
4092
4018static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) 4093static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
4019{ 4094{
4020 struct nfs4_lockdata *data; 4095 struct nfs4_lockdata *data;
@@ -4039,8 +4114,11 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
4039 return -ENOMEM; 4114 return -ENOMEM;
4040 if (IS_SETLKW(cmd)) 4115 if (IS_SETLKW(cmd))
4041 data->arg.block = 1; 4116 data->arg.block = 1;
4042 if (recovery_type == NFS_LOCK_RECLAIM) 4117 if (recovery_type > NFS_LOCK_NEW) {
4118 if (recovery_type == NFS_LOCK_RECLAIM)
4043 data->arg.reclaim = NFS_LOCK_RECLAIM; 4119 data->arg.reclaim = NFS_LOCK_RECLAIM;
4120 task_setup_data.callback_ops = &nfs4_recover_lock_ops;
4121 }
4044 msg.rpc_argp = &data->arg, 4122 msg.rpc_argp = &data->arg,
4045 msg.rpc_resp = &data->res, 4123 msg.rpc_resp = &data->res,
4046 task_setup_data.callback_data = data; 4124 task_setup_data.callback_data = data;
@@ -4891,7 +4969,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
4891 args.sa_cache_this = 0; 4969 args.sa_cache_this = 0;
4892 4970
4893 return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args, 4971 return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args,
4894 &res, 0); 4972 &res, args.sa_cache_this, 1);
4895} 4973}
4896 4974
4897void nfs41_sequence_call_done(struct rpc_task *task, void *data) 4975void nfs41_sequence_call_done(struct rpc_task *task, void *data)
@@ -4973,6 +5051,7 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
4973{ 5051{
4974 struct nfs4_reclaim_complete_data *calldata = data; 5052 struct nfs4_reclaim_complete_data *calldata = data;
4975 5053
5054 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
4976 if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args, 5055 if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args,
4977 &calldata->res.seq_res, 0, task)) 5056 &calldata->res.seq_res, 0, task))
4978 return; 5057 return;