diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 13:47:44 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 13:47:44 -0500 |
| commit | e4bdda1bc3123a9e65f4dd93a23041fde8ed3dc2 (patch) | |
| tree | c2f75cc08bb4c5cbd9103e14399ea5ab66ce960d | |
| parent | 74f3ae743427b87e43b5cb9f4257021ae8ad4267 (diff) | |
| parent | 380454126f1357db9270f9d1ca05dfe1a6e4ad47 (diff) | |
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
NFSv4: Fix a regression in the NFSv4 state manager
NFSv4: Release the sequence id before restarting a CLOSE rpc call
nfs41: fix session fore channel negotiation
nfs41: do not zero seqid portion of stateid on close
nfs: run state manager in privileged mode
nfs: make recovery state manager operations privileged
nfs: enforce FIFO ordering of operations trying to acquire slot
rpc: add a new priority in RPC task
nfs: remove rpc_task argument from nfs4_find_slot
rpc: add rpc_queue_empty function
nfs: change nfs4_do_setlk params to identify recovery type
nfs: do not do a LOOKUP after open
nfs: minor cleanup of session draining
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 5 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 203 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 60 | ||||
| -rw-r--r-- | include/linux/sunrpc/sched.h | 14 | ||||
| -rw-r--r-- | net/sunrpc/sched.c | 15 |
5 files changed, 223 insertions, 74 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 7e57b04e4014..865265bdca03 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -108,6 +108,10 @@ enum { | |||
| 108 | NFS_OWNER_RECLAIM_NOGRACE | 108 | NFS_OWNER_RECLAIM_NOGRACE |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | #define NFS_LOCK_NEW 0 | ||
| 112 | #define NFS_LOCK_RECLAIM 1 | ||
| 113 | #define NFS_LOCK_EXPIRED 2 | ||
| 114 | |||
| 111 | /* | 115 | /* |
| 112 | * struct nfs4_state maintains the client-side state for a given | 116 | * struct nfs4_state maintains the client-side state for a given |
| 113 | * (state_owner,inode) tuple (OPEN) or state_owner (LOCK). | 117 | * (state_owner,inode) tuple (OPEN) or state_owner (LOCK). |
| @@ -282,6 +286,7 @@ extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter); | |||
| 282 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | 286 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); |
| 283 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); | 287 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); |
| 284 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); | 288 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); |
| 289 | extern void nfs_release_seqid(struct nfs_seqid *seqid); | ||
| 285 | extern void nfs_free_seqid(struct nfs_seqid *seqid); | 290 | extern void nfs_free_seqid(struct nfs_seqid *seqid); |
| 286 | 291 | ||
| 287 | extern const nfs4_stateid zero_stateid; | 292 | extern const nfs4_stateid zero_stateid; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9f5f11ecfd93..198d51d17c13 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); |
| @@ -341,6 +342,27 @@ nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid) | |||
| 341 | free_slotid, tbl->highest_used_slotid); | 342 | free_slotid, tbl->highest_used_slotid); |
| 342 | } | 343 | } |
| 343 | 344 | ||
| 345 | /* | ||
| 346 | * Signal state manager thread if session is drained | ||
| 347 | */ | ||
| 348 | static void nfs41_check_drain_session_complete(struct nfs4_session *ses) | ||
| 349 | { | ||
| 350 | struct rpc_task *task; | ||
| 351 | |||
| 352 | if (!test_bit(NFS4CLNT_SESSION_DRAINING, &ses->clp->cl_state)) { | ||
| 353 | task = rpc_wake_up_next(&ses->fc_slot_table.slot_tbl_waitq); | ||
| 354 | if (task) | ||
| 355 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 356 | return; | ||
| 357 | } | ||
| 358 | |||
| 359 | if (ses->fc_slot_table.highest_used_slotid != -1) | ||
| 360 | return; | ||
| 361 | |||
| 362 | dprintk("%s COMPLETE: Session Drained\n", __func__); | ||
| 363 | complete(&ses->complete); | ||
| 364 | } | ||
| 365 | |||
| 344 | static void nfs41_sequence_free_slot(const struct nfs_client *clp, | 366 | static void nfs41_sequence_free_slot(const struct nfs_client *clp, |
| 345 | struct nfs4_sequence_res *res) | 367 | struct nfs4_sequence_res *res) |
| 346 | { | 368 | { |
| @@ -356,15 +378,7 @@ static void nfs41_sequence_free_slot(const struct nfs_client *clp, | |||
| 356 | 378 | ||
| 357 | spin_lock(&tbl->slot_tbl_lock); | 379 | spin_lock(&tbl->slot_tbl_lock); |
| 358 | nfs4_free_slot(tbl, res->sr_slotid); | 380 | nfs4_free_slot(tbl, res->sr_slotid); |
| 359 | 381 | nfs41_check_drain_session_complete(clp->cl_session); | |
| 360 | /* Signal state manager thread if session is drained */ | ||
| 361 | if (test_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) { | ||
| 362 | if (tbl->highest_used_slotid == -1) { | ||
| 363 | dprintk("%s COMPLETE: Session Drained\n", __func__); | ||
| 364 | complete(&clp->cl_session->complete); | ||
| 365 | } | ||
| 366 | } else | ||
| 367 | rpc_wake_up_next(&tbl->slot_tbl_waitq); | ||
| 368 | spin_unlock(&tbl->slot_tbl_lock); | 382 | spin_unlock(&tbl->slot_tbl_lock); |
| 369 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 383 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; |
| 370 | } | 384 | } |
| @@ -421,7 +435,7 @@ out: | |||
| 421 | * Note: must be called with under the slot_tbl_lock. | 435 | * Note: must be called with under the slot_tbl_lock. |
| 422 | */ | 436 | */ |
| 423 | static u8 | 437 | static u8 |
| 424 | nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task) | 438 | nfs4_find_slot(struct nfs4_slot_table *tbl) |
| 425 | { | 439 | { |
| 426 | int slotid; | 440 | int slotid; |
| 427 | u8 ret_id = NFS4_MAX_SLOT_TABLE; | 441 | u8 ret_id = NFS4_MAX_SLOT_TABLE; |
| @@ -463,7 +477,8 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
| 463 | tbl = &session->fc_slot_table; | 477 | tbl = &session->fc_slot_table; |
| 464 | 478 | ||
| 465 | spin_lock(&tbl->slot_tbl_lock); | 479 | spin_lock(&tbl->slot_tbl_lock); |
| 466 | if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state)) { | 480 | if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state) && |
| 481 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | ||
| 467 | /* | 482 | /* |
| 468 | * The state manager will wait until the slot table is empty. | 483 | * The state manager will wait until the slot table is empty. |
| 469 | * Schedule the reset thread | 484 | * Schedule the reset thread |
| @@ -474,7 +489,15 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
| 474 | return -EAGAIN; | 489 | return -EAGAIN; |
| 475 | } | 490 | } |
| 476 | 491 | ||
| 477 | slotid = nfs4_find_slot(tbl, task); | 492 | if (!rpc_queue_empty(&tbl->slot_tbl_waitq) && |
| 493 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | ||
| 494 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | ||
| 495 | spin_unlock(&tbl->slot_tbl_lock); | ||
| 496 | dprintk("%s enforce FIFO order\n", __func__); | ||
| 497 | return -EAGAIN; | ||
| 498 | } | ||
| 499 | |||
| 500 | slotid = nfs4_find_slot(tbl); | ||
| 478 | if (slotid == NFS4_MAX_SLOT_TABLE) { | 501 | if (slotid == NFS4_MAX_SLOT_TABLE) { |
| 479 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); | 502 | rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL); |
| 480 | spin_unlock(&tbl->slot_tbl_lock); | 503 | spin_unlock(&tbl->slot_tbl_lock); |
| @@ -483,6 +506,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
| 483 | } | 506 | } |
| 484 | spin_unlock(&tbl->slot_tbl_lock); | 507 | spin_unlock(&tbl->slot_tbl_lock); |
| 485 | 508 | ||
| 509 | rpc_task_set_priority(task, RPC_PRIORITY_NORMAL); | ||
| 486 | slot = tbl->slots + slotid; | 510 | slot = tbl->slots + slotid; |
| 487 | args->sa_session = session; | 511 | args->sa_session = session; |
| 488 | args->sa_slotid = slotid; | 512 | args->sa_slotid = slotid; |
| @@ -545,6 +569,12 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | |||
| 545 | rpc_call_start(task); | 569 | rpc_call_start(task); |
| 546 | } | 570 | } |
| 547 | 571 | ||
| 572 | static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata) | ||
| 573 | { | ||
| 574 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 575 | nfs41_call_sync_prepare(task, calldata); | ||
| 576 | } | ||
| 577 | |||
| 548 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | 578 | static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) |
| 549 | { | 579 | { |
| 550 | struct nfs41_call_sync_data *data = calldata; | 580 | struct nfs41_call_sync_data *data = calldata; |
| @@ -557,12 +587,18 @@ struct rpc_call_ops nfs41_call_sync_ops = { | |||
| 557 | .rpc_call_done = nfs41_call_sync_done, | 587 | .rpc_call_done = nfs41_call_sync_done, |
| 558 | }; | 588 | }; |
| 559 | 589 | ||
| 590 | struct rpc_call_ops nfs41_call_priv_sync_ops = { | ||
| 591 | .rpc_call_prepare = nfs41_call_priv_sync_prepare, | ||
| 592 | .rpc_call_done = nfs41_call_sync_done, | ||
| 593 | }; | ||
| 594 | |||
| 560 | static int nfs4_call_sync_sequence(struct nfs_client *clp, | 595 | static int nfs4_call_sync_sequence(struct nfs_client *clp, |
| 561 | struct rpc_clnt *clnt, | 596 | struct rpc_clnt *clnt, |
| 562 | struct rpc_message *msg, | 597 | struct rpc_message *msg, |
| 563 | struct nfs4_sequence_args *args, | 598 | struct nfs4_sequence_args *args, |
| 564 | struct nfs4_sequence_res *res, | 599 | struct nfs4_sequence_res *res, |
| 565 | int cache_reply) | 600 | int cache_reply, |
| 601 | int privileged) | ||
| 566 | { | 602 | { |
| 567 | int ret; | 603 | int ret; |
| 568 | struct rpc_task *task; | 604 | struct rpc_task *task; |
| @@ -580,6 +616,8 @@ static int nfs4_call_sync_sequence(struct nfs_client *clp, | |||
| 580 | }; | 616 | }; |
| 581 | 617 | ||
| 582 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 618 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; |
| 619 | if (privileged) | ||
| 620 | task_setup.callback_ops = &nfs41_call_priv_sync_ops; | ||
| 583 | task = rpc_run_task(&task_setup); | 621 | task = rpc_run_task(&task_setup); |
| 584 | if (IS_ERR(task)) | 622 | if (IS_ERR(task)) |
| 585 | ret = PTR_ERR(task); | 623 | ret = PTR_ERR(task); |
| @@ -597,7 +635,7 @@ int _nfs4_call_sync_session(struct nfs_server *server, | |||
| 597 | int cache_reply) | 635 | int cache_reply) |
| 598 | { | 636 | { |
| 599 | return nfs4_call_sync_sequence(server->nfs_client, server->client, | 637 | return nfs4_call_sync_sequence(server->nfs_client, server->client, |
| 600 | msg, args, res, cache_reply); | 638 | msg, args, res, cache_reply, 0); |
| 601 | } | 639 | } |
| 602 | 640 | ||
| 603 | #endif /* CONFIG_NFS_V4_1 */ | 641 | #endif /* CONFIG_NFS_V4_1 */ |
| @@ -1035,7 +1073,7 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod | |||
| 1035 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); | 1073 | memset(&opendata->o_res, 0, sizeof(opendata->o_res)); |
| 1036 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); | 1074 | memset(&opendata->c_res, 0, sizeof(opendata->c_res)); |
| 1037 | nfs4_init_opendata_res(opendata); | 1075 | nfs4_init_opendata_res(opendata); |
| 1038 | ret = _nfs4_proc_open(opendata); | 1076 | ret = _nfs4_recover_proc_open(opendata); |
| 1039 | if (ret != 0) | 1077 | if (ret != 0) |
| 1040 | return ret; | 1078 | return ret; |
| 1041 | newstate = nfs4_opendata_to_nfs4_state(opendata); | 1079 | newstate = nfs4_opendata_to_nfs4_state(opendata); |
| @@ -1326,6 +1364,12 @@ out_no_action: | |||
| 1326 | 1364 | ||
| 1327 | } | 1365 | } |
| 1328 | 1366 | ||
| 1367 | static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata) | ||
| 1368 | { | ||
| 1369 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 1370 | nfs4_open_prepare(task, calldata); | ||
| 1371 | } | ||
| 1372 | |||
| 1329 | static void nfs4_open_done(struct rpc_task *task, void *calldata) | 1373 | static void nfs4_open_done(struct rpc_task *task, void *calldata) |
| 1330 | { | 1374 | { |
| 1331 | struct nfs4_opendata *data = calldata; | 1375 | struct nfs4_opendata *data = calldata; |
| @@ -1384,10 +1428,13 @@ static const struct rpc_call_ops nfs4_open_ops = { | |||
| 1384 | .rpc_release = nfs4_open_release, | 1428 | .rpc_release = nfs4_open_release, |
| 1385 | }; | 1429 | }; |
| 1386 | 1430 | ||
| 1387 | /* | 1431 | static const struct rpc_call_ops nfs4_recover_open_ops = { |
| 1388 | * Note: On error, nfs4_proc_open will free the struct nfs4_opendata | 1432 | .rpc_call_prepare = nfs4_recover_open_prepare, |
| 1389 | */ | 1433 | .rpc_call_done = nfs4_open_done, |
| 1390 | static int _nfs4_proc_open(struct nfs4_opendata *data) | 1434 | .rpc_release = nfs4_open_release, |
| 1435 | }; | ||
| 1436 | |||
| 1437 | static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover) | ||
| 1391 | { | 1438 | { |
| 1392 | struct inode *dir = data->dir->d_inode; | 1439 | struct inode *dir = data->dir->d_inode; |
| 1393 | struct nfs_server *server = NFS_SERVER(dir); | 1440 | struct nfs_server *server = NFS_SERVER(dir); |
| @@ -1414,21 +1461,57 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 1414 | data->rpc_done = 0; | 1461 | data->rpc_done = 0; |
| 1415 | data->rpc_status = 0; | 1462 | data->rpc_status = 0; |
| 1416 | data->cancelled = 0; | 1463 | data->cancelled = 0; |
| 1464 | if (isrecover) | ||
| 1465 | task_setup_data.callback_ops = &nfs4_recover_open_ops; | ||
| 1417 | task = rpc_run_task(&task_setup_data); | 1466 | task = rpc_run_task(&task_setup_data); |
| 1418 | if (IS_ERR(task)) | 1467 | if (IS_ERR(task)) |
| 1419 | return PTR_ERR(task); | 1468 | return PTR_ERR(task); |
| 1420 | status = nfs4_wait_for_completion_rpc_task(task); | 1469 | status = nfs4_wait_for_completion_rpc_task(task); |
| 1421 | if (status != 0) { | 1470 | if (status != 0) { |
| 1422 | data->cancelled = 1; | 1471 | data->cancelled = 1; |
| 1423 | smp_wmb(); | 1472 | smp_wmb(); |
| 1424 | } else | 1473 | } else |
| 1425 | status = data->rpc_status; | 1474 | status = data->rpc_status; |
| 1426 | rpc_put_task(task); | 1475 | rpc_put_task(task); |
| 1476 | |||
| 1477 | return status; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data) | ||
| 1481 | { | ||
| 1482 | struct inode *dir = data->dir->d_inode; | ||
| 1483 | struct nfs_openres *o_res = &data->o_res; | ||
| 1484 | int status; | ||
| 1485 | |||
| 1486 | status = nfs4_run_open_task(data, 1); | ||
| 1427 | if (status != 0 || !data->rpc_done) | 1487 | if (status != 0 || !data->rpc_done) |
| 1428 | return status; | 1488 | return status; |
| 1429 | 1489 | ||
| 1430 | if (o_res->fh.size == 0) | 1490 | nfs_refresh_inode(dir, o_res->dir_attr); |
| 1431 | _nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr); | 1491 | |
| 1492 | if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | ||
| 1493 | status = _nfs4_proc_open_confirm(data); | ||
| 1494 | if (status != 0) | ||
| 1495 | return status; | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | return status; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | /* | ||
| 1502 | * Note: On error, nfs4_proc_open will free the struct nfs4_opendata | ||
| 1503 | */ | ||
| 1504 | static int _nfs4_proc_open(struct nfs4_opendata *data) | ||
| 1505 | { | ||
| 1506 | struct inode *dir = data->dir->d_inode; | ||
| 1507 | struct nfs_server *server = NFS_SERVER(dir); | ||
| 1508 | struct nfs_openargs *o_arg = &data->o_arg; | ||
| 1509 | struct nfs_openres *o_res = &data->o_res; | ||
| 1510 | int status; | ||
| 1511 | |||
| 1512 | status = nfs4_run_open_task(data, 0); | ||
| 1513 | if (status != 0 || !data->rpc_done) | ||
| 1514 | return status; | ||
| 1432 | 1515 | ||
| 1433 | if (o_arg->open_flags & O_CREAT) { | 1516 | if (o_arg->open_flags & O_CREAT) { |
| 1434 | update_changeattr(dir, &o_res->cinfo); | 1517 | update_changeattr(dir, &o_res->cinfo); |
| @@ -1752,11 +1835,10 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
| 1752 | if (calldata->arg.fmode == 0) | 1835 | if (calldata->arg.fmode == 0) |
| 1753 | break; | 1836 | break; |
| 1754 | default: | 1837 | default: |
| 1755 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) { | 1838 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) |
| 1756 | nfs_restart_rpc(task, server->nfs_client); | 1839 | rpc_restart_call_prepare(task); |
| 1757 | return; | ||
| 1758 | } | ||
| 1759 | } | 1840 | } |
| 1841 | nfs_release_seqid(calldata->arg.seqid); | ||
| 1760 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | 1842 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); |
| 1761 | } | 1843 | } |
| 1762 | 1844 | ||
| @@ -1848,8 +1930,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
| 1848 | calldata->state = state; | 1930 | calldata->state = state; |
| 1849 | calldata->arg.fh = NFS_FH(state->inode); | 1931 | calldata->arg.fh = NFS_FH(state->inode); |
| 1850 | calldata->arg.stateid = &state->open_stateid; | 1932 | calldata->arg.stateid = &state->open_stateid; |
| 1851 | if (nfs4_has_session(server->nfs_client)) | ||
| 1852 | memset(calldata->arg.stateid->data, 0, 4); /* clear seqid */ | ||
| 1853 | /* Serialization for the sequence id */ | 1933 | /* Serialization for the sequence id */ |
| 1854 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); | 1934 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); |
| 1855 | if (calldata->arg.seqid == NULL) | 1935 | if (calldata->arg.seqid == NULL) |
| @@ -3941,6 +4021,12 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
| 3941 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); | 4021 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); |
| 3942 | } | 4022 | } |
| 3943 | 4023 | ||
| 4024 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) | ||
| 4025 | { | ||
| 4026 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 4027 | nfs4_lock_prepare(task, calldata); | ||
| 4028 | } | ||
| 4029 | |||
| 3944 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) | 4030 | static void nfs4_lock_done(struct rpc_task *task, void *calldata) |
| 3945 | { | 4031 | { |
| 3946 | struct nfs4_lockdata *data = calldata; | 4032 | struct nfs4_lockdata *data = calldata; |
| @@ -3996,7 +4082,13 @@ static const struct rpc_call_ops nfs4_lock_ops = { | |||
| 3996 | .rpc_release = nfs4_lock_release, | 4082 | .rpc_release = nfs4_lock_release, |
| 3997 | }; | 4083 | }; |
| 3998 | 4084 | ||
| 3999 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int reclaim) | 4085 | static const struct rpc_call_ops nfs4_recover_lock_ops = { |
| 4086 | .rpc_call_prepare = nfs4_recover_lock_prepare, | ||
| 4087 | .rpc_call_done = nfs4_lock_done, | ||
| 4088 | .rpc_release = nfs4_lock_release, | ||
| 4089 | }; | ||
| 4090 | |||
| 4091 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type) | ||
| 4000 | { | 4092 | { |
| 4001 | struct nfs4_lockdata *data; | 4093 | struct nfs4_lockdata *data; |
| 4002 | struct rpc_task *task; | 4094 | struct rpc_task *task; |
| @@ -4020,8 +4112,11 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
| 4020 | return -ENOMEM; | 4112 | return -ENOMEM; |
| 4021 | if (IS_SETLKW(cmd)) | 4113 | if (IS_SETLKW(cmd)) |
| 4022 | data->arg.block = 1; | 4114 | data->arg.block = 1; |
| 4023 | if (reclaim != 0) | 4115 | if (recovery_type > NFS_LOCK_NEW) { |
| 4024 | data->arg.reclaim = 1; | 4116 | if (recovery_type == NFS_LOCK_RECLAIM) |
| 4117 | data->arg.reclaim = NFS_LOCK_RECLAIM; | ||
| 4118 | task_setup_data.callback_ops = &nfs4_recover_lock_ops; | ||
| 4119 | } | ||
| 4025 | msg.rpc_argp = &data->arg, | 4120 | msg.rpc_argp = &data->arg, |
| 4026 | msg.rpc_resp = &data->res, | 4121 | msg.rpc_resp = &data->res, |
| 4027 | task_setup_data.callback_data = data; | 4122 | task_setup_data.callback_data = data; |
| @@ -4048,7 +4143,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request | |||
| 4048 | /* Cache the lock if possible... */ | 4143 | /* Cache the lock if possible... */ |
| 4049 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 4144 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
| 4050 | return 0; | 4145 | return 0; |
| 4051 | err = _nfs4_do_setlk(state, F_SETLK, request, 1); | 4146 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM); |
| 4052 | if (err != -NFS4ERR_DELAY) | 4147 | if (err != -NFS4ERR_DELAY) |
| 4053 | break; | 4148 | break; |
| 4054 | nfs4_handle_exception(server, err, &exception); | 4149 | nfs4_handle_exception(server, err, &exception); |
| @@ -4068,7 +4163,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
| 4068 | do { | 4163 | do { |
| 4069 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 4164 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
| 4070 | return 0; | 4165 | return 0; |
| 4071 | err = _nfs4_do_setlk(state, F_SETLK, request, 0); | 4166 | err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED); |
| 4072 | switch (err) { | 4167 | switch (err) { |
| 4073 | default: | 4168 | default: |
| 4074 | goto out; | 4169 | goto out; |
| @@ -4104,7 +4199,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
| 4104 | status = do_vfs_lock(request->fl_file, request); | 4199 | status = do_vfs_lock(request->fl_file, request); |
| 4105 | goto out_unlock; | 4200 | goto out_unlock; |
| 4106 | } | 4201 | } |
| 4107 | status = _nfs4_do_setlk(state, cmd, request, 0); | 4202 | status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW); |
| 4108 | if (status != 0) | 4203 | if (status != 0) |
| 4109 | goto out_unlock; | 4204 | goto out_unlock; |
| 4110 | /* Note: we always want to sleep here! */ | 4205 | /* Note: we always want to sleep here! */ |
| @@ -4187,7 +4282,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
| 4187 | if (err != 0) | 4282 | if (err != 0) |
| 4188 | goto out; | 4283 | goto out; |
| 4189 | do { | 4284 | do { |
| 4190 | err = _nfs4_do_setlk(state, F_SETLK, fl, 0); | 4285 | err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW); |
| 4191 | switch (err) { | 4286 | switch (err) { |
| 4192 | default: | 4287 | default: |
| 4193 | printk(KERN_ERR "%s: unhandled error %d.\n", | 4288 | printk(KERN_ERR "%s: unhandled error %d.\n", |
| @@ -4395,11 +4490,12 @@ static void nfs4_get_lease_time_prepare(struct rpc_task *task, | |||
| 4395 | (struct nfs4_get_lease_time_data *)calldata; | 4490 | (struct nfs4_get_lease_time_data *)calldata; |
| 4396 | 4491 | ||
| 4397 | dprintk("--> %s\n", __func__); | 4492 | dprintk("--> %s\n", __func__); |
| 4493 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 4398 | /* just setup sequence, do not trigger session recovery | 4494 | /* just setup sequence, do not trigger session recovery |
| 4399 | since we're invoked within one */ | 4495 | since we're invoked within one */ |
| 4400 | ret = nfs41_setup_sequence(data->clp->cl_session, | 4496 | ret = nfs41_setup_sequence(data->clp->cl_session, |
| 4401 | &data->args->la_seq_args, | 4497 | &data->args->la_seq_args, |
| 4402 | &data->res->lr_seq_res, 0, task); | 4498 | &data->res->lr_seq_res, 0, task); |
| 4403 | 4499 | ||
| 4404 | BUG_ON(ret == -EAGAIN); | 4500 | BUG_ON(ret == -EAGAIN); |
| 4405 | rpc_call_start(task); | 4501 | rpc_call_start(task); |
| @@ -4619,7 +4715,7 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
| 4619 | tbl = &session->fc_slot_table; | 4715 | tbl = &session->fc_slot_table; |
| 4620 | tbl->highest_used_slotid = -1; | 4716 | tbl->highest_used_slotid = -1; |
| 4621 | spin_lock_init(&tbl->slot_tbl_lock); | 4717 | spin_lock_init(&tbl->slot_tbl_lock); |
| 4622 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); | 4718 | rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table"); |
| 4623 | 4719 | ||
| 4624 | tbl = &session->bc_slot_table; | 4720 | tbl = &session->bc_slot_table; |
| 4625 | tbl->highest_used_slotid = -1; | 4721 | tbl->highest_used_slotid = -1; |
| @@ -4838,14 +4934,22 @@ int nfs4_init_session(struct nfs_server *server) | |||
| 4838 | { | 4934 | { |
| 4839 | struct nfs_client *clp = server->nfs_client; | 4935 | struct nfs_client *clp = server->nfs_client; |
| 4840 | struct nfs4_session *session; | 4936 | struct nfs4_session *session; |
| 4937 | unsigned int rsize, wsize; | ||
| 4841 | int ret; | 4938 | int ret; |
| 4842 | 4939 | ||
| 4843 | if (!nfs4_has_session(clp)) | 4940 | if (!nfs4_has_session(clp)) |
| 4844 | return 0; | 4941 | return 0; |
| 4845 | 4942 | ||
| 4943 | rsize = server->rsize; | ||
| 4944 | if (rsize == 0) | ||
| 4945 | rsize = NFS_MAX_FILE_IO_SIZE; | ||
| 4946 | wsize = server->wsize; | ||
| 4947 | if (wsize == 0) | ||
| 4948 | wsize = NFS_MAX_FILE_IO_SIZE; | ||
| 4949 | |||
| 4846 | session = clp->cl_session; | 4950 | session = clp->cl_session; |
| 4847 | session->fc_attrs.max_rqst_sz = server->wsize + nfs41_maxwrite_overhead; | 4951 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; |
| 4848 | session->fc_attrs.max_resp_sz = server->rsize + nfs41_maxread_overhead; | 4952 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; |
| 4849 | 4953 | ||
| 4850 | ret = nfs4_recover_expired_lease(server); | 4954 | ret = nfs4_recover_expired_lease(server); |
| 4851 | if (!ret) | 4955 | if (!ret) |
| @@ -4871,7 +4975,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 4871 | args.sa_cache_this = 0; | 4975 | args.sa_cache_this = 0; |
| 4872 | 4976 | ||
| 4873 | return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args, | 4977 | return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args, |
| 4874 | &res, 0); | 4978 | &res, args.sa_cache_this, 1); |
| 4875 | } | 4979 | } |
| 4876 | 4980 | ||
| 4877 | void nfs41_sequence_call_done(struct rpc_task *task, void *data) | 4981 | void nfs41_sequence_call_done(struct rpc_task *task, void *data) |
| @@ -4953,6 +5057,7 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) | |||
| 4953 | { | 5057 | { |
| 4954 | struct nfs4_reclaim_complete_data *calldata = data; | 5058 | struct nfs4_reclaim_complete_data *calldata = data; |
| 4955 | 5059 | ||
| 5060 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 4956 | if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args, | 5061 | if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args, |
| 4957 | &calldata->res.seq_res, 0, task)) | 5062 | &calldata->res.seq_res, 0, task)) |
| 4958 | return; | 5063 | return; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e76427e6346f..6d263ed79e92 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -135,16 +135,30 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp) | |||
| 135 | return status; | 135 | return status; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static void nfs41_end_drain_session(struct nfs_client *clp, | 138 | static void nfs4_end_drain_session(struct nfs_client *clp) |
| 139 | struct nfs4_session *ses) | ||
| 140 | { | 139 | { |
| 141 | if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) | 140 | struct nfs4_session *ses = clp->cl_session; |
| 142 | rpc_wake_up(&ses->fc_slot_table.slot_tbl_waitq); | 141 | int max_slots; |
| 142 | |||
| 143 | if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) { | ||
| 144 | spin_lock(&ses->fc_slot_table.slot_tbl_lock); | ||
| 145 | max_slots = ses->fc_slot_table.max_slots; | ||
| 146 | while (max_slots--) { | ||
| 147 | struct rpc_task *task; | ||
| 148 | |||
| 149 | task = rpc_wake_up_next(&ses->fc_slot_table. | ||
| 150 | slot_tbl_waitq); | ||
| 151 | if (!task) | ||
| 152 | break; | ||
| 153 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | ||
| 154 | } | ||
| 155 | spin_unlock(&ses->fc_slot_table.slot_tbl_lock); | ||
| 156 | } | ||
| 143 | } | 157 | } |
| 144 | 158 | ||
| 145 | static int nfs41_begin_drain_session(struct nfs_client *clp, | 159 | static int nfs4_begin_drain_session(struct nfs_client *clp) |
| 146 | struct nfs4_session *ses) | ||
| 147 | { | 160 | { |
| 161 | struct nfs4_session *ses = clp->cl_session; | ||
| 148 | struct nfs4_slot_table *tbl = &ses->fc_slot_table; | 162 | struct nfs4_slot_table *tbl = &ses->fc_slot_table; |
| 149 | 163 | ||
| 150 | spin_lock(&tbl->slot_tbl_lock); | 164 | spin_lock(&tbl->slot_tbl_lock); |
| @@ -162,16 +176,13 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
| 162 | { | 176 | { |
| 163 | int status; | 177 | int status; |
| 164 | 178 | ||
| 165 | status = nfs41_begin_drain_session(clp, clp->cl_session); | 179 | nfs4_begin_drain_session(clp); |
| 166 | if (status != 0) | ||
| 167 | goto out; | ||
| 168 | status = nfs4_proc_exchange_id(clp, cred); | 180 | status = nfs4_proc_exchange_id(clp, cred); |
| 169 | if (status != 0) | 181 | if (status != 0) |
| 170 | goto out; | 182 | goto out; |
| 171 | status = nfs4_proc_create_session(clp); | 183 | status = nfs4_proc_create_session(clp); |
| 172 | if (status != 0) | 184 | if (status != 0) |
| 173 | goto out; | 185 | goto out; |
| 174 | nfs41_end_drain_session(clp, clp->cl_session); | ||
| 175 | nfs41_setup_state_renewal(clp); | 186 | nfs41_setup_state_renewal(clp); |
| 176 | nfs_mark_client_ready(clp, NFS_CS_READY); | 187 | nfs_mark_client_ready(clp, NFS_CS_READY); |
| 177 | out: | 188 | out: |
| @@ -755,16 +766,21 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | |||
| 755 | return new; | 766 | return new; |
| 756 | } | 767 | } |
| 757 | 768 | ||
| 758 | void nfs_free_seqid(struct nfs_seqid *seqid) | 769 | void nfs_release_seqid(struct nfs_seqid *seqid) |
| 759 | { | 770 | { |
| 760 | if (!list_empty(&seqid->list)) { | 771 | if (!list_empty(&seqid->list)) { |
| 761 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 772 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
| 762 | 773 | ||
| 763 | spin_lock(&sequence->lock); | 774 | spin_lock(&sequence->lock); |
| 764 | list_del(&seqid->list); | 775 | list_del_init(&seqid->list); |
| 765 | spin_unlock(&sequence->lock); | 776 | spin_unlock(&sequence->lock); |
| 766 | rpc_wake_up(&sequence->wait); | 777 | rpc_wake_up(&sequence->wait); |
| 767 | } | 778 | } |
| 779 | } | ||
| 780 | |||
| 781 | void nfs_free_seqid(struct nfs_seqid *seqid) | ||
| 782 | { | ||
| 783 | nfs_release_seqid(seqid); | ||
| 768 | kfree(seqid); | 784 | kfree(seqid); |
| 769 | } | 785 | } |
| 770 | 786 | ||
| @@ -1257,13 +1273,9 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | |||
| 1257 | 1273 | ||
| 1258 | static int nfs4_reset_session(struct nfs_client *clp) | 1274 | static int nfs4_reset_session(struct nfs_client *clp) |
| 1259 | { | 1275 | { |
| 1260 | struct nfs4_session *ses = clp->cl_session; | ||
| 1261 | int status; | 1276 | int status; |
| 1262 | 1277 | ||
| 1263 | status = nfs41_begin_drain_session(clp, ses); | 1278 | nfs4_begin_drain_session(clp); |
| 1264 | if (status != 0) | ||
| 1265 | return status; | ||
| 1266 | |||
| 1267 | status = nfs4_proc_destroy_session(clp->cl_session); | 1279 | status = nfs4_proc_destroy_session(clp->cl_session); |
| 1268 | if (status && status != -NFS4ERR_BADSESSION && | 1280 | if (status && status != -NFS4ERR_BADSESSION && |
| 1269 | status != -NFS4ERR_DEADSESSION) { | 1281 | status != -NFS4ERR_DEADSESSION) { |
| @@ -1279,19 +1291,17 @@ static int nfs4_reset_session(struct nfs_client *clp) | |||
| 1279 | out: | 1291 | out: |
| 1280 | /* | 1292 | /* |
| 1281 | * Let the state manager reestablish state | 1293 | * Let the state manager reestablish state |
| 1282 | * without waking other tasks yet. | ||
| 1283 | */ | 1294 | */ |
| 1284 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { | 1295 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && |
| 1285 | /* Wake up the next rpc task */ | 1296 | status == 0) |
| 1286 | nfs41_end_drain_session(clp, ses); | 1297 | nfs41_setup_state_renewal(clp); |
| 1287 | if (status == 0) | 1298 | |
| 1288 | nfs41_setup_state_renewal(clp); | ||
| 1289 | } | ||
| 1290 | return status; | 1299 | return status; |
| 1291 | } | 1300 | } |
| 1292 | 1301 | ||
| 1293 | #else /* CONFIG_NFS_V4_1 */ | 1302 | #else /* CONFIG_NFS_V4_1 */ |
| 1294 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | 1303 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
| 1304 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | ||
| 1295 | #endif /* CONFIG_NFS_V4_1 */ | 1305 | #endif /* CONFIG_NFS_V4_1 */ |
| 1296 | 1306 | ||
| 1297 | /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors | 1307 | /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors |
| @@ -1382,6 +1392,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
| 1382 | goto out_error; | 1392 | goto out_error; |
| 1383 | } | 1393 | } |
| 1384 | 1394 | ||
| 1395 | nfs4_end_drain_session(clp); | ||
| 1385 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { | 1396 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { |
| 1386 | nfs_client_return_marked_delegations(clp); | 1397 | nfs_client_return_marked_delegations(clp); |
| 1387 | continue; | 1398 | continue; |
| @@ -1398,6 +1409,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
| 1398 | out_error: | 1409 | out_error: |
| 1399 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" | 1410 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" |
| 1400 | " with error %d\n", clp->cl_hostname, -status); | 1411 | " with error %d\n", clp->cl_hostname, -status); |
| 1412 | nfs4_end_drain_session(clp); | ||
| 1401 | nfs4_clear_state_manager_bit(clp); | 1413 | nfs4_clear_state_manager_bit(clp); |
| 1402 | } | 1414 | } |
| 1403 | 1415 | ||
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 1906782ec86b..7bc7fd5291ce 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
| @@ -173,7 +173,8 @@ struct rpc_task_setup { | |||
| 173 | #define RPC_PRIORITY_LOW (-1) | 173 | #define RPC_PRIORITY_LOW (-1) |
| 174 | #define RPC_PRIORITY_NORMAL (0) | 174 | #define RPC_PRIORITY_NORMAL (0) |
| 175 | #define RPC_PRIORITY_HIGH (1) | 175 | #define RPC_PRIORITY_HIGH (1) |
| 176 | #define RPC_NR_PRIORITY (1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW) | 176 | #define RPC_PRIORITY_PRIVILEGED (2) |
| 177 | #define RPC_NR_PRIORITY (1 + RPC_PRIORITY_PRIVILEGED - RPC_PRIORITY_LOW) | ||
| 177 | 178 | ||
| 178 | struct rpc_timer { | 179 | struct rpc_timer { |
| 179 | struct timer_list timer; | 180 | struct timer_list timer; |
| @@ -229,6 +230,7 @@ void rpc_wake_up_queued_task(struct rpc_wait_queue *, | |||
| 229 | void rpc_wake_up(struct rpc_wait_queue *); | 230 | void rpc_wake_up(struct rpc_wait_queue *); |
| 230 | struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *); | 231 | struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *); |
| 231 | void rpc_wake_up_status(struct rpc_wait_queue *, int); | 232 | void rpc_wake_up_status(struct rpc_wait_queue *, int); |
| 233 | int rpc_queue_empty(struct rpc_wait_queue *); | ||
| 232 | void rpc_delay(struct rpc_task *, unsigned long); | 234 | void rpc_delay(struct rpc_task *, unsigned long); |
| 233 | void * rpc_malloc(struct rpc_task *, size_t); | 235 | void * rpc_malloc(struct rpc_task *, size_t); |
| 234 | void rpc_free(void *); | 236 | void rpc_free(void *); |
| @@ -254,6 +256,16 @@ static inline int rpc_wait_for_completion_task(struct rpc_task *task) | |||
| 254 | return __rpc_wait_for_completion_task(task, NULL); | 256 | return __rpc_wait_for_completion_task(task, NULL); |
| 255 | } | 257 | } |
| 256 | 258 | ||
| 259 | static inline void rpc_task_set_priority(struct rpc_task *task, unsigned char prio) | ||
| 260 | { | ||
| 261 | task->tk_priority = prio - RPC_PRIORITY_LOW; | ||
| 262 | } | ||
| 263 | |||
| 264 | static inline int rpc_task_has_priority(struct rpc_task *task, unsigned char prio) | ||
| 265 | { | ||
| 266 | return (task->tk_priority + RPC_PRIORITY_LOW == prio); | ||
| 267 | } | ||
| 268 | |||
| 257 | #ifdef RPC_DEBUG | 269 | #ifdef RPC_DEBUG |
| 258 | static inline const char * rpc_qname(struct rpc_wait_queue *q) | 270 | static inline const char * rpc_qname(struct rpc_wait_queue *q) |
| 259 | { | 271 | { |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index cef74ba0666c..aae6907fd546 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
| @@ -210,6 +210,7 @@ void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qnam | |||
| 210 | { | 210 | { |
| 211 | __rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY); | 211 | __rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY); |
| 212 | } | 212 | } |
| 213 | EXPORT_SYMBOL_GPL(rpc_init_priority_wait_queue); | ||
| 213 | 214 | ||
| 214 | void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 215 | void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
| 215 | { | 216 | { |
| @@ -385,6 +386,20 @@ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct r | |||
| 385 | } | 386 | } |
| 386 | 387 | ||
| 387 | /* | 388 | /* |
| 389 | * Tests whether rpc queue is empty | ||
| 390 | */ | ||
| 391 | int rpc_queue_empty(struct rpc_wait_queue *queue) | ||
| 392 | { | ||
| 393 | int res; | ||
| 394 | |||
| 395 | spin_lock_bh(&queue->lock); | ||
| 396 | res = queue->qlen; | ||
| 397 | spin_unlock_bh(&queue->lock); | ||
| 398 | return (res == 0); | ||
| 399 | } | ||
| 400 | EXPORT_SYMBOL_GPL(rpc_queue_empty); | ||
| 401 | |||
| 402 | /* | ||
| 388 | * Wake up a task on a specific queue | 403 | * Wake up a task on a specific queue |
| 389 | */ | 404 | */ |
| 390 | void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task) | 405 | void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task) |
