diff options
author | Sage Weil <sage@newdream.net> | 2010-02-22 18:12:16 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2010-02-23 17:26:35 -0500 |
commit | 2600d2dd5085ab6fb09540226138a60055abf335 (patch) | |
tree | 5aeb8a110eb7a41dab2d16b3a5ba8d67ad068a82 | |
parent | a6369741c48815fedfce7072b7a9cd98b5bafd56 (diff) |
ceph: drop messages on unregistered mds sessions; cleanup
Verify the mds session is currently registered before handling
incoming messages. Clean up message handlers to pull mds out
of session->s_mds instead of less trustworthy src field.
Clean up con_{get,put} debug output.
Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r-- | fs/ceph/caps.c | 2 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 85 | ||||
-rw-r--r-- | fs/ceph/snap.c | 17 | ||||
-rw-r--r-- | fs/ceph/super.h | 1 |
4 files changed, 46 insertions, 59 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index b6154ffe70df..bb846164addc 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -2600,7 +2600,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, | |||
2600 | struct inode *inode; | 2600 | struct inode *inode; |
2601 | struct ceph_cap *cap; | 2601 | struct ceph_cap *cap; |
2602 | struct ceph_mds_caps *h; | 2602 | struct ceph_mds_caps *h; |
2603 | int mds = le64_to_cpu(msg->hdr.src.name.num); | 2603 | int mds = session->s_mds; |
2604 | int op; | 2604 | int op; |
2605 | u32 seq; | 2605 | u32 seq; |
2606 | struct ceph_vino vino; | 2606 | struct ceph_vino vino; |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 124c0c17a14a..4d00ea2af000 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -309,6 +309,15 @@ static bool __have_session(struct ceph_mds_client *mdsc, int mds) | |||
309 | return mdsc->sessions[mds]; | 309 | return mdsc->sessions[mds]; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int __verify_registered_session(struct ceph_mds_client *mdsc, | ||
313 | struct ceph_mds_session *s) | ||
314 | { | ||
315 | if (s->s_mds >= mdsc->max_sessions || | ||
316 | mdsc->sessions[s->s_mds] != s) | ||
317 | return -ENOENT; | ||
318 | return 0; | ||
319 | } | ||
320 | |||
312 | /* | 321 | /* |
313 | * create+register a new session for given mds. | 322 | * create+register a new session for given mds. |
314 | * called under mdsc->mutex. | 323 | * called under mdsc->mutex. |
@@ -382,10 +391,11 @@ fail_realloc: | |||
382 | /* | 391 | /* |
383 | * called under mdsc->mutex | 392 | * called under mdsc->mutex |
384 | */ | 393 | */ |
385 | static void unregister_session(struct ceph_mds_client *mdsc, | 394 | static void __unregister_session(struct ceph_mds_client *mdsc, |
386 | struct ceph_mds_session *s) | 395 | struct ceph_mds_session *s) |
387 | { | 396 | { |
388 | dout("unregister_session mds%d %p\n", s->s_mds, s); | 397 | dout("__unregister_session mds%d %p\n", s->s_mds, s); |
398 | BUG_ON(mdsc->sessions[s->s_mds] != s); | ||
389 | mdsc->sessions[s->s_mds] = NULL; | 399 | mdsc->sessions[s->s_mds] = NULL; |
390 | ceph_con_close(&s->s_con); | 400 | ceph_con_close(&s->s_con); |
391 | ceph_put_mds_session(s); | 401 | ceph_put_mds_session(s); |
@@ -1740,10 +1750,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
1740 | struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */ | 1750 | struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */ |
1741 | u64 tid; | 1751 | u64 tid; |
1742 | int err, result; | 1752 | int err, result; |
1743 | int mds; | 1753 | int mds = session->s_mds; |
1744 | 1754 | ||
1745 | if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS) | ||
1746 | return; | ||
1747 | if (msg->front.iov_len < sizeof(*head)) { | 1755 | if (msg->front.iov_len < sizeof(*head)) { |
1748 | pr_err("mdsc_handle_reply got corrupt (short) reply\n"); | 1756 | pr_err("mdsc_handle_reply got corrupt (short) reply\n"); |
1749 | ceph_msg_dump(msg); | 1757 | ceph_msg_dump(msg); |
@@ -1760,7 +1768,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
1760 | return; | 1768 | return; |
1761 | } | 1769 | } |
1762 | dout("handle_reply %p\n", req); | 1770 | dout("handle_reply %p\n", req); |
1763 | mds = le64_to_cpu(msg->hdr.src.name.num); | ||
1764 | 1771 | ||
1765 | /* correct session? */ | 1772 | /* correct session? */ |
1766 | if (!req->r_session && req->r_session != session) { | 1773 | if (!req->r_session && req->r_session != session) { |
@@ -1884,7 +1891,9 @@ out: | |||
1884 | /* | 1891 | /* |
1885 | * handle mds notification that our request has been forwarded. | 1892 | * handle mds notification that our request has been forwarded. |
1886 | */ | 1893 | */ |
1887 | static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) | 1894 | static void handle_forward(struct ceph_mds_client *mdsc, |
1895 | struct ceph_mds_session *session, | ||
1896 | struct ceph_msg *msg) | ||
1888 | { | 1897 | { |
1889 | struct ceph_mds_request *req; | 1898 | struct ceph_mds_request *req; |
1890 | u64 tid; | 1899 | u64 tid; |
@@ -1894,11 +1903,7 @@ static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) | |||
1894 | int err = -EINVAL; | 1903 | int err = -EINVAL; |
1895 | void *p = msg->front.iov_base; | 1904 | void *p = msg->front.iov_base; |
1896 | void *end = p + msg->front.iov_len; | 1905 | void *end = p + msg->front.iov_len; |
1897 | int from_mds, state; | 1906 | int state; |
1898 | |||
1899 | if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS) | ||
1900 | goto bad; | ||
1901 | from_mds = le64_to_cpu(msg->hdr.src.name.num); | ||
1902 | 1907 | ||
1903 | ceph_decode_need(&p, end, sizeof(u64)+2*sizeof(u32), bad); | 1908 | ceph_decode_need(&p, end, sizeof(u64)+2*sizeof(u32), bad); |
1904 | tid = ceph_decode_64(&p); | 1909 | tid = ceph_decode_64(&p); |
@@ -1915,6 +1920,9 @@ static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) | |||
1915 | goto out; /* dup reply? */ | 1920 | goto out; /* dup reply? */ |
1916 | } | 1921 | } |
1917 | 1922 | ||
1923 | if (next_mds >= mdsc->max_sessions) | ||
1924 | goto out; | ||
1925 | |||
1918 | state = mdsc->sessions[next_mds]->s_state; | 1926 | state = mdsc->sessions[next_mds]->s_state; |
1919 | if (fwd_seq <= req->r_num_fwd) { | 1927 | if (fwd_seq <= req->r_num_fwd) { |
1920 | dout("forward %llu to mds%d - old seq %d <= %d\n", | 1928 | dout("forward %llu to mds%d - old seq %d <= %d\n", |
@@ -1945,14 +1953,10 @@ static void handle_session(struct ceph_mds_session *session, | |||
1945 | struct ceph_mds_client *mdsc = session->s_mdsc; | 1953 | struct ceph_mds_client *mdsc = session->s_mdsc; |
1946 | u32 op; | 1954 | u32 op; |
1947 | u64 seq; | 1955 | u64 seq; |
1948 | int mds; | 1956 | int mds = session->s_mds; |
1949 | struct ceph_mds_session_head *h = msg->front.iov_base; | 1957 | struct ceph_mds_session_head *h = msg->front.iov_base; |
1950 | int wake = 0; | 1958 | int wake = 0; |
1951 | 1959 | ||
1952 | if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS) | ||
1953 | return; | ||
1954 | mds = le64_to_cpu(msg->hdr.src.name.num); | ||
1955 | |||
1956 | /* decode */ | 1960 | /* decode */ |
1957 | if (msg->front.iov_len != sizeof(*h)) | 1961 | if (msg->front.iov_len != sizeof(*h)) |
1958 | goto bad; | 1962 | goto bad; |
@@ -1960,6 +1964,8 @@ static void handle_session(struct ceph_mds_session *session, | |||
1960 | seq = le64_to_cpu(h->seq); | 1964 | seq = le64_to_cpu(h->seq); |
1961 | 1965 | ||
1962 | mutex_lock(&mdsc->mutex); | 1966 | mutex_lock(&mdsc->mutex); |
1967 | if (op == CEPH_SESSION_CLOSE) | ||
1968 | __unregister_session(mdsc, session); | ||
1963 | /* FIXME: this ttl calculation is generous */ | 1969 | /* FIXME: this ttl calculation is generous */ |
1964 | session->s_ttl = jiffies + HZ*mdsc->mdsmap->m_session_autoclose; | 1970 | session->s_ttl = jiffies + HZ*mdsc->mdsmap->m_session_autoclose; |
1965 | mutex_unlock(&mdsc->mutex); | 1971 | mutex_unlock(&mdsc->mutex); |
@@ -1990,7 +1996,6 @@ static void handle_session(struct ceph_mds_session *session, | |||
1990 | break; | 1996 | break; |
1991 | 1997 | ||
1992 | case CEPH_SESSION_CLOSE: | 1998 | case CEPH_SESSION_CLOSE: |
1993 | unregister_session(mdsc, session); | ||
1994 | remove_session_caps(session); | 1999 | remove_session_caps(session); |
1995 | wake = 1; /* for good measure */ | 2000 | wake = 1; /* for good measure */ |
1996 | complete(&mdsc->session_close_waiters); | 2001 | complete(&mdsc->session_close_waiters); |
@@ -2269,7 +2274,7 @@ static void check_new_map(struct ceph_mds_client *mdsc, | |||
2269 | /* the session never opened, just close it | 2274 | /* the session never opened, just close it |
2270 | * out now */ | 2275 | * out now */ |
2271 | __wake_requests(mdsc, &s->s_waiting); | 2276 | __wake_requests(mdsc, &s->s_waiting); |
2272 | unregister_session(mdsc, s); | 2277 | __unregister_session(mdsc, s); |
2273 | } else { | 2278 | } else { |
2274 | /* just close it */ | 2279 | /* just close it */ |
2275 | mutex_unlock(&mdsc->mutex); | 2280 | mutex_unlock(&mdsc->mutex); |
@@ -2329,24 +2334,22 @@ void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry) | |||
2329 | di->lease_session = NULL; | 2334 | di->lease_session = NULL; |
2330 | } | 2335 | } |
2331 | 2336 | ||
2332 | static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg) | 2337 | static void handle_lease(struct ceph_mds_client *mdsc, |
2338 | struct ceph_mds_session *session, | ||
2339 | struct ceph_msg *msg) | ||
2333 | { | 2340 | { |
2334 | struct super_block *sb = mdsc->client->sb; | 2341 | struct super_block *sb = mdsc->client->sb; |
2335 | struct inode *inode; | 2342 | struct inode *inode; |
2336 | struct ceph_mds_session *session; | ||
2337 | struct ceph_inode_info *ci; | 2343 | struct ceph_inode_info *ci; |
2338 | struct dentry *parent, *dentry; | 2344 | struct dentry *parent, *dentry; |
2339 | struct ceph_dentry_info *di; | 2345 | struct ceph_dentry_info *di; |
2340 | int mds; | 2346 | int mds = session->s_mds; |
2341 | struct ceph_mds_lease *h = msg->front.iov_base; | 2347 | struct ceph_mds_lease *h = msg->front.iov_base; |
2342 | struct ceph_vino vino; | 2348 | struct ceph_vino vino; |
2343 | int mask; | 2349 | int mask; |
2344 | struct qstr dname; | 2350 | struct qstr dname; |
2345 | int release = 0; | 2351 | int release = 0; |
2346 | 2352 | ||
2347 | if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS) | ||
2348 | return; | ||
2349 | mds = le64_to_cpu(msg->hdr.src.name.num); | ||
2350 | dout("handle_lease from mds%d\n", mds); | 2353 | dout("handle_lease from mds%d\n", mds); |
2351 | 2354 | ||
2352 | /* decode */ | 2355 | /* decode */ |
@@ -2360,15 +2363,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg) | |||
2360 | if (dname.len != get_unaligned_le32(h+1)) | 2363 | if (dname.len != get_unaligned_le32(h+1)) |
2361 | goto bad; | 2364 | goto bad; |
2362 | 2365 | ||
2363 | /* find session */ | ||
2364 | mutex_lock(&mdsc->mutex); | ||
2365 | session = __ceph_lookup_mds_session(mdsc, mds); | ||
2366 | mutex_unlock(&mdsc->mutex); | ||
2367 | if (!session) { | ||
2368 | pr_err("handle_lease got lease but no session mds%d\n", mds); | ||
2369 | return; | ||
2370 | } | ||
2371 | |||
2372 | mutex_lock(&session->s_mutex); | 2366 | mutex_lock(&session->s_mutex); |
2373 | session->s_seq++; | 2367 | session->s_seq++; |
2374 | 2368 | ||
@@ -2437,7 +2431,6 @@ release: | |||
2437 | out: | 2431 | out: |
2438 | iput(inode); | 2432 | iput(inode); |
2439 | mutex_unlock(&session->s_mutex); | 2433 | mutex_unlock(&session->s_mutex); |
2440 | ceph_put_mds_session(session); | ||
2441 | return; | 2434 | return; |
2442 | 2435 | ||
2443 | bad: | 2436 | bad: |
@@ -2794,7 +2787,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc) | |||
2794 | for (i = 0; i < mdsc->max_sessions; i++) { | 2787 | for (i = 0; i < mdsc->max_sessions; i++) { |
2795 | if (mdsc->sessions[i]) { | 2788 | if (mdsc->sessions[i]) { |
2796 | session = get_session(mdsc->sessions[i]); | 2789 | session = get_session(mdsc->sessions[i]); |
2797 | unregister_session(mdsc, session); | 2790 | __unregister_session(mdsc, session); |
2798 | mutex_unlock(&mdsc->mutex); | 2791 | mutex_unlock(&mdsc->mutex); |
2799 | mutex_lock(&session->s_mutex); | 2792 | mutex_lock(&session->s_mutex); |
2800 | remove_session_caps(session); | 2793 | remove_session_caps(session); |
@@ -2891,8 +2884,7 @@ static struct ceph_connection *con_get(struct ceph_connection *con) | |||
2891 | struct ceph_mds_session *s = con->private; | 2884 | struct ceph_mds_session *s = con->private; |
2892 | 2885 | ||
2893 | if (get_session(s)) { | 2886 | if (get_session(s)) { |
2894 | dout("mdsc con_get %p %d -> %d\n", s, | 2887 | dout("mdsc con_get %p ok (%d)\n", s, atomic_read(&s->s_ref)); |
2895 | atomic_read(&s->s_ref) - 1, atomic_read(&s->s_ref)); | ||
2896 | return con; | 2888 | return con; |
2897 | } | 2889 | } |
2898 | dout("mdsc con_get %p FAIL\n", s); | 2890 | dout("mdsc con_get %p FAIL\n", s); |
@@ -2903,9 +2895,8 @@ static void con_put(struct ceph_connection *con) | |||
2903 | { | 2895 | { |
2904 | struct ceph_mds_session *s = con->private; | 2896 | struct ceph_mds_session *s = con->private; |
2905 | 2897 | ||
2906 | dout("mdsc con_put %p %d -> %d\n", s, atomic_read(&s->s_ref), | ||
2907 | atomic_read(&s->s_ref) - 1); | ||
2908 | ceph_put_mds_session(s); | 2898 | ceph_put_mds_session(s); |
2899 | dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref)); | ||
2909 | } | 2900 | } |
2910 | 2901 | ||
2911 | /* | 2902 | /* |
@@ -2926,6 +2917,13 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) | |||
2926 | struct ceph_mds_client *mdsc = s->s_mdsc; | 2917 | struct ceph_mds_client *mdsc = s->s_mdsc; |
2927 | int type = le16_to_cpu(msg->hdr.type); | 2918 | int type = le16_to_cpu(msg->hdr.type); |
2928 | 2919 | ||
2920 | mutex_lock(&mdsc->mutex); | ||
2921 | if (__verify_registered_session(mdsc, s) < 0) { | ||
2922 | mutex_unlock(&mdsc->mutex); | ||
2923 | goto out; | ||
2924 | } | ||
2925 | mutex_unlock(&mdsc->mutex); | ||
2926 | |||
2929 | switch (type) { | 2927 | switch (type) { |
2930 | case CEPH_MSG_MDS_MAP: | 2928 | case CEPH_MSG_MDS_MAP: |
2931 | ceph_mdsc_handle_map(mdsc, msg); | 2929 | ceph_mdsc_handle_map(mdsc, msg); |
@@ -2937,22 +2935,23 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) | |||
2937 | handle_reply(s, msg); | 2935 | handle_reply(s, msg); |
2938 | break; | 2936 | break; |
2939 | case CEPH_MSG_CLIENT_REQUEST_FORWARD: | 2937 | case CEPH_MSG_CLIENT_REQUEST_FORWARD: |
2940 | handle_forward(mdsc, msg); | 2938 | handle_forward(mdsc, s, msg); |
2941 | break; | 2939 | break; |
2942 | case CEPH_MSG_CLIENT_CAPS: | 2940 | case CEPH_MSG_CLIENT_CAPS: |
2943 | ceph_handle_caps(s, msg); | 2941 | ceph_handle_caps(s, msg); |
2944 | break; | 2942 | break; |
2945 | case CEPH_MSG_CLIENT_SNAP: | 2943 | case CEPH_MSG_CLIENT_SNAP: |
2946 | ceph_handle_snap(mdsc, msg); | 2944 | ceph_handle_snap(mdsc, s, msg); |
2947 | break; | 2945 | break; |
2948 | case CEPH_MSG_CLIENT_LEASE: | 2946 | case CEPH_MSG_CLIENT_LEASE: |
2949 | handle_lease(mdsc, msg); | 2947 | handle_lease(mdsc, s, msg); |
2950 | break; | 2948 | break; |
2951 | 2949 | ||
2952 | default: | 2950 | default: |
2953 | pr_err("received unknown message type %d %s\n", type, | 2951 | pr_err("received unknown message type %d %s\n", type, |
2954 | ceph_msg_type_name(type)); | 2952 | ceph_msg_type_name(type)); |
2955 | } | 2953 | } |
2954 | out: | ||
2956 | ceph_msg_put(msg); | 2955 | ceph_msg_put(msg); |
2957 | } | 2956 | } |
2958 | 2957 | ||
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 49d0c4c59d81..bf2a5f3846a4 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -713,11 +713,11 @@ static void flush_snaps(struct ceph_mds_client *mdsc) | |||
713 | * directory into another realm. | 713 | * directory into another realm. |
714 | */ | 714 | */ |
715 | void ceph_handle_snap(struct ceph_mds_client *mdsc, | 715 | void ceph_handle_snap(struct ceph_mds_client *mdsc, |
716 | struct ceph_mds_session *session, | ||
716 | struct ceph_msg *msg) | 717 | struct ceph_msg *msg) |
717 | { | 718 | { |
718 | struct super_block *sb = mdsc->client->sb; | 719 | struct super_block *sb = mdsc->client->sb; |
719 | struct ceph_mds_session *session; | 720 | int mds = session->s_mds; |
720 | int mds; | ||
721 | u64 split; | 721 | u64 split; |
722 | int op; | 722 | int op; |
723 | int trace_len; | 723 | int trace_len; |
@@ -730,10 +730,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, | |||
730 | int i; | 730 | int i; |
731 | int locked_rwsem = 0; | 731 | int locked_rwsem = 0; |
732 | 732 | ||
733 | if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS) | ||
734 | return; | ||
735 | mds = le64_to_cpu(msg->hdr.src.name.num); | ||
736 | |||
737 | /* decode */ | 733 | /* decode */ |
738 | if (msg->front.iov_len < sizeof(*h)) | 734 | if (msg->front.iov_len < sizeof(*h)) |
739 | goto bad; | 735 | goto bad; |
@@ -749,15 +745,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, | |||
749 | dout("handle_snap from mds%d op %s split %llx tracelen %d\n", mds, | 745 | dout("handle_snap from mds%d op %s split %llx tracelen %d\n", mds, |
750 | ceph_snap_op_name(op), split, trace_len); | 746 | ceph_snap_op_name(op), split, trace_len); |
751 | 747 | ||
752 | /* find session */ | ||
753 | mutex_lock(&mdsc->mutex); | ||
754 | session = __ceph_lookup_mds_session(mdsc, mds); | ||
755 | mutex_unlock(&mdsc->mutex); | ||
756 | if (!session) { | ||
757 | dout("WTF, got snap but no session for mds%d\n", mds); | ||
758 | return; | ||
759 | } | ||
760 | |||
761 | mutex_lock(&session->s_mutex); | 748 | mutex_lock(&session->s_mutex); |
762 | session->s_seq++; | 749 | session->s_seq++; |
763 | mutex_unlock(&session->s_mutex); | 750 | mutex_unlock(&session->s_mutex); |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 384f0e2e7c68..ff7aaa32736c 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -707,6 +707,7 @@ extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc, | |||
707 | extern int ceph_update_snap_trace(struct ceph_mds_client *m, | 707 | extern int ceph_update_snap_trace(struct ceph_mds_client *m, |
708 | void *p, void *e, bool deletion); | 708 | void *p, void *e, bool deletion); |
709 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, | 709 | extern void ceph_handle_snap(struct ceph_mds_client *mdsc, |
710 | struct ceph_mds_session *session, | ||
710 | struct ceph_msg *msg); | 711 | struct ceph_msg *msg); |
711 | extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, | 712 | extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, |
712 | struct ceph_snap_context *snapc); | 713 | struct ceph_snap_context *snapc); |