diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
| -rw-r--r-- | fs/nfs/nfs4state.c | 143 |
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 | ||
| 67 | const nfs4_stateid zero_stateid; | 68 | const nfs4_stateid zero_stateid; |
| 68 | static DEFINE_MUTEX(nfs_clid_init_mutex); | 69 | static DEFINE_MUTEX(nfs_clid_init_mutex); |
| 69 | static LIST_HEAD(nfs4_clientid_list); | ||
| 70 | 70 | ||
| 71 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 71 | int 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 | */ | ||
| 271 | void 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 | |||
| 275 | static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl) | 278 | static 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 | */ |
| 1087 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) | 1089 | static 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 | } |
| 1210 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); | 1211 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery); |
| 1211 | 1212 | ||
| 1213 | int 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 | |||
| 1229 | int 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 | ||
| 1564 | static 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 | |||
| 1572 | static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | 1591 | static 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 | } |
| 1908 | EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); | 1920 | EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery); |
| 1909 | 1921 | ||
| 1910 | void nfs41_handle_recall_slot(struct nfs_client *clp) | 1922 | static 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 | ||
| 1929 | void nfs41_server_notify_target_slotid_update(struct nfs_client *clp) | ||
| 1930 | { | ||
| 1931 | nfs41_ping_server(clp); | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp) | ||
| 1935 | { | ||
| 1936 | nfs41_ping_server(clp); | ||
| 1937 | } | ||
| 1938 | |||
| 1918 | static void nfs4_reset_all_state(struct nfs_client *clp) | 1939 | static 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 | ||
| 2027 | static 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 | |||
| 2056 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) | 2048 | static 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 */ |
| 2084 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | 2076 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
| 2085 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | 2077 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } |
| 2086 | static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | ||
| 2087 | 2078 | ||
| 2088 | static int nfs4_bind_conn_to_session(struct nfs_client *clp) | 2079 | static 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; |
