diff options
author | Alexandros Batsakis <batsakis@netapp.com> | 2009-12-15 00:27:57 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-15 13:58:07 -0500 |
commit | b257957e502a2c467c3c75005215a3f45ecb7f25 (patch) | |
tree | 261271f8f3d6c30a0b6c2eb7f3680a23b93eec6f /fs/nfs/nfs4proc.c | |
parent | 689cf5c15baf603a8041565ff0bd0d65d1634fd7 (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/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 115 |
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 | ||
65 | struct nfs4_opendata; | 65 | struct nfs4_opendata; |
66 | static int _nfs4_proc_open(struct nfs4_opendata *data); | 66 | static int _nfs4_proc_open(struct nfs4_opendata *data); |
67 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | ||
67 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 68 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
68 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 69 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
69 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 70 | static 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 | ||
571 | static 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 | |||
570 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | 577 | static 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 | ||
589 | struct 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 | |||
582 | static int nfs4_call_sync_sequence(struct nfs_client *clp, | 594 | static 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 | ||
1366 | static 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 | |||
1351 | static void nfs4_open_done(struct rpc_task *task, void *calldata) | 1372 | static 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 | /* | 1430 | static 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, |
1412 | static int _nfs4_proc_open(struct nfs4_opendata *data) | 1433 | .rpc_release = nfs4_open_release, |
1434 | }; | ||
1435 | |||
1436 | static 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 | |||
1479 | static 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 | */ | ||
1503 | static 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 | ||
4026 | static 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 | |||
3963 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) | 4032 | static 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 | ||
4087 | static 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 | |||
4018 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) | 4093 | static 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 | ||
4897 | void nfs41_sequence_call_done(struct rpc_task *task, void *data) | 4975 | void 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; |