diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 114 |
1 files changed, 78 insertions, 36 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f38300e9f171..55148def5540 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1606,10 +1606,15 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | |||
1606 | return -ESERVERFAULT; | 1606 | return -ESERVERFAULT; |
1607 | /* Lease confirmation error: retry after purging the lease */ | 1607 | /* Lease confirmation error: retry after purging the lease */ |
1608 | ssleep(1); | 1608 | ssleep(1); |
1609 | case -NFS4ERR_CLID_INUSE: | ||
1610 | case -NFS4ERR_STALE_CLIENTID: | 1609 | case -NFS4ERR_STALE_CLIENTID: |
1611 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 1610 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
1612 | break; | 1611 | break; |
1612 | case -NFS4ERR_CLID_INUSE: | ||
1613 | pr_err("NFS: Server %s reports our clientid is in use\n", | ||
1614 | clp->cl_hostname); | ||
1615 | nfs_mark_client_ready(clp, -EPERM); | ||
1616 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
1617 | return -EPERM; | ||
1613 | case -EACCES: | 1618 | case -EACCES: |
1614 | if (clp->cl_machine_cred == NULL) | 1619 | if (clp->cl_machine_cred == NULL) |
1615 | return -EACCES; | 1620 | return -EACCES; |
@@ -1642,7 +1647,7 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | |||
1642 | return 0; | 1647 | return 0; |
1643 | } | 1648 | } |
1644 | 1649 | ||
1645 | static int nfs4_reclaim_lease(struct nfs_client *clp) | 1650 | static int nfs4_establish_lease(struct nfs_client *clp) |
1646 | { | 1651 | { |
1647 | struct rpc_cred *cred; | 1652 | struct rpc_cred *cred; |
1648 | const struct nfs4_state_recovery_ops *ops = | 1653 | const struct nfs4_state_recovery_ops *ops = |
@@ -1655,7 +1660,41 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) | |||
1655 | status = ops->establish_clid(clp, cred); | 1660 | status = ops->establish_clid(clp, cred); |
1656 | put_rpccred(cred); | 1661 | put_rpccred(cred); |
1657 | if (status != 0) | 1662 | if (status != 0) |
1663 | return status; | ||
1664 | pnfs_destroy_all_layouts(clp); | ||
1665 | return 0; | ||
1666 | } | ||
1667 | |||
1668 | /* | ||
1669 | * Returns zero or a negative errno. NFS4ERR values are converted | ||
1670 | * to local errno values. | ||
1671 | */ | ||
1672 | static int nfs4_reclaim_lease(struct nfs_client *clp) | ||
1673 | { | ||
1674 | int status; | ||
1675 | |||
1676 | status = nfs4_establish_lease(clp); | ||
1677 | if (status < 0) | ||
1678 | return nfs4_handle_reclaim_lease_error(clp, status); | ||
1679 | if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state)) | ||
1680 | nfs4_state_start_reclaim_nograce(clp); | ||
1681 | if (!test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) | ||
1682 | set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); | ||
1683 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | ||
1684 | clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1685 | return 0; | ||
1686 | } | ||
1687 | |||
1688 | static int nfs4_purge_lease(struct nfs_client *clp) | ||
1689 | { | ||
1690 | int status; | ||
1691 | |||
1692 | status = nfs4_establish_lease(clp); | ||
1693 | if (status < 0) | ||
1658 | return nfs4_handle_reclaim_lease_error(clp, status); | 1694 | return nfs4_handle_reclaim_lease_error(clp, status); |
1695 | clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
1696 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1697 | nfs4_state_start_reclaim_nograce(clp); | ||
1659 | return 0; | 1698 | return 0; |
1660 | } | 1699 | } |
1661 | 1700 | ||
@@ -1764,6 +1803,8 @@ static int nfs4_reset_session(struct nfs_client *clp) | |||
1764 | struct rpc_cred *cred; | 1803 | struct rpc_cred *cred; |
1765 | int status; | 1804 | int status; |
1766 | 1805 | ||
1806 | if (!nfs4_has_session(clp)) | ||
1807 | return 0; | ||
1767 | nfs4_begin_drain_session(clp); | 1808 | nfs4_begin_drain_session(clp); |
1768 | cred = nfs4_get_exchange_id_cred(clp); | 1809 | cred = nfs4_get_exchange_id_cred(clp); |
1769 | status = nfs4_proc_destroy_session(clp->cl_session, cred); | 1810 | status = nfs4_proc_destroy_session(clp->cl_session, cred); |
@@ -1792,12 +1833,14 @@ out: | |||
1792 | 1833 | ||
1793 | static int nfs4_recall_slot(struct nfs_client *clp) | 1834 | static int nfs4_recall_slot(struct nfs_client *clp) |
1794 | { | 1835 | { |
1795 | struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table; | 1836 | struct nfs4_slot_table *fc_tbl; |
1796 | struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs; | ||
1797 | struct nfs4_slot *new, *old; | 1837 | struct nfs4_slot *new, *old; |
1798 | int i; | 1838 | int i; |
1799 | 1839 | ||
1840 | if (!nfs4_has_session(clp)) | ||
1841 | return 0; | ||
1800 | nfs4_begin_drain_session(clp); | 1842 | nfs4_begin_drain_session(clp); |
1843 | fc_tbl = &clp->cl_session->fc_slot_table; | ||
1801 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), | 1844 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), |
1802 | GFP_NOFS); | 1845 | GFP_NOFS); |
1803 | if (!new) | 1846 | if (!new) |
@@ -1810,11 +1853,10 @@ static int nfs4_recall_slot(struct nfs_client *clp) | |||
1810 | fc_tbl->slots = new; | 1853 | fc_tbl->slots = new; |
1811 | fc_tbl->max_slots = fc_tbl->target_max_slots; | 1854 | fc_tbl->max_slots = fc_tbl->target_max_slots; |
1812 | fc_tbl->target_max_slots = 0; | 1855 | fc_tbl->target_max_slots = 0; |
1813 | fc_attrs->max_reqs = fc_tbl->max_slots; | 1856 | clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots; |
1814 | spin_unlock(&fc_tbl->slot_tbl_lock); | 1857 | spin_unlock(&fc_tbl->slot_tbl_lock); |
1815 | 1858 | ||
1816 | kfree(old); | 1859 | kfree(old); |
1817 | nfs4_end_drain_session(clp); | ||
1818 | return 0; | 1860 | return 0; |
1819 | } | 1861 | } |
1820 | 1862 | ||
@@ -1823,6 +1865,8 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
1823 | struct rpc_cred *cred; | 1865 | struct rpc_cred *cred; |
1824 | int ret; | 1866 | int ret; |
1825 | 1867 | ||
1868 | if (!nfs4_has_session(clp)) | ||
1869 | return 0; | ||
1826 | nfs4_begin_drain_session(clp); | 1870 | nfs4_begin_drain_session(clp); |
1827 | cred = nfs4_get_exchange_id_cred(clp); | 1871 | cred = nfs4_get_exchange_id_cred(clp); |
1828 | ret = nfs4_proc_bind_conn_to_session(clp, cred); | 1872 | ret = nfs4_proc_bind_conn_to_session(clp, cred); |
@@ -1857,37 +1901,29 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
1857 | static void nfs4_state_manager(struct nfs_client *clp) | 1901 | static void nfs4_state_manager(struct nfs_client *clp) |
1858 | { | 1902 | { |
1859 | int status = 0; | 1903 | int status = 0; |
1904 | const char *section = "", *section_sep = ""; | ||
1860 | 1905 | ||
1861 | /* Ensure exclusive access to NFSv4 state */ | 1906 | /* Ensure exclusive access to NFSv4 state */ |
1862 | do { | 1907 | do { |
1863 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { | 1908 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { |
1864 | status = nfs4_reclaim_lease(clp); | 1909 | section = "purge state"; |
1910 | status = nfs4_purge_lease(clp); | ||
1865 | if (status < 0) | 1911 | if (status < 0) |
1866 | goto out_error; | 1912 | goto out_error; |
1867 | clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | 1913 | continue; |
1868 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1869 | } | 1914 | } |
1870 | 1915 | ||
1871 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { | 1916 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { |
1917 | section = "lease expired"; | ||
1872 | /* We're going to have to re-establish a clientid */ | 1918 | /* We're going to have to re-establish a clientid */ |
1873 | status = nfs4_reclaim_lease(clp); | 1919 | status = nfs4_reclaim_lease(clp); |
1874 | if (status < 0) | 1920 | if (status < 0) |
1875 | goto out_error; | 1921 | goto out_error; |
1876 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | 1922 | continue; |
1877 | continue; | ||
1878 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | ||
1879 | |||
1880 | if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, | ||
1881 | &clp->cl_state)) | ||
1882 | nfs4_state_start_reclaim_nograce(clp); | ||
1883 | else | ||
1884 | set_bit(NFS4CLNT_RECLAIM_REBOOT, | ||
1885 | &clp->cl_state); | ||
1886 | |||
1887 | pnfs_destroy_all_layouts(clp); | ||
1888 | } | 1923 | } |
1889 | 1924 | ||
1890 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { | 1925 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { |
1926 | section = "check lease"; | ||
1891 | status = nfs4_check_lease(clp); | 1927 | status = nfs4_check_lease(clp); |
1892 | if (status < 0) | 1928 | if (status < 0) |
1893 | goto out_error; | 1929 | goto out_error; |
@@ -1896,8 +1932,8 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1896 | } | 1932 | } |
1897 | 1933 | ||
1898 | /* Initialize or reset the session */ | 1934 | /* Initialize or reset the session */ |
1899 | if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) | 1935 | if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { |
1900 | && nfs4_has_session(clp)) { | 1936 | section = "reset session"; |
1901 | status = nfs4_reset_session(clp); | 1937 | status = nfs4_reset_session(clp); |
1902 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | 1938 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1903 | continue; | 1939 | continue; |
@@ -1907,15 +1943,26 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1907 | 1943 | ||
1908 | /* Send BIND_CONN_TO_SESSION */ | 1944 | /* Send BIND_CONN_TO_SESSION */ |
1909 | if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, | 1945 | if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, |
1910 | &clp->cl_state) && nfs4_has_session(clp)) { | 1946 | &clp->cl_state)) { |
1947 | section = "bind conn to session"; | ||
1911 | status = nfs4_bind_conn_to_session(clp); | 1948 | status = nfs4_bind_conn_to_session(clp); |
1912 | if (status < 0) | 1949 | if (status < 0) |
1913 | goto out_error; | 1950 | goto out_error; |
1914 | continue; | 1951 | continue; |
1915 | } | 1952 | } |
1916 | 1953 | ||
1954 | /* Recall session slots */ | ||
1955 | if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) { | ||
1956 | section = "recall slot"; | ||
1957 | status = nfs4_recall_slot(clp); | ||
1958 | if (status < 0) | ||
1959 | goto out_error; | ||
1960 | continue; | ||
1961 | } | ||
1962 | |||
1917 | /* First recover reboot state... */ | 1963 | /* First recover reboot state... */ |
1918 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { | 1964 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
1965 | section = "reclaim reboot"; | ||
1919 | status = nfs4_do_reclaim(clp, | 1966 | status = nfs4_do_reclaim(clp, |
1920 | clp->cl_mvops->reboot_recovery_ops); | 1967 | clp->cl_mvops->reboot_recovery_ops); |
1921 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1968 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
@@ -1930,6 +1977,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1930 | 1977 | ||
1931 | /* Now recover expired state... */ | 1978 | /* Now recover expired state... */ |
1932 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { | 1979 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
1980 | section = "reclaim nograce"; | ||
1933 | status = nfs4_do_reclaim(clp, | 1981 | status = nfs4_do_reclaim(clp, |
1934 | clp->cl_mvops->nograce_recovery_ops); | 1982 | clp->cl_mvops->nograce_recovery_ops); |
1935 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1983 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
@@ -1945,15 +1993,6 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1945 | nfs_client_return_marked_delegations(clp); | 1993 | nfs_client_return_marked_delegations(clp); |
1946 | continue; | 1994 | continue; |
1947 | } | 1995 | } |
1948 | /* Recall session slots */ | ||
1949 | if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state) | ||
1950 | && nfs4_has_session(clp)) { | ||
1951 | status = nfs4_recall_slot(clp); | ||
1952 | if (status < 0) | ||
1953 | goto out_error; | ||
1954 | continue; | ||
1955 | } | ||
1956 | |||
1957 | 1996 | ||
1958 | nfs4_clear_state_manager_bit(clp); | 1997 | nfs4_clear_state_manager_bit(clp); |
1959 | /* Did we race with an attempt to give us more work? */ | 1998 | /* Did we race with an attempt to give us more work? */ |
@@ -1964,8 +2003,11 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1964 | } while (atomic_read(&clp->cl_count) > 1); | 2003 | } while (atomic_read(&clp->cl_count) > 1); |
1965 | return; | 2004 | return; |
1966 | out_error: | 2005 | out_error: |
1967 | pr_warn_ratelimited("NFS: state manager failed on NFSv4 server %s" | 2006 | if (strlen(section)) |
1968 | " with error %d\n", clp->cl_hostname, -status); | 2007 | section_sep = ": "; |
2008 | pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" | ||
2009 | " with error %d\n", section_sep, section, | ||
2010 | clp->cl_hostname, -status); | ||
1969 | nfs4_end_drain_session(clp); | 2011 | nfs4_end_drain_session(clp); |
1970 | nfs4_clear_state_manager_bit(clp); | 2012 | nfs4_clear_state_manager_bit(clp); |
1971 | } | 2013 | } |