aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c114
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
1645static int nfs4_reclaim_lease(struct nfs_client *clp) 1650static 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 */
1672static 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
1688static 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
1793static int nfs4_recall_slot(struct nfs_client *clp) 1834static 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)
1857static void nfs4_state_manager(struct nfs_client *clp) 1901static 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;
1966out_error: 2005out_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}