Commit 2600d2dd authored by Sage Weil's avatar Sage Weil

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: default avatarSage Weil <sage@newdream.net>
parent a6369741
...@@ -2600,7 +2600,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, ...@@ -2600,7 +2600,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
struct inode *inode; struct inode *inode;
struct ceph_cap *cap; struct ceph_cap *cap;
struct ceph_mds_caps *h; struct ceph_mds_caps *h;
int mds = le64_to_cpu(msg->hdr.src.name.num); int mds = session->s_mds;
int op; int op;
u32 seq; u32 seq;
struct ceph_vino vino; struct ceph_vino vino;
......
...@@ -309,6 +309,15 @@ static bool __have_session(struct ceph_mds_client *mdsc, int mds) ...@@ -309,6 +309,15 @@ static bool __have_session(struct ceph_mds_client *mdsc, int mds)
return mdsc->sessions[mds]; return mdsc->sessions[mds];
} }
static int __verify_registered_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *s)
{
if (s->s_mds >= mdsc->max_sessions ||
mdsc->sessions[s->s_mds] != s)
return -ENOENT;
return 0;
}
/* /*
* create+register a new session for given mds. * create+register a new session for given mds.
* called under mdsc->mutex. * called under mdsc->mutex.
...@@ -382,10 +391,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, ...@@ -382,10 +391,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
/* /*
* called under mdsc->mutex * called under mdsc->mutex
*/ */
static void unregister_session(struct ceph_mds_client *mdsc, static void __unregister_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *s) struct ceph_mds_session *s)
{ {
dout("unregister_session mds%d %p\n", s->s_mds, s); dout("__unregister_session mds%d %p\n", s->s_mds, s);
BUG_ON(mdsc->sessions[s->s_mds] != s);
mdsc->sessions[s->s_mds] = NULL; mdsc->sessions[s->s_mds] = NULL;
ceph_con_close(&s->s_con); ceph_con_close(&s->s_con);
ceph_put_mds_session(s); ceph_put_mds_session(s);
...@@ -1740,10 +1750,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) ...@@ -1740,10 +1750,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */ struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */
u64 tid; u64 tid;
int err, result; int err, result;
int mds; int mds = session->s_mds;
if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS)
return;
if (msg->front.iov_len < sizeof(*head)) { if (msg->front.iov_len < sizeof(*head)) {
pr_err("mdsc_handle_reply got corrupt (short) reply\n"); pr_err("mdsc_handle_reply got corrupt (short) reply\n");
ceph_msg_dump(msg); ceph_msg_dump(msg);
...@@ -1760,7 +1768,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) ...@@ -1760,7 +1768,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
return; return;
} }
dout("handle_reply %p\n", req); dout("handle_reply %p\n", req);
mds = le64_to_cpu(msg->hdr.src.name.num);
/* correct session? */ /* correct session? */
if (!req->r_session && req->r_session != session) { if (!req->r_session && req->r_session != session) {
...@@ -1884,7 +1891,9 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) ...@@ -1884,7 +1891,9 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
/* /*
* handle mds notification that our request has been forwarded. * handle mds notification that our request has been forwarded.
*/ */
static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) static void handle_forward(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{ {
struct ceph_mds_request *req; struct ceph_mds_request *req;
u64 tid; u64 tid;
...@@ -1894,11 +1903,7 @@ static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) ...@@ -1894,11 +1903,7 @@ static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
int err = -EINVAL; int err = -EINVAL;
void *p = msg->front.iov_base; void *p = msg->front.iov_base;
void *end = p + msg->front.iov_len; void *end = p + msg->front.iov_len;
int from_mds, state; int state;
if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS)
goto bad;
from_mds = le64_to_cpu(msg->hdr.src.name.num);
ceph_decode_need(&p, end, sizeof(u64)+2*sizeof(u32), bad); ceph_decode_need(&p, end, sizeof(u64)+2*sizeof(u32), bad);
tid = ceph_decode_64(&p); tid = ceph_decode_64(&p);
...@@ -1915,6 +1920,9 @@ static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) ...@@ -1915,6 +1920,9 @@ static void handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
goto out; /* dup reply? */ goto out; /* dup reply? */
} }
if (next_mds >= mdsc->max_sessions)
goto out;
state = mdsc->sessions[next_mds]->s_state; state = mdsc->sessions[next_mds]->s_state;
if (fwd_seq <= req->r_num_fwd) { if (fwd_seq <= req->r_num_fwd) {
dout("forward %llu to mds%d - old seq %d <= %d\n", 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,14 +1953,10 @@ static void handle_session(struct ceph_mds_session *session,
struct ceph_mds_client *mdsc = session->s_mdsc; struct ceph_mds_client *mdsc = session->s_mdsc;
u32 op; u32 op;
u64 seq; u64 seq;
int mds; int mds = session->s_mds;
struct ceph_mds_session_head *h = msg->front.iov_base; struct ceph_mds_session_head *h = msg->front.iov_base;
int wake = 0; int wake = 0;
if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS)
return;
mds = le64_to_cpu(msg->hdr.src.name.num);
/* decode */ /* decode */
if (msg->front.iov_len != sizeof(*h)) if (msg->front.iov_len != sizeof(*h))
goto bad; goto bad;
...@@ -1960,6 +1964,8 @@ static void handle_session(struct ceph_mds_session *session, ...@@ -1960,6 +1964,8 @@ static void handle_session(struct ceph_mds_session *session,
seq = le64_to_cpu(h->seq); seq = le64_to_cpu(h->seq);
mutex_lock(&mdsc->mutex); mutex_lock(&mdsc->mutex);
if (op == CEPH_SESSION_CLOSE)
__unregister_session(mdsc, session);
/* FIXME: this ttl calculation is generous */ /* FIXME: this ttl calculation is generous */
session->s_ttl = jiffies + HZ*mdsc->mdsmap->m_session_autoclose; session->s_ttl = jiffies + HZ*mdsc->mdsmap->m_session_autoclose;
mutex_unlock(&mdsc->mutex); mutex_unlock(&mdsc->mutex);
...@@ -1990,7 +1996,6 @@ static void handle_session(struct ceph_mds_session *session, ...@@ -1990,7 +1996,6 @@ static void handle_session(struct ceph_mds_session *session,
break; break;
case CEPH_SESSION_CLOSE: case CEPH_SESSION_CLOSE:
unregister_session(mdsc, session);
remove_session_caps(session); remove_session_caps(session);
wake = 1; /* for good measure */ wake = 1; /* for good measure */
complete(&mdsc->session_close_waiters); complete(&mdsc->session_close_waiters);
...@@ -2269,7 +2274,7 @@ static void check_new_map(struct ceph_mds_client *mdsc, ...@@ -2269,7 +2274,7 @@ static void check_new_map(struct ceph_mds_client *mdsc,
/* the session never opened, just close it /* the session never opened, just close it
* out now */ * out now */
__wake_requests(mdsc, &s->s_waiting); __wake_requests(mdsc, &s->s_waiting);
unregister_session(mdsc, s); __unregister_session(mdsc, s);
} else { } else {
/* just close it */ /* just close it */
mutex_unlock(&mdsc->mutex); mutex_unlock(&mdsc->mutex);
...@@ -2329,24 +2334,22 @@ void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry) ...@@ -2329,24 +2334,22 @@ void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry)
di->lease_session = NULL; di->lease_session = NULL;
} }
static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg) static void handle_lease(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{ {
struct super_block *sb = mdsc->client->sb; struct super_block *sb = mdsc->client->sb;
struct inode *inode; struct inode *inode;
struct ceph_mds_session *session;
struct ceph_inode_info *ci; struct ceph_inode_info *ci;
struct dentry *parent, *dentry; struct dentry *parent, *dentry;
struct ceph_dentry_info *di; struct ceph_dentry_info *di;
int mds; int mds = session->s_mds;
struct ceph_mds_lease *h = msg->front.iov_base; struct ceph_mds_lease *h = msg->front.iov_base;
struct ceph_vino vino; struct ceph_vino vino;
int mask; int mask;
struct qstr dname; struct qstr dname;
int release = 0; int release = 0;
if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS)
return;
mds = le64_to_cpu(msg->hdr.src.name.num);
dout("handle_lease from mds%d\n", mds); dout("handle_lease from mds%d\n", mds);
/* decode */ /* decode */
...@@ -2360,15 +2363,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg) ...@@ -2360,15 +2363,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
if (dname.len != get_unaligned_le32(h+1)) if (dname.len != get_unaligned_le32(h+1))
goto bad; goto bad;
/* find session */
mutex_lock(&mdsc->mutex);
session = __ceph_lookup_mds_session(mdsc, mds);
mutex_unlock(&mdsc->mutex);
if (!session) {
pr_err("handle_lease got lease but no session mds%d\n", mds);
return;
}
mutex_lock(&session->s_mutex); mutex_lock(&session->s_mutex);
session->s_seq++; session->s_seq++;
...@@ -2437,7 +2431,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg) ...@@ -2437,7 +2431,6 @@ static void handle_lease(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
out: out:
iput(inode); iput(inode);
mutex_unlock(&session->s_mutex); mutex_unlock(&session->s_mutex);
ceph_put_mds_session(session);
return; return;
bad: bad:
...@@ -2794,7 +2787,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc) ...@@ -2794,7 +2787,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
for (i = 0; i < mdsc->max_sessions; i++) { for (i = 0; i < mdsc->max_sessions; i++) {
if (mdsc->sessions[i]) { if (mdsc->sessions[i]) {
session = get_session(mdsc->sessions[i]); session = get_session(mdsc->sessions[i]);
unregister_session(mdsc, session); __unregister_session(mdsc, session);
mutex_unlock(&mdsc->mutex); mutex_unlock(&mdsc->mutex);
mutex_lock(&session->s_mutex); mutex_lock(&session->s_mutex);
remove_session_caps(session); remove_session_caps(session);
...@@ -2891,8 +2884,7 @@ static struct ceph_connection *con_get(struct ceph_connection *con) ...@@ -2891,8 +2884,7 @@ static struct ceph_connection *con_get(struct ceph_connection *con)
struct ceph_mds_session *s = con->private; struct ceph_mds_session *s = con->private;
if (get_session(s)) { if (get_session(s)) {
dout("mdsc con_get %p %d -> %d\n", s, dout("mdsc con_get %p ok (%d)\n", s, atomic_read(&s->s_ref));
atomic_read(&s->s_ref) - 1, atomic_read(&s->s_ref));
return con; return con;
} }
dout("mdsc con_get %p FAIL\n", s); dout("mdsc con_get %p FAIL\n", s);
...@@ -2903,9 +2895,8 @@ static void con_put(struct ceph_connection *con) ...@@ -2903,9 +2895,8 @@ static void con_put(struct ceph_connection *con)
{ {
struct ceph_mds_session *s = con->private; struct ceph_mds_session *s = con->private;
dout("mdsc con_put %p %d -> %d\n", s, atomic_read(&s->s_ref),
atomic_read(&s->s_ref) - 1);
ceph_put_mds_session(s); ceph_put_mds_session(s);
dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref));
} }
/* /*
...@@ -2926,6 +2917,13 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) ...@@ -2926,6 +2917,13 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_mds_client *mdsc = s->s_mdsc;
int type = le16_to_cpu(msg->hdr.type); int type = le16_to_cpu(msg->hdr.type);
mutex_lock(&mdsc->mutex);
if (__verify_registered_session(mdsc, s) < 0) {
mutex_unlock(&mdsc->mutex);
goto out;
}
mutex_unlock(&mdsc->mutex);
switch (type) { switch (type) {
case CEPH_MSG_MDS_MAP: case CEPH_MSG_MDS_MAP:
ceph_mdsc_handle_map(mdsc, msg); ceph_mdsc_handle_map(mdsc, msg);
...@@ -2937,22 +2935,23 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) ...@@ -2937,22 +2935,23 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
handle_reply(s, msg); handle_reply(s, msg);
break; break;
case CEPH_MSG_CLIENT_REQUEST_FORWARD: case CEPH_MSG_CLIENT_REQUEST_FORWARD:
handle_forward(mdsc, msg); handle_forward(mdsc, s, msg);
break; break;
case CEPH_MSG_CLIENT_CAPS: case CEPH_MSG_CLIENT_CAPS:
ceph_handle_caps(s, msg); ceph_handle_caps(s, msg);
break; break;
case CEPH_MSG_CLIENT_SNAP: case CEPH_MSG_CLIENT_SNAP:
ceph_handle_snap(mdsc, msg); ceph_handle_snap(mdsc, s, msg);
break; break;
case CEPH_MSG_CLIENT_LEASE: case CEPH_MSG_CLIENT_LEASE:
handle_lease(mdsc, msg); handle_lease(mdsc, s, msg);
break; break;
default: default:
pr_err("received unknown message type %d %s\n", type, pr_err("received unknown message type %d %s\n", type,
ceph_msg_type_name(type)); ceph_msg_type_name(type));
} }
out:
ceph_msg_put(msg); ceph_msg_put(msg);
} }
......
...@@ -713,11 +713,11 @@ static void flush_snaps(struct ceph_mds_client *mdsc) ...@@ -713,11 +713,11 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
* directory into another realm. * directory into another realm.
*/ */
void ceph_handle_snap(struct ceph_mds_client *mdsc, void ceph_handle_snap(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg) struct ceph_msg *msg)
{ {
struct super_block *sb = mdsc->client->sb; struct super_block *sb = mdsc->client->sb;
struct ceph_mds_session *session; int mds = session->s_mds;
int mds;
u64 split; u64 split;
int op; int op;
int trace_len; int trace_len;
...@@ -730,10 +730,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, ...@@ -730,10 +730,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
int i; int i;
int locked_rwsem = 0; int locked_rwsem = 0;
if (msg->hdr.src.name.type != CEPH_ENTITY_TYPE_MDS)
return;
mds = le64_to_cpu(msg->hdr.src.name.num);
/* decode */ /* decode */
if (msg->front.iov_len < sizeof(*h)) if (msg->front.iov_len < sizeof(*h))
goto bad; goto bad;
...@@ -749,15 +745,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, ...@@ -749,15 +745,6 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
dout("handle_snap from mds%d op %s split %llx tracelen %d\n", mds, dout("handle_snap from mds%d op %s split %llx tracelen %d\n", mds,
ceph_snap_op_name(op), split, trace_len); ceph_snap_op_name(op), split, trace_len);
/* find session */
mutex_lock(&mdsc->mutex);
session = __ceph_lookup_mds_session(mdsc, mds);
mutex_unlock(&mdsc->mutex);
if (!session) {
dout("WTF, got snap but no session for mds%d\n", mds);
return;
}
mutex_lock(&session->s_mutex); mutex_lock(&session->s_mutex);
session->s_seq++; session->s_seq++;
mutex_unlock(&session->s_mutex); mutex_unlock(&session->s_mutex);
......
...@@ -707,6 +707,7 @@ extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc, ...@@ -707,6 +707,7 @@ extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
extern int ceph_update_snap_trace(struct ceph_mds_client *m, extern int ceph_update_snap_trace(struct ceph_mds_client *m,
void *p, void *e, bool deletion); void *p, void *e, bool deletion);
extern void ceph_handle_snap(struct ceph_mds_client *mdsc, extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg); struct ceph_msg *msg);
extern void ceph_queue_cap_snap(struct ceph_inode_info *ci, extern void ceph_queue_cap_snap(struct ceph_inode_info *ci,
struct ceph_snap_context *snapc); struct ceph_snap_context *snapc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment