Whamcloud - gitweb
land 0.5.20.3 b_devel onto HEAD (b_devel will remain)
[fs/lustre-release.git] / lustre / lov / lov_pack.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5  *   Author: Andreas Dilger <adilger@clusterfs.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
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.
12  *
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.
17  *
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.
21  *
22  * (Un)packing of OST/MDS requests
23  *
24  */
25
26 #define DEBUG_SUBSYSTEM S_LLITE
27 #ifndef __KERNEL__
28 #include <liblustre.h>
29 #endif
30
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>
36
37 /* lov_packdesc() is in mds/mds_lov.c */
38 void lov_unpackdesc(struct lov_desc *ld)
39 {
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);
44 }
45
46 void lov_dump_lmm(int level, struct lov_mds_md *lmm)
47 {
48         struct lov_object_id *loi;
49         int idx;
50
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;
57              idx++, loi++)
58                 CDEBUG(level, "ost idx %u subobj "LPX64"\n", idx,
59                        loi->l_object_id);
60 }
61
62 #define LMM_ASSERT(test)                                                \
63 do {                                                                    \
64         if (!(test)) lov_dump_lmm(D_ERROR, lmm);                        \
65         LASSERT(test); /* so we know what assertion failed */           \
66 } while(0)
67
68 /* Pack LOV object metadata for shipment to the MDS.
69  *
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
73  *     per stripe.
74  */
75 int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
76                struct lov_stripe_md *lsm)
77 {
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;
84         int lmm_size;
85         int i;
86         ENTRY;
87
88         if (lsm) {
89                 int i, max = 0;
90                 if (lsm->lsm_magic != LOV_MAGIC) {
91                         CERROR("bad mem LOV MAGIC: %#010x != %#010x\n",
92                                lsm->lsm_magic, LOV_MAGIC);
93                         RETURN(-EINVAL);
94                 }
95                 stripe_count = lsm->lsm_stripe_count;
96
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;
100                 }
101                 ost_count = max + 1;
102         }
103
104         /* XXX LOV STACKING call into osc for sizes */
105         lmm_size = lov_mds_md_size(ost_count);
106
107         if (!lmmp)
108                 RETURN(lmm_size);
109
110         if (*lmmp && !lsm) {
111                 /* endianness */
112                 ost_count = ((*lmmp)->lmm_ost_count);
113                 OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
114                 *lmmp = NULL;
115                 RETURN(0);
116         }
117
118         if (!*lmmp) {
119                 OBD_ALLOC(*lmmp, lmm_size);
120                 if (!*lmmp)
121                         RETURN(-ENOMEM);
122         }
123
124         lmm = *lmmp;
125
126         lmm->lmm_stripe_count = (stripe_count);
127         if (!lsm)
128                 RETURN(lmm_size);
129
130         /* XXX endianness */
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);
137
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);
144         }
145
146         RETURN(lmm_size);
147 }
148
149 static int lov_get_stripecnt(struct lov_obd *lov, int stripe_count)
150 {
151         if (!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;
155
156         return stripe_count;
157 }
158
159 int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
160                  struct lov_mds_md *lmm)
161 {
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;
166         int ost_count;
167         int ost_offset = 0;
168         int stripe_count;
169         int lsm_size;
170         int i;
171         ENTRY;
172
173         if (lmm) {
174                 /* endianness */
175                 if (lmm->lmm_magic != LOV_MAGIC) {
176                         CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
177                                lmm->lmm_magic, LOV_MAGIC);
178                         RETURN(-EINVAL);
179                 }
180                 stripe_count = (lmm->lmm_stripe_count);
181                 LASSERT(stripe_count);
182         } else
183                 stripe_count = lov_get_stripecnt(lov, 0);
184
185         /* XXX LOV STACKING call into osc for sizes */
186         lsm_size = lov_stripe_md_size(stripe_count);
187
188         if (!lsmp)
189                 RETURN(lsm_size);
190
191         if (*lsmp && !lmm) {
192                 stripe_count = (*lsmp)->lsm_stripe_count;
193                 OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
194                 *lsmp = NULL;
195                 RETURN(0);
196         }
197
198         if (!*lsmp) {
199                 OBD_ALLOC(*lsmp, lsm_size);
200                 if (!*lsmp)
201                         RETURN(-ENOMEM);
202         }
203
204         lsm = *lsmp;
205
206         lsm->lsm_stripe_count = stripe_count;
207         if (!lmm)
208                 RETURN(lsm_size);
209
210         /* XXX endianness */
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);
215
216         ost_count = (lmm->lmm_ost_count);
217
218         LMM_ASSERT(lsm->lsm_object_id);
219         LMM_ASSERT(ost_count);
220
221         for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
222                 ost_offset %= ost_count;
223
224                 if (!lmm->lmm_objects[ost_offset].l_object_id)
225                         continue;
226
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;
231                 loi++;
232         }
233         LMM_ASSERT(loi - lsm->lsm_oinfo > 0);
234         LMM_ASSERT(loi - lsm->lsm_oinfo == stripe_count);
235
236         RETURN(lsm_size);
237 }
238
239 /* Configure object striping information on a new file.
240  *
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.
245  */
246 int lov_setstripe(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
247                   struct lov_mds_md *lmmu)
248 {
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;
253         int stripe_count;
254         int rc;
255         ENTRY;
256
257         rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
258         if (rc)
259                 RETURN(-EFAULT);
260
261         if (lmm.lmm_magic != LOV_MAGIC) {
262                 CERROR("bad wire LOV MAGIC: %#08x != %#08x\n",
263                        lmm.lmm_magic, LOV_MAGIC);
264                 RETURN(-EINVAL);
265         }
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);
271                 RETURN(-EINVAL);
272         }
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);
277                 RETURN(-EINVAL);
278         }
279 #endif
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);
283                 RETURN(-EINVAL);
284         }
285         stripe_count = lov_get_stripecnt(lov, lmm.lmm_stripe_count);
286
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);
290                 RETURN(-EINVAL);
291         }
292
293         /* XXX LOV STACKING call into osc for sizes */
294         OBD_ALLOC(lsm, lov_stripe_md_size(stripe_count));
295         if (!lsm)
296                 RETURN(-ENOMEM);
297
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;
302
303         *lsmp = lsm;
304
305         RETURN(rc);
306 }
307
308 /* Retrieve object striping information.
309  *
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.
313  */
314 int lov_getstripe(struct lustre_handle *conn, struct lov_stripe_md *lsm,
315                   struct lov_mds_md *lmmu)
316 {
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;
321         ENTRY;
322
323         if (!lsm)
324                 RETURN(-ENODATA);
325
326         rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
327         if (rc)
328                 RETURN(-EFAULT);
329
330         if (lmm.lmm_magic != LOV_MAGIC)
331                 RETURN(-EINVAL);
332
333         ost_count = lov->desc.ld_tgt_count;
334
335         /* XXX we _could_ check if indices > user lmm_ost_count are zero */
336         if (lmm.lmm_ost_count < ost_count)
337                 RETURN(-EOVERFLOW);
338
339         rc = lov_packmd(conn, &lmmk, lsm);
340         if (rc < 0)
341                 RETURN(rc);
342
343         lmm_size = rc;
344         rc = 0;
345
346         if (lmm_size && copy_to_user(lmmu, lmmk, lmm_size))
347                 rc = -EFAULT;
348
349         obd_free_wiremd(conn, &lmmk);
350
351         RETURN(rc);
352 }