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/messenger.h> 113d14c5d2SYehuda Sadeh #include <linux/ceph/decode.h> 122f2dc053SSage Weil 13*522dc510SXiubo Li #include "mdsmap.h" 1438d46409SXiubo Li #include "mds_client.h" 152f2dc053SSage Weil #include "super.h" 162f2dc053SSage Weil 175d47648fSXiubo Li #define CEPH_MDS_IS_READY(i, ignore_laggy) \ 18b38c9eb4SXiubo Li (m->m_info[i].state > 0 && ignore_laggy ? true : !m->m_info[i].laggy) 192f2dc053SSage Weil 205d47648fSXiubo Li static int __mdsmap_get_random_mds(struct ceph_mdsmap *m, bool ignore_laggy) 212f2dc053SSage Weil { 222f2dc053SSage Weil int n = 0; 2374d6f030SXiubo Li int i, j; 24a84cd293SSam Lang 252f2dc053SSage Weil /* count */ 26b38c9eb4SXiubo Li for (i = 0; i < m->possible_max_rank; i++) 275d47648fSXiubo Li if (CEPH_MDS_IS_READY(i, ignore_laggy)) 282f2dc053SSage Weil n++; 292f2dc053SSage Weil if (n == 0) 302f2dc053SSage Weil return -1; 312f2dc053SSage Weil 322f2dc053SSage Weil /* pick */ 338032bf12SJason A. Donenfeld n = get_random_u32_below(n); 34b38c9eb4SXiubo Li for (j = 0, i = 0; i < m->possible_max_rank; i++) { 355d47648fSXiubo Li if (CEPH_MDS_IS_READY(i, ignore_laggy)) 3674d6f030SXiubo Li j++; 3774d6f030SXiubo Li if (j > n) 3874d6f030SXiubo Li break; 3974d6f030SXiubo Li } 402f2dc053SSage Weil 412f2dc053SSage Weil return i; 422f2dc053SSage Weil } 432f2dc053SSage Weil 445d47648fSXiubo Li /* 455d47648fSXiubo Li * choose a random mds that is "up" (i.e. has a state > 0), or -1. 465d47648fSXiubo Li */ 475d47648fSXiubo Li int ceph_mdsmap_get_random_mds(struct ceph_mdsmap *m) 485d47648fSXiubo Li { 495d47648fSXiubo Li int mds; 505d47648fSXiubo Li 515d47648fSXiubo Li mds = __mdsmap_get_random_mds(m, false); 52b38c9eb4SXiubo Li if (mds == m->possible_max_rank || mds == -1) 535d47648fSXiubo Li mds = __mdsmap_get_random_mds(m, true); 545d47648fSXiubo Li 55b38c9eb4SXiubo Li return mds == m->possible_max_rank ? -1 : mds; 565d47648fSXiubo Li } 575d47648fSXiubo Li 58e9e427f0SYan, Zheng #define __decode_and_drop_type(p, end, type, bad) \ 59e9e427f0SYan, Zheng do { \ 60e9e427f0SYan, Zheng if (*p + sizeof(type) > end) \ 61e9e427f0SYan, Zheng goto bad; \ 62e9e427f0SYan, Zheng *p += sizeof(type); \ 63e9e427f0SYan, Zheng } while (0) 64e9e427f0SYan, Zheng 65e9e427f0SYan, Zheng #define __decode_and_drop_set(p, end, type, 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(type) * n; \ 71e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad); \ 72e9e427f0SYan, Zheng *p += need; \ 73e9e427f0SYan, Zheng } while (0) 74e9e427f0SYan, Zheng 75e9e427f0SYan, Zheng #define __decode_and_drop_map(p, end, ktype, vtype, bad) \ 76e9e427f0SYan, Zheng do { \ 77e9e427f0SYan, Zheng u32 n; \ 78e9e427f0SYan, Zheng size_t need; \ 79e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad); \ 80e9e427f0SYan, Zheng need = (sizeof(ktype) + sizeof(vtype)) * n; \ 81e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad); \ 82e9e427f0SYan, Zheng *p += need; \ 83e9e427f0SYan, Zheng } while (0) 84e9e427f0SYan, Zheng 85e9e427f0SYan, Zheng 86e9e427f0SYan, Zheng static int __decode_and_drop_compat_set(void **p, void* end) 87e9e427f0SYan, Zheng { 88e9e427f0SYan, Zheng int i; 89e9e427f0SYan, Zheng /* compat, ro_compat, incompat*/ 90e9e427f0SYan, Zheng for (i = 0; i < 3; i++) { 91e9e427f0SYan, Zheng u32 n; 92e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad); 93e9e427f0SYan, Zheng /* mask */ 94e9e427f0SYan, Zheng *p += sizeof(u64); 95e9e427f0SYan, Zheng /* names (map<u64, string>) */ 96e9e427f0SYan, Zheng n = ceph_decode_32(p); 97e9e427f0SYan, Zheng while (n-- > 0) { 98e9e427f0SYan, Zheng u32 len; 99e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), 100e9e427f0SYan, Zheng bad); 101e9e427f0SYan, Zheng *p += sizeof(u64); 102e9e427f0SYan, Zheng len = ceph_decode_32(p); 103e9e427f0SYan, Zheng ceph_decode_need(p, end, len, bad); 104e9e427f0SYan, Zheng *p += len; 105e9e427f0SYan, Zheng } 106e9e427f0SYan, Zheng } 107e9e427f0SYan, Zheng return 0; 108e9e427f0SYan, Zheng bad: 109e9e427f0SYan, Zheng return -1; 110e9e427f0SYan, Zheng } 111e9e427f0SYan, Zheng 1122f2dc053SSage Weil /* 1132f2dc053SSage Weil * Decode an MDS map 1142f2dc053SSage Weil * 1152f2dc053SSage Weil * Ignore any fields we don't care about (there are quite a few of 1162f2dc053SSage Weil * them). 1172f2dc053SSage Weil */ 118197b7d79SXiubo Li struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p, 119197b7d79SXiubo Li void *end, bool msgr2) 1202f2dc053SSage Weil { 12138d46409SXiubo Li struct ceph_client *cl = mdsc->fsc->client; 1222f2dc053SSage Weil struct ceph_mdsmap *m; 1239ec7cab1SSage Weil const void *start = *p; 1242f2dc053SSage Weil int i, j, n; 125f3848af1SJeff Layton int err; 1268e298debSJia Yang u8 mdsmap_v; 127e9e427f0SYan, Zheng u16 mdsmap_ev; 128d517b398SXiubo Li u32 target; 1292f2dc053SSage Weil 1302f2dc053SSage Weil m = kzalloc(sizeof(*m), GFP_NOFS); 131d37b1d99SMarkus Elfring if (!m) 1322f2dc053SSage Weil return ERR_PTR(-ENOMEM); 1332f2dc053SSage Weil 134d463a43dSYan, Zheng ceph_decode_need(p, end, 1 + 1, bad); 135d463a43dSYan, Zheng mdsmap_v = ceph_decode_8(p); 1368e298debSJia Yang *p += sizeof(u8); /* mdsmap_cv */ 137d463a43dSYan, Zheng if (mdsmap_v >= 4) { 138d463a43dSYan, Zheng u32 mdsmap_len; 139d463a43dSYan, Zheng ceph_decode_32_safe(p, end, mdsmap_len, bad); 140d463a43dSYan, Zheng if (end < *p + mdsmap_len) 1414f6a7e5eSSage Weil goto bad; 142d463a43dSYan, Zheng end = *p + mdsmap_len; 1434f6a7e5eSSage Weil } 1442f2dc053SSage Weil 1452f2dc053SSage Weil ceph_decode_need(p, end, 8*sizeof(u32) + sizeof(u64), bad); 146c89136eaSSage Weil m->m_epoch = ceph_decode_32(p); 147c89136eaSSage Weil m->m_client_epoch = ceph_decode_32(p); 148c89136eaSSage Weil m->m_last_failure = ceph_decode_32(p); 149c89136eaSSage Weil m->m_root = ceph_decode_32(p); 150c89136eaSSage Weil m->m_session_timeout = ceph_decode_32(p); 151c89136eaSSage Weil m->m_session_autoclose = ceph_decode_32(p); 152c89136eaSSage Weil m->m_max_file_size = ceph_decode_64(p); 153c89136eaSSage Weil m->m_max_mds = ceph_decode_32(p); 1544d7ace02SXiubo Li 1554d7ace02SXiubo Li /* 156b38c9eb4SXiubo Li * pick out the active nodes as the m_num_active_mds, the 157b38c9eb4SXiubo Li * m_num_active_mds maybe larger than m_max_mds when decreasing 158b38c9eb4SXiubo Li * the max_mds in cluster side, in other case it should less 159b38c9eb4SXiubo Li * than or equal to m_max_mds. 1604d7ace02SXiubo Li */ 161b38c9eb4SXiubo Li m->m_num_active_mds = n = ceph_decode_32(p); 1624d7ace02SXiubo Li 1634d7ace02SXiubo Li /* 164b38c9eb4SXiubo Li * the possible max rank, it maybe larger than the m_num_active_mds, 1654d7ace02SXiubo Li * for example if the mds_max == 2 in the cluster, when the MDS(0) 1664d7ace02SXiubo Li * was laggy and being replaced by a new MDS, we will temporarily 1674d7ace02SXiubo Li * receive a new mds map with n_num_mds == 1 and the active MDS(1), 168b38c9eb4SXiubo Li * and the mds rank >= m_num_active_mds. 1694d7ace02SXiubo Li */ 170b38c9eb4SXiubo Li m->possible_max_rank = max(m->m_num_active_mds, m->m_max_mds); 1712f2dc053SSage Weil 172b38c9eb4SXiubo Li m->m_info = kcalloc(m->possible_max_rank, sizeof(*m->m_info), GFP_NOFS); 173d37b1d99SMarkus Elfring if (!m->m_info) 174e9e427f0SYan, Zheng goto nomem; 1752f2dc053SSage Weil 1762f2dc053SSage Weil /* pick out active nodes from mds_info (state > 0) */ 1772f2dc053SSage Weil for (i = 0; i < n; i++) { 17894045e11SSage Weil u64 global_id; 1792f2dc053SSage Weil u32 namelen; 1802f2dc053SSage Weil s32 mds, inc, state; 181d463a43dSYan, Zheng u8 info_v; 182d463a43dSYan, Zheng void *info_end = NULL; 1832f2dc053SSage Weil struct ceph_entity_addr addr; 1842f2dc053SSage Weil u32 num_export_targets; 1852f2dc053SSage Weil void *pexport_targets = NULL; 1860deb01c9SSage Weil struct ceph_timespec laggy_since; 1876af86528SDan Carpenter struct ceph_mds_info *info; 188da08e1e1SXiubo Li bool laggy; 1892f2dc053SSage Weil 190d463a43dSYan, Zheng ceph_decode_need(p, end, sizeof(u64) + 1, bad); 19194045e11SSage Weil global_id = ceph_decode_64(p); 192d463a43dSYan, Zheng info_v= ceph_decode_8(p); 193d463a43dSYan, Zheng if (info_v >= 4) { 194d463a43dSYan, Zheng u32 info_len; 195d463a43dSYan, Zheng ceph_decode_need(p, end, 1 + sizeof(u32), bad); 1968e298debSJia Yang *p += sizeof(u8); /* info_cv */ 197d463a43dSYan, Zheng info_len = ceph_decode_32(p); 198d463a43dSYan, Zheng info_end = *p + info_len; 199d463a43dSYan, Zheng if (info_end > end) 200d463a43dSYan, Zheng goto bad; 201d463a43dSYan, Zheng } 202d463a43dSYan, Zheng 203d463a43dSYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad); 20494045e11SSage Weil *p += sizeof(u64); 205c89136eaSSage Weil namelen = ceph_decode_32(p); /* skip mds name */ 2062f2dc053SSage Weil *p += namelen; 2072f2dc053SSage Weil 208a5cbd5fcSIlya Dryomov ceph_decode_32_safe(p, end, mds, bad); 209a5cbd5fcSIlya Dryomov ceph_decode_32_safe(p, end, inc, bad); 210a5cbd5fcSIlya Dryomov ceph_decode_32_safe(p, end, state, bad); 2118e298debSJia Yang *p += sizeof(u64); /* state_seq */ 212a5cbd5fcSIlya Dryomov if (info_v >= 8) 213a5cbd5fcSIlya Dryomov err = ceph_decode_entity_addrvec(p, end, msgr2, &addr); 214a5cbd5fcSIlya Dryomov else 215f3848af1SJeff Layton err = ceph_decode_entity_addr(p, end, &addr); 216f3848af1SJeff Layton if (err) 217f3848af1SJeff Layton goto corrupt; 218a5cbd5fcSIlya Dryomov 219a5cbd5fcSIlya Dryomov ceph_decode_copy_safe(p, end, &laggy_since, sizeof(laggy_since), 220a5cbd5fcSIlya Dryomov bad); 221da08e1e1SXiubo Li laggy = laggy_since.tv_sec != 0 || laggy_since.tv_nsec != 0; 2222f2dc053SSage Weil *p += sizeof(u32); 2232f2dc053SSage Weil ceph_decode_32_safe(p, end, namelen, bad); 224e251e288SSage Weil *p += namelen; 225d463a43dSYan, Zheng if (info_v >= 2) { 2262f2dc053SSage Weil ceph_decode_32_safe(p, end, num_export_targets, bad); 2272f2dc053SSage Weil pexport_targets = *p; 228e251e288SSage Weil *p += num_export_targets * sizeof(u32); 2292f2dc053SSage Weil } else { 2302f2dc053SSage Weil num_export_targets = 0; 2312f2dc053SSage Weil } 2322f2dc053SSage Weil 233d463a43dSYan, Zheng if (info_end && *p != info_end) { 234d463a43dSYan, Zheng if (*p > info_end) 235d463a43dSYan, Zheng goto bad; 236d463a43dSYan, Zheng *p = info_end; 237d463a43dSYan, Zheng } 238d463a43dSYan, Zheng 23938d46409SXiubo Li doutc(cl, "%d/%d %lld mds%d.%d %s %s%s\n", i+1, n, global_id, 24038d46409SXiubo Li mds, inc, ceph_pr_addr(&addr), 24138d46409SXiubo Li ceph_mds_state_name(state), laggy ? "(laggy)" : ""); 2426af86528SDan Carpenter 243b38c9eb4SXiubo Li if (mds < 0 || mds >= m->possible_max_rank) { 24438d46409SXiubo Li pr_warn_client(cl, "got incorrect mds(%d)\n", mds); 2456af86528SDan Carpenter continue; 2464d7ace02SXiubo Li } 2476af86528SDan Carpenter 2484d7ace02SXiubo Li if (state <= 0) { 24938d46409SXiubo Li doutc(cl, "got incorrect state(%s)\n", 2504d7ace02SXiubo Li ceph_mds_state_name(state)); 2514d7ace02SXiubo Li continue; 25276201b63SYan, Zheng } 25376201b63SYan, Zheng 2546af86528SDan Carpenter info = &m->m_info[mds]; 2556af86528SDan Carpenter info->global_id = global_id; 2566af86528SDan Carpenter info->state = state; 2576af86528SDan Carpenter info->addr = addr; 258da08e1e1SXiubo Li info->laggy = laggy; 2596af86528SDan Carpenter info->num_export_targets = num_export_targets; 2602f2dc053SSage Weil if (num_export_targets) { 2616af86528SDan Carpenter info->export_targets = kcalloc(num_export_targets, 2626af86528SDan Carpenter sizeof(u32), GFP_NOFS); 263d37b1d99SMarkus Elfring if (!info->export_targets) 264e9e427f0SYan, Zheng goto nomem; 265d517b398SXiubo Li for (j = 0; j < num_export_targets; j++) { 266d517b398SXiubo Li target = ceph_decode_32(&pexport_targets); 267d517b398SXiubo Li info->export_targets[j] = target; 268d517b398SXiubo Li } 2692f2dc053SSage Weil } else { 2706af86528SDan Carpenter info->export_targets = NULL; 2712f2dc053SSage Weil } 2722f2dc053SSage Weil } 2732f2dc053SSage Weil 2742f2dc053SSage Weil /* pg_pools */ 2752f2dc053SSage Weil ceph_decode_32_safe(p, end, n, bad); 2762f2dc053SSage Weil m->m_num_data_pg_pools = n; 2774f6a7e5eSSage Weil m->m_data_pg_pools = kcalloc(n, sizeof(u64), GFP_NOFS); 2782f2dc053SSage Weil if (!m->m_data_pg_pools) 279e9e427f0SYan, Zheng goto nomem; 2804f6a7e5eSSage Weil ceph_decode_need(p, end, sizeof(u64)*(n+1), bad); 2812f2dc053SSage Weil for (i = 0; i < n; i++) 2824f6a7e5eSSage Weil m->m_data_pg_pools[i] = ceph_decode_64(p); 2834f6a7e5eSSage Weil m->m_cas_pg_pool = ceph_decode_64(p); 284e9e427f0SYan, Zheng m->m_enabled = m->m_epoch > 1; 2852f2dc053SSage Weil 286e9e427f0SYan, Zheng mdsmap_ev = 1; 287e9e427f0SYan, Zheng if (mdsmap_v >= 2) { 288e9e427f0SYan, Zheng ceph_decode_16_safe(p, end, mdsmap_ev, bad_ext); 289e9e427f0SYan, Zheng } 290e9e427f0SYan, Zheng if (mdsmap_ev >= 3) { 291e9e427f0SYan, Zheng if (__decode_and_drop_compat_set(p, end) < 0) 292e9e427f0SYan, Zheng goto bad_ext; 293e9e427f0SYan, Zheng } 294e9e427f0SYan, Zheng /* metadata_pool */ 295e9e427f0SYan, Zheng if (mdsmap_ev < 5) { 296e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u32, bad_ext); 297e9e427f0SYan, Zheng } else { 298e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u64, bad_ext); 299e9e427f0SYan, Zheng } 300e9e427f0SYan, Zheng 301e9e427f0SYan, Zheng /* created + modified + tableserver */ 302e9e427f0SYan, Zheng __decode_and_drop_type(p, end, struct ceph_timespec, bad_ext); 303e9e427f0SYan, Zheng __decode_and_drop_type(p, end, struct ceph_timespec, bad_ext); 304e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u32, bad_ext); 305e9e427f0SYan, Zheng 306e9e427f0SYan, Zheng /* in */ 307e9e427f0SYan, Zheng { 308e9e427f0SYan, Zheng int num_laggy = 0; 309e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad_ext); 310e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u32) * n, bad_ext); 311e9e427f0SYan, Zheng 312e9e427f0SYan, Zheng for (i = 0; i < n; i++) { 313e9e427f0SYan, Zheng s32 mds = ceph_decode_32(p); 314b38c9eb4SXiubo Li if (mds >= 0 && mds < m->possible_max_rank) { 315e9e427f0SYan, Zheng if (m->m_info[mds].laggy) 316e9e427f0SYan, Zheng num_laggy++; 317e9e427f0SYan, Zheng } 318e9e427f0SYan, Zheng } 319e9e427f0SYan, Zheng m->m_num_laggy = num_laggy; 32076201b63SYan, Zheng 321b38c9eb4SXiubo Li if (n > m->possible_max_rank) { 32276201b63SYan, Zheng void *new_m_info = krealloc(m->m_info, 32376201b63SYan, Zheng n * sizeof(*m->m_info), 32476201b63SYan, Zheng GFP_NOFS | __GFP_ZERO); 32576201b63SYan, Zheng if (!new_m_info) 32676201b63SYan, Zheng goto nomem; 32776201b63SYan, Zheng m->m_info = new_m_info; 32876201b63SYan, Zheng } 329b38c9eb4SXiubo Li m->possible_max_rank = n; 330e9e427f0SYan, Zheng } 331e9e427f0SYan, Zheng 332e9e427f0SYan, Zheng /* inc */ 333e9e427f0SYan, Zheng __decode_and_drop_map(p, end, u32, u32, bad_ext); 334e9e427f0SYan, Zheng /* up */ 335e9e427f0SYan, Zheng __decode_and_drop_map(p, end, u32, u64, bad_ext); 336e9e427f0SYan, Zheng /* failed */ 337e9e427f0SYan, Zheng __decode_and_drop_set(p, end, u32, bad_ext); 338e9e427f0SYan, Zheng /* stopped */ 339e9e427f0SYan, Zheng __decode_and_drop_set(p, end, u32, bad_ext); 340e9e427f0SYan, Zheng 341e9e427f0SYan, Zheng if (mdsmap_ev >= 4) { 342e9e427f0SYan, Zheng /* last_failure_osd_epoch */ 343e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u32, bad_ext); 344e9e427f0SYan, Zheng } 345e9e427f0SYan, Zheng if (mdsmap_ev >= 6) { 346e9e427f0SYan, Zheng /* ever_allowed_snaps */ 347e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u8, bad_ext); 348e9e427f0SYan, Zheng /* explicitly_allowed_snaps */ 349e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u8, bad_ext); 350e9e427f0SYan, Zheng } 351e9e427f0SYan, Zheng if (mdsmap_ev >= 7) { 352e9e427f0SYan, Zheng /* inline_data_enabled */ 353e9e427f0SYan, Zheng __decode_and_drop_type(p, end, u8, bad_ext); 354e9e427f0SYan, Zheng } 355e9e427f0SYan, Zheng if (mdsmap_ev >= 8) { 356e9e427f0SYan, Zheng /* enabled */ 357e9e427f0SYan, Zheng ceph_decode_8_safe(p, end, m->m_enabled, bad_ext); 358d93231a6SLuís Henriques /* fs_name */ 359d93231a6SLuís Henriques ceph_decode_skip_string(p, end, bad_ext); 360e9e427f0SYan, Zheng } 361e9e427f0SYan, Zheng /* damaged */ 362e9e427f0SYan, Zheng if (mdsmap_ev >= 9) { 363e9e427f0SYan, Zheng size_t need; 364e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad_ext); 365e9e427f0SYan, Zheng need = sizeof(u32) * n; 366e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad_ext); 367e9e427f0SYan, Zheng *p += need; 368e9e427f0SYan, Zheng m->m_damaged = n > 0; 369e9e427f0SYan, Zheng } else { 370e9e427f0SYan, Zheng m->m_damaged = false; 371e9e427f0SYan, Zheng } 372d93231a6SLuís Henriques if (mdsmap_ev >= 17) { 373d93231a6SLuís Henriques /* balancer */ 374d93231a6SLuís Henriques ceph_decode_skip_string(p, end, bad_ext); 375d93231a6SLuís Henriques /* standby_count_wanted */ 376d93231a6SLuís Henriques ceph_decode_skip_32(p, end, bad_ext); 377d93231a6SLuís Henriques /* old_max_mds */ 378d93231a6SLuís Henriques ceph_decode_skip_32(p, end, bad_ext); 379d93231a6SLuís Henriques /* min_compat_client */ 380d93231a6SLuís Henriques ceph_decode_skip_8(p, end, bad_ext); 381d93231a6SLuís Henriques /* required_client_features */ 382d93231a6SLuís Henriques ceph_decode_skip_set(p, end, 64, bad_ext); 383d93231a6SLuís Henriques ceph_decode_64_safe(p, end, m->m_max_xattr_size, bad_ext); 384d93231a6SLuís Henriques } else { 385d93231a6SLuís Henriques /* This forces the usage of the (sync) SETXATTR Op */ 386d93231a6SLuís Henriques m->m_max_xattr_size = 0; 387d93231a6SLuís Henriques } 388e9e427f0SYan, Zheng bad_ext: 38938d46409SXiubo Li doutc(cl, "m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n", 390da08e1e1SXiubo Li !!m->m_enabled, !!m->m_damaged, m->m_num_laggy); 391d463a43dSYan, Zheng *p = end; 39238d46409SXiubo Li doutc(cl, "success epoch %u\n", m->m_epoch); 3932f2dc053SSage Weil return m; 394e9e427f0SYan, Zheng nomem: 3952f2dc053SSage Weil err = -ENOMEM; 396e9e427f0SYan, Zheng goto out_err; 397f3848af1SJeff Layton corrupt: 39838d46409SXiubo Li pr_err_client(cl, "corrupt mdsmap\n"); 3999ec7cab1SSage Weil print_hex_dump(KERN_DEBUG, "mdsmap: ", 4009ec7cab1SSage Weil DUMP_PREFIX_OFFSET, 16, 1, 4019ec7cab1SSage Weil start, end - start, true); 402e9e427f0SYan, Zheng out_err: 4032f2dc053SSage Weil ceph_mdsmap_destroy(m); 404c213b50bSEmil Goode return ERR_PTR(err); 405f3848af1SJeff Layton bad: 406f3848af1SJeff Layton err = -EINVAL; 407f3848af1SJeff Layton goto corrupt; 4082f2dc053SSage Weil } 4092f2dc053SSage Weil 4102f2dc053SSage Weil void ceph_mdsmap_destroy(struct ceph_mdsmap *m) 4112f2dc053SSage Weil { 4122f2dc053SSage Weil int i; 4132f2dc053SSage Weil 414a9e6ffbcSTuo Li if (m->m_info) { 415b38c9eb4SXiubo Li for (i = 0; i < m->possible_max_rank; i++) 4162f2dc053SSage Weil kfree(m->m_info[i].export_targets); 4172f2dc053SSage Weil kfree(m->m_info); 418a9e6ffbcSTuo Li } 4192f2dc053SSage Weil kfree(m->m_data_pg_pools); 4202f2dc053SSage Weil kfree(m); 4212f2dc053SSage Weil } 422e9e427f0SYan, Zheng 423e9e427f0SYan, Zheng bool ceph_mdsmap_is_cluster_available(struct ceph_mdsmap *m) 424e9e427f0SYan, Zheng { 425e9e427f0SYan, Zheng int i, nr_active = 0; 426e9e427f0SYan, Zheng if (!m->m_enabled) 427e9e427f0SYan, Zheng return false; 428e9e427f0SYan, Zheng if (m->m_damaged) 429e9e427f0SYan, Zheng return false; 4304d7ace02SXiubo Li if (m->m_num_laggy == m->m_num_active_mds) 431e9e427f0SYan, Zheng return false; 432b38c9eb4SXiubo Li for (i = 0; i < m->possible_max_rank; i++) { 433e9e427f0SYan, Zheng if (m->m_info[i].state == CEPH_MDS_STATE_ACTIVE) 434e9e427f0SYan, Zheng nr_active++; 435e9e427f0SYan, Zheng } 436e9e427f0SYan, Zheng return nr_active > 0; 437e9e427f0SYan, Zheng } 438