diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 225 |
1 files changed, 167 insertions, 58 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 7f0fcfc1fe9d..c679b9ecef63 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -57,6 +57,8 @@ | |||
57 | #include "internal.h" | 57 | #include "internal.h" |
58 | #include "pnfs.h" | 58 | #include "pnfs.h" |
59 | 59 | ||
60 | #define NFSDBG_FACILITY NFSDBG_STATE | ||
61 | |||
60 | #define OPENOWNER_POOL_SIZE 8 | 62 | #define OPENOWNER_POOL_SIZE 8 |
61 | 63 | ||
62 | const nfs4_stateid zero_stateid; | 64 | const nfs4_stateid zero_stateid; |
@@ -254,7 +256,7 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
254 | goto out; | 256 | goto out; |
255 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 257 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
256 | do_confirm: | 258 | do_confirm: |
257 | status = nfs4_proc_create_session(clp); | 259 | status = nfs4_proc_create_session(clp, cred); |
258 | if (status != 0) | 260 | if (status != 0) |
259 | goto out; | 261 | goto out; |
260 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 262 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
@@ -1106,6 +1108,8 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp) | |||
1106 | return; | 1108 | return; |
1107 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | 1109 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1108 | set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | 1110 | set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
1111 | dprintk("%s: scheduling lease recovery for server %s\n", __func__, | ||
1112 | clp->cl_hostname); | ||
1109 | nfs4_schedule_state_manager(clp); | 1113 | nfs4_schedule_state_manager(clp); |
1110 | } | 1114 | } |
1111 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); | 1115 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); |
@@ -1122,6 +1126,8 @@ static void nfs40_handle_cb_pathdown(struct nfs_client *clp) | |||
1122 | { | 1126 | { |
1123 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1127 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
1124 | nfs_expire_all_delegations(clp); | 1128 | nfs_expire_all_delegations(clp); |
1129 | dprintk("%s: handling CB_PATHDOWN recovery for server %s\n", __func__, | ||
1130 | clp->cl_hostname); | ||
1125 | } | 1131 | } |
1126 | 1132 | ||
1127 | void nfs4_schedule_path_down_recovery(struct nfs_client *clp) | 1133 | void nfs4_schedule_path_down_recovery(struct nfs_client *clp) |
@@ -1158,6 +1164,8 @@ void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4 | |||
1158 | struct nfs_client *clp = server->nfs_client; | 1164 | struct nfs_client *clp = server->nfs_client; |
1159 | 1165 | ||
1160 | nfs4_state_mark_reclaim_nograce(clp, state); | 1166 | nfs4_state_mark_reclaim_nograce(clp, state); |
1167 | dprintk("%s: scheduling stateid recovery for server %s\n", __func__, | ||
1168 | clp->cl_hostname); | ||
1161 | nfs4_schedule_state_manager(clp); | 1169 | nfs4_schedule_state_manager(clp); |
1162 | } | 1170 | } |
1163 | EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery); | 1171 | EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery); |
@@ -1491,19 +1499,25 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
1491 | case -NFS4ERR_BADSLOT: | 1499 | case -NFS4ERR_BADSLOT: |
1492 | case -NFS4ERR_BAD_HIGH_SLOT: | 1500 | case -NFS4ERR_BAD_HIGH_SLOT: |
1493 | case -NFS4ERR_DEADSESSION: | 1501 | case -NFS4ERR_DEADSESSION: |
1494 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
1495 | case -NFS4ERR_SEQ_FALSE_RETRY: | 1502 | case -NFS4ERR_SEQ_FALSE_RETRY: |
1496 | case -NFS4ERR_SEQ_MISORDERED: | 1503 | case -NFS4ERR_SEQ_MISORDERED: |
1497 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | 1504 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
1498 | /* Zero session reset errors */ | 1505 | /* Zero session reset errors */ |
1499 | break; | 1506 | break; |
1507 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
1508 | set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | ||
1509 | break; | ||
1500 | case -EKEYEXPIRED: | 1510 | case -EKEYEXPIRED: |
1501 | /* Nothing we can do */ | 1511 | /* Nothing we can do */ |
1502 | nfs4_warn_keyexpired(clp->cl_hostname); | 1512 | nfs4_warn_keyexpired(clp->cl_hostname); |
1503 | break; | 1513 | break; |
1504 | default: | 1514 | default: |
1515 | dprintk("%s: failed to handle error %d for server %s\n", | ||
1516 | __func__, error, clp->cl_hostname); | ||
1505 | return error; | 1517 | return error; |
1506 | } | 1518 | } |
1519 | dprintk("%s: handled error %d for server %s\n", __func__, error, | ||
1520 | clp->cl_hostname); | ||
1507 | return 0; | 1521 | return 0; |
1508 | } | 1522 | } |
1509 | 1523 | ||
@@ -1572,34 +1586,82 @@ out: | |||
1572 | return nfs4_recovery_handle_error(clp, status); | 1586 | return nfs4_recovery_handle_error(clp, status); |
1573 | } | 1587 | } |
1574 | 1588 | ||
1589 | /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors | ||
1590 | * on EXCHANGE_ID for v4.1 | ||
1591 | */ | ||
1592 | static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | ||
1593 | { | ||
1594 | switch (status) { | ||
1595 | case -NFS4ERR_SEQ_MISORDERED: | ||
1596 | if (test_and_set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) | ||
1597 | return -ESERVERFAULT; | ||
1598 | /* Lease confirmation error: retry after purging the lease */ | ||
1599 | ssleep(1); | ||
1600 | case -NFS4ERR_CLID_INUSE: | ||
1601 | case -NFS4ERR_STALE_CLIENTID: | ||
1602 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
1603 | break; | ||
1604 | case -EACCES: | ||
1605 | if (clp->cl_machine_cred == NULL) | ||
1606 | return -EACCES; | ||
1607 | /* Handle case where the user hasn't set up machine creds */ | ||
1608 | nfs4_clear_machine_cred(clp); | ||
1609 | case -NFS4ERR_DELAY: | ||
1610 | case -ETIMEDOUT: | ||
1611 | case -EAGAIN: | ||
1612 | ssleep(1); | ||
1613 | break; | ||
1614 | |||
1615 | case -NFS4ERR_MINOR_VERS_MISMATCH: | ||
1616 | if (clp->cl_cons_state == NFS_CS_SESSION_INITING) | ||
1617 | nfs_mark_client_ready(clp, -EPROTONOSUPPORT); | ||
1618 | dprintk("%s: exit with error %d for server %s\n", | ||
1619 | __func__, -EPROTONOSUPPORT, clp->cl_hostname); | ||
1620 | return -EPROTONOSUPPORT; | ||
1621 | case -EKEYEXPIRED: | ||
1622 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1623 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | ||
1624 | * in nfs4_exchange_id */ | ||
1625 | default: | ||
1626 | dprintk("%s: exit with error %d for server %s\n", __func__, | ||
1627 | status, clp->cl_hostname); | ||
1628 | return status; | ||
1629 | } | ||
1630 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1631 | dprintk("%s: handled error %d for server %s\n", __func__, status, | ||
1632 | clp->cl_hostname); | ||
1633 | return 0; | ||
1634 | } | ||
1635 | |||
1575 | static int nfs4_reclaim_lease(struct nfs_client *clp) | 1636 | static int nfs4_reclaim_lease(struct nfs_client *clp) |
1576 | { | 1637 | { |
1577 | struct rpc_cred *cred; | 1638 | struct rpc_cred *cred; |
1578 | const struct nfs4_state_recovery_ops *ops = | 1639 | const struct nfs4_state_recovery_ops *ops = |
1579 | clp->cl_mvops->reboot_recovery_ops; | 1640 | clp->cl_mvops->reboot_recovery_ops; |
1580 | int status = -ENOENT; | 1641 | int status; |
1581 | 1642 | ||
1582 | cred = ops->get_clid_cred(clp); | 1643 | cred = ops->get_clid_cred(clp); |
1583 | if (cred != NULL) { | 1644 | if (cred == NULL) |
1584 | status = ops->establish_clid(clp, cred); | 1645 | return -ENOENT; |
1585 | put_rpccred(cred); | 1646 | status = ops->establish_clid(clp, cred); |
1586 | /* Handle case where the user hasn't set up machine creds */ | 1647 | put_rpccred(cred); |
1587 | if (status == -EACCES && cred == clp->cl_machine_cred) { | 1648 | if (status != 0) |
1588 | nfs4_clear_machine_cred(clp); | 1649 | return nfs4_handle_reclaim_lease_error(clp, status); |
1589 | status = -EAGAIN; | 1650 | return 0; |
1590 | } | ||
1591 | if (status == -NFS4ERR_MINOR_VERS_MISMATCH) | ||
1592 | status = -EPROTONOSUPPORT; | ||
1593 | } | ||
1594 | return status; | ||
1595 | } | 1651 | } |
1596 | 1652 | ||
1597 | #ifdef CONFIG_NFS_V4_1 | 1653 | #ifdef CONFIG_NFS_V4_1 |
1598 | void nfs4_schedule_session_recovery(struct nfs4_session *session) | 1654 | void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) |
1599 | { | 1655 | { |
1600 | struct nfs_client *clp = session->clp; | 1656 | struct nfs_client *clp = session->clp; |
1601 | 1657 | ||
1602 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | 1658 | switch (err) { |
1659 | default: | ||
1660 | set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | ||
1661 | break; | ||
1662 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
1663 | set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | ||
1664 | } | ||
1603 | nfs4_schedule_lease_recovery(clp); | 1665 | nfs4_schedule_lease_recovery(clp); |
1604 | } | 1666 | } |
1605 | EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); | 1667 | EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); |
@@ -1607,14 +1669,19 @@ EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); | |||
1607 | void nfs41_handle_recall_slot(struct nfs_client *clp) | 1669 | void nfs41_handle_recall_slot(struct nfs_client *clp) |
1608 | { | 1670 | { |
1609 | set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); | 1671 | set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); |
1672 | dprintk("%s: scheduling slot recall for server %s\n", __func__, | ||
1673 | clp->cl_hostname); | ||
1610 | nfs4_schedule_state_manager(clp); | 1674 | nfs4_schedule_state_manager(clp); |
1611 | } | 1675 | } |
1612 | 1676 | ||
1613 | static void nfs4_reset_all_state(struct nfs_client *clp) | 1677 | static void nfs4_reset_all_state(struct nfs_client *clp) |
1614 | { | 1678 | { |
1615 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { | 1679 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |
1616 | clp->cl_boot_time = CURRENT_TIME; | 1680 | set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); |
1681 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
1617 | nfs4_state_start_reclaim_nograce(clp); | 1682 | nfs4_state_start_reclaim_nograce(clp); |
1683 | dprintk("%s: scheduling reset of all state for server %s!\n", | ||
1684 | __func__, clp->cl_hostname); | ||
1618 | nfs4_schedule_state_manager(clp); | 1685 | nfs4_schedule_state_manager(clp); |
1619 | } | 1686 | } |
1620 | } | 1687 | } |
@@ -1623,33 +1690,50 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp) | |||
1623 | { | 1690 | { |
1624 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { | 1691 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |
1625 | nfs4_state_start_reclaim_reboot(clp); | 1692 | nfs4_state_start_reclaim_reboot(clp); |
1693 | dprintk("%s: server %s rebooted!\n", __func__, | ||
1694 | clp->cl_hostname); | ||
1626 | nfs4_schedule_state_manager(clp); | 1695 | nfs4_schedule_state_manager(clp); |
1627 | } | 1696 | } |
1628 | } | 1697 | } |
1629 | 1698 | ||
1630 | static void nfs41_handle_state_revoked(struct nfs_client *clp) | 1699 | static void nfs41_handle_state_revoked(struct nfs_client *clp) |
1631 | { | 1700 | { |
1632 | /* Temporary */ | ||
1633 | nfs4_reset_all_state(clp); | 1701 | nfs4_reset_all_state(clp); |
1702 | dprintk("%s: state revoked on server %s\n", __func__, clp->cl_hostname); | ||
1634 | } | 1703 | } |
1635 | 1704 | ||
1636 | static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp) | 1705 | static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp) |
1637 | { | 1706 | { |
1638 | /* This will need to handle layouts too */ | 1707 | /* This will need to handle layouts too */ |
1639 | nfs_expire_all_delegations(clp); | 1708 | nfs_expire_all_delegations(clp); |
1709 | dprintk("%s: Recallable state revoked on server %s!\n", __func__, | ||
1710 | clp->cl_hostname); | ||
1640 | } | 1711 | } |
1641 | 1712 | ||
1642 | static void nfs41_handle_cb_path_down(struct nfs_client *clp) | 1713 | static void nfs41_handle_backchannel_fault(struct nfs_client *clp) |
1643 | { | 1714 | { |
1644 | nfs_expire_all_delegations(clp); | 1715 | nfs_expire_all_delegations(clp); |
1645 | if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) | 1716 | if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) |
1646 | nfs4_schedule_state_manager(clp); | 1717 | nfs4_schedule_state_manager(clp); |
1718 | dprintk("%s: server %s declared a backchannel fault\n", __func__, | ||
1719 | clp->cl_hostname); | ||
1720 | } | ||
1721 | |||
1722 | static void nfs41_handle_cb_path_down(struct nfs_client *clp) | ||
1723 | { | ||
1724 | if (test_and_set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, | ||
1725 | &clp->cl_state) == 0) | ||
1726 | nfs4_schedule_state_manager(clp); | ||
1647 | } | 1727 | } |
1648 | 1728 | ||
1649 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | 1729 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) |
1650 | { | 1730 | { |
1651 | if (!flags) | 1731 | if (!flags) |
1652 | return; | 1732 | return; |
1733 | |||
1734 | dprintk("%s: \"%s\" (client ID %llx) flags=0x%08x\n", | ||
1735 | __func__, clp->cl_hostname, clp->cl_clientid, flags); | ||
1736 | |||
1653 | if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) | 1737 | if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) |
1654 | nfs41_handle_server_reboot(clp); | 1738 | nfs41_handle_server_reboot(clp); |
1655 | if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | | 1739 | if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | |
@@ -1659,18 +1743,21 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | |||
1659 | nfs41_handle_state_revoked(clp); | 1743 | nfs41_handle_state_revoked(clp); |
1660 | if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) | 1744 | if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) |
1661 | nfs41_handle_recallable_state_revoked(clp); | 1745 | nfs41_handle_recallable_state_revoked(clp); |
1662 | if (flags & (SEQ4_STATUS_CB_PATH_DOWN | | 1746 | if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT) |
1663 | SEQ4_STATUS_BACKCHANNEL_FAULT | | 1747 | nfs41_handle_backchannel_fault(clp); |
1664 | SEQ4_STATUS_CB_PATH_DOWN_SESSION)) | 1748 | else if (flags & (SEQ4_STATUS_CB_PATH_DOWN | |
1749 | SEQ4_STATUS_CB_PATH_DOWN_SESSION)) | ||
1665 | nfs41_handle_cb_path_down(clp); | 1750 | nfs41_handle_cb_path_down(clp); |
1666 | } | 1751 | } |
1667 | 1752 | ||
1668 | static int nfs4_reset_session(struct nfs_client *clp) | 1753 | static int nfs4_reset_session(struct nfs_client *clp) |
1669 | { | 1754 | { |
1755 | struct rpc_cred *cred; | ||
1670 | int status; | 1756 | int status; |
1671 | 1757 | ||
1672 | nfs4_begin_drain_session(clp); | 1758 | nfs4_begin_drain_session(clp); |
1673 | status = nfs4_proc_destroy_session(clp->cl_session); | 1759 | cred = nfs4_get_exchange_id_cred(clp); |
1760 | status = nfs4_proc_destroy_session(clp->cl_session, cred); | ||
1674 | if (status && status != -NFS4ERR_BADSESSION && | 1761 | if (status && status != -NFS4ERR_BADSESSION && |
1675 | status != -NFS4ERR_DEADSESSION) { | 1762 | status != -NFS4ERR_DEADSESSION) { |
1676 | status = nfs4_recovery_handle_error(clp, status); | 1763 | status = nfs4_recovery_handle_error(clp, status); |
@@ -1678,19 +1765,26 @@ static int nfs4_reset_session(struct nfs_client *clp) | |||
1678 | } | 1765 | } |
1679 | 1766 | ||
1680 | memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); | 1767 | memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); |
1681 | status = nfs4_proc_create_session(clp); | 1768 | status = nfs4_proc_create_session(clp, cred); |
1682 | if (status) { | 1769 | if (status) { |
1683 | status = nfs4_recovery_handle_error(clp, status); | 1770 | dprintk("%s: session reset failed with status %d for server %s!\n", |
1771 | __func__, status, clp->cl_hostname); | ||
1772 | status = nfs4_handle_reclaim_lease_error(clp, status); | ||
1684 | goto out; | 1773 | goto out; |
1685 | } | 1774 | } |
1686 | clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); | 1775 | clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); |
1687 | /* create_session negotiated new slot table */ | 1776 | /* create_session negotiated new slot table */ |
1688 | clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); | 1777 | clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); |
1778 | clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | ||
1779 | dprintk("%s: session reset was successful for server %s!\n", | ||
1780 | __func__, clp->cl_hostname); | ||
1689 | 1781 | ||
1690 | /* Let the state manager reestablish state */ | 1782 | /* Let the state manager reestablish state */ |
1691 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | 1783 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1692 | nfs41_setup_state_renewal(clp); | 1784 | nfs41_setup_state_renewal(clp); |
1693 | out: | 1785 | out: |
1786 | if (cred) | ||
1787 | put_rpccred(cred); | ||
1694 | return status; | 1788 | return status; |
1695 | } | 1789 | } |
1696 | 1790 | ||
@@ -1722,37 +1816,41 @@ static int nfs4_recall_slot(struct nfs_client *clp) | |||
1722 | return 0; | 1816 | return 0; |
1723 | } | 1817 | } |
1724 | 1818 | ||
1725 | #else /* CONFIG_NFS_V4_1 */ | 1819 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) |
1726 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | ||
1727 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | ||
1728 | static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | ||
1729 | #endif /* CONFIG_NFS_V4_1 */ | ||
1730 | |||
1731 | /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors | ||
1732 | * on EXCHANGE_ID for v4.1 | ||
1733 | */ | ||
1734 | static void nfs4_set_lease_expired(struct nfs_client *clp, int status) | ||
1735 | { | 1820 | { |
1736 | switch (status) { | 1821 | struct rpc_cred *cred; |
1737 | case -NFS4ERR_CLID_INUSE: | 1822 | int ret; |
1738 | case -NFS4ERR_STALE_CLIENTID: | 1823 | |
1739 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 1824 | nfs4_begin_drain_session(clp); |
1825 | cred = nfs4_get_exchange_id_cred(clp); | ||
1826 | ret = nfs4_proc_bind_conn_to_session(clp, cred); | ||
1827 | if (cred) | ||
1828 | put_rpccred(cred); | ||
1829 | clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | ||
1830 | switch (ret) { | ||
1831 | case 0: | ||
1832 | dprintk("%s: bind_conn_to_session was successful for server %s!\n", | ||
1833 | __func__, clp->cl_hostname); | ||
1740 | break; | 1834 | break; |
1741 | case -NFS4ERR_DELAY: | 1835 | case -NFS4ERR_DELAY: |
1742 | case -ETIMEDOUT: | ||
1743 | case -EAGAIN: | ||
1744 | ssleep(1); | 1836 | ssleep(1); |
1837 | set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); | ||
1745 | break; | 1838 | break; |
1746 | |||
1747 | case -EKEYEXPIRED: | ||
1748 | nfs4_warn_keyexpired(clp->cl_hostname); | ||
1749 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | ||
1750 | * in nfs4_exchange_id */ | ||
1751 | default: | 1839 | default: |
1752 | return; | 1840 | return nfs4_recovery_handle_error(clp, ret); |
1753 | } | 1841 | } |
1754 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1842 | return 0; |
1755 | } | 1843 | } |
1844 | #else /* CONFIG_NFS_V4_1 */ | ||
1845 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | ||
1846 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | ||
1847 | static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | ||
1848 | |||
1849 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) | ||
1850 | { | ||
1851 | return 0; | ||
1852 | } | ||
1853 | #endif /* CONFIG_NFS_V4_1 */ | ||
1756 | 1854 | ||
1757 | static void nfs4_state_manager(struct nfs_client *clp) | 1855 | static void nfs4_state_manager(struct nfs_client *clp) |
1758 | { | 1856 | { |
@@ -1760,19 +1858,21 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1760 | 1858 | ||
1761 | /* Ensure exclusive access to NFSv4 state */ | 1859 | /* Ensure exclusive access to NFSv4 state */ |
1762 | do { | 1860 | do { |
1861 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { | ||
1862 | status = nfs4_reclaim_lease(clp); | ||
1863 | if (status < 0) | ||
1864 | goto out_error; | ||
1865 | clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
1866 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1867 | } | ||
1868 | |||
1763 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { | 1869 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { |
1764 | /* We're going to have to re-establish a clientid */ | 1870 | /* We're going to have to re-establish a clientid */ |
1765 | status = nfs4_reclaim_lease(clp); | 1871 | status = nfs4_reclaim_lease(clp); |
1766 | if (status) { | 1872 | if (status < 0) |
1767 | nfs4_set_lease_expired(clp, status); | ||
1768 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, | ||
1769 | &clp->cl_state)) | ||
1770 | continue; | ||
1771 | if (clp->cl_cons_state == | ||
1772 | NFS_CS_SESSION_INITING) | ||
1773 | nfs_mark_client_ready(clp, status); | ||
1774 | goto out_error; | 1873 | goto out_error; |
1775 | } | 1874 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1875 | continue; | ||
1776 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | 1876 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); |
1777 | 1877 | ||
1778 | if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, | 1878 | if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, |
@@ -1803,6 +1903,15 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1803 | goto out_error; | 1903 | goto out_error; |
1804 | } | 1904 | } |
1805 | 1905 | ||
1906 | /* Send BIND_CONN_TO_SESSION */ | ||
1907 | if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, | ||
1908 | &clp->cl_state) && nfs4_has_session(clp)) { | ||
1909 | status = nfs4_bind_conn_to_session(clp); | ||
1910 | if (status < 0) | ||
1911 | goto out_error; | ||
1912 | continue; | ||
1913 | } | ||
1914 | |||
1806 | /* First recover reboot state... */ | 1915 | /* First recover reboot state... */ |
1807 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { | 1916 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
1808 | status = nfs4_do_reclaim(clp, | 1917 | status = nfs4_do_reclaim(clp, |