Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
18 | * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
19 | * | |
20 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
21 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
30 | * Copyright (c) 2011, 2012, Intel Corporation. | |
31 | */ | |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | * | |
36 | * lustre/lov/lov_ea.c | |
37 | * | |
38 | * Author: Wang Di <wangdi@clusterfs.com> | |
39 | */ | |
40 | ||
41 | #define DEBUG_SUBSYSTEM S_LOV | |
42 | ||
43 | #include <asm/div64.h> | |
9fdaf8c0 | 44 | #include "../../include/linux/libcfs/libcfs.h" |
d7e09d03 | 45 | |
0cf0f7a7 GKH |
46 | #include "../include/obd_class.h" |
47 | #include "../include/lustre/lustre_idl.h" | |
d7e09d03 PT |
48 | |
49 | #include "lov_internal.h" | |
50 | ||
51 | struct lovea_unpack_args { | |
52 | struct lov_stripe_md *lsm; | |
53 | int cursor; | |
54 | }; | |
55 | ||
56 | static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes, | |
57 | __u16 stripe_count) | |
58 | { | |
5dd16419 | 59 | if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) { |
d7e09d03 | 60 | CERROR("bad stripe count %d\n", stripe_count); |
53b78538 | 61 | lov_dump_lmm_common(D_WARNING, lmm); |
d7e09d03 PT |
62 | return -EINVAL; |
63 | } | |
64 | ||
65 | if (lmm_oi_id(&lmm->lmm_oi) == 0) { | |
66 | CERROR("zero object id\n"); | |
53b78538 | 67 | lov_dump_lmm_common(D_WARNING, lmm); |
d7e09d03 PT |
68 | return -EINVAL; |
69 | } | |
70 | ||
5dd16419 | 71 | if (lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_RAID0) { |
d7e09d03 | 72 | CERROR("bad striping pattern\n"); |
53b78538 | 73 | lov_dump_lmm_common(D_WARNING, lmm); |
d7e09d03 PT |
74 | return -EINVAL; |
75 | } | |
76 | ||
77 | if (lmm->lmm_stripe_size == 0 || | |
53b78538 | 78 | (le32_to_cpu(lmm->lmm_stripe_size)&(LOV_MIN_STRIPE_SIZE-1)) != 0) { |
d7e09d03 PT |
79 | CERROR("bad stripe size %u\n", |
80 | le32_to_cpu(lmm->lmm_stripe_size)); | |
53b78538 | 81 | lov_dump_lmm_common(D_WARNING, lmm); |
d7e09d03 PT |
82 | return -EINVAL; |
83 | } | |
84 | return 0; | |
85 | } | |
86 | ||
87 | struct lov_stripe_md *lsm_alloc_plain(__u16 stripe_count, int *size) | |
88 | { | |
89 | struct lov_stripe_md *lsm; | |
90 | struct lov_oinfo *loi; | |
91 | int i, oinfo_ptrs_size; | |
92 | ||
93 | LASSERT(stripe_count <= LOV_MAX_STRIPE_COUNT); | |
94 | ||
95 | oinfo_ptrs_size = sizeof(struct lov_oinfo *) * stripe_count; | |
96 | *size = sizeof(struct lov_stripe_md) + oinfo_ptrs_size; | |
97 | ||
98 | OBD_ALLOC_LARGE(lsm, *size); | |
99 | if (!lsm) | |
76b8f538 | 100 | return NULL; |
d7e09d03 PT |
101 | |
102 | for (i = 0; i < stripe_count; i++) { | |
0be19afa | 103 | OBD_SLAB_ALLOC_PTR_GFP(loi, lov_oinfo_slab, GFP_NOFS); |
d7e09d03 PT |
104 | if (loi == NULL) |
105 | goto err; | |
106 | lsm->lsm_oinfo[i] = loi; | |
107 | } | |
108 | lsm->lsm_stripe_count = stripe_count; | |
109 | return lsm; | |
110 | ||
111 | err: | |
112 | while (--i >= 0) | |
113 | OBD_SLAB_FREE(lsm->lsm_oinfo[i], lov_oinfo_slab, sizeof(*loi)); | |
114 | OBD_FREE_LARGE(lsm, *size); | |
115 | return NULL; | |
116 | } | |
117 | ||
118 | void lsm_free_plain(struct lov_stripe_md *lsm) | |
119 | { | |
120 | __u16 stripe_count = lsm->lsm_stripe_count; | |
121 | int i; | |
122 | ||
123 | for (i = 0; i < stripe_count; i++) | |
124 | OBD_SLAB_FREE(lsm->lsm_oinfo[i], lov_oinfo_slab, | |
125 | sizeof(struct lov_oinfo)); | |
126 | OBD_FREE_LARGE(lsm, sizeof(struct lov_stripe_md) + | |
127 | stripe_count * sizeof(struct lov_oinfo *)); | |
128 | } | |
129 | ||
130 | static void lsm_unpackmd_common(struct lov_stripe_md *lsm, | |
131 | struct lov_mds_md *lmm) | |
132 | { | |
133 | /* | |
134 | * This supposes lov_mds_md_v1/v3 first fields are | |
135 | * are the same | |
136 | */ | |
137 | lmm_oi_le_to_cpu(&lsm->lsm_oi, &lmm->lmm_oi); | |
138 | lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size); | |
139 | lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern); | |
140 | lsm->lsm_layout_gen = le16_to_cpu(lmm->lmm_layout_gen); | |
141 | lsm->lsm_pool_name[0] = '\0'; | |
142 | } | |
143 | ||
144 | static void | |
145 | lsm_stripe_by_index_plain(struct lov_stripe_md *lsm, int *stripeno, | |
21aef7d9 | 146 | u64 *lov_off, u64 *swidth) |
d7e09d03 PT |
147 | { |
148 | if (swidth) | |
21aef7d9 | 149 | *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; |
d7e09d03 PT |
150 | } |
151 | ||
152 | static void | |
153 | lsm_stripe_by_offset_plain(struct lov_stripe_md *lsm, int *stripeno, | |
21aef7d9 | 154 | u64 *lov_off, u64 *swidth) |
d7e09d03 PT |
155 | { |
156 | if (swidth) | |
21aef7d9 | 157 | *swidth = (u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count; |
d7e09d03 PT |
158 | } |
159 | ||
160 | static int lsm_destroy_plain(struct lov_stripe_md *lsm, struct obdo *oa, | |
161 | struct obd_export *md_exp) | |
162 | { | |
163 | return 0; | |
164 | } | |
165 | ||
166 | /* Find minimum stripe maxbytes value. For inactive or | |
167 | * reconnecting targets use LUSTRE_STRIPE_MAXBYTES. */ | |
168 | static void lov_tgt_maxbytes(struct lov_tgt_desc *tgt, __u64 *stripe_maxbytes) | |
169 | { | |
170 | struct obd_import *imp = tgt->ltd_obd->u.cli.cl_import; | |
171 | ||
172 | if (imp == NULL || !tgt->ltd_active) { | |
173 | *stripe_maxbytes = LUSTRE_STRIPE_MAXBYTES; | |
174 | return; | |
175 | } | |
176 | ||
177 | spin_lock(&imp->imp_lock); | |
178 | if (imp->imp_state == LUSTRE_IMP_FULL && | |
179 | (imp->imp_connect_data.ocd_connect_flags & OBD_CONNECT_MAXBYTES) && | |
180 | imp->imp_connect_data.ocd_maxbytes > 0) { | |
181 | if (*stripe_maxbytes > imp->imp_connect_data.ocd_maxbytes) | |
182 | *stripe_maxbytes = imp->imp_connect_data.ocd_maxbytes; | |
183 | } else { | |
184 | *stripe_maxbytes = LUSTRE_STRIPE_MAXBYTES; | |
185 | } | |
186 | spin_unlock(&imp->imp_lock); | |
187 | } | |
188 | ||
189 | static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes, | |
190 | __u16 *stripe_count) | |
191 | { | |
192 | if (lmm_bytes < sizeof(*lmm)) { | |
193 | CERROR("lov_mds_md_v1 too small: %d, need at least %d\n", | |
194 | lmm_bytes, (int)sizeof(*lmm)); | |
195 | return -EINVAL; | |
196 | } | |
197 | ||
198 | *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); | |
5dd16419 JX |
199 | if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) |
200 | *stripe_count = 0; | |
d7e09d03 PT |
201 | |
202 | if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)) { | |
203 | CERROR("LOV EA V1 too small: %d, need %d\n", | |
204 | lmm_bytes, lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)); | |
53b78538 | 205 | lov_dump_lmm_common(D_WARNING, lmm); |
d7e09d03 PT |
206 | return -EINVAL; |
207 | } | |
208 | ||
209 | return lsm_lmm_verify_common(lmm, lmm_bytes, *stripe_count); | |
210 | } | |
211 | ||
212 | int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, | |
213 | struct lov_mds_md_v1 *lmm) | |
214 | { | |
215 | struct lov_oinfo *loi; | |
216 | int i; | |
5dd16419 | 217 | int stripe_count; |
d7e09d03 PT |
218 | __u64 stripe_maxbytes = OBD_OBJECT_EOF; |
219 | ||
220 | lsm_unpackmd_common(lsm, lmm); | |
221 | ||
5dd16419 JX |
222 | stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; |
223 | ||
224 | for (i = 0; i < stripe_count; i++) { | |
d7e09d03 PT |
225 | /* XXX LOV STACKING call down to osc_unpackmd() */ |
226 | loi = lsm->lsm_oinfo[i]; | |
227 | ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi); | |
228 | loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx); | |
229 | loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen); | |
230 | if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) { | |
231 | CERROR("OST index %d more than OST count %d\n", | |
232 | loi->loi_ost_idx, lov->desc.ld_tgt_count); | |
233 | lov_dump_lmm_v1(D_WARNING, lmm); | |
234 | return -EINVAL; | |
235 | } | |
236 | if (!lov->lov_tgts[loi->loi_ost_idx]) { | |
237 | CERROR("OST index %d missing\n", loi->loi_ost_idx); | |
238 | lov_dump_lmm_v1(D_WARNING, lmm); | |
239 | return -EINVAL; | |
240 | } | |
241 | /* calculate the minimum stripe max bytes */ | |
242 | lov_tgt_maxbytes(lov->lov_tgts[loi->loi_ost_idx], | |
243 | &stripe_maxbytes); | |
244 | } | |
245 | ||
246 | lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; | |
5dd16419 JX |
247 | if (lsm->lsm_stripe_count == 0) |
248 | lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; | |
d7e09d03 PT |
249 | |
250 | return 0; | |
251 | } | |
252 | ||
253 | const struct lsm_operations lsm_v1_ops = { | |
254 | .lsm_free = lsm_free_plain, | |
255 | .lsm_destroy = lsm_destroy_plain, | |
256 | .lsm_stripe_by_index = lsm_stripe_by_index_plain, | |
257 | .lsm_stripe_by_offset = lsm_stripe_by_offset_plain, | |
258 | .lsm_lmm_verify = lsm_lmm_verify_v1, | |
259 | .lsm_unpackmd = lsm_unpackmd_v1, | |
260 | }; | |
261 | ||
262 | static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes, | |
263 | __u16 *stripe_count) | |
264 | { | |
265 | struct lov_mds_md_v3 *lmm; | |
266 | ||
267 | lmm = (struct lov_mds_md_v3 *)lmmv1; | |
268 | ||
269 | if (lmm_bytes < sizeof(*lmm)) { | |
270 | CERROR("lov_mds_md_v3 too small: %d, need at least %d\n", | |
271 | lmm_bytes, (int)sizeof(*lmm)); | |
272 | return -EINVAL; | |
273 | } | |
274 | ||
275 | *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); | |
5dd16419 JX |
276 | if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) |
277 | *stripe_count = 0; | |
d7e09d03 PT |
278 | |
279 | if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)) { | |
280 | CERROR("LOV EA V3 too small: %d, need %d\n", | |
281 | lmm_bytes, lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)); | |
53b78538 | 282 | lov_dump_lmm_common(D_WARNING, lmm); |
d7e09d03 PT |
283 | return -EINVAL; |
284 | } | |
285 | ||
286 | return lsm_lmm_verify_common((struct lov_mds_md_v1 *)lmm, lmm_bytes, | |
287 | *stripe_count); | |
288 | } | |
289 | ||
290 | int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm, | |
291 | struct lov_mds_md *lmmv1) | |
292 | { | |
293 | struct lov_mds_md_v3 *lmm; | |
294 | struct lov_oinfo *loi; | |
295 | int i; | |
5dd16419 | 296 | int stripe_count; |
d7e09d03 PT |
297 | __u64 stripe_maxbytes = OBD_OBJECT_EOF; |
298 | int cplen = 0; | |
299 | ||
300 | lmm = (struct lov_mds_md_v3 *)lmmv1; | |
301 | ||
302 | lsm_unpackmd_common(lsm, (struct lov_mds_md_v1 *)lmm); | |
5dd16419 JX |
303 | |
304 | stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; | |
305 | ||
d7e09d03 PT |
306 | cplen = strlcpy(lsm->lsm_pool_name, lmm->lmm_pool_name, |
307 | sizeof(lsm->lsm_pool_name)); | |
308 | if (cplen >= sizeof(lsm->lsm_pool_name)) | |
309 | return -E2BIG; | |
310 | ||
5dd16419 | 311 | for (i = 0; i < stripe_count; i++) { |
d7e09d03 PT |
312 | /* XXX LOV STACKING call down to osc_unpackmd() */ |
313 | loi = lsm->lsm_oinfo[i]; | |
314 | ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi); | |
315 | loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx); | |
316 | loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen); | |
317 | if (loi->loi_ost_idx >= lov->desc.ld_tgt_count) { | |
318 | CERROR("OST index %d more than OST count %d\n", | |
319 | loi->loi_ost_idx, lov->desc.ld_tgt_count); | |
320 | lov_dump_lmm_v3(D_WARNING, lmm); | |
321 | return -EINVAL; | |
322 | } | |
323 | if (!lov->lov_tgts[loi->loi_ost_idx]) { | |
324 | CERROR("OST index %d missing\n", loi->loi_ost_idx); | |
325 | lov_dump_lmm_v3(D_WARNING, lmm); | |
326 | return -EINVAL; | |
327 | } | |
328 | /* calculate the minimum stripe max bytes */ | |
329 | lov_tgt_maxbytes(lov->lov_tgts[loi->loi_ost_idx], | |
330 | &stripe_maxbytes); | |
331 | } | |
332 | ||
333 | lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; | |
5dd16419 JX |
334 | if (lsm->lsm_stripe_count == 0) |
335 | lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; | |
d7e09d03 PT |
336 | |
337 | return 0; | |
338 | } | |
339 | ||
340 | const struct lsm_operations lsm_v3_ops = { | |
341 | .lsm_free = lsm_free_plain, | |
342 | .lsm_destroy = lsm_destroy_plain, | |
343 | .lsm_stripe_by_index = lsm_stripe_by_index_plain, | |
344 | .lsm_stripe_by_offset = lsm_stripe_by_offset_plain, | |
345 | .lsm_lmm_verify = lsm_lmm_verify_v3, | |
346 | .lsm_unpackmd = lsm_unpackmd_v3, | |
347 | }; | |
081b7265 JH |
348 | |
349 | void dump_lsm(unsigned int level, const struct lov_stripe_md *lsm) | |
350 | { | |
2d00bd17 JP |
351 | CDEBUG(level, "lsm %p, objid " DOSTID ", maxbytes %#llx, magic 0x%08X, stripe_size %u, stripe_count %u, refc: %d, layout_gen %u, pool [" LOV_POOLNAMEF "]\n", |
352 | lsm, | |
081b7265 JH |
353 | POSTID(&lsm->lsm_oi), lsm->lsm_maxbytes, lsm->lsm_magic, |
354 | lsm->lsm_stripe_size, lsm->lsm_stripe_count, | |
355 | atomic_read(&lsm->lsm_refc), lsm->lsm_layout_gen, | |
356 | lsm->lsm_pool_name); | |
357 | } |