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
165d47648fSXiubo Li #define CEPH_MDS_IS_READY(i, ignore_laggy) \
17b38c9eb4SXiubo Li (m->m_info[i].state > 0 && ignore_laggy ? true : !m->m_info[i].laggy)
182f2dc053SSage Weil
__mdsmap_get_random_mds(struct ceph_mdsmap * m,bool ignore_laggy)195d47648fSXiubo Li static int __mdsmap_get_random_mds(struct ceph_mdsmap *m, bool ignore_laggy)
202f2dc053SSage Weil {
212f2dc053SSage Weil int n = 0;
2274d6f030SXiubo Li int i, j;
23a84cd293SSam Lang
242f2dc053SSage Weil /* count */
25b38c9eb4SXiubo Li for (i = 0; i < m->possible_max_rank; i++)
265d47648fSXiubo Li if (CEPH_MDS_IS_READY(i, ignore_laggy))
272f2dc053SSage Weil n++;
282f2dc053SSage Weil if (n == 0)
292f2dc053SSage Weil return -1;
302f2dc053SSage Weil
312f2dc053SSage Weil /* pick */
328032bf12SJason A. Donenfeld n = get_random_u32_below(n);
33b38c9eb4SXiubo Li for (j = 0, i = 0; i < m->possible_max_rank; i++) {
345d47648fSXiubo Li if (CEPH_MDS_IS_READY(i, ignore_laggy))
3574d6f030SXiubo Li j++;
3674d6f030SXiubo Li if (j > n)
3774d6f030SXiubo Li break;
3874d6f030SXiubo Li }
392f2dc053SSage Weil
402f2dc053SSage Weil return i;
412f2dc053SSage Weil }
422f2dc053SSage Weil
435d47648fSXiubo Li /*
445d47648fSXiubo Li * choose a random mds that is "up" (i.e. has a state > 0), or -1.
455d47648fSXiubo Li */
ceph_mdsmap_get_random_mds(struct ceph_mdsmap * m)465d47648fSXiubo Li int ceph_mdsmap_get_random_mds(struct ceph_mdsmap *m)
475d47648fSXiubo Li {
485d47648fSXiubo Li int mds;
495d47648fSXiubo Li
505d47648fSXiubo Li mds = __mdsmap_get_random_mds(m, false);
51b38c9eb4SXiubo Li if (mds == m->possible_max_rank || mds == -1)
525d47648fSXiubo Li mds = __mdsmap_get_random_mds(m, true);
535d47648fSXiubo Li
54b38c9eb4SXiubo Li return mds == m->possible_max_rank ? -1 : mds;
555d47648fSXiubo Li }
565d47648fSXiubo Li
57e9e427f0SYan, Zheng #define __decode_and_drop_type(p, end, type, bad) \
58e9e427f0SYan, Zheng do { \
59e9e427f0SYan, Zheng if (*p + sizeof(type) > end) \
60e9e427f0SYan, Zheng goto bad; \
61e9e427f0SYan, Zheng *p += sizeof(type); \
62e9e427f0SYan, Zheng } while (0)
63e9e427f0SYan, Zheng
64e9e427f0SYan, Zheng #define __decode_and_drop_set(p, end, type, bad) \
65e9e427f0SYan, Zheng do { \
66e9e427f0SYan, Zheng u32 n; \
67e9e427f0SYan, Zheng size_t need; \
68e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad); \
69e9e427f0SYan, Zheng need = sizeof(type) * n; \
70e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad); \
71e9e427f0SYan, Zheng *p += need; \
72e9e427f0SYan, Zheng } while (0)
73e9e427f0SYan, Zheng
74e9e427f0SYan, Zheng #define __decode_and_drop_map(p, end, ktype, vtype, bad) \
75e9e427f0SYan, Zheng do { \
76e9e427f0SYan, Zheng u32 n; \
77e9e427f0SYan, Zheng size_t need; \
78e9e427f0SYan, Zheng ceph_decode_32_safe(p, end, n, bad); \
79e9e427f0SYan, Zheng need = (sizeof(ktype) + sizeof(vtype)) * n; \
80e9e427f0SYan, Zheng ceph_decode_need(p, end, need, bad); \
81e9e427f0SYan, Zheng *p += need; \
82e9e427f0SYan, Zheng } while (0)
83e9e427f0SYan, Zheng
84e9e427f0SYan, Zheng
__decode_and_drop_compat_set(void ** p,void * end)85e9e427f0SYan, Zheng static int __decode_and_drop_compat_set(void **p, void* end)
86e9e427f0SYan, Zheng {
87e9e427f0SYan, Zheng int i;
88e9e427f0SYan, Zheng /* compat, ro_compat, incompat*/
89e9e427f0SYan, Zheng for (i = 0; i < 3; i++) {
90e9e427f0SYan, Zheng u32 n;
91e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
92e9e427f0SYan, Zheng /* mask */
93e9e427f0SYan, Zheng *p += sizeof(u64);
94e9e427f0SYan, Zheng /* names (map<u64, string>) */
95e9e427f0SYan, Zheng n = ceph_decode_32(p);
96e9e427f0SYan, Zheng while (n-- > 0) {
97e9e427f0SYan, Zheng u32 len;
98e9e427f0SYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32),
99e9e427f0SYan, Zheng bad);
100e9e427f0SYan, Zheng *p += sizeof(u64);
101e9e427f0SYan, Zheng len = ceph_decode_32(p);
102e9e427f0SYan, Zheng ceph_decode_need(p, end, len, bad);
103e9e427f0SYan, Zheng *p += len;
104e9e427f0SYan, Zheng }
105e9e427f0SYan, Zheng }
106e9e427f0SYan, Zheng return 0;
107e9e427f0SYan, Zheng bad:
108e9e427f0SYan, Zheng return -1;
109e9e427f0SYan, Zheng }
110e9e427f0SYan, Zheng
1112f2dc053SSage Weil /*
1122f2dc053SSage Weil * Decode an MDS map
1132f2dc053SSage Weil *
1142f2dc053SSage Weil * Ignore any fields we don't care about (there are quite a few of
1152f2dc053SSage Weil * them).
1162f2dc053SSage Weil */
ceph_mdsmap_decode(struct ceph_mds_client * mdsc,void ** p,void * end,bool msgr2)117*2e2023e9SXiubo Li struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
118*2e2023e9SXiubo Li void *end, bool msgr2)
1192f2dc053SSage Weil {
1202f2dc053SSage Weil struct ceph_mdsmap *m;
1219ec7cab1SSage Weil const void *start = *p;
1222f2dc053SSage Weil int i, j, n;
123f3848af1SJeff Layton int err;
1248e298debSJia Yang u8 mdsmap_v;
125e9e427f0SYan, Zheng u16 mdsmap_ev;
126d517b398SXiubo Li u32 target;
1272f2dc053SSage Weil
1282f2dc053SSage Weil m = kzalloc(sizeof(*m), GFP_NOFS);
129d37b1d99SMarkus Elfring if (!m)
1302f2dc053SSage Weil return ERR_PTR(-ENOMEM);
1312f2dc053SSage Weil
132d463a43dSYan, Zheng ceph_decode_need(p, end, 1 + 1, bad);
133d463a43dSYan, Zheng mdsmap_v = ceph_decode_8(p);
1348e298debSJia Yang *p += sizeof(u8); /* mdsmap_cv */
135d463a43dSYan, Zheng if (mdsmap_v >= 4) {
136d463a43dSYan, Zheng u32 mdsmap_len;
137d463a43dSYan, Zheng ceph_decode_32_safe(p, end, mdsmap_len, bad);
138d463a43dSYan, Zheng if (end < *p + mdsmap_len)
1394f6a7e5eSSage Weil goto bad;
140d463a43dSYan, Zheng end = *p + mdsmap_len;
1414f6a7e5eSSage Weil }
1422f2dc053SSage Weil
1432f2dc053SSage Weil ceph_decode_need(p, end, 8*sizeof(u32) + sizeof(u64), bad);
144c89136eaSSage Weil m->m_epoch = ceph_decode_32(p);
145c89136eaSSage Weil m->m_client_epoch = ceph_decode_32(p);
146c89136eaSSage Weil m->m_last_failure = ceph_decode_32(p);
147c89136eaSSage Weil m->m_root = ceph_decode_32(p);
148c89136eaSSage Weil m->m_session_timeout = ceph_decode_32(p);
149c89136eaSSage Weil m->m_session_autoclose = ceph_decode_32(p);
150c89136eaSSage Weil m->m_max_file_size = ceph_decode_64(p);
151c89136eaSSage Weil m->m_max_mds = ceph_decode_32(p);
1524d7ace02SXiubo Li
1534d7ace02SXiubo Li /*
154b38c9eb4SXiubo Li * pick out the active nodes as the m_num_active_mds, the
155b38c9eb4SXiubo Li * m_num_active_mds maybe larger than m_max_mds when decreasing
156b38c9eb4SXiubo Li * the max_mds in cluster side, in other case it should less
157b38c9eb4SXiubo Li * than or equal to m_max_mds.
1584d7ace02SXiubo Li */
159b38c9eb4SXiubo Li m->m_num_active_mds = n = ceph_decode_32(p);
1604d7ace02SXiubo Li
1614d7ace02SXiubo Li /*
162b38c9eb4SXiubo Li * the possible max rank, it maybe larger than the m_num_active_mds,
1634d7ace02SXiubo Li * for example if the mds_max == 2 in the cluster, when the MDS(0)
1644d7ace02SXiubo Li * was laggy and being replaced by a new MDS, we will temporarily
1654d7ace02SXiubo Li * receive a new mds map with n_num_mds == 1 and the active MDS(1),
166b38c9eb4SXiubo Li * and the mds rank >= m_num_active_mds.
1674d7ace02SXiubo Li */
168b38c9eb4SXiubo Li m->possible_max_rank = max(m->m_num_active_mds, m->m_max_mds);
1692f2dc053SSage Weil
170b38c9eb4SXiubo Li m->m_info = kcalloc(m->possible_max_rank, sizeof(*m->m_info), GFP_NOFS);
171d37b1d99SMarkus Elfring if (!m->m_info)
172e9e427f0SYan, Zheng goto nomem;
1732f2dc053SSage Weil
1742f2dc053SSage Weil /* pick out active nodes from mds_info (state > 0) */
1752f2dc053SSage Weil for (i = 0; i < n; i++) {
17694045e11SSage Weil u64 global_id;
1772f2dc053SSage Weil u32 namelen;
1782f2dc053SSage Weil s32 mds, inc, state;
179d463a43dSYan, Zheng u8 info_v;
180d463a43dSYan, Zheng void *info_end = NULL;
1812f2dc053SSage Weil struct ceph_entity_addr addr;
1822f2dc053SSage Weil u32 num_export_targets;
1832f2dc053SSage Weil void *pexport_targets = NULL;
1840deb01c9SSage Weil struct ceph_timespec laggy_since;
1856af86528SDan Carpenter struct ceph_mds_info *info;
186da08e1e1SXiubo Li bool laggy;
1872f2dc053SSage Weil
188d463a43dSYan, Zheng ceph_decode_need(p, end, sizeof(u64) + 1, bad);
18994045e11SSage Weil global_id = ceph_decode_64(p);
190d463a43dSYan, Zheng info_v= ceph_decode_8(p);
191d463a43dSYan, Zheng if (info_v >= 4) {
192d463a43dSYan, Zheng u32 info_len;
193d463a43dSYan, Zheng ceph_decode_need(p, end, 1 + sizeof(u32), bad);
1948e298debSJia Yang *p += sizeof(u8); /* info_cv */
195d463a43dSYan, Zheng info_len = ceph_decode_32(p);
196d463a43dSYan, Zheng info_end = *p + info_len;
197d463a43dSYan, Zheng if (info_end > end)
198d463a43dSYan, Zheng goto bad;
199d463a43dSYan, Zheng }
200d463a43dSYan, Zheng
201d463a43dSYan, Zheng ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
20294045e11SSage Weil *p += sizeof(u64);
203c89136eaSSage Weil namelen = ceph_decode_32(p); /* skip mds name */
2042f2dc053SSage Weil *p += namelen;
2052f2dc053SSage Weil
206a5cbd5fcSIlya Dryomov ceph_decode_32_safe(p, end, mds, bad);
207a5cbd5fcSIlya Dryomov ceph_decode_32_safe(p, end, inc, bad);
208a5cbd5fcSIlya Dryomov ceph_decode_32_safe(p, end, state, bad);
2098e298debSJia Yang *p += sizeof(u64); /* state_seq */
210a5cbd5fcSIlya Dryomov if (info_v >= 8)
211a5cbd5fcSIlya Dryomov err = ceph_decode_entity_addrvec(p, end, msgr2, &addr);
212a5cbd5fcSIlya Dryomov else
213f3848af1SJeff Layton err = ceph_decode_entity_addr(p, end, &addr);
214f3848af1SJeff Layton if (err)
215f3848af1SJeff Layton goto corrupt;
216a5cbd5fcSIlya Dryomov
217a5cbd5fcSIlya Dryomov ceph_decode_copy_safe(p, end, &laggy_since, sizeof(laggy_since),
218a5cbd5fcSIlya Dryomov bad);
219da08e1e1SXiubo Li laggy = laggy_since.tv_sec != 0 || laggy_since.tv_nsec != 0;
2202f2dc053SSage Weil *p += sizeof(u32);
2212f2dc053SSage Weil ceph_decode_32_safe(p, end, namelen, bad);
222e251e288SSage Weil *p += namelen;
223d463a43dSYan, Zheng if (info_v >= 2) {
2242f2dc053SSage Weil ceph_decode_32_safe(p, end, num_export_targets, bad);
2252f2dc053SSage Weil pexport_targets = *p;
226e251e288SSage Weil *p += num_export_targets * sizeof(u32);
2272f2dc053SSage Weil } else {
2282f2dc053SSage Weil num_export_targets = 0;
2292f2dc053SSage Weil }
2302f2dc053SSage Weil
231d463a43dSYan, Zheng if (info_end && *p != info_end) {
232d463a43dSYan, Zheng if (*p > info_end)
233d463a43dSYan, Zheng goto bad;
234d463a43dSYan, Zheng *p = info_end;
235d463a43dSYan, Zheng }
236d463a43dSYan, Zheng
237da08e1e1SXiubo Li dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n",
2383d14c5d2SYehuda Sadeh i+1, n, global_id, mds, inc,
239b726ec97SJeff Layton ceph_pr_addr(&addr),
240da08e1e1SXiubo Li ceph_mds_state_name(state),
241da08e1e1SXiubo Li laggy ? "(laggy)" : "");
2426af86528SDan Carpenter
243b38c9eb4SXiubo Li if (mds < 0 || mds >= m->possible_max_rank) {
2444d7ace02SXiubo Li pr_warn("mdsmap_decode got incorrect mds(%d)\n", mds);
2456af86528SDan Carpenter continue;
2464d7ace02SXiubo Li }
2476af86528SDan Carpenter
2484d7ace02SXiubo Li if (state <= 0) {
249ccd1acdfSLuis Henriques dout("mdsmap_decode 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);
383641eb2d9SXiubo Li /* bal_rank_mask */
384641eb2d9SXiubo Li ceph_decode_skip_string(p, end, bad_ext);
385641eb2d9SXiubo Li }
386641eb2d9SXiubo Li if (mdsmap_ev >= 18) {
387d93231a6SLuís Henriques ceph_decode_64_safe(p, end, m->m_max_xattr_size, bad_ext);
388d93231a6SLuís Henriques }
389e9e427f0SYan, Zheng bad_ext:
390da08e1e1SXiubo Li dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
391da08e1e1SXiubo Li !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
392d463a43dSYan, Zheng *p = end;
3932f2dc053SSage Weil dout("mdsmap_decode success epoch %u\n", m->m_epoch);
3942f2dc053SSage Weil return m;
395e9e427f0SYan, Zheng nomem:
3962f2dc053SSage Weil err = -ENOMEM;
397e9e427f0SYan, Zheng goto out_err;
398f3848af1SJeff Layton corrupt:
3992f2dc053SSage Weil pr_err("corrupt mdsmap\n");
4009ec7cab1SSage Weil print_hex_dump(KERN_DEBUG, "mdsmap: ",
4019ec7cab1SSage Weil DUMP_PREFIX_OFFSET, 16, 1,
4029ec7cab1SSage Weil start, end - start, true);
403e9e427f0SYan, Zheng out_err:
4042f2dc053SSage Weil ceph_mdsmap_destroy(m);
405c213b50bSEmil Goode return ERR_PTR(err);
406f3848af1SJeff Layton bad:
407f3848af1SJeff Layton err = -EINVAL;
408f3848af1SJeff Layton goto corrupt;
4092f2dc053SSage Weil }
4102f2dc053SSage Weil
ceph_mdsmap_destroy(struct ceph_mdsmap * m)4112f2dc053SSage Weil void ceph_mdsmap_destroy(struct ceph_mdsmap *m)
4122f2dc053SSage Weil {
4132f2dc053SSage Weil int i;
4142f2dc053SSage Weil
415a9e6ffbcSTuo Li if (m->m_info) {
416b38c9eb4SXiubo Li for (i = 0; i < m->possible_max_rank; i++)
4172f2dc053SSage Weil kfree(m->m_info[i].export_targets);
4182f2dc053SSage Weil kfree(m->m_info);
419a9e6ffbcSTuo Li }
4202f2dc053SSage Weil kfree(m->m_data_pg_pools);
4212f2dc053SSage Weil kfree(m);
4222f2dc053SSage Weil }
423e9e427f0SYan, Zheng
ceph_mdsmap_is_cluster_available(struct ceph_mdsmap * m)424e9e427f0SYan, Zheng bool ceph_mdsmap_is_cluster_available(struct ceph_mdsmap *m)
425e9e427f0SYan, Zheng {
426e9e427f0SYan, Zheng int i, nr_active = 0;
427e9e427f0SYan, Zheng if (!m->m_enabled)
428e9e427f0SYan, Zheng return false;
429e9e427f0SYan, Zheng if (m->m_damaged)
430e9e427f0SYan, Zheng return false;
4314d7ace02SXiubo Li if (m->m_num_laggy == m->m_num_active_mds)
432e9e427f0SYan, Zheng return false;
433b38c9eb4SXiubo Li for (i = 0; i < m->possible_max_rank; i++) {
434e9e427f0SYan, Zheng if (m->m_info[i].state == CEPH_MDS_STATE_ACTIVE)
435e9e427f0SYan, Zheng nr_active++;
436e9e427f0SYan, Zheng }
437e9e427f0SYan, Zheng return nr_active > 0;
438e9e427f0SYan, Zheng }
439