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.c143
1 files changed, 62 insertions, 81 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c351e6b39838..9448c579d41a 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -57,6 +57,7 @@
57#include "callback.h" 57#include "callback.h"
58#include "delegation.h" 58#include "delegation.h"
59#include "internal.h" 59#include "internal.h"
60#include "nfs4session.h"
60#include "pnfs.h" 61#include "pnfs.h"
61#include "netns.h" 62#include "netns.h"
62 63
@@ -66,7 +67,6 @@
66 67
67const nfs4_stateid zero_stateid; 68const nfs4_stateid zero_stateid;
68static DEFINE_MUTEX(nfs_clid_init_mutex); 69static DEFINE_MUTEX(nfs_clid_init_mutex);
69static LIST_HEAD(nfs4_clientid_list);
70 70
71int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) 71int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
72{ 72{
@@ -254,24 +254,27 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
254{ 254{
255 struct nfs4_session *ses = clp->cl_session; 255 struct nfs4_session *ses = clp->cl_session;
256 struct nfs4_slot_table *tbl; 256 struct nfs4_slot_table *tbl;
257 int max_slots;
258 257
259 if (ses == NULL) 258 if (ses == NULL)
260 return; 259 return;
261 tbl = &ses->fc_slot_table; 260 tbl = &ses->fc_slot_table;
262 if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { 261 if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
263 spin_lock(&tbl->slot_tbl_lock); 262 spin_lock(&tbl->slot_tbl_lock);
264 max_slots = tbl->max_slots; 263 nfs41_wake_slot_table(tbl);
265 while (max_slots--) {
266 if (rpc_wake_up_first(&tbl->slot_tbl_waitq,
267 nfs4_set_task_privileged,
268 NULL) == NULL)
269 break;
270 }
271 spin_unlock(&tbl->slot_tbl_lock); 264 spin_unlock(&tbl->slot_tbl_lock);
272 } 265 }
273} 266}
274 267
268/*
269 * Signal state manager thread if session fore channel is drained
270 */
271void nfs4_session_drain_complete(struct nfs4_session *session,
272 struct nfs4_slot_table *tbl)
273{
274 if (nfs4_session_draining(session))
275 complete(&tbl->complete);
276}
277
275static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) 278static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl)
276{ 279{
277 spin_lock(&tbl->slot_tbl_lock); 280 spin_lock(&tbl->slot_tbl_lock);
@@ -303,7 +306,6 @@ static void nfs41_finish_session_reset(struct nfs_client *clp)
303 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); 306 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
304 clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); 307 clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
305 /* create_session negotiated new slot table */ 308 /* create_session negotiated new slot table */
306 clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
307 clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); 309 clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
308 nfs41_setup_state_renewal(clp); 310 nfs41_setup_state_renewal(clp);
309} 311}
@@ -1086,7 +1088,6 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
1086 */ 1088 */
1087static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) 1089static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
1088{ 1090{
1089 BUG_ON(list_first_entry(&seqid->sequence->list, struct nfs_seqid, list) != seqid);
1090 switch (status) { 1091 switch (status) {
1091 case 0: 1092 case 0:
1092 break; 1093 break;
@@ -1209,6 +1210,40 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp)
1209} 1210}
1210EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); 1211EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery);
1211 1212
1213int nfs4_wait_clnt_recover(struct nfs_client *clp)
1214{
1215 int res;
1216
1217 might_sleep();
1218
1219 res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING,
1220 nfs_wait_bit_killable, TASK_KILLABLE);
1221 if (res)
1222 return res;
1223
1224 if (clp->cl_cons_state < 0)
1225 return clp->cl_cons_state;
1226 return 0;
1227}
1228
1229int nfs4_client_recover_expired_lease(struct nfs_client *clp)
1230{
1231 unsigned int loop;
1232 int ret;
1233
1234 for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
1235 ret = nfs4_wait_clnt_recover(clp);
1236 if (ret != 0)
1237 break;
1238 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
1239 !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state))
1240 break;
1241 nfs4_schedule_state_manager(clp);
1242 ret = -EIO;
1243 }
1244 return ret;
1245}
1246
1212/* 1247/*
1213 * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN 1248 * nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
1214 * @clp: client to process 1249 * @clp: client to process
@@ -1401,14 +1436,6 @@ restart:
1401 /* Mark the file as being 'closed' */ 1436 /* Mark the file as being 'closed' */
1402 state->state = 0; 1437 state->state = 0;
1403 break; 1438 break;
1404 case -EKEYEXPIRED:
1405 /*
1406 * User RPCSEC_GSS context has expired.
1407 * We cannot recover this stateid now, so
1408 * skip it and allow recovery thread to
1409 * proceed.
1410 */
1411 break;
1412 case -NFS4ERR_ADMIN_REVOKED: 1439 case -NFS4ERR_ADMIN_REVOKED:
1413 case -NFS4ERR_STALE_STATEID: 1440 case -NFS4ERR_STALE_STATEID:
1414 case -NFS4ERR_BAD_STATEID: 1441 case -NFS4ERR_BAD_STATEID:
@@ -1561,14 +1588,6 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
1561 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); 1588 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
1562} 1589}
1563 1590
1564static void nfs4_warn_keyexpired(const char *s)
1565{
1566 printk_ratelimited(KERN_WARNING "Error: state manager"
1567 " encountered RPCSEC_GSS session"
1568 " expired against NFSv4 server %s.\n",
1569 s);
1570}
1571
1572static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) 1591static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1573{ 1592{
1574 switch (error) { 1593 switch (error) {
@@ -1602,10 +1621,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1602 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: 1621 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
1603 set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state); 1622 set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
1604 break; 1623 break;
1605 case -EKEYEXPIRED:
1606 /* Nothing we can do */
1607 nfs4_warn_keyexpired(clp->cl_hostname);
1608 break;
1609 default: 1624 default:
1610 dprintk("%s: failed to handle error %d for server %s\n", 1625 dprintk("%s: failed to handle error %d for server %s\n",
1611 __func__, error, clp->cl_hostname); 1626 __func__, error, clp->cl_hostname);
@@ -1722,8 +1737,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
1722 dprintk("%s: exit with error %d for server %s\n", 1737 dprintk("%s: exit with error %d for server %s\n",
1723 __func__, -EPROTONOSUPPORT, clp->cl_hostname); 1738 __func__, -EPROTONOSUPPORT, clp->cl_hostname);
1724 return -EPROTONOSUPPORT; 1739 return -EPROTONOSUPPORT;
1725 case -EKEYEXPIRED:
1726 nfs4_warn_keyexpired(clp->cl_hostname);
1727 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery 1740 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1728 * in nfs4_exchange_id */ 1741 * in nfs4_exchange_id */
1729 default: 1742 default:
@@ -1876,7 +1889,6 @@ again:
1876 break; 1889 break;
1877 1890
1878 case -EKEYEXPIRED: 1891 case -EKEYEXPIRED:
1879 nfs4_warn_keyexpired(clp->cl_hostname);
1880 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery 1892 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1881 * in nfs4_exchange_id */ 1893 * in nfs4_exchange_id */
1882 status = -EKEYEXPIRED; 1894 status = -EKEYEXPIRED;
@@ -1907,14 +1919,23 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
1907} 1919}
1908EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); 1920EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery);
1909 1921
1910void nfs41_handle_recall_slot(struct nfs_client *clp) 1922static void nfs41_ping_server(struct nfs_client *clp)
1911{ 1923{
1912 set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); 1924 /* Use CHECK_LEASE to ping the server with a SEQUENCE */
1913 dprintk("%s: scheduling slot recall for server %s\n", __func__, 1925 set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
1914 clp->cl_hostname);
1915 nfs4_schedule_state_manager(clp); 1926 nfs4_schedule_state_manager(clp);
1916} 1927}
1917 1928
1929void nfs41_server_notify_target_slotid_update(struct nfs_client *clp)
1930{
1931 nfs41_ping_server(clp);
1932}
1933
1934void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp)
1935{
1936 nfs41_ping_server(clp);
1937}
1938
1918static void nfs4_reset_all_state(struct nfs_client *clp) 1939static void nfs4_reset_all_state(struct nfs_client *clp)
1919{ 1940{
1920 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { 1941 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
@@ -2024,35 +2045,6 @@ out:
2024 return status; 2045 return status;
2025} 2046}
2026 2047
2027static int nfs4_recall_slot(struct nfs_client *clp)
2028{
2029 struct nfs4_slot_table *fc_tbl;
2030 struct nfs4_slot *new, *old;
2031 int i;
2032
2033 if (!nfs4_has_session(clp))
2034 return 0;
2035 nfs4_begin_drain_session(clp);
2036 fc_tbl = &clp->cl_session->fc_slot_table;
2037 new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
2038 GFP_NOFS);
2039 if (!new)
2040 return -ENOMEM;
2041
2042 spin_lock(&fc_tbl->slot_tbl_lock);
2043 for (i = 0; i < fc_tbl->target_max_slots; i++)
2044 new[i].seq_nr = fc_tbl->slots[i].seq_nr;
2045 old = fc_tbl->slots;
2046 fc_tbl->slots = new;
2047 fc_tbl->max_slots = fc_tbl->target_max_slots;
2048 fc_tbl->target_max_slots = 0;
2049 clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
2050 spin_unlock(&fc_tbl->slot_tbl_lock);
2051
2052 kfree(old);
2053 return 0;
2054}
2055
2056static int nfs4_bind_conn_to_session(struct nfs_client *clp) 2048static int nfs4_bind_conn_to_session(struct nfs_client *clp)
2057{ 2049{
2058 struct rpc_cred *cred; 2050 struct rpc_cred *cred;
@@ -2083,7 +2075,6 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
2083#else /* CONFIG_NFS_V4_1 */ 2075#else /* CONFIG_NFS_V4_1 */
2084static int nfs4_reset_session(struct nfs_client *clp) { return 0; } 2076static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
2085static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } 2077static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
2086static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
2087 2078
2088static int nfs4_bind_conn_to_session(struct nfs_client *clp) 2079static int nfs4_bind_conn_to_session(struct nfs_client *clp)
2089{ 2080{
@@ -2115,15 +2106,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
2115 continue; 2106 continue;
2116 } 2107 }
2117 2108
2118 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
2119 section = "check lease";
2120 status = nfs4_check_lease(clp);
2121 if (status < 0)
2122 goto out_error;
2123 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
2124 continue;
2125 }
2126
2127 /* Initialize or reset the session */ 2109 /* Initialize or reset the session */
2128 if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { 2110 if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) {
2129 section = "reset session"; 2111 section = "reset session";
@@ -2144,10 +2126,9 @@ static void nfs4_state_manager(struct nfs_client *clp)
2144 continue; 2126 continue;
2145 } 2127 }
2146 2128
2147 /* Recall session slots */ 2129 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
2148 if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) { 2130 section = "check lease";
2149 section = "recall slot"; 2131 status = nfs4_check_lease(clp);
2150 status = nfs4_recall_slot(clp);
2151 if (status < 0) 2132 if (status < 0)
2152 goto out_error; 2133 goto out_error;
2153 continue; 2134 continue;