1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5 * Author: Andreas Dilger <adilger@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * (Un)packing of OST/MDS requests
26 #define DEBUG_SUBSYSTEM S_LLITE
28 #include <linux/lustre_net.h>
29 #include <linux/obd.h>
30 #include <linux/obd_lov.h>
31 #include <linux/obd_class.h>
32 #include <linux/obd_support.h>
34 /* lov_packdesc() is in mds/mds_lov.c */
35 void lov_unpackdesc(struct lov_desc *ld)
37 ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
38 ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
39 ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
40 ld->ld_pattern = HTON__u32(ld->ld_pattern);
43 void lov_dump_lmm(int level, struct lov_mds_md *lmm)
45 struct lov_object_id *loi;
48 CDEBUG(level, "objid "LPX64", magic %#08x, ost_count %u\n",
49 lmm->lmm_object_id, lmm->lmm_magic, lmm->lmm_ost_count);
50 CDEBUG(level,"stripe_size %u, stripe_count %u, stripe_offset %u\n",
51 lmm->lmm_stripe_size, lmm->lmm_stripe_count,
52 lmm->lmm_stripe_offset);
53 for (idx = 0, loi = lmm->lmm_objects; idx < lmm->lmm_ost_count;
55 CDEBUG(level, "ost idx %u subobj "LPX64"\n", idx,
59 #define LMM_ASSERT(test) \
61 if (!(test)) lov_dump_lmm(D_ERROR, lmm); \
62 LASSERT(test); /* so we know what assertion failed */ \
65 /* Pack LOV object metadata for shipment to the MDS.
67 * XXX In the future, this will be enhanced to get the EA size from the
68 * underlying OSC device(s) to get their EA sizes so we can stack
69 * LOVs properly. For now lov_mds_md_size() just assumes one obd_id
72 int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
73 struct lov_stripe_md *lsm)
75 struct obd_device *obd = class_conn2obd(conn);
76 struct lov_obd *lov = &obd->u.lov;
77 struct lov_oinfo *loi;
78 struct lov_mds_md *lmm;
79 int ost_count = lov->desc.ld_tgt_count;
80 int stripe_count = ost_count;
87 if (lsm->lsm_magic != LOV_MAGIC) {
88 CERROR("bad mem LOV MAGIC: %#010x != %#010x\n",
89 lsm->lsm_magic, LOV_MAGIC);
92 stripe_count = lsm->lsm_stripe_count;
94 for (i = 0,loi = lsm->lsm_oinfo; i < stripe_count; i++,loi++) {
95 if (loi->loi_ost_idx > max)
96 max = loi->loi_ost_idx;
101 /* XXX LOV STACKING call into osc for sizes */
102 lmm_size = lov_mds_md_size(ost_count);
109 ost_count = ((*lmmp)->lmm_ost_count);
110 OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
116 OBD_ALLOC(*lmmp, lmm_size);
123 lmm->lmm_stripe_count = (stripe_count);
128 lmm->lmm_magic = (lsm->lsm_magic);
129 lmm->lmm_object_id = (lsm->lsm_object_id);
130 LASSERT(lsm->lsm_object_id);
131 lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
132 lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
133 lmm->lmm_ost_count = (ost_count);
135 /* Only fill in the object ids which we are actually using.
136 * Assumes lmm_objects is otherwise zero-filled. */
137 for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++) {
138 /* XXX call down to osc_packmd() to do the packing */
139 LASSERT(loi->loi_id);
140 lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
146 static int lov_get_stripecnt(struct lov_obd *lov, int stripe_count)
149 stripe_count = lov->desc.ld_default_stripe_count;
150 if (!stripe_count || stripe_count > lov->desc.ld_active_tgt_count)
151 stripe_count = lov->desc.ld_active_tgt_count;
156 int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
157 struct lov_mds_md *lmm)
159 struct obd_device *obd = class_conn2obd(conn);
160 struct lov_obd *lov = &obd->u.lov;
161 struct lov_stripe_md *lsm;
162 struct lov_oinfo *loi;
172 if (lmm->lmm_magic != LOV_MAGIC) {
173 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
174 lmm->lmm_magic, LOV_MAGIC);
177 stripe_count = (lmm->lmm_stripe_count);
178 LASSERT(stripe_count);
180 stripe_count = lov_get_stripecnt(lov, 0);
182 /* XXX LOV STACKING call into osc for sizes */
183 lsm_size = lov_stripe_md_size(stripe_count);
189 stripe_count = (*lsmp)->lsm_stripe_count;
190 OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
196 OBD_ALLOC(*lsmp, lsm_size);
203 lsm->lsm_stripe_count = stripe_count;
208 ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
209 lsm->lsm_magic = (lmm->lmm_magic);
210 lsm->lsm_object_id = (lmm->lmm_object_id);
211 lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
213 ost_count = (lmm->lmm_ost_count);
215 LMM_ASSERT(lsm->lsm_object_id);
216 LMM_ASSERT(ost_count);
218 for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
219 ost_offset %= ost_count;
221 if (!lmm->lmm_objects[ost_offset].l_object_id)
224 LMM_ASSERT(loi - lsm->lsm_oinfo < stripe_count);
225 /* XXX LOV STACKING call down to osc_unpackmd() */
226 loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
227 loi->loi_ost_idx = ost_offset;
230 LMM_ASSERT(loi - lsm->lsm_oinfo > 0);
231 LMM_ASSERT(loi - lsm->lsm_oinfo == stripe_count);
236 /* Configure object striping information on a new file.
238 * @lmmu is a pointer to a user struct with one or more of the fields set to
239 * indicate the application preference: lmm_stripe_count, lmm_stripe_size,
240 * lmm_stripe_offset, and lmm_stripe_pattern. lmm_magic must be LOV_MAGIC.
241 * @lsmp is a pointer to an in-core stripe MD that needs to be filled in.
243 int lov_setstripe(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
244 struct lov_mds_md *lmmu)
246 struct obd_device *obd = class_conn2obd(conn);
247 struct lov_obd *lov = &obd->u.lov;
248 struct lov_mds_md lmm;
249 struct lov_stripe_md *lsm;
254 rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
258 if (lmm.lmm_magic != LOV_MAGIC) {
259 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
260 lmm.lmm_magic, LOV_MAGIC);
263 if (lmm.lmm_stripe_count > lov->desc.ld_tgt_count) {
264 CERROR("stripe count %u more than OST count %d\n",
265 lmm.lmm_stripe_count, lov->desc.ld_tgt_count);
268 if (lmm.lmm_stripe_offset >= lov->desc.ld_tgt_count &&
269 lmm.lmm_stripe_offset != 0xffffffff) {
270 CERROR("stripe offset %u more than max OST index %d\n",
271 lmm.lmm_stripe_offset, lov->desc.ld_tgt_count);
274 if (lmm.lmm_stripe_size & (PAGE_SIZE - 1)) {
275 CERROR("stripe size %u not multiple of %lu\n",
276 lmm.lmm_stripe_size, PAGE_SIZE);
279 if ((__u64)lmm.lmm_stripe_size * lmm.lmm_stripe_count > ~0UL) {
280 CERROR("stripe width %ux%u > %lu on 32-bit system\n",
281 lmm.lmm_stripe_size, (int)lmm.lmm_stripe_count, ~0UL);
285 stripe_count = lov_get_stripecnt(lov, lmm.lmm_stripe_count);
287 /* XXX LOV STACKING call into osc for sizes */
288 OBD_ALLOC(lsm, lov_stripe_md_size(stripe_count));
292 lsm->lsm_magic = LOV_MAGIC;
293 lsm->lsm_stripe_count = stripe_count;
294 lsm->lsm_stripe_offset = lmm.lmm_stripe_offset;
295 lsm->lsm_stripe_size = lmm.lmm_stripe_size;
302 /* Retrieve object striping information.
304 * @lmmu is a pointer to an in-core struct with lmm_ost_count indicating
305 * the maximum number of OST indices which will fit in the user buffer.
306 * lmm_magic must be LOV_MAGIC.
308 int lov_getstripe(struct lustre_handle *conn, struct lov_stripe_md *lsm,
309 struct lov_mds_md *lmmu)
311 struct obd_device *obd = class_conn2obd(conn);
312 struct lov_obd *lov = &obd->u.lov;
313 struct lov_mds_md lmm, *lmmk = NULL;
314 int ost_count, rc, lmm_size;
320 rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
324 if (lmm.lmm_magic != LOV_MAGIC)
327 ost_count = lov->desc.ld_tgt_count;
329 /* XXX we _could_ check if indices > user lmm_ost_count are zero */
330 if (lmm.lmm_ost_count < ost_count)
333 rc = lov_packmd(conn, &lmmk, lsm);
340 if (lmm_size && copy_to_user(lmmu, lmmk, lmm_size))
343 obd_free_wiremd(conn, &lmmk);