1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * (Un)packing of OST/MDS requests
25 #define DEBUG_SUBSYSTEM S_LLITE
27 #include <linux/lustre_net.h>
28 #include <linux/obd.h>
29 #include <linux/obd_lov.h>
30 #include <linux/obd_class.h>
31 #include <linux/obd_support.h>
33 /* lov_packdesc() is in mds/mds_lov.c */
34 void lov_unpackdesc(struct lov_desc *ld)
36 ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
37 ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
38 ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
39 ld->ld_pattern = HTON__u32(ld->ld_pattern);
42 void lov_dump_lmm(int level, struct lov_mds_md *lmm)
44 struct lov_object_id *loi;
47 CDEBUG(level, "objid "LPX64", magic %#08x, ost_count %u\n",
48 lmm->lmm_object_id, lmm->lmm_magic, lmm->lmm_ost_count);
49 CDEBUG(level,"stripe_size %u, stripe_count %u, stripe_offset %u\n",
50 lmm->lmm_stripe_size, lmm->lmm_stripe_count,
51 lmm->lmm_stripe_offset);
52 for (idx = 0, loi = lmm->lmm_objects; idx < lmm->lmm_ost_count;
54 CDEBUG(level, "ost idx %u subobj "LPX64"\n", idx,
58 #define LMM_ASSERT(test) \
60 if (!(test)) lov_dump_lmm(D_ERROR, lmm); \
61 LASSERT(test); /* so we know what assertion failed */ \
64 /* Pack LOV object metadata for shipment to the MDS.
66 * XXX In the future, this will be enhanced to get the EA size from the
67 * underlying OSC device(s) to get their EA sizes so we can stack
68 * LOVs properly. For now lov_mds_md_size() just assumes one obd_id
71 int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
72 struct lov_stripe_md *lsm)
74 struct obd_device *obd = class_conn2obd(conn);
75 struct lov_obd *lov = &obd->u.lov;
76 struct lov_oinfo *loi;
77 struct lov_mds_md *lmm;
78 int ost_count = lov->desc.ld_tgt_count;
79 int stripe_count = ost_count;
86 if (lsm->lsm_magic != LOV_MAGIC) {
87 CERROR("bad mem LOV MAGIC: %#010x != %#010x\n",
88 lsm->lsm_magic, LOV_MAGIC);
91 stripe_count = lsm->lsm_stripe_count;
93 for (i = 0,loi = lsm->lsm_oinfo; i < stripe_count; i++,loi++) {
94 if (loi->loi_ost_idx > max)
95 max = loi->loi_ost_idx;
100 /* XXX LOV STACKING call into osc for sizes */
101 lmm_size = lov_mds_md_size(ost_count);
108 ost_count = ((*lmmp)->lmm_ost_count);
109 OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
115 OBD_ALLOC(*lmmp, lmm_size);
122 lmm->lmm_stripe_count = (stripe_count);
127 lmm->lmm_magic = (lsm->lsm_magic);
128 lmm->lmm_object_id = (lsm->lsm_object_id);
129 LASSERT(lsm->lsm_object_id);
130 lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
131 lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
132 lmm->lmm_ost_count = (ost_count);
134 /* Only fill in the object ids which we are actually using.
135 * Assumes lmm_objects is otherwise zero-filled. */
136 for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++) {
137 /* XXX call down to osc_packmd() to do the packing */
138 LASSERT(loi->loi_id);
139 lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
145 static int lov_get_stripecnt(struct lov_obd *lov, int stripe_count)
148 stripe_count = lov->desc.ld_default_stripe_count;
149 if (!stripe_count || stripe_count > lov->desc.ld_active_tgt_count)
150 stripe_count = lov->desc.ld_active_tgt_count;
155 int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
156 struct lov_mds_md *lmm)
158 struct obd_device *obd = class_conn2obd(conn);
159 struct lov_obd *lov = &obd->u.lov;
160 struct lov_stripe_md *lsm;
161 struct lov_oinfo *loi;
171 if (lmm->lmm_magic != LOV_MAGIC) {
172 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
173 lmm->lmm_magic, LOV_MAGIC);
176 stripe_count = (lmm->lmm_stripe_count);
177 LASSERT(stripe_count);
179 stripe_count = lov_get_stripecnt(lov, 0);
181 /* XXX LOV STACKING call into osc for sizes */
182 lsm_size = lov_stripe_md_size(stripe_count);
188 stripe_count = (*lsmp)->lsm_stripe_count;
189 OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
195 OBD_ALLOC(*lsmp, lsm_size);
202 lsm->lsm_stripe_count = stripe_count;
207 ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
208 lsm->lsm_magic = (lmm->lmm_magic);
209 lsm->lsm_object_id = (lmm->lmm_object_id);
210 lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
212 ost_count = (lmm->lmm_ost_count);
214 LMM_ASSERT(lsm->lsm_object_id);
215 LMM_ASSERT(ost_count);
217 for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
218 ost_offset %= ost_count;
220 if (!lmm->lmm_objects[ost_offset].l_object_id)
223 LMM_ASSERT(loi - lsm->lsm_oinfo < stripe_count);
224 /* XXX LOV STACKING call down to osc_unpackmd() */
225 loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
226 loi->loi_ost_idx = ost_offset;
229 LMM_ASSERT(loi - lsm->lsm_oinfo > 0);
230 LMM_ASSERT(loi - lsm->lsm_oinfo == stripe_count);
235 /* Configure object striping information on a new file.
237 * @lmmu is a pointer to a user struct with one or more of the fields set to
238 * indicate the application preference: lmm_stripe_count, lmm_stripe_size,
239 * lmm_stripe_offset, and lmm_stripe_pattern. lmm_magic must be LOV_MAGIC.
240 * @lsmp is a pointer to an in-core stripe MD that needs to be filled in.
242 int lov_setstripe(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
243 struct lov_mds_md *lmmu)
245 struct obd_device *obd = class_conn2obd(conn);
246 struct lov_obd *lov = &obd->u.lov;
247 struct lov_mds_md lmm;
248 struct lov_stripe_md *lsm;
253 rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
257 if (lmm.lmm_magic != LOV_MAGIC) {
258 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
259 lmm.lmm_magic, LOV_MAGIC);
262 if (lmm.lmm_stripe_count > lov->desc.ld_tgt_count) {
263 CERROR("stripe count %d more than OST count %d\n",
264 (int)lmm.lmm_stripe_count, lov->desc.ld_tgt_count);
267 if (lmm.lmm_stripe_offset >= lov->desc.ld_tgt_count) {
268 CERROR("stripe offset %d more than max OST index %d\n",
269 (int)lmm.lmm_stripe_count, lov->desc.ld_tgt_count);
272 if (lmm.lmm_stripe_size & (PAGE_SIZE - 1)) {
273 CERROR("stripe size %u not multiple of %lu\n",
274 lmm.lmm_stripe_size, PAGE_SIZE);
277 if (lmm.lmm_stripe_size * lmm.lmm_stripe_count > ~0UL) {
278 CERROR("stripe width %ux%u > %lu on 32-bit system\n",
279 lmm.lmm_stripe_size, (int)lmm.lmm_stripe_count, ~0UL);
283 stripe_count = lov_get_stripecnt(lov, lmm.lmm_stripe_count);
285 /* XXX LOV STACKING call into osc for sizes */
286 OBD_ALLOC(lsm, lov_stripe_md_size(stripe_count));
290 lsm->lsm_magic = LOV_MAGIC;
291 /* This is all validated in lov_create() */
292 lsm->lsm_stripe_count = stripe_count;
293 lsm->lsm_stripe_offset = lmm.lmm_stripe_offset;
294 lsm->lsm_stripe_size = lmm.lmm_stripe_size;
301 /* Retrieve object striping information.
303 * @lmmu is a pointer to an in-core struct with lmm_ost_count indicating
304 * the maximum number of OST indices which will fit in the user buffer.
305 * lmm_magic must be LOV_MAGIC.
307 int lov_getstripe(struct lustre_handle *conn, struct lov_stripe_md *lsm,
308 struct lov_mds_md *lmmu)
310 struct obd_device *obd = class_conn2obd(conn);
311 struct lov_obd *lov = &obd->u.lov;
312 struct lov_mds_md lmm, *lmmk = NULL;
313 int ost_count, rc, lmm_size;
319 rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
323 if (lmm.lmm_magic != LOV_MAGIC)
326 ost_count = lov->desc.ld_tgt_count;
328 /* XXX we _could_ check if indices > user lmm_ost_count are zero */
329 if (lmm.lmm_ost_count < ost_count)
332 rc = lov_packmd(conn, &lmmk, lsm);
339 if (lmm_size && copy_to_user(lmmu, lmmk, lmm_size))
342 obd_free_wiremd(conn, &lmmk);