1 #include <linux/ceph/ceph_debug.h>
5 #include <linux/random.h>
6 #include <linux/slab.h>
7 #include <linux/types.h>
9 #include <linux/ceph/mdsmap.h>
10 #include <linux/ceph/messenger.h>
11 #include <linux/ceph/decode.h>
17 * choose a random mds that is "up" (i.e. has a state > 0), or -1.
19 int ceph_mdsmap_get_random_mds(struct ceph_mdsmap
*m
)
24 /* special case for one mds */
25 if (1 == m
->m_max_mds
&& m
->m_info
[0].state
> 0)
29 for (i
= 0; i
< m
->m_max_mds
; i
++)
30 if (m
->m_info
[i
].state
> 0)
36 n
= prandom_u32() % n
;
38 for (i
= 0; n
> 0; i
++, n
--)
39 while (m
->m_info
[i
].state
<= 0)
48 * Ignore any fields we don't care about (there are quite a few of
51 struct ceph_mdsmap
*ceph_mdsmap_decode(void **p
, void *end
)
53 struct ceph_mdsmap
*m
;
54 const void *start
= *p
;
57 u8 mdsmap_v
, mdsmap_cv
;
59 m
= kzalloc(sizeof(*m
), GFP_NOFS
);
61 return ERR_PTR(-ENOMEM
);
63 ceph_decode_need(p
, end
, 1 + 1, bad
);
64 mdsmap_v
= ceph_decode_8(p
);
65 mdsmap_cv
= ceph_decode_8(p
);
68 ceph_decode_32_safe(p
, end
, mdsmap_len
, bad
);
69 if (end
< *p
+ mdsmap_len
)
71 end
= *p
+ mdsmap_len
;
74 ceph_decode_need(p
, end
, 8*sizeof(u32
) + sizeof(u64
), bad
);
75 m
->m_epoch
= ceph_decode_32(p
);
76 m
->m_client_epoch
= ceph_decode_32(p
);
77 m
->m_last_failure
= ceph_decode_32(p
);
78 m
->m_root
= ceph_decode_32(p
);
79 m
->m_session_timeout
= ceph_decode_32(p
);
80 m
->m_session_autoclose
= ceph_decode_32(p
);
81 m
->m_max_file_size
= ceph_decode_64(p
);
82 m
->m_max_mds
= ceph_decode_32(p
);
84 m
->m_info
= kcalloc(m
->m_max_mds
, sizeof(*m
->m_info
), GFP_NOFS
);
85 if (m
->m_info
== NULL
)
88 /* pick out active nodes from mds_info (state > 0) */
89 n
= ceph_decode_32(p
);
90 for (i
= 0; i
< n
; i
++) {
96 void *info_end
= NULL
;
97 struct ceph_entity_addr addr
;
98 u32 num_export_targets
;
99 void *pexport_targets
= NULL
;
100 struct ceph_timespec laggy_since
;
101 struct ceph_mds_info
*info
;
103 ceph_decode_need(p
, end
, sizeof(u64
) + 1, bad
);
104 global_id
= ceph_decode_64(p
);
105 info_v
= ceph_decode_8(p
);
109 ceph_decode_need(p
, end
, 1 + sizeof(u32
), bad
);
110 info_cv
= ceph_decode_8(p
);
111 info_len
= ceph_decode_32(p
);
112 info_end
= *p
+ info_len
;
117 ceph_decode_need(p
, end
, sizeof(u64
) + sizeof(u32
), bad
);
119 namelen
= ceph_decode_32(p
); /* skip mds name */
122 ceph_decode_need(p
, end
,
123 4*sizeof(u32
) + sizeof(u64
) +
124 sizeof(addr
) + sizeof(struct ceph_timespec
),
126 mds
= ceph_decode_32(p
);
127 inc
= ceph_decode_32(p
);
128 state
= ceph_decode_32(p
);
129 state_seq
= ceph_decode_64(p
);
130 ceph_decode_copy(p
, &addr
, sizeof(addr
));
131 ceph_decode_addr(&addr
);
132 ceph_decode_copy(p
, &laggy_since
, sizeof(laggy_since
));
134 ceph_decode_32_safe(p
, end
, namelen
, bad
);
137 ceph_decode_32_safe(p
, end
, num_export_targets
, bad
);
138 pexport_targets
= *p
;
139 *p
+= num_export_targets
* sizeof(u32
);
141 num_export_targets
= 0;
144 if (info_end
&& *p
!= info_end
) {
150 dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s\n",
151 i
+1, n
, global_id
, mds
, inc
,
152 ceph_pr_addr(&addr
.in_addr
),
153 ceph_mds_state_name(state
));
155 if (mds
< 0 || mds
>= m
->m_max_mds
|| state
<= 0)
158 info
= &m
->m_info
[mds
];
159 info
->global_id
= global_id
;
162 info
->laggy
= (laggy_since
.tv_sec
!= 0 ||
163 laggy_since
.tv_nsec
!= 0);
164 info
->num_export_targets
= num_export_targets
;
165 if (num_export_targets
) {
166 info
->export_targets
= kcalloc(num_export_targets
,
167 sizeof(u32
), GFP_NOFS
);
168 if (info
->export_targets
== NULL
)
170 for (j
= 0; j
< num_export_targets
; j
++)
171 info
->export_targets
[j
] =
172 ceph_decode_32(&pexport_targets
);
174 info
->export_targets
= NULL
;
179 ceph_decode_32_safe(p
, end
, n
, bad
);
180 m
->m_num_data_pg_pools
= n
;
181 m
->m_data_pg_pools
= kcalloc(n
, sizeof(u64
), GFP_NOFS
);
182 if (!m
->m_data_pg_pools
)
184 ceph_decode_need(p
, end
, sizeof(u64
)*(n
+1), bad
);
185 for (i
= 0; i
< n
; i
++)
186 m
->m_data_pg_pools
[i
] = ceph_decode_64(p
);
187 m
->m_cas_pg_pool
= ceph_decode_64(p
);
189 /* ok, we don't care about the rest. */
191 dout("mdsmap_decode success epoch %u\n", m
->m_epoch
);
197 pr_err("corrupt mdsmap\n");
198 print_hex_dump(KERN_DEBUG
, "mdsmap: ",
199 DUMP_PREFIX_OFFSET
, 16, 1,
200 start
, end
- start
, true);
201 ceph_mdsmap_destroy(m
);
205 void ceph_mdsmap_destroy(struct ceph_mdsmap
*m
)
209 for (i
= 0; i
< m
->m_max_mds
; i
++)
210 kfree(m
->m_info
[i
].export_targets
);
212 kfree(m
->m_data_pg_pools
);