1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 23d14c5d2SYehuda Sadeh #include <linux/ceph/ceph_debug.h> 32f2dc053SSage Weil 42f2dc053SSage Weil #include <linux/bug.h> 52f2dc053SSage Weil #include <linux/err.h> 62f2dc053SSage Weil #include <linux/random.h> 72f2dc053SSage Weil #include <linux/slab.h> 82f2dc053SSage Weil #include <linux/types.h> 92f2dc053SSage Weil 103d14c5d2SYehuda Sadeh #include <linux/ceph/mdsmap.h> 113d14c5d2SYehuda Sadeh #include <linux/ceph/messenger.h> 123d14c5d2SYehuda Sadeh #include <linux/ceph/decode.h> 132f2dc053SSage Weil 142f2dc053SSage Weil #include "super.h" 152f2dc053SSage Weil 162f2dc053SSage Weil 172f2dc053SSage Weil /* 182f2dc053SSage Weil * choose a random mds that is "up" (i.e. has a state > 0), or -1. 192f2dc053SSage Weil */ 202f2dc053SSage Weil int ceph_mdsmap_get_random_mds(struct ceph_mdsmap *m) 212f2dc053SSage Weil { 222f2dc053SSage Weil int n = 0; 2374d6f030SXiubo Li int i, j; 24a84cd293SSam Lang 25a84cd293SSam Lang /* special case for one mds */ 2676201b63SYan, Zheng if (1 == m->m_num_mds && m->m_info[0].state > 0) 27a84cd293SSam Lang return 0; 282f2dc053SSage Weil 292f2dc053SSage Weil /* count */ 3076201b63SYan, Zheng for (i = 0; i < m->m_num_mds; i++) 312f2dc053SSage Weil if (m->m_info[i].state > 0) 322f2dc053SSage Weil n++; 332f2dc053SSage Weil if (n == 0) 342f2dc053SSage Weil return -1; 352f2dc053SSage Weil 362f2dc053SSage Weil /* pick */ 37a84cd293SSam Lang n = prandom_u32() % n; 3874d6f030SXiubo Li for (j = 0, i = 0; i < m->m_num_mds; i++) { 3974d6f030SXiubo Li if (m->m_info[i].state > 0) 4074d6f030SXiubo Li j++; 4174d6f030SXiubo Li if (j > n) 4274d6f030SXiubo Li break; 4374d6f030SXiubo Li } 442f2dc053SSage Weil 452f2dc053SSage Weil return i; 462f2dc053SSage Weil } 472f2dc053SSage Weil 48e9e427f0SYan, Zheng #define __decode_and_drop_type(p, end, type, bad) \ 49e9e427f0SYan, Zheng do { \ 50e9e427f0SYan, Zheng if (*p + sizeof(type) > end) \ 51e9e427f0SYan, Zheng goto bad; \ 52e9e427f0SYan, Zheng *p += sizeof(type); \ 53e9e427f0SYan, Zheng } while (0) 54e9e427f0SYan, Zheng 55e9e427f0SYan, Zheng #define __decode_and_drop_set(p, end, type, bad) \ 56e9e427f0SYan, Zheng do { \ 57e9e427f0SYan, Zheng u32 n; \ 58e9e427f0SYan, Zheng size_t need; \ 59e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad); \ 60e9e427f0SYan, Zheng need = sizeof(type) * n; \ 61e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad); \ 62e9e427f0SYan, Zheng *p += need; \ 63e9e427f0SYan, Zheng } while (0) 64e9e427f0SYan, Zheng 65e9e427f0SYan, Zheng #define __decode_and_drop_map(p, end, ktype, vtype, bad) \ 66e9e427f0SYan, Zheng do { \ 67e9e427f0SYan, Zheng u32 n; \ 68e9e427f0SYan, Zheng size_t need; \ 69e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad); \ 70e9e427f0SYan, Zheng need = (sizeof(ktype) + sizeof(vtype)) * n; \ 71e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad); \ 72e9e427f0SYan, Zheng *p += need; \ 73e9e427f0SYan, Zheng } while (0) 74e9e427f0SYan, Zheng 75e9e427f0SYan, Zheng 76e9e427f0SYan, Zheng static int __decode_and_drop_compat_set(void **p, void* end) 77e9e427f0SYan, Zheng { 78e9e427f0SYan, Zheng int i; 79e9e427f0SYan, Zheng /* compat, ro_compat, incompat*/ 80e9e427f0SYan, Zheng for (i = 0; i < 3; i++) { 81e9e427f0SYan, Zheng u32 n; 82e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad); 83e9e427f0SYan, Zheng /* mask */ 84e9e427f0SYan, Zheng *p += sizeof(u64); 85e9e427f0SYan, Zheng /* names (map<u64, string>) */ 86e9e427f0SYan, Zheng n = ceph_decode_32(p); 87e9e427f0SYan, Zheng while (n-- > 0) { 88e9e427f0SYan, Zheng u32 len; 89e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), 90e9e427f0SYan, Zheng bad); 91e9e427f0SYan, Zheng *p += sizeof(u64); 92e9e427f0SYan, Zheng len = ceph_decode_32(p); 93e9e427f0SYan, Zheng ceph_decode_need(p, end, len, bad); 94e9e427f0SYan, Zheng *p += len; 95e9e427f0SYan, Zheng } 96e9e427f0SYan, Zheng } 97e9e427f0SYan, Zheng return 0; 98e9e427f0SYan, Zheng bad: 99e9e427f0SYan, Zheng return -1; 100e9e427f0SYan, Zheng } 101e9e427f0SYan, Zheng 1022f2dc053SSage Weil /* 1032f2dc053SSage Weil * Decode an MDS map 1042f2dc053SSage Weil * 1052f2dc053SSage Weil * Ignore any fields we don't care about (there are quite a few of 1062f2dc053SSage Weil * them). 1072f2dc053SSage Weil */ 1082f2dc053SSage Weil struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end) 1092f2dc053SSage Weil { 1102f2dc053SSage Weil struct ceph_mdsmap *m; 1119ec7cab1SSage Weil const void *start = *p; 1122f2dc053SSage Weil int i, j, n; 113f3848af1SJeff Layton int err; 114d463a43dSYan, Zheng u8 mdsmap_v, mdsmap_cv; 115e9e427f0SYan, Zheng u16 mdsmap_ev; 116*4d7ace02SXiubo Li u32 possible_max_rank; 1172f2dc053SSage Weil 1182f2dc053SSage Weil m = kzalloc(sizeof(*m), GFP_NOFS); 119d37b1d99SMarkus Elfring if (!m) 1202f2dc053SSage Weil return ERR_PTR(-ENOMEM); 1212f2dc053SSage Weil 122d463a43dSYan, Zheng ceph_decode_need(p, end, 1 + 1, bad); 123d463a43dSYan, Zheng mdsmap_v = ceph_decode_8(p); 124d463a43dSYan, Zheng mdsmap_cv = ceph_decode_8(p); 125d463a43dSYan, Zheng if (mdsmap_v >= 4) { 126d463a43dSYan, Zheng u32 mdsmap_len; 127d463a43dSYan, Zheng ceph_decode_32_safe(p, end, mdsmap_len, bad); 128d463a43dSYan, Zheng if (end < *p + mdsmap_len) 1294f6a7e5eSSage Weil goto bad; 130d463a43dSYan, Zheng end = *p + mdsmap_len; 1314f6a7e5eSSage Weil } 1322f2dc053SSage Weil 1332f2dc053SSage Weil ceph_decode_need(p, end, 8*sizeof(u32) + sizeof(u64), bad); 134c89136eaSSage Weil m->m_epoch = ceph_decode_32(p); 135c89136eaSSage Weil m->m_client_epoch = ceph_decode_32(p); 136c89136eaSSage Weil m->m_last_failure = ceph_decode_32(p); 137c89136eaSSage Weil m->m_root = ceph_decode_32(p); 138c89136eaSSage Weil m->m_session_timeout = ceph_decode_32(p); 139c89136eaSSage Weil m->m_session_autoclose = ceph_decode_32(p); 140c89136eaSSage Weil m->m_max_file_size = ceph_decode_64(p); 141c89136eaSSage Weil m->m_max_mds = ceph_decode_32(p); 142*4d7ace02SXiubo Li 143*4d7ace02SXiubo Li /* 144*4d7ace02SXiubo Li * pick out the active nodes as the m_num_mds, the m_num_mds 145*4d7ace02SXiubo Li * maybe larger than m_max_mds when decreasing the max_mds in 146*4d7ace02SXiubo Li * cluster side, in other case it should less than or equal 147*4d7ace02SXiubo Li * to m_max_mds. 148*4d7ace02SXiubo Li */ 149*4d7ace02SXiubo Li m->m_num_mds = n = ceph_decode_32(p); 150*4d7ace02SXiubo Li m->m_num_active_mds = m->m_num_mds; 151*4d7ace02SXiubo Li 152*4d7ace02SXiubo Li /* 153*4d7ace02SXiubo Li * the possible max rank, it maybe larger than the m->m_num_mds, 154*4d7ace02SXiubo Li * for example if the mds_max == 2 in the cluster, when the MDS(0) 155*4d7ace02SXiubo Li * was laggy and being replaced by a new MDS, we will temporarily 156*4d7ace02SXiubo Li * receive a new mds map with n_num_mds == 1 and the active MDS(1), 157*4d7ace02SXiubo Li * and the mds rank >= m->m_num_mds. 158*4d7ace02SXiubo Li */ 159*4d7ace02SXiubo Li possible_max_rank = max((u32)m->m_num_mds, m->m_max_mds); 1602f2dc053SSage Weil 16176201b63SYan, Zheng m->m_info = kcalloc(m->m_num_mds, sizeof(*m->m_info), GFP_NOFS); 162d37b1d99SMarkus Elfring if (!m->m_info) 163e9e427f0SYan, Zheng goto nomem; 1642f2dc053SSage Weil 1652f2dc053SSage Weil /* pick out active nodes from mds_info (state > 0) */ 1662f2dc053SSage Weil for (i = 0; i < n; i++) { 16794045e11SSage Weil u64 global_id; 1682f2dc053SSage Weil u32 namelen; 1692f2dc053SSage Weil s32 mds, inc, state; 1702f2dc053SSage Weil u64 state_seq; 171d463a43dSYan, Zheng u8 info_v; 172d463a43dSYan, Zheng void *info_end = NULL; 1732f2dc053SSage Weil struct ceph_entity_addr addr; 1742f2dc053SSage Weil u32 num_export_targets; 1752f2dc053SSage Weil void *pexport_targets = NULL; 1760deb01c9SSage Weil struct ceph_timespec laggy_since; 1776af86528SDan Carpenter struct ceph_mds_info *info; 178da08e1e1SXiubo Li bool laggy; 1792f2dc053SSage Weil 180d463a43dSYan, Zheng ceph_decode_need(p, end, sizeof(u64) + 1, bad); 18194045e11SSage Weil global_id = ceph_decode_64(p); 182d463a43dSYan, Zheng info_v= ceph_decode_8(p); 183d463a43dSYan, Zheng if (info_v >= 4) { 184d463a43dSYan, Zheng u32 info_len; 185d463a43dSYan, Zheng u8 info_cv; 186d463a43dSYan, Zheng ceph_decode_need(p, end, 1 + sizeof(u32), bad); 187d463a43dSYan, Zheng info_cv = ceph_decode_8(p); 188d463a43dSYan, Zheng info_len = ceph_decode_32(p); 189d463a43dSYan, Zheng info_end = *p + info_len; 190d463a43dSYan, Zheng if (info_end > end) 191d463a43dSYan, Zheng goto bad; 192d463a43dSYan, Zheng } 193d463a43dSYan, Zheng 194d463a43dSYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad); 19594045e11SSage Weil *p += sizeof(u64); 196c89136eaSSage Weil namelen = ceph_decode_32(p); /* skip mds name */ 1972f2dc053SSage Weil *p += namelen; 1982f2dc053SSage Weil 1992f2dc053SSage Weil ceph_decode_need(p, end, 200e251e288SSage Weil 4*sizeof(u32) + sizeof(u64) + 2012f2dc053SSage Weil sizeof(addr) + sizeof(struct ceph_timespec), 2022f2dc053SSage Weil bad); 203c89136eaSSage Weil mds = ceph_decode_32(p); 204c89136eaSSage Weil inc = ceph_decode_32(p); 205c89136eaSSage Weil state = ceph_decode_32(p); 206c89136eaSSage Weil state_seq = ceph_decode_64(p); 207f3848af1SJeff Layton err = ceph_decode_entity_addr(p, end, &addr); 208f3848af1SJeff Layton if (err) 209f3848af1SJeff Layton goto corrupt; 2100deb01c9SSage Weil ceph_decode_copy(p, &laggy_since, sizeof(laggy_since)); 211da08e1e1SXiubo Li laggy = laggy_since.tv_sec != 0 || laggy_since.tv_nsec != 0; 2122f2dc053SSage Weil *p += sizeof(u32); 2132f2dc053SSage Weil ceph_decode_32_safe(p, end, namelen, bad); 214e251e288SSage Weil *p += namelen; 215d463a43dSYan, Zheng if (info_v >= 2) { 2162f2dc053SSage Weil ceph_decode_32_safe(p, end, num_export_targets, bad); 2172f2dc053SSage Weil pexport_targets = *p; 218e251e288SSage Weil *p += num_export_targets * sizeof(u32); 2192f2dc053SSage Weil } else { 2202f2dc053SSage Weil num_export_targets = 0; 2212f2dc053SSage Weil } 2222f2dc053SSage Weil 223d463a43dSYan, Zheng if (info_end && *p != info_end) { 224d463a43dSYan, Zheng if (*p > info_end) 225d463a43dSYan, Zheng goto bad; 226d463a43dSYan, Zheng *p = info_end; 227d463a43dSYan, Zheng } 228d463a43dSYan, Zheng 229da08e1e1SXiubo Li dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n", 2303d14c5d2SYehuda Sadeh i+1, n, global_id, mds, inc, 231b726ec97SJeff Layton ceph_pr_addr(&addr), 232da08e1e1SXiubo Li ceph_mds_state_name(state), 233da08e1e1SXiubo Li laggy ? "(laggy)" : ""); 2346af86528SDan Carpenter 235*4d7ace02SXiubo Li if (mds < 0 || mds >= possible_max_rank) { 236*4d7ace02SXiubo Li pr_warn("mdsmap_decode got incorrect mds(%d)\n", mds); 2376af86528SDan Carpenter continue; 238*4d7ace02SXiubo Li } 2396af86528SDan Carpenter 240*4d7ace02SXiubo Li if (state <= 0) { 241*4d7ace02SXiubo Li pr_warn("mdsmap_decode got incorrect state(%s)\n", 242*4d7ace02SXiubo Li ceph_mds_state_name(state)); 243*4d7ace02SXiubo Li continue; 24476201b63SYan, Zheng } 24576201b63SYan, Zheng 2466af86528SDan Carpenter info = &m->m_info[mds]; 2476af86528SDan Carpenter info->global_id = global_id; 2486af86528SDan Carpenter info->state = state; 2496af86528SDan Carpenter info->addr = addr; 250da08e1e1SXiubo Li info->laggy = laggy; 2516af86528SDan Carpenter info->num_export_targets = num_export_targets; 2522f2dc053SSage Weil if (num_export_targets) { 2536af86528SDan Carpenter info->export_targets = kcalloc(num_export_targets, 2546af86528SDan Carpenter sizeof(u32), GFP_NOFS); 255d37b1d99SMarkus Elfring if (!info->export_targets) 256e9e427f0SYan, Zheng goto nomem; 2572f2dc053SSage Weil for (j = 0; j < num_export_targets; j++) 2586af86528SDan Carpenter info->export_targets[j] = 259c89136eaSSage Weil ceph_decode_32(&pexport_targets); 2602f2dc053SSage Weil } else { 2616af86528SDan Carpenter info->export_targets = NULL; 2622f2dc053SSage Weil } 2632f2dc053SSage Weil } 2642f2dc053SSage Weil 2652f2dc053SSage Weil /* pg_pools */ 2662f2dc053SSage Weil ceph_decode_32_safe(p, end, n, bad); 2672f2dc053SSage Weil m->m_num_data_pg_pools = n; 2684f6a7e5eSSage Weil m->m_data_pg_pools = kcalloc(n, sizeof(u64), GFP_NOFS); 2692f2dc053SSage Weil if (!m->m_data_pg_pools) 270e9e427f0SYan, Zheng goto nomem; 2714f6a7e5eSSage Weil ceph_decode_need(p, end, sizeof(u64)*(n+1), bad); 2722f2dc053SSage Weil for (i = 0; i < n; i++) 2734f6a7e5eSSage Weil m->m_data_pg_pools[i] = ceph_decode_64(p); 2744f6a7e5eSSage Weil m->m_cas_pg_pool = ceph_decode_64(p); 275e9e427f0SYan, Zheng m->m_enabled = m->m_epoch > 1; 2762f2dc053SSage Weil 277e9e427f0SYan, Zheng mdsmap_ev = 1; 278e9e427f0SYan, Zheng if (mdsmap_v >= 2) { 279e9e427f0SYan, Zheng ceph_decode_16_safe(p, end, mdsmap_ev, bad_ext); 280e9e427f0SYan, Zheng } 281e9e427f0SYan, Zheng if (mdsmap_ev >= 3) { 282e9e427f0SYan, Zheng if (__decode_and_drop_compat_set(p, end) < 0) 283e9e427f0SYan, Zheng goto bad_ext; 284e9e427f0SYan, Zheng } 285e9e427f0SYan, Zheng /* metadata_pool */ 286e9e427f0SYan, Zheng if (mdsmap_ev < 5) { 287e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u32, bad_ext); 288e9e427f0SYan, Zheng } else { 289e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u64, bad_ext); 290e9e427f0SYan, Zheng } 291e9e427f0SYan, Zheng 292e9e427f0SYan, Zheng /* created + modified + tableserver */ 293e9e427f0SYan, Zheng __decode_and_drop_type(p, end, struct ceph_timespec, bad_ext); 294e9e427f0SYan, Zheng __decode_and_drop_type(p, end, struct ceph_timespec, bad_ext); 295e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u32, bad_ext); 296e9e427f0SYan, Zheng 297e9e427f0SYan, Zheng /* in */ 298e9e427f0SYan, Zheng { 299e9e427f0SYan, Zheng int num_laggy = 0; 300e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad_ext); 301e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u32) * n, bad_ext); 302e9e427f0SYan, Zheng 303e9e427f0SYan, Zheng for (i = 0; i < n; i++) { 304e9e427f0SYan, Zheng s32 mds = ceph_decode_32(p); 30576201b63SYan, Zheng if (mds >= 0 && mds < m->m_num_mds) { 306e9e427f0SYan, Zheng if (m->m_info[mds].laggy) 307e9e427f0SYan, Zheng num_laggy++; 308e9e427f0SYan, Zheng } 309e9e427f0SYan, Zheng } 310e9e427f0SYan, Zheng m->m_num_laggy = num_laggy; 31176201b63SYan, Zheng 31276201b63SYan, Zheng if (n > m->m_num_mds) { 31376201b63SYan, Zheng void *new_m_info = krealloc(m->m_info, 31476201b63SYan, Zheng n * sizeof(*m->m_info), 31576201b63SYan, Zheng GFP_NOFS | __GFP_ZERO); 31676201b63SYan, Zheng if (!new_m_info) 31776201b63SYan, Zheng goto nomem; 31876201b63SYan, Zheng m->m_info = new_m_info; 31976201b63SYan, Zheng } 32076201b63SYan, Zheng m->m_num_mds = n; 321e9e427f0SYan, Zheng } 322e9e427f0SYan, Zheng 323e9e427f0SYan, Zheng /* inc */ 324e9e427f0SYan, Zheng __decode_and_drop_map(p, end, u32, u32, bad_ext); 325e9e427f0SYan, Zheng /* up */ 326e9e427f0SYan, Zheng __decode_and_drop_map(p, end, u32, u64, bad_ext); 327e9e427f0SYan, Zheng /* failed */ 328e9e427f0SYan, Zheng __decode_and_drop_set(p, end, u32, bad_ext); 329e9e427f0SYan, Zheng /* stopped */ 330e9e427f0SYan, Zheng __decode_and_drop_set(p, end, u32, bad_ext); 331e9e427f0SYan, Zheng 332e9e427f0SYan, Zheng if (mdsmap_ev >= 4) { 333e9e427f0SYan, Zheng /* last_failure_osd_epoch */ 334e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u32, bad_ext); 335e9e427f0SYan, Zheng } 336e9e427f0SYan, Zheng if (mdsmap_ev >= 6) { 337e9e427f0SYan, Zheng /* ever_allowed_snaps */ 338e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u8, bad_ext); 339e9e427f0SYan, Zheng /* explicitly_allowed_snaps */ 340e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u8, bad_ext); 341e9e427f0SYan, Zheng } 342e9e427f0SYan, Zheng if (mdsmap_ev >= 7) { 343e9e427f0SYan, Zheng /* inline_data_enabled */ 344e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u8, bad_ext); 345e9e427f0SYan, Zheng } 346e9e427f0SYan, Zheng if (mdsmap_ev >= 8) { 347e9e427f0SYan, Zheng u32 name_len; 348e9e427f0SYan, Zheng /* enabled */ 349e9e427f0SYan, Zheng ceph_decode_8_safe(p, end, m->m_enabled, bad_ext); 350e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, name_len, bad_ext); 351e9e427f0SYan, Zheng ceph_decode_need(p, end, name_len, bad_ext); 352e9e427f0SYan, Zheng *p += name_len; 353e9e427f0SYan, Zheng } 354e9e427f0SYan, Zheng /* damaged */ 355e9e427f0SYan, Zheng if (mdsmap_ev >= 9) { 356e9e427f0SYan, Zheng size_t need; 357e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad_ext); 358e9e427f0SYan, Zheng need = sizeof(u32) * n; 359e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad_ext); 360e9e427f0SYan, Zheng *p += need; 361e9e427f0SYan, Zheng m->m_damaged = n > 0; 362e9e427f0SYan, Zheng } else { 363e9e427f0SYan, Zheng m->m_damaged = false; 364e9e427f0SYan, Zheng } 365e9e427f0SYan, Zheng bad_ext: 366da08e1e1SXiubo Li dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n", 367da08e1e1SXiubo Li !!m->m_enabled, !!m->m_damaged, m->m_num_laggy); 368d463a43dSYan, Zheng *p = end; 3692f2dc053SSage Weil dout("mdsmap_decode success epoch %u\n", m->m_epoch); 3702f2dc053SSage Weil return m; 371e9e427f0SYan, Zheng nomem: 3722f2dc053SSage Weil err = -ENOMEM; 373e9e427f0SYan, Zheng goto out_err; 374f3848af1SJeff Layton corrupt: 3752f2dc053SSage Weil pr_err("corrupt mdsmap\n"); 3769ec7cab1SSage Weil print_hex_dump(KERN_DEBUG, "mdsmap: ", 3779ec7cab1SSage Weil DUMP_PREFIX_OFFSET, 16, 1, 3789ec7cab1SSage Weil start, end - start, true); 379e9e427f0SYan, Zheng out_err: 3802f2dc053SSage Weil ceph_mdsmap_destroy(m); 381c213b50bSEmil Goode return ERR_PTR(err); 382f3848af1SJeff Layton bad: 383f3848af1SJeff Layton err = -EINVAL; 384f3848af1SJeff Layton goto corrupt; 3852f2dc053SSage Weil } 3862f2dc053SSage Weil 3872f2dc053SSage Weil void ceph_mdsmap_destroy(struct ceph_mdsmap *m) 3882f2dc053SSage Weil { 3892f2dc053SSage Weil int i; 3902f2dc053SSage Weil 39176201b63SYan, Zheng for (i = 0; i < m->m_num_mds; i++) 3922f2dc053SSage Weil kfree(m->m_info[i].export_targets); 3932f2dc053SSage Weil kfree(m->m_info); 3942f2dc053SSage Weil kfree(m->m_data_pg_pools); 3952f2dc053SSage Weil kfree(m); 3962f2dc053SSage Weil } 397e9e427f0SYan, Zheng 398e9e427f0SYan, Zheng bool ceph_mdsmap_is_cluster_available(struct ceph_mdsmap *m) 399e9e427f0SYan, Zheng { 400e9e427f0SYan, Zheng int i, nr_active = 0; 401e9e427f0SYan, Zheng if (!m->m_enabled) 402e9e427f0SYan, Zheng return false; 403e9e427f0SYan, Zheng if (m->m_damaged) 404e9e427f0SYan, Zheng return false; 405*4d7ace02SXiubo Li if (m->m_num_laggy == m->m_num_active_mds) 406e9e427f0SYan, Zheng return false; 40776201b63SYan, Zheng for (i = 0; i < m->m_num_mds; i++) { 408e9e427f0SYan, Zheng if (m->m_info[i].state == CEPH_MDS_STATE_ACTIVE) 409e9e427f0SYan, Zheng nr_active++; 410e9e427f0SYan, Zheng } 411e9e427f0SYan, Zheng return nr_active > 0; 412e9e427f0SYan, Zheng } 413