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 <liblustre.h>
31 #include <linux/lustre_net.h>
32 #include <linux/obd.h>
33 #include <linux/obd_lov.h>
34 #include <linux/obd_class.h>
35 #include <linux/obd_support.h>
37 /* lov_packdesc() is in mds/mds_lov.c */
38 void lov_unpackdesc(struct lov_desc *ld)
40 ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
41 ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
42 ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
43 ld->ld_pattern = HTON__u32(ld->ld_pattern);
46 void lov_dump_lmm(int level, struct lov_mds_md *lmm)
48 struct lov_object_id *loi;
51 CDEBUG(level, "objid "LPX64", magic %#08x, ost_count %u\n",
52 lmm->lmm_object_id, lmm->lmm_magic, lmm->lmm_ost_count);
53 CDEBUG(level,"stripe_size %u, stripe_count %u, stripe_offset %u\n",
54 lmm->lmm_stripe_size, lmm->lmm_stripe_count,
55 lmm->lmm_stripe_offset);
56 for (idx = 0, loi = lmm->lmm_objects; idx < lmm->lmm_ost_count;
58 CDEBUG(level, "ost idx %u subobj "LPX64"\n", idx,
62 #define LMM_ASSERT(test) \
64 if (!(test)) lov_dump_lmm(D_ERROR, lmm); \
65 LASSERT(test); /* so we know what assertion failed */ \
68 /* Pack LOV object metadata for shipment to the MDS.
70 * XXX In the future, this will be enhanced to get the EA size from the
71 * underlying OSC device(s) to get their EA sizes so we can stack
72 * LOVs properly. For now lov_mds_md_size() just assumes one obd_id
75 int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
76 struct lov_stripe_md *lsm)
78 struct obd_device *obd = class_conn2obd(conn);
79 struct lov_obd *lov = &obd->u.lov;
80 struct lov_oinfo *loi;
81 struct lov_mds_md *lmm;
82 int ost_count = lov->desc.ld_tgt_count;
83 int stripe_count = ost_count;
90 if (lsm->lsm_magic != LOV_MAGIC) {
91 CERROR("bad mem LOV MAGIC: %#010x != %#010x\n",
92 lsm->lsm_magic, LOV_MAGIC);
95 stripe_count = lsm->lsm_stripe_count;
97 for (i = 0,loi = lsm->lsm_oinfo; i < stripe_count; i++,loi++) {
98 if (loi->loi_ost_idx > max)
99 max = loi->loi_ost_idx;
104 /* XXX LOV STACKING call into osc for sizes */
105 lmm_size = lov_mds_md_size(ost_count);
112 ost_count = ((*lmmp)->lmm_ost_count);
113 OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
119 OBD_ALLOC(*lmmp, lmm_size);
126 lmm->lmm_stripe_count = (stripe_count);
131 lmm->lmm_magic = (lsm->lsm_magic);
132 lmm->lmm_object_id = (lsm->lsm_object_id);
133 LASSERT(lsm->lsm_object_id);
134 lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
135 lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
136 lmm->lmm_ost_count = (ost_count);
138 /* Only fill in the object ids which we are actually using.
139 * Assumes lmm_objects is otherwise zero-filled. */
140 for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++) {
141 /* XXX call down to osc_packmd() to do the packing */
142 LASSERT(loi->loi_id);
143 lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
149 static int lov_get_stripecnt(struct lov_obd *lov, int stripe_count)
152 stripe_count = lov->desc.ld_default_stripe_count;
153 if (!stripe_count || stripe_count > lov->desc.ld_active_tgt_count)
154 stripe_count = lov->desc.ld_active_tgt_count;
159 int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
160 struct lov_mds_md *lmm)
162 struct obd_device *obd = class_conn2obd(conn);
163 struct lov_obd *lov = &obd->u.lov;
164 struct lov_stripe_md *lsm;
165 struct lov_oinfo *loi;
175 if (lmm->lmm_magic != LOV_MAGIC) {
176 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
177 lmm->lmm_magic, LOV_MAGIC);
180 stripe_count = (lmm->lmm_stripe_count);
181 LASSERT(stripe_count);
183 stripe_count = lov_get_stripecnt(lov, 0);
185 /* XXX LOV STACKING call into osc for sizes */
186 lsm_size = lov_stripe_md_size(stripe_count);
192 stripe_count = (*lsmp)->lsm_stripe_count;
193 OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
199 OBD_ALLOC(*lsmp, lsm_size);
206 lsm->lsm_stripe_count = stripe_count;
211 ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
212 lsm->lsm_magic = (lmm->lmm_magic);
213 lsm->lsm_object_id = (lmm->lmm_object_id);
214 lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
216 ost_count = (lmm->lmm_ost_count);
218 LMM_ASSERT(lsm->lsm_object_id);
219 LMM_ASSERT(ost_count);
221 for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
222 ost_offset %= ost_count;
224 if (!lmm->lmm_objects[ost_offset].l_object_id)
227 LMM_ASSERT(loi - lsm->lsm_oinfo < stripe_count);
228 /* XXX LOV STACKING call down to osc_unpackmd() */
229 loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
230 loi->loi_ost_idx = ost_offset;
233 LMM_ASSERT(loi - lsm->lsm_oinfo > 0);
234 LMM_ASSERT(loi - lsm->lsm_oinfo == stripe_count);
239 /* Configure object striping information on a new file.
241 * @lmmu is a pointer to a user struct with one or more of the fields set to
242 * indicate the application preference: lmm_stripe_count, lmm_stripe_size,
243 * lmm_stripe_offset, and lmm_stripe_pattern. lmm_magic must be LOV_MAGIC.
244 * @lsmp is a pointer to an in-core stripe MD that needs to be filled in.
246 int lov_setstripe(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
247 struct lov_mds_md *lmmu)
249 struct obd_device *obd = class_conn2obd(conn);
250 struct lov_obd *lov = &obd->u.lov;
251 struct lov_mds_md lmm;
252 struct lov_stripe_md *lsm;
257 rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
261 if (lmm.lmm_magic != LOV_MAGIC) {
262 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
263 lmm.lmm_magic, LOV_MAGIC);
266 #if 0 /* the stripe_count/offset is "advisory", and it gets fixed later */
267 if (lmm.lmm_stripe_count > lov->desc.ld_tgt_count &&
268 lmm.lmm_stripe_count != 0xffffffff) {
269 CERROR("stripe count %u more than OST count %d\n",
270 lmm.lmm_stripe_count, lov->desc.ld_tgt_count);
273 if (lmm.lmm_stripe_offset >= lov->desc.ld_tgt_count &&
274 lmm.lmm_stripe_offset != 0xffffffff) {
275 CERROR("stripe offset %u more than max OST index %d\n",
276 lmm.lmm_stripe_offset, lov->desc.ld_tgt_count);
280 if (lmm.lmm_stripe_size & (PAGE_SIZE - 1)) {
281 CERROR("stripe size %u not multiple of %lu\n",
282 lmm.lmm_stripe_size, PAGE_SIZE);
285 stripe_count = lov_get_stripecnt(lov, lmm.lmm_stripe_count);
287 if ((__u64)lmm.lmm_stripe_size * stripe_count > ~0UL) {
288 CERROR("stripe width %ux%u > %lu on 32-bit system\n",
289 lmm.lmm_stripe_size, (int)lmm.lmm_stripe_count, ~0UL);
293 /* XXX LOV STACKING call into osc for sizes */
294 OBD_ALLOC(lsm, lov_stripe_md_size(stripe_count));
298 lsm->lsm_magic = LOV_MAGIC;
299 lsm->lsm_stripe_count = stripe_count;
300 lsm->lsm_stripe_offset = lmm.lmm_stripe_offset;
301 lsm->lsm_stripe_size = lmm.lmm_stripe_size;
308 /* Retrieve object striping information.
310 * @lmmu is a pointer to an in-core struct with lmm_ost_count indicating
311 * the maximum number of OST indices which will fit in the user buffer.
312 * lmm_magic must be LOV_MAGIC.
314 int lov_getstripe(struct lustre_handle *conn, struct lov_stripe_md *lsm,
315 struct lov_mds_md *lmmu)
317 struct obd_device *obd = class_conn2obd(conn);
318 struct lov_obd *lov = &obd->u.lov;
319 struct lov_mds_md lmm, *lmmk = NULL;
320 int ost_count, rc, lmm_size;
326 rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
330 if (lmm.lmm_magic != LOV_MAGIC)
333 ost_count = lov->desc.ld_tgt_count;
335 /* XXX we _could_ check if indices > user lmm_ost_count are zero */
336 if (lmm.lmm_ost_count < ost_count)
339 rc = lov_packmd(conn, &lmmk, lsm);
346 if (lmm_size && copy_to_user(lmmu, lmmk, lmm_size))
349 obd_free_wiremd(conn, &lmmk);