Whamcloud - gitweb
Land b1_2 onto HEAD (20040304_171022)
[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_LOV
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 #include <linux/lustre_user.h>
37
38 #include "lov_internal.h"
39
40 void lov_dump_lmm_v0(int level, struct lov_mds_md_v0 *lmm)
41 {
42         int i, num_ost, stripe, idx;
43
44         num_ost = le32_to_cpu(lmm->lmm_ost_count);
45         idx = le32_to_cpu(lmm->lmm_stripe_offset);
46         CDEBUG(level, "objid "LPX64", magic 0x%08X, ost_count %u\n",
47                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
48                num_ost);
49         CDEBUG(level,"stripe_size %u, stripe_count %u, stripe_offset %u\n",
50                le32_to_cpu(lmm->lmm_stripe_size),
51                le32_to_cpu(lmm->lmm_stripe_count), idx);
52         for (i = stripe = 0; i < le32_to_cpu(lmm->lmm_ost_count); i++, idx++) {
53                 idx %= num_ost;
54                 if (lmm->lmm_objects[idx].l_object_id == 0)
55                         continue;
56                 CDEBUG(level, "stripe %u idx %u subobj "LPX64"\n", stripe, idx,
57                        le64_to_cpu(lmm->lmm_objects[idx].l_object_id));
58                 stripe++;
59         }
60 }
61
62 void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm)
63 {
64         struct lov_ost_data_v1 *lod;
65         int i;
66
67         CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
68                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
69                le32_to_cpu(lmm->lmm_pattern));
70         CDEBUG(level,"stripe_size %u, stripe_count %u\n",
71                le32_to_cpu(lmm->lmm_stripe_size),
72                le32_to_cpu(lmm->lmm_stripe_count));
73         for (i = 0, lod = lmm->lmm_objects;
74              i < le32_to_cpu(lmm->lmm_stripe_count); i++, lod++)
75                 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
76                        i, le32_to_cpu(lod->l_ost_idx),
77                        le64_to_cpu(lod->l_object_gr),
78                        le64_to_cpu(lod->l_object_id));
79 }
80
81 #define LMM_ASSERT(test)                                                \
82 do {                                                                    \
83         if (!(test)) lov_dump_lmm(D_ERROR, lmm);                        \
84         LASSERT(test); /* so we know what assertion failed */           \
85 } while(0)
86
87 /* Pack LOV object metadata for disk storage.  It is packed in LE byte
88  * order and is opaque to the networking layer.
89  *
90  * XXX In the future, this will be enhanced to get the EA size from the
91  *     underlying OSC device(s) to get their EA sizes so we can stack
92  *     LOVs properly.  For now lov_mds_md_size() just assumes one obd_id
93  *     per stripe.
94  */
95 int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
96                struct lov_stripe_md *lsm)
97 {
98         struct obd_device *obd = class_exp2obd(exp);
99         struct lov_obd *lov = &obd->u.lov;
100         struct lov_oinfo *loi;
101         struct lov_mds_md *lmm;
102         int stripe_count = lov->desc.ld_tgt_count;
103         int lmm_size;
104         int i;
105         ENTRY;
106
107         if (lsm) {
108                 if (lsm->lsm_magic != LOV_MAGIC) {
109                         CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X\n",
110                                lsm->lsm_magic, LOV_MAGIC);
111                         RETURN(-EINVAL);
112                 }
113                 stripe_count = lsm->lsm_stripe_count;
114         }
115
116         /* XXX LOV STACKING call into osc for sizes */
117         lmm_size = lov_mds_md_size(stripe_count);
118
119         if (!lmmp)
120                 RETURN(lmm_size);
121
122         if (*lmmp && !lsm) {
123                 stripe_count = le32_to_cpu((*lmmp)->lmm_stripe_count);
124                 OBD_FREE(*lmmp, lov_mds_md_size(stripe_count));
125                 *lmmp = NULL;
126                 RETURN(0);
127         }
128
129         if (!*lmmp) {
130                 OBD_ALLOC(*lmmp, lmm_size);
131                 if (!*lmmp)
132                         RETURN(-ENOMEM);
133         }
134
135         lmm = *lmmp;
136         lmm->lmm_magic = cpu_to_le32(LOV_MAGIC); /* only write new format */
137
138         if (!lsm)
139                 RETURN(lmm_size);
140
141         lmm->lmm_object_id = cpu_to_le64(lsm->lsm_object_id);
142         lmm->lmm_object_gr = cpu_to_le64(lsm->lsm_object_gr);
143         lmm->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size);
144         lmm->lmm_stripe_count = cpu_to_le32(stripe_count);
145         lmm->lmm_pattern = cpu_to_le32(lsm->lsm_pattern);
146
147         for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++) {
148                 /* XXX LOV STACKING call down to osc_packmd() to do packing */
149                 LASSERT(loi->loi_id);
150                 lmm->lmm_objects[i].l_object_id = cpu_to_le64(loi->loi_id);
151                 lmm->lmm_objects[i].l_object_gr = cpu_to_le64(loi->loi_gr);
152                 lmm->lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen);
153                 lmm->lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx);
154         }
155
156         RETURN(lmm_size);
157 }
158
159 int lov_get_stripecnt(struct lov_obd *lov, int stripe_count)
160 {
161         if (!stripe_count)
162                 stripe_count = lov->desc.ld_default_stripe_count;
163         if (!stripe_count || stripe_count > lov->desc.ld_active_tgt_count)
164                 stripe_count = lov->desc.ld_active_tgt_count;
165
166         return stripe_count;
167 }
168
169 static int lov_verify_lmm_v0(struct lov_mds_md_v0 *lmm, int lmm_bytes,
170                              int *stripe_count)
171 {
172         if (lmm_bytes < sizeof(*lmm)) {
173                 CERROR("lov_mds_md too small: %d, need at least %d\n",
174                        lmm_bytes, (int)sizeof(*lmm));
175                 return -EINVAL;
176         }
177
178         *stripe_count = le16_to_cpu(lmm->lmm_stripe_count);
179
180         if (*stripe_count == 0 ||
181             *stripe_count > le32_to_cpu(lmm->lmm_ost_count)) {
182                 CERROR("bad stripe count %d\n", *stripe_count);
183                 lov_dump_lmm_v0(D_WARNING, lmm);
184                 return -EINVAL;
185         }
186
187         if (lmm_bytes < lov_mds_md_v0_size(*stripe_count)) {
188                 CERROR("LOV EA too small: %d, need %d\n",
189                        lmm_bytes, lov_mds_md_size(*stripe_count));
190                 lov_dump_lmm_v0(D_WARNING, lmm);
191                 return -EINVAL;
192         }
193
194         if (lmm->lmm_object_id == 0) {
195                 CERROR("zero object id\n");
196                 lov_dump_lmm_v0(D_WARNING, lmm);
197                 return -EINVAL;
198         }
199
200         if (le32_to_cpu(lmm->lmm_stripe_offset) >
201             le32_to_cpu(lmm->lmm_ost_count)) {
202                 CERROR("stripe offset %d more than number of OSTs %d\n",
203                        le32_to_cpu(lmm->lmm_stripe_offset),
204                        le32_to_cpu(lmm->lmm_ost_count));
205                 lov_dump_lmm_v0(D_WARNING, lmm);
206                 return -EINVAL;
207         }
208
209         if (lmm->lmm_stripe_size == 0) {
210                 CERROR("zero stripe size\n");
211                 lov_dump_lmm_v0(D_WARNING, lmm);
212                 return -EINVAL;
213         }
214
215         return 0;
216 }
217
218 static int lov_verify_lmm_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes,
219                              int *stripe_count)
220 {
221         if (lmm_bytes < sizeof(*lmm)) {
222                 CERROR("lov_mds_md too small: %d, need at least %d\n",
223                        lmm_bytes, (int)sizeof(*lmm));
224                 return -EINVAL;
225         }
226
227         if (lmm->lmm_magic != le32_to_cpu(LOV_MAGIC_V1)) {
228                 CERROR("bad disk LOV MAGIC: 0x%08X\n",
229                        le32_to_cpu(*(__u32 *)lmm));
230                 return -EINVAL;
231         }
232
233         *stripe_count = le32_to_cpu(lmm->lmm_stripe_count);
234
235         if (*stripe_count == 0) {
236                 CERROR("bad stripe count %d\n", *stripe_count);
237                 lov_dump_lmm_v1(D_WARNING, lmm);
238                 return -EINVAL;
239         }
240
241         if (lmm_bytes < lov_mds_md_size(*stripe_count)) {
242                 CERROR("LOV EA too small: %d, need %d\n",
243                        lmm_bytes, lov_mds_md_size(*stripe_count));
244                 lov_dump_lmm_v1(D_WARNING, lmm);
245                 return -EINVAL;
246         }
247
248         if (lmm->lmm_object_id == 0) {
249                 CERROR("zero object id\n");
250                 lov_dump_lmm_v1(D_WARNING, lmm);
251                 return -EINVAL;
252         }
253
254         if (lmm->lmm_pattern != cpu_to_le32(LOV_PATTERN_RAID0)) {
255                 CERROR("bad striping pattern\n");
256                 lov_dump_lmm_v1(D_WARNING, lmm);
257                 return -EINVAL;
258         }
259
260         if (lmm->lmm_stripe_size == 0 ||
261             (__u64)le32_to_cpu(lmm->lmm_stripe_size) * *stripe_count > ~0UL) {
262                 CERROR("bad stripe size %u\n",
263                        le32_to_cpu(lmm->lmm_stripe_size));
264                 lov_dump_lmm_v1(D_WARNING, lmm);
265                 return -EINVAL;
266         }
267
268         return 0;
269 }
270
271 static int lov_verify_lmm(void *lmm, int lmm_bytes, int *stripe_count)
272 {
273         switch (le32_to_cpu(*(__u32 *)lmm)) {
274         case LOV_MAGIC_V1:
275                 return lov_verify_lmm_v1(lmm, lmm_bytes, stripe_count);
276         case LOV_MAGIC_V0:
277                 return lov_verify_lmm_v0(lmm, lmm_bytes, stripe_count);
278         default:
279                 CERROR("bad disk LOV MAGIC: 0x%08X\n",
280                        le32_to_cpu(*(__u32 *)lmm));
281                 return -EINVAL;
282         }
283 }
284
285 int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count, int pattern)
286 {
287         int lsm_size = lov_stripe_md_size(stripe_count);
288         struct lov_oinfo *loi;
289         int i;
290
291         OBD_ALLOC(*lsmp, lsm_size);
292         if (!*lsmp)
293                 return -ENOMEM;
294
295         (*lsmp)->lsm_magic = LOV_MAGIC;
296         (*lsmp)->lsm_stripe_count = stripe_count;
297         (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count;
298         (*lsmp)->lsm_xfersize = PTL_MTU * stripe_count;
299         (*lsmp)->lsm_pattern = pattern;
300         (*lsmp)->lsm_oinfo[0].loi_ost_idx = ~0;
301
302         for (i = 0, loi = (*lsmp)->lsm_oinfo; i < stripe_count; i++, loi++)
303                 loi_init(loi);
304
305         return lsm_size;
306 }
307
308 void lov_free_memmd(struct lov_stripe_md **lsmp)
309 {
310         OBD_FREE(*lsmp, lov_stripe_md_size((*lsmp)->lsm_stripe_count));
311         *lsmp = NULL;
312 }
313
314 int lov_unpackmd_v0(struct lov_obd *lov, struct lov_stripe_md *lsm,
315                     struct lov_mds_md_v0 *lmm)
316 {
317         struct lov_oinfo *loi;
318         int i, ost_offset, ost_count;
319
320         lsm->lsm_object_id = le64_to_cpu(lmm->lmm_object_id);
321         /* lsm->lsm_object_gr = 0; implicit */
322         lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size);
323         lsm->lsm_xfersize = lsm->lsm_stripe_size * lsm->lsm_stripe_count;
324         lsm->lsm_pattern = LOV_PATTERN_RAID0;
325         ost_offset = le32_to_cpu(lmm->lmm_stripe_offset);
326         ost_count = le16_to_cpu(lmm->lmm_ost_count);
327
328         for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
329                 ost_offset %= ost_count;
330
331                 if (!lmm->lmm_objects[ost_offset].l_object_id)
332                         continue;
333
334                 loi->loi_id =
335                         le64_to_cpu(lmm->lmm_objects[ost_offset].l_object_id);
336                 /* loi->loi_gr = 0; implicit */
337                 loi->loi_ost_idx = ost_offset;
338                 /* loi->loi_ost_gen = 0; implicit */
339                 loi++;
340         }
341
342         if (loi - lsm->lsm_oinfo != lsm->lsm_stripe_count) {
343                 CERROR("missing objects in lmm struct\n");
344                 lov_dump_lmm_v0(D_WARNING, lmm);
345                 return -EINVAL;
346         }
347
348         return 0;
349 }
350
351 int lov_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
352                     struct lov_mds_md_v1 *lmm)
353 {
354         struct lov_oinfo *loi;
355         int i;
356
357         lsm->lsm_object_id = le64_to_cpu(lmm->lmm_object_id);
358         lsm->lsm_object_gr = le64_to_cpu(lmm->lmm_object_gr);
359         lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size);
360         lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern);
361         lsm->lsm_xfersize = lsm->lsm_stripe_size * lsm->lsm_stripe_count;
362
363         for (i = 0, loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++) {
364                 /* XXX LOV STACKING call down to osc_unpackmd() */
365                 loi->loi_id = le64_to_cpu(lmm->lmm_objects[i].l_object_id);
366                 loi->loi_gr = le64_to_cpu(lmm->lmm_objects[i].l_object_gr);
367                 loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx);
368                 loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen);
369                 if (loi->loi_ost_idx > lov->desc.ld_tgt_count) {
370                         CERROR("OST index %d more than OST count %d\n",
371                                loi->loi_ost_idx, lov->desc.ld_tgt_count);
372                         lov_dump_lmm_v1(D_WARNING, lmm);
373                         return -EINVAL;
374                 }
375                 loi++;
376         }
377
378         return 0;
379 }
380
381 /* Unpack LOV object metadata from disk storage.  It is packed in LE byte
382  * order and is opaque to the networking layer.
383  */
384 int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
385                  struct lov_mds_md *lmm, int lmm_bytes)
386 {
387         struct obd_device *obd = class_exp2obd(exp);
388         struct lov_obd *lov = &obd->u.lov;
389         int rc = 0, stripe_count, lsm_size;
390         ENTRY;
391
392         /* If passed an MDS struct use values from there, otherwise defaults */
393         if (lmm) {
394                 rc = lov_verify_lmm(lmm, lmm_bytes, &stripe_count);
395                 if (rc)
396                         RETURN(rc);
397         } else {
398                 stripe_count = lov_get_stripecnt(lov, 0);
399         }
400
401         /* If we aren't passed an lsmp struct, we just want the size */
402         if (!lsmp)
403                 /* XXX LOV STACKING call into osc for sizes */
404                 RETURN(lov_stripe_md_size(stripe_count));
405
406         /* If we are passed an allocated struct but nothing to unpack, free */
407         if (*lsmp && !lmm) {
408                 lov_free_memmd(lsmp);
409                 RETURN(0);
410         }
411
412         lsm_size = lov_alloc_memmd(lsmp, stripe_count, LOV_PATTERN_RAID0);
413         if (lsm_size < 0)
414                 RETURN(lsm_size);
415
416         /* If we are passed a pointer but nothing to unpack, we only alloc */
417         if (!lmm)
418                 RETURN(lsm_size);
419
420         switch (le32_to_cpu(lmm->lmm_magic)) {
421         case LOV_MAGIC_V1:
422                 rc = lov_unpackmd_v1(lov, *lsmp, lmm);
423                 break;
424         case LOV_MAGIC_V0:
425                 rc = lov_unpackmd_v0(lov, *lsmp, (void *)lmm);
426                 break;
427         }
428
429         if (rc) {
430                 lov_free_memmd(lsmp);
431                 RETURN(rc);
432         }
433
434         RETURN(lsm_size);
435 }
436
437 /* Configure object striping information on a new file.
438  *
439  * @lmmu is a pointer to a user struct with one or more of the fields set to
440  * indicate the application preference: lmm_stripe_count, lmm_stripe_size,
441  * lmm_stripe_offset, and lmm_stripe_pattern.  lmm_magic must be LOV_MAGIC.
442  * @lsmp is a pointer to an in-core stripe MD that needs to be filled in.
443  */
444 int lov_setstripe(struct obd_export *exp, struct lov_stripe_md **lsmp,
445                   struct lov_user_md *lump)
446 {
447         struct obd_device *obd = class_exp2obd(exp);
448         struct lov_obd *lov = &obd->u.lov;
449         struct lov_user_md lum;
450         int stripe_count;
451         int rc;
452         ENTRY;
453
454         rc = copy_from_user(&lum, lump, sizeof(lum));
455         if (rc)
456                 RETURN(-EFAULT);
457
458         if (lum.lmm_magic != LOV_USER_MAGIC) {
459                 CDEBUG(D_IOCTL, "bad userland LOV MAGIC: %#08x != %#08x\n",
460                        lum.lmm_magic, LOV_USER_MAGIC);
461                 RETURN(-EINVAL);
462         }
463
464         if (lum.lmm_pattern == 0) {
465                 lum.lmm_pattern = lov->desc.ld_pattern ?
466                         lov->desc.ld_pattern : LOV_PATTERN_RAID0;
467         }
468
469         if (lum.lmm_pattern != LOV_PATTERN_RAID0) {
470                 CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n",
471                        lum.lmm_pattern);
472                 RETURN(-EINVAL);
473         }
474
475         if (lum.lmm_stripe_size & (PAGE_SIZE - 1)) {
476                 CDEBUG(D_IOCTL, "stripe size %u not multiple of %lu\n",
477                        lum.lmm_stripe_size, PAGE_SIZE);
478                 RETURN(-EINVAL);
479         }
480
481         if ((lum.lmm_stripe_offset >= lov->desc.ld_active_tgt_count) &&
482             (lum.lmm_stripe_offset != (typeof(lum.lmm_stripe_offset))(-1))) {
483                 CDEBUG(D_IOCTL, "stripe offset %u > number of active OSTs %u\n",
484                        lum.lmm_stripe_offset, lov->desc.ld_active_tgt_count);
485                 RETURN(-EINVAL);
486         }
487         stripe_count = lov_get_stripecnt(lov, lum.lmm_stripe_count);
488
489         if ((__u64)lum.lmm_stripe_size * stripe_count > ~0UL) {
490                 CDEBUG(D_IOCTL, "stripe width %ux%u > %lu on 32-bit system\n",
491                        lum.lmm_stripe_size, (int)lum.lmm_stripe_count, ~0UL);
492                 RETURN(-EINVAL);
493         }
494
495         rc = lov_alloc_memmd(lsmp, stripe_count, lum.lmm_pattern);
496
497         if (rc < 0)
498                 RETURN(rc);
499
500         (*lsmp)->lsm_oinfo[0].loi_ost_idx = lum.lmm_stripe_offset;
501         (*lsmp)->lsm_stripe_size = lum.lmm_stripe_size;
502         (*lsmp)->lsm_xfersize = lum.lmm_stripe_size * stripe_count;
503
504         RETURN(0);
505 }
506
507 int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
508                   struct lov_user_md *lump)
509 {
510         int i;
511         int rc;
512         struct obd_export *oexp;
513         struct lov_obd *lov = &exp->exp_obd->u.lov;
514         obd_id last_id = 0;
515
516         for (i = 0; i < lump->lmm_stripe_count; i++) {
517                 __u32 len = sizeof(last_id);
518                 oexp = lov->tgts[lump->lmm_objects[i].l_ost_idx].ltd_exp;
519                 rc = obd_get_info(oexp, strlen("last_id"), "last_id", 
520                                   &len, &last_id); 
521                 if (rc)
522                         RETURN(rc);
523                 if (last_id < lump->lmm_objects[i].l_object_id) {
524                         CERROR("Setting EA for object > than last id on "
525                           "ost idx %d "LPD64" > "LPD64" \n", 
526                           lump->lmm_objects[i].l_ost_idx,
527                           lump->lmm_objects[i].l_object_id, last_id);
528                         RETURN(-EINVAL);
529                 }
530         }
531
532         rc = lov_setstripe(exp, lsmp, lump);
533         if (rc) 
534                 RETURN(rc);
535         for (i = 0; i < lump->lmm_stripe_count; i++) {
536                 (*lsmp)->lsm_oinfo[i].loi_ost_idx = 
537                                                  lump->lmm_objects[i].l_ost_idx;
538                 (*lsmp)->lsm_oinfo[i].loi_id = lump->lmm_objects[i].l_object_id;
539                 (*lsmp)->lsm_oinfo[i].loi_gr = lump->lmm_objects[i].l_object_gr;
540         }
541         RETURN(0);
542 }
543
544
545 /* Retrieve object striping information.
546  *
547  * @lump is a pointer to an in-core struct with lmm_ost_count indicating
548  * the maximum number of OST indices which will fit in the user buffer.
549  * lmm_magic must be LOV_USER_MAGIC.
550  */
551 int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm,
552                   struct lov_user_md *lump)
553 {
554         struct lov_user_md lum;
555         struct lov_mds_md *lmmk = NULL;
556         int rc, lmm_size;
557         ENTRY;
558
559         if (!lsm)
560                 RETURN(-ENODATA);
561
562         rc = copy_from_user(&lum, lump, sizeof(lum));
563         if (rc)
564                 RETURN(-EFAULT);
565
566         if (lum.lmm_magic != LOV_USER_MAGIC)
567                 RETURN(-EINVAL);
568
569         rc = lov_packmd(exp, &lmmk, lsm);
570         if (rc < 0)
571                 RETURN(rc);
572         lmm_size = rc;
573         rc = 0;
574
575         /* FIXME: Bug 1185 - copy fields properly when structs change */
576         LASSERT(sizeof(lum) == sizeof(*lmmk));
577         LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lmmk->lmm_objects[0]));
578
579         /* User wasn't expecting this many OST entries */
580         if (lum.lmm_stripe_count == 0) {
581                 if (copy_to_user(lump, lmmk, sizeof(lum)))
582                         rc = -EFAULT;
583         } else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) {
584                 rc = -EOVERFLOW;
585         } else if (copy_to_user(lump, lmmk, lmm_size)) {
586                 rc = -EFAULT;
587         }
588
589         obd_free_diskmd(exp, &lmmk);
590
591         RETURN(rc);
592 }