Blame view

fs/ceph/mdsmap.c 4.31 KB
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1
  #include <linux/ceph/ceph_debug.h>
2f2dc0534   Sage Weil   ceph: MDS client
2
3
4
5
6
7
  
  #include <linux/bug.h>
  #include <linux/err.h>
  #include <linux/random.h>
  #include <linux/slab.h>
  #include <linux/types.h>
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
8
9
10
  #include <linux/ceph/mdsmap.h>
  #include <linux/ceph/messenger.h>
  #include <linux/ceph/decode.h>
2f2dc0534   Sage Weil   ceph: MDS client
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  
  #include "super.h"
  
  
  /*
   * choose a random mds that is "up" (i.e. has a state > 0), or -1.
   */
  int ceph_mdsmap_get_random_mds(struct ceph_mdsmap *m)
  {
  	int n = 0;
  	int i;
  	char r;
  
  	/* count */
  	for (i = 0; i < m->m_max_mds; i++)
  		if (m->m_info[i].state > 0)
  			n++;
  	if (n == 0)
  		return -1;
  
  	/* pick */
  	get_random_bytes(&r, 1);
  	n = r % n;
  	i = 0;
  	for (i = 0; n > 0; i++, n--)
  		while (m->m_info[i].state <= 0)
  			i++;
  
  	return i;
  }
  
  /*
   * Decode an MDS map
   *
   * Ignore any fields we don't care about (there are quite a few of
   * them).
   */
  struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
  {
  	struct ceph_mdsmap *m;
9ec7cab14   Sage Weil   ceph: hex dump co...
51
  	const void *start = *p;
2f2dc0534   Sage Weil   ceph: MDS client
52
53
54
55
56
57
58
59
60
61
62
  	int i, j, n;
  	int err = -EINVAL;
  	u16 version;
  
  	m = kzalloc(sizeof(*m), GFP_NOFS);
  	if (m == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	ceph_decode_16_safe(p, end, version, bad);
  
  	ceph_decode_need(p, end, 8*sizeof(u32) + sizeof(u64), bad);
c89136ea4   Sage Weil   ceph: convert enc...
63
64
65
66
67
68
69
70
  	m->m_epoch = ceph_decode_32(p);
  	m->m_client_epoch = ceph_decode_32(p);
  	m->m_last_failure = ceph_decode_32(p);
  	m->m_root = ceph_decode_32(p);
  	m->m_session_timeout = ceph_decode_32(p);
  	m->m_session_autoclose = ceph_decode_32(p);
  	m->m_max_file_size = ceph_decode_64(p);
  	m->m_max_mds = ceph_decode_32(p);
2f2dc0534   Sage Weil   ceph: MDS client
71
72
73
74
75
76
  
  	m->m_info = kcalloc(m->m_max_mds, sizeof(*m->m_info), GFP_NOFS);
  	if (m->m_info == NULL)
  		goto badmem;
  
  	/* pick out active nodes from mds_info (state > 0) */
c89136ea4   Sage Weil   ceph: convert enc...
77
  	n = ceph_decode_32(p);
2f2dc0534   Sage Weil   ceph: MDS client
78
  	for (i = 0; i < n; i++) {
94045e115   Sage Weil   ceph: decode upda...
79
  		u64 global_id;
2f2dc0534   Sage Weil   ceph: MDS client
80
81
82
83
84
85
86
  		u32 namelen;
  		s32 mds, inc, state;
  		u64 state_seq;
  		u8 infoversion;
  		struct ceph_entity_addr addr;
  		u32 num_export_targets;
  		void *pexport_targets = NULL;
0deb01c99   Sage Weil   ceph: track laggy...
87
  		struct ceph_timespec laggy_since;
2f2dc0534   Sage Weil   ceph: MDS client
88

94045e115   Sage Weil   ceph: decode upda...
89
90
  		ceph_decode_need(p, end, sizeof(u64)*2 + 1 + sizeof(u32), bad);
  		global_id = ceph_decode_64(p);
c89136ea4   Sage Weil   ceph: convert enc...
91
  		infoversion = ceph_decode_8(p);
94045e115   Sage Weil   ceph: decode upda...
92
  		*p += sizeof(u64);
c89136ea4   Sage Weil   ceph: convert enc...
93
  		namelen = ceph_decode_32(p);  /* skip mds name */
2f2dc0534   Sage Weil   ceph: MDS client
94
95
96
  		*p += namelen;
  
  		ceph_decode_need(p, end,
e251e2880   Sage Weil   ceph: fix mdsmap ...
97
  				 4*sizeof(u32) + sizeof(u64) +
2f2dc0534   Sage Weil   ceph: MDS client
98
99
  				 sizeof(addr) + sizeof(struct ceph_timespec),
  				 bad);
c89136ea4   Sage Weil   ceph: convert enc...
100
101
102
103
  		mds = ceph_decode_32(p);
  		inc = ceph_decode_32(p);
  		state = ceph_decode_32(p);
  		state_seq = ceph_decode_64(p);
94045e115   Sage Weil   ceph: decode upda...
104
105
  		ceph_decode_copy(p, &addr, sizeof(addr));
  		ceph_decode_addr(&addr);
0deb01c99   Sage Weil   ceph: track laggy...
106
  		ceph_decode_copy(p, &laggy_since, sizeof(laggy_since));
2f2dc0534   Sage Weil   ceph: MDS client
107
108
  		*p += sizeof(u32);
  		ceph_decode_32_safe(p, end, namelen, bad);
e251e2880   Sage Weil   ceph: fix mdsmap ...
109
  		*p += namelen;
2f2dc0534   Sage Weil   ceph: MDS client
110
111
112
  		if (infoversion >= 2) {
  			ceph_decode_32_safe(p, end, num_export_targets, bad);
  			pexport_targets = *p;
e251e2880   Sage Weil   ceph: fix mdsmap ...
113
  			*p += num_export_targets * sizeof(u32);
2f2dc0534   Sage Weil   ceph: MDS client
114
115
116
  		} else {
  			num_export_targets = 0;
  		}
94045e115   Sage Weil   ceph: decode upda...
117
118
  		dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s
  ",
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
119
120
  		     i+1, n, global_id, mds, inc,
  		     ceph_pr_addr(&addr.in_addr),
2f2dc0534   Sage Weil   ceph: MDS client
121
122
  		     ceph_mds_state_name(state));
  		if (mds >= 0 && mds < m->m_max_mds && state > 0) {
94045e115   Sage Weil   ceph: decode upda...
123
  			m->m_info[mds].global_id = global_id;
2f2dc0534   Sage Weil   ceph: MDS client
124
125
  			m->m_info[mds].state = state;
  			m->m_info[mds].addr = addr;
0deb01c99   Sage Weil   ceph: track laggy...
126
127
128
  			m->m_info[mds].laggy =
  				(laggy_since.tv_sec != 0 ||
  				 laggy_since.tv_nsec != 0);
2f2dc0534   Sage Weil   ceph: MDS client
129
130
131
132
133
134
  			m->m_info[mds].num_export_targets = num_export_targets;
  			if (num_export_targets) {
  				m->m_info[mds].export_targets =
  					kcalloc(num_export_targets, sizeof(u32),
  						GFP_NOFS);
  				for (j = 0; j < num_export_targets; j++)
c89136ea4   Sage Weil   ceph: convert enc...
135
136
  					m->m_info[mds].export_targets[j] =
  					       ceph_decode_32(&pexport_targets);
2f2dc0534   Sage Weil   ceph: MDS client
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  			} else {
  				m->m_info[mds].export_targets = NULL;
  			}
  		}
  	}
  
  	/* pg_pools */
  	ceph_decode_32_safe(p, end, n, bad);
  	m->m_num_data_pg_pools = n;
  	m->m_data_pg_pools = kcalloc(n, sizeof(u32), GFP_NOFS);
  	if (!m->m_data_pg_pools)
  		goto badmem;
  	ceph_decode_need(p, end, sizeof(u32)*(n+1), bad);
  	for (i = 0; i < n; i++)
c89136ea4   Sage Weil   ceph: convert enc...
151
152
  		m->m_data_pg_pools[i] = ceph_decode_32(p);
  	m->m_cas_pg_pool = ceph_decode_32(p);
2f2dc0534   Sage Weil   ceph: MDS client
153
154
155
156
157
158
159
160
161
162
163
  
  	/* ok, we don't care about the rest. */
  	dout("mdsmap_decode success epoch %u
  ", m->m_epoch);
  	return m;
  
  badmem:
  	err = -ENOMEM;
  bad:
  	pr_err("corrupt mdsmap
  ");
9ec7cab14   Sage Weil   ceph: hex dump co...
164
165
166
  	print_hex_dump(KERN_DEBUG, "mdsmap: ",
  		       DUMP_PREFIX_OFFSET, 16, 1,
  		       start, end - start, true);
2f2dc0534   Sage Weil   ceph: MDS client
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  	ceph_mdsmap_destroy(m);
  	return ERR_PTR(-EINVAL);
  }
  
  void ceph_mdsmap_destroy(struct ceph_mdsmap *m)
  {
  	int i;
  
  	for (i = 0; i < m->m_max_mds; i++)
  		kfree(m->m_info[i].export_targets);
  	kfree(m->m_info);
  	kfree(m->m_data_pg_pools);
  	kfree(m);
  }