Loading fs/ceph/mds_client.c +42 −4 Original line number Diff line number Diff line Loading @@ -2777,6 +2777,25 @@ static void handle_forward(struct ceph_mds_client *mdsc, pr_err("mdsc_handle_forward decode error err=%d\n", err); } static int __decode_and_drop_session_metadata(void **p, void *end) { /* map<string,string> */ u32 n; ceph_decode_32_safe(p, end, n, bad); while (n-- > 0) { u32 len; ceph_decode_32_safe(p, end, len, bad); ceph_decode_need(p, end, len, bad); *p += len; ceph_decode_32_safe(p, end, len, bad); ceph_decode_need(p, end, len, bad); *p += len; } return 0; bad: return -1; } /* * handle a mds session control message */ Loading @@ -2784,18 +2803,36 @@ static void handle_session(struct ceph_mds_session *session, struct ceph_msg *msg) { struct ceph_mds_client *mdsc = session->s_mdsc; int mds = session->s_mds; int msg_version = le16_to_cpu(msg->hdr.version); void *p = msg->front.iov_base; void *end = p + msg->front.iov_len; struct ceph_mds_session_head *h; u32 op; u64 seq; int mds = session->s_mds; struct ceph_mds_session_head *h = msg->front.iov_base; unsigned long features = 0; int wake = 0; /* decode */ if (msg->front.iov_len < sizeof(*h)) goto bad; ceph_decode_need(&p, end, sizeof(*h), bad); h = p; p += sizeof(*h); op = le32_to_cpu(h->op); seq = le64_to_cpu(h->seq); if (msg_version >= 3) { u32 len; /* version >= 2, metadata */ if (__decode_and_drop_session_metadata(&p, end) < 0) goto bad; /* version >= 3, feature bits */ ceph_decode_32_safe(&p, end, len, bad); ceph_decode_need(&p, end, len, bad); memcpy(&features, p, min_t(size_t, len, sizeof(features))); p += len; } mutex_lock(&mdsc->mutex); if (op == CEPH_SESSION_CLOSE) { get_session(session); Loading @@ -2821,6 +2858,7 @@ static void handle_session(struct ceph_mds_session *session, if (session->s_state == CEPH_MDS_SESSION_RECONNECTING) pr_info("mds%d reconnect success\n", session->s_mds); session->s_state = CEPH_MDS_SESSION_OPEN; session->s_features = features; renewed_caps(mdsc, session, 0); wake = 1; if (mdsc->stopping) Loading fs/ceph/mds_client.h +2 −1 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ struct ceph_mds_session { int s_mds; int s_state; unsigned long s_ttl; /* time until mds kills us */ unsigned long s_features; u64 s_seq; /* incoming msg seq # */ struct mutex s_mutex; /* serialize session messages */ Loading Loading
fs/ceph/mds_client.c +42 −4 Original line number Diff line number Diff line Loading @@ -2777,6 +2777,25 @@ static void handle_forward(struct ceph_mds_client *mdsc, pr_err("mdsc_handle_forward decode error err=%d\n", err); } static int __decode_and_drop_session_metadata(void **p, void *end) { /* map<string,string> */ u32 n; ceph_decode_32_safe(p, end, n, bad); while (n-- > 0) { u32 len; ceph_decode_32_safe(p, end, len, bad); ceph_decode_need(p, end, len, bad); *p += len; ceph_decode_32_safe(p, end, len, bad); ceph_decode_need(p, end, len, bad); *p += len; } return 0; bad: return -1; } /* * handle a mds session control message */ Loading @@ -2784,18 +2803,36 @@ static void handle_session(struct ceph_mds_session *session, struct ceph_msg *msg) { struct ceph_mds_client *mdsc = session->s_mdsc; int mds = session->s_mds; int msg_version = le16_to_cpu(msg->hdr.version); void *p = msg->front.iov_base; void *end = p + msg->front.iov_len; struct ceph_mds_session_head *h; u32 op; u64 seq; int mds = session->s_mds; struct ceph_mds_session_head *h = msg->front.iov_base; unsigned long features = 0; int wake = 0; /* decode */ if (msg->front.iov_len < sizeof(*h)) goto bad; ceph_decode_need(&p, end, sizeof(*h), bad); h = p; p += sizeof(*h); op = le32_to_cpu(h->op); seq = le64_to_cpu(h->seq); if (msg_version >= 3) { u32 len; /* version >= 2, metadata */ if (__decode_and_drop_session_metadata(&p, end) < 0) goto bad; /* version >= 3, feature bits */ ceph_decode_32_safe(&p, end, len, bad); ceph_decode_need(&p, end, len, bad); memcpy(&features, p, min_t(size_t, len, sizeof(features))); p += len; } mutex_lock(&mdsc->mutex); if (op == CEPH_SESSION_CLOSE) { get_session(session); Loading @@ -2821,6 +2858,7 @@ static void handle_session(struct ceph_mds_session *session, if (session->s_state == CEPH_MDS_SESSION_RECONNECTING) pr_info("mds%d reconnect success\n", session->s_mds); session->s_state = CEPH_MDS_SESSION_OPEN; session->s_features = features; renewed_caps(mdsc, session, 0); wake = 1; if (mdsc->stopping) Loading
fs/ceph/mds_client.h +2 −1 Original line number Diff line number Diff line Loading @@ -152,6 +152,7 @@ struct ceph_mds_session { int s_mds; int s_state; unsigned long s_ttl; /* time until mds kills us */ unsigned long s_features; u64 s_seq; /* incoming msg seq # */ struct mutex s_mutex; /* serialize session messages */ Loading