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
13522dc510SXiubo 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
__mdsmap_get_random_mds(struct ceph_mdsmap * m,bool ignore_laggy)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 */
ceph_mdsmap_get_random_mds(struct ceph_mdsmap * m)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
__decode_and_drop_compat_set(void ** p,void * end)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 */
ceph_mdsmap_decode(struct ceph_mds_client * mdsc,void ** p,void * end,bool msgr2)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);
383*51d31149SXiubo Li /* bal_rank_mask */
384*51d31149SXiubo Li ceph_decode_skip_string(p, end, bad_ext);
385*51d31149SXiubo Li }
386*51d31149SXiubo 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:
39038d46409SXiubo Li doutc(cl, "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;
39338d46409SXiubo Li doutc(cl, "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:
39938d46409SXiubo Li pr_err_client(cl, "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