X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flov%2Flov_pack.c;h=164bceca977252c152c694fcac9c5118b3f689ac;hb=7a7e17d4db28fac1ca4bc333d60cbeb8dbc530d6;hp=bbb40de35da5235591a7d8abd9d6538775375b17;hpb=576c9a8212bc6607146d99e3413f7a24cbf91b5c;p=fs%2Flustre-release.git diff --git a/lustre/lov/lov_pack.c b/lustre/lov/lov_pack.c index bbb40de..164bcec 100644 --- a/lustre/lov/lov_pack.c +++ b/lustre/lov/lov_pack.c @@ -23,7 +23,7 @@ * */ -#define DEBUG_SUBSYSTEM S_LLITE +#define DEBUG_SUBSYSTEM S_LOV #ifndef __KERNEL__ #include #endif @@ -33,21 +33,49 @@ #include #include #include +#include -void lov_dump_lmm(int level, struct lov_mds_md *lmm) +#include "lov_internal.h" + +void lov_dump_lmm_v0(int level, struct lov_mds_md_v0 *lmm) { - struct lov_object_id *loi; - int idx; + int i, num_ost, stripe, idx; - CDEBUG(level, "objid "LPX64", magic %#08x, ost_count %u\n", - lmm->lmm_object_id, lmm->lmm_magic, lmm->lmm_ost_count); + num_ost = le32_to_cpu(lmm->lmm_ost_count); + idx = le32_to_cpu(lmm->lmm_stripe_offset); + CDEBUG(level, "objid "LPX64", magic 0x%08X, ost_count %u\n", + le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic), + num_ost); CDEBUG(level,"stripe_size %u, stripe_count %u, stripe_offset %u\n", - lmm->lmm_stripe_size, lmm->lmm_stripe_count, - lmm->lmm_stripe_offset); - for (idx = 0, loi = lmm->lmm_objects; idx < lmm->lmm_ost_count; - idx++, loi++) - CDEBUG(level, "ost idx %u subobj "LPX64"\n", idx, - loi->l_object_id); + le32_to_cpu(lmm->lmm_stripe_size), + le32_to_cpu(lmm->lmm_stripe_count), idx); + for (i = stripe = 0; i < le32_to_cpu(lmm->lmm_ost_count); i++, idx++) { + idx %= num_ost; + if (lmm->lmm_objects[idx].l_object_id == 0) + continue; + CDEBUG(level, "stripe %u idx %u subobj "LPX64"\n", stripe, idx, + le64_to_cpu(lmm->lmm_objects[idx].l_object_id)); + stripe++; + } +} + +void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm) +{ + struct lov_ost_data_v1 *lod; + int i; + + CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n", + le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic), + le32_to_cpu(lmm->lmm_pattern)); + CDEBUG(level,"stripe_size %u, stripe_count %u\n", + le32_to_cpu(lmm->lmm_stripe_size), + le32_to_cpu(lmm->lmm_stripe_count)); + for (i = 0, lod = lmm->lmm_objects; + i < le32_to_cpu(lmm->lmm_stripe_count); i++, lod++) + CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n", + i, le32_to_cpu(lod->l_ost_idx), + le64_to_cpu(lod->l_object_gr), + le64_to_cpu(lod->l_object_id)); } #define LMM_ASSERT(test) \ @@ -64,44 +92,36 @@ do { \ * LOVs properly. For now lov_mds_md_size() just assumes one obd_id * per stripe. */ -int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp, +int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { - struct obd_device *obd = class_conn2obd(conn); + struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; struct lov_oinfo *loi; struct lov_mds_md *lmm; - int ost_count = lov->desc.ld_tgt_count; - int stripe_count = ost_count; + int stripe_count = lov->desc.ld_tgt_count; int lmm_size; int i; ENTRY; if (lsm) { - int i, max = 0; if (lsm->lsm_magic != LOV_MAGIC) { - CERROR("bad mem LOV MAGIC: %#010x != %#010x\n", + CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X\n", lsm->lsm_magic, LOV_MAGIC); RETURN(-EINVAL); } stripe_count = lsm->lsm_stripe_count; - - for (i = 0,loi = lsm->lsm_oinfo; i < stripe_count; i++,loi++) { - if (loi->loi_ost_idx > max) - max = loi->loi_ost_idx; - } - ost_count = max + 1; } /* XXX LOV STACKING call into osc for sizes */ - lmm_size = lov_mds_md_size(ost_count); + lmm_size = lov_mds_md_size(stripe_count); if (!lmmp) RETURN(lmm_size); if (*lmmp && !lsm) { - ost_count = le32_to_cpu ((*lmmp)->lmm_ost_count); - OBD_FREE(*lmmp, lov_mds_md_size(ost_count)); + stripe_count = le32_to_cpu((*lmmp)->lmm_stripe_count); + OBD_FREE(*lmmp, lov_mds_md_size(stripe_count)); *lmmp = NULL; RETURN(0); } @@ -113,30 +133,30 @@ int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp, } lmm = *lmmp; - lmm->lmm_magic = cpu_to_le32 (LOV_MAGIC); - lmm->lmm_ost_count = cpu_to_le16 (ost_count); + lmm->lmm_magic = cpu_to_le32(LOV_MAGIC); /* only write new format */ if (!lsm) RETURN(lmm_size); - lmm->lmm_object_id = cpu_to_le64 (lsm->lsm_object_id); - lmm->lmm_stripe_count = cpu_to_le16 (stripe_count); - lmm->lmm_stripe_size = cpu_to_le32 (lsm->lsm_stripe_size); - lmm->lmm_stripe_offset = cpu_to_le32 (lsm->lsm_stripe_offset); + lmm->lmm_object_id = cpu_to_le64(lsm->lsm_object_id); + lmm->lmm_object_gr = cpu_to_le64(lsm->lsm_object_gr); + lmm->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); + lmm->lmm_stripe_count = cpu_to_le32(stripe_count); + lmm->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); - /* Only fill in the object ids which we are actually using. - * Assumes lmm_objects is otherwise zero-filled. */ for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++) { - /* XXX call down to osc_packmd() to do the packing */ - LASSERT (loi->loi_id); - lmm->lmm_objects[loi->loi_ost_idx].l_object_id = - cpu_to_le64 (loi->loi_id); + /* XXX LOV STACKING call down to osc_packmd() to do packing */ + LASSERT(loi->loi_id); + lmm->lmm_objects[i].l_object_id = cpu_to_le64(loi->loi_id); + lmm->lmm_objects[i].l_object_gr = cpu_to_le64(loi->loi_gr); + lmm->lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); + lmm->lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } RETURN(lmm_size); } -static int lov_get_stripecnt(struct lov_obd *lov, int stripe_count) +int lov_get_stripecnt(struct lov_obd *lov, int stripe_count) { if (!stripe_count) stripe_count = lov->desc.ld_default_stripe_count; @@ -146,85 +166,164 @@ static int lov_get_stripecnt(struct lov_obd *lov, int stripe_count) return stripe_count; } -/* Unpack LOV object metadata from disk storage. It is packed in LE byte - * order and is opaque to the networking layer. - */ -int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_bytes) +static int lov_verify_lmm_v0(struct lov_mds_md_v0 *lmm, int lmm_bytes, + int *stripe_count) { - struct obd_device *obd = class_conn2obd(conn); - struct lov_obd *lov = &obd->u.lov; - struct lov_stripe_md *lsm; - struct lov_oinfo *loi; - int ost_count = 0; - int ost_offset = 0; - int stripe_count; - int lsm_size; - int i; - ENTRY; + if (lmm_bytes < sizeof(*lmm)) { + CERROR("lov_mds_md too small: %d, need at least %d\n", + lmm_bytes, (int)sizeof(*lmm)); + return -EINVAL; + } - if (lmm) { - if (lmm_bytes < sizeof (*lmm)) { - CERROR("lov_mds_md too small: %d, need %d\n", - lmm_bytes, (int)sizeof(*lmm)); - RETURN(-EINVAL); - } - if (le32_to_cpu (lmm->lmm_magic) != LOV_MAGIC) { - CERROR("bad disk LOV MAGIC: %#08x != %#08x\n", - le32_to_cpu (lmm->lmm_magic), LOV_MAGIC); - RETURN(-EINVAL); - } + *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); - ost_count = le16_to_cpu (lmm->lmm_ost_count); - stripe_count = le16_to_cpu (lmm->lmm_stripe_count); + if (*stripe_count == 0 || + *stripe_count > le32_to_cpu(lmm->lmm_ost_count)) { + CERROR("bad stripe count %d\n", *stripe_count); + lov_dump_lmm_v0(D_WARNING, lmm); + return -EINVAL; + } - if (ost_count == 0 || stripe_count == 0) { - CERROR ("zero ost %d or stripe %d count\n", - ost_count, stripe_count); - RETURN (-EINVAL); - } + if (lmm_bytes < lov_mds_md_v0_size(*stripe_count)) { + CERROR("LOV EA too small: %d, need %d\n", + lmm_bytes, lov_mds_md_v0_size(*stripe_count)); + lov_dump_lmm_v0(D_WARNING, lmm); + return -EINVAL; + } - if (lmm_bytes < lov_mds_md_size (ost_count)) { - CERROR ("lov_mds_md too small: %d, need %d\n", - lmm_bytes, lov_mds_md_size (ost_count)); - RETURN (-EINVAL); - } - } else - stripe_count = lov_get_stripecnt(lov, 0); + if (lmm->lmm_object_id == 0) { + CERROR("zero object id\n"); + lov_dump_lmm_v0(D_WARNING, lmm); + return -EINVAL; + } - /* XXX LOV STACKING call into osc for sizes */ - lsm_size = lov_stripe_md_size(stripe_count); + if (le32_to_cpu(lmm->lmm_stripe_offset) > + le32_to_cpu(lmm->lmm_ost_count)) { + CERROR("stripe offset %d more than number of OSTs %d\n", + le32_to_cpu(lmm->lmm_stripe_offset), + le32_to_cpu(lmm->lmm_ost_count)); + lov_dump_lmm_v0(D_WARNING, lmm); + return -EINVAL; + } - if (!lsmp) - RETURN(lsm_size); + if (lmm->lmm_stripe_size == 0) { + CERROR("zero stripe size\n"); + lov_dump_lmm_v0(D_WARNING, lmm); + return -EINVAL; + } - if (*lsmp && !lmm) { - stripe_count = (*lsmp)->lsm_stripe_count; - OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count)); - *lsmp = NULL; - RETURN(0); + return 0; +} + +static int lov_verify_lmm_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes, + int *stripe_count) +{ + if (lmm_bytes < sizeof(*lmm)) { + CERROR("lov_mds_md too small: %d, need at least %d\n", + lmm_bytes, (int)sizeof(*lmm)); + return -EINVAL; } - if (!*lsmp) { - OBD_ALLOC(*lsmp, lsm_size); - if (!*lsmp) - RETURN(-ENOMEM); + if (lmm->lmm_magic != le32_to_cpu(LOV_MAGIC_V1)) { + CERROR("bad disk LOV MAGIC: 0x%08X\n", + le32_to_cpu(*(__u32 *)lmm)); + return -EINVAL; } - lsm = *lsmp; - lsm->lsm_magic = LOV_MAGIC; - lsm->lsm_stripe_count = stripe_count; - lsm->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count; + *stripe_count = le32_to_cpu(lmm->lmm_stripe_count); - if (!lmm) - RETURN(lsm_size); + if (*stripe_count == 0) { + CERROR("bad stripe count %d\n", *stripe_count); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + if (lmm_bytes < lov_mds_md_v1_size(*stripe_count)) { + CERROR("LOV EA too small: %d, need %d\n", + lmm_bytes, lov_mds_md_v1_size(*stripe_count)); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + if (lmm->lmm_object_id == 0) { + CERROR("zero object id\n"); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + if (lmm->lmm_pattern != cpu_to_le32(LOV_PATTERN_RAID0)) { + CERROR("bad striping pattern\n"); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + if (lmm->lmm_stripe_size == 0 || + (__u64)le32_to_cpu(lmm->lmm_stripe_size) * *stripe_count > ~0UL) { + CERROR("bad stripe size %u\n", + le32_to_cpu(lmm->lmm_stripe_size)); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + + return 0; +} - lsm->lsm_object_id = le64_to_cpu (lmm->lmm_object_id); - lsm->lsm_stripe_size = le32_to_cpu (lmm->lmm_stripe_size); - ost_offset = lsm->lsm_stripe_offset = le32_to_cpu (lmm->lmm_stripe_offset); +static int lov_verify_lmm(void *lmm, int lmm_bytes, int *stripe_count) +{ + switch (le32_to_cpu(*(__u32 *)lmm)) { + case LOV_MAGIC_V1: + return lov_verify_lmm_v1(lmm, lmm_bytes, stripe_count); + case LOV_MAGIC_V0: + return lov_verify_lmm_v0(lmm, lmm_bytes, stripe_count); + default: + CERROR("bad disk LOV MAGIC: 0x%08X\n", + le32_to_cpu(*(__u32 *)lmm)); + return -EINVAL; + } +} + +int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count, int pattern) +{ + int lsm_size = lov_stripe_md_size(stripe_count); + struct lov_oinfo *loi; + int i; + + OBD_ALLOC(*lsmp, lsm_size); + if (!*lsmp) + return -ENOMEM; + + (*lsmp)->lsm_magic = LOV_MAGIC; + (*lsmp)->lsm_stripe_count = stripe_count; + (*lsmp)->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count; + (*lsmp)->lsm_xfersize = PTLRPC_MAX_BRW_SIZE * stripe_count; + (*lsmp)->lsm_pattern = pattern; + (*lsmp)->lsm_oinfo[0].loi_ost_idx = ~0; + + for (i = 0, loi = (*lsmp)->lsm_oinfo; i < stripe_count; i++, loi++) + loi_init(loi); + + return lsm_size; +} + +void lov_free_memmd(struct lov_stripe_md **lsmp) +{ + OBD_FREE(*lsmp, lov_stripe_md_size((*lsmp)->lsm_stripe_count)); + *lsmp = NULL; +} + +int lov_unpackmd_v0(struct lov_obd *lov, struct lov_stripe_md *lsm, + struct lov_mds_md_v0 *lmm) +{ + struct lov_oinfo *loi; + int i, ost_offset, ost_count; - LMM_ASSERT(lsm->lsm_object_id); - LMM_ASSERT(ost_count); + lsm->lsm_object_id = le64_to_cpu(lmm->lmm_object_id); + /* lsm->lsm_object_gr = 0; implicit */ + lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size); + lsm->lsm_xfersize = lsm->lsm_stripe_size * lsm->lsm_stripe_count; + lsm->lsm_pattern = LOV_PATTERN_RAID0; + ost_offset = le32_to_cpu(lmm->lmm_stripe_offset); + ost_count = le16_to_cpu(lmm->lmm_ost_count); for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) { ost_offset %= ost_count; @@ -232,17 +331,105 @@ int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp, if (!lmm->lmm_objects[ost_offset].l_object_id) continue; - LMM_ASSERT(loi - lsm->lsm_oinfo < stripe_count); - /* XXX LOV STACKING call down to osc_unpackmd() */ loi->loi_id = - le64_to_cpu (lmm->lmm_objects[ost_offset].l_object_id); + le64_to_cpu(lmm->lmm_objects[ost_offset].l_object_id); + /* loi->loi_gr = 0; implicit */ loi->loi_ost_idx = ost_offset; - loi->loi_dirty_ot = &loi->loi_dirty_ot_inline; - ot_init(loi->loi_dirty_ot); + /* loi->loi_ost_gen = 0; implicit */ loi++; } - LMM_ASSERT(loi - lsm->lsm_oinfo > 0); - LMM_ASSERT(loi - lsm->lsm_oinfo == stripe_count); + + if (loi - lsm->lsm_oinfo != lsm->lsm_stripe_count) { + CERROR("missing objects in lmm struct\n"); + lov_dump_lmm_v0(D_WARNING, lmm); + return -EINVAL; + } + + return 0; +} + +int lov_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, + struct lov_mds_md_v1 *lmm) +{ + struct lov_oinfo *loi; + int i; + + lsm->lsm_object_id = le64_to_cpu(lmm->lmm_object_id); + lsm->lsm_object_gr = le64_to_cpu(lmm->lmm_object_gr); + lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size); + lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern); + lsm->lsm_xfersize = lsm->lsm_stripe_size * lsm->lsm_stripe_count; + + for (i = 0, loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++) { + /* XXX LOV STACKING call down to osc_unpackmd() */ + loi->loi_id = le64_to_cpu(lmm->lmm_objects[i].l_object_id); + loi->loi_gr = le64_to_cpu(lmm->lmm_objects[i].l_object_gr); + loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx); + loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen); + if (loi->loi_ost_idx > lov->desc.ld_tgt_count) { + CERROR("OST index %d more than OST count %d\n", + loi->loi_ost_idx, lov->desc.ld_tgt_count); + lov_dump_lmm_v1(D_WARNING, lmm); + return -EINVAL; + } + loi++; + } + + return 0; +} + +/* Unpack LOV object metadata from disk storage. It is packed in LE byte + * order and is opaque to the networking layer. + */ +int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int lmm_bytes) +{ + struct obd_device *obd = class_exp2obd(exp); + struct lov_obd *lov = &obd->u.lov; + int rc = 0, stripe_count, lsm_size; + ENTRY; + + /* If passed an MDS struct use values from there, otherwise defaults */ + if (lmm) { + rc = lov_verify_lmm(lmm, lmm_bytes, &stripe_count); + if (rc) + RETURN(rc); + } else { + stripe_count = lov_get_stripecnt(lov, 0); + } + + /* If we aren't passed an lsmp struct, we just want the size */ + if (!lsmp) + /* XXX LOV STACKING call into osc for sizes */ + RETURN(lov_stripe_md_size(stripe_count)); + + /* If we are passed an allocated struct but nothing to unpack, free */ + if (*lsmp && !lmm) { + lov_free_memmd(lsmp); + RETURN(0); + } + + lsm_size = lov_alloc_memmd(lsmp, stripe_count, LOV_PATTERN_RAID0); + if (lsm_size < 0) + RETURN(lsm_size); + + /* If we are passed a pointer but nothing to unpack, we only alloc */ + if (!lmm) + RETURN(lsm_size); + + switch (le32_to_cpu(lmm->lmm_magic)) { + case LOV_MAGIC_V1: + rc = lov_unpackmd_v1(lov, *lsmp, lmm); + break; + case LOV_MAGIC_V0: + rc = lov_unpackmd_v0(lov, *lsmp, (void *)lmm); + break; + } + + if (rc) { + lov_free_memmd(lsmp); + RETURN(rc); + } RETURN(lsm_size); } @@ -254,108 +441,153 @@ int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp, * lmm_stripe_offset, and lmm_stripe_pattern. lmm_magic must be LOV_MAGIC. * @lsmp is a pointer to an in-core stripe MD that needs to be filled in. */ -int lov_setstripe(struct lustre_handle *conn, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmmu) +int lov_setstripe(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_user_md *lump) { - struct obd_device *obd = class_conn2obd(conn); + struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; - struct lov_mds_md lmm; - struct lov_stripe_md *lsm; + struct lov_user_md lum; int stripe_count; int rc; ENTRY; - rc = copy_from_user(&lmm, lmmu, sizeof(lmm)); + rc = copy_from_user(&lum, lump, sizeof(lum)); if (rc) RETURN(-EFAULT); - /* Bug 1185 FIXME: struct lov_mds_md is little-endian everywhere else */ - - if (lmm.lmm_magic != LOV_MAGIC) { - CERROR("bad userland LOV MAGIC: %#08x != %#08x\n", - lmm.lmm_magic, LOV_MAGIC); + if (lum.lmm_magic != LOV_USER_MAGIC) { + CDEBUG(D_IOCTL, "bad userland LOV MAGIC: %#08x != %#08x\n", + lum.lmm_magic, LOV_USER_MAGIC); RETURN(-EINVAL); } -#if 0 /* the stripe_count/offset is "advisory", and it gets fixed later */ - if (lmm.lmm_stripe_count > lov->desc.ld_tgt_count && - lmm.lmm_stripe_count != 0xffffffff) { - CERROR("stripe count %u more than OST count %d\n", - lmm.lmm_stripe_count, lov->desc.ld_tgt_count); + + if (lum.lmm_pattern == 0) { + lum.lmm_pattern = lov->desc.ld_pattern ? + lov->desc.ld_pattern : LOV_PATTERN_RAID0; + } + + if (lum.lmm_pattern != LOV_PATTERN_RAID0) { + CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n", + lum.lmm_pattern); RETURN(-EINVAL); } - if (lmm.lmm_stripe_offset >= lov->desc.ld_tgt_count && - lmm.lmm_stripe_offset != 0xffffffff) { - CERROR("stripe offset %u more than max OST index %d\n", - lmm.lmm_stripe_offset, lov->desc.ld_tgt_count); + + if (lum.lmm_stripe_size & (PAGE_SIZE - 1)) { + CDEBUG(D_IOCTL, "stripe size %u not multiple of %lu\n", + lum.lmm_stripe_size, PAGE_SIZE); RETURN(-EINVAL); } -#endif - if (lmm.lmm_stripe_size & (PAGE_SIZE - 1)) { - CERROR("stripe size %u not multiple of %lu\n", - lmm.lmm_stripe_size, PAGE_SIZE); + + if ((lum.lmm_stripe_offset >= lov->desc.ld_active_tgt_count) && + (lum.lmm_stripe_offset != (typeof(lum.lmm_stripe_offset))(-1))) { + CDEBUG(D_IOCTL, "stripe offset %u > number of active OSTs %u\n", + lum.lmm_stripe_offset, lov->desc.ld_active_tgt_count); RETURN(-EINVAL); } - stripe_count = lov_get_stripecnt(lov, lmm.lmm_stripe_count); + stripe_count = lov_get_stripecnt(lov, lum.lmm_stripe_count); - if ((__u64)lmm.lmm_stripe_size * stripe_count > ~0UL) { - CERROR("stripe width %ux%u > %lu on 32-bit system\n", - lmm.lmm_stripe_size, (int)lmm.lmm_stripe_count, ~0UL); + if ((__u64)lum.lmm_stripe_size * stripe_count > ~0UL) { + CDEBUG(D_IOCTL, "stripe width %ux%u > %lu on 32-bit system\n", + lum.lmm_stripe_size, (int)lum.lmm_stripe_count, ~0UL); RETURN(-EINVAL); } - /* XXX LOV STACKING call into osc for sizes */ - OBD_ALLOC(lsm, lov_stripe_md_size(stripe_count)); - if (!lsm) - RETURN(-ENOMEM); + rc = lov_alloc_memmd(lsmp, stripe_count, lum.lmm_pattern); + + if (rc < 0) + RETURN(rc); - lsm->lsm_magic = LOV_MAGIC; - lsm->lsm_stripe_count = stripe_count; - lsm->lsm_stripe_offset = lmm.lmm_stripe_offset; - lsm->lsm_stripe_size = lmm.lmm_stripe_size; - lsm->lsm_maxbytes = LUSTRE_STRIPE_MAXBYTES * stripe_count; + (*lsmp)->lsm_oinfo[0].loi_ost_idx = lum.lmm_stripe_offset; + (*lsmp)->lsm_stripe_size = lum.lmm_stripe_size; + (*lsmp)->lsm_xfersize = lum.lmm_stripe_size * stripe_count; - *lsmp = lsm; + RETURN(0); +} - RETURN(rc); +int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_user_md *lump) +{ + int i; + int rc; + struct obd_export *oexp; + struct lov_obd *lov = &exp->exp_obd->u.lov; + obd_id last_id = 0; + + for (i = 0; i < lump->lmm_stripe_count; i++) { + __u32 len = sizeof(last_id); + oexp = lov->tgts[lump->lmm_objects[i].l_ost_idx].ltd_exp; + rc = obd_get_info(oexp, strlen("last_id"), "last_id", + &len, &last_id); + if (rc) + RETURN(rc); + if (lump->lmm_objects[i].l_object_id > last_id) { + CERROR("Setting EA for object > than last id on " + "ost idx %d "LPD64" > "LPD64" \n", + lump->lmm_objects[i].l_ost_idx, + lump->lmm_objects[i].l_object_id, last_id); + RETURN(-EINVAL); + } + } + + rc = lov_setstripe(exp, lsmp, lump); + if (rc) + RETURN(rc); + + for (i = 0; i < lump->lmm_stripe_count; i++) { + (*lsmp)->lsm_oinfo[i].loi_ost_idx = + lump->lmm_objects[i].l_ost_idx; + (*lsmp)->lsm_oinfo[i].loi_id = lump->lmm_objects[i].l_object_id; + (*lsmp)->lsm_oinfo[i].loi_gr = lump->lmm_objects[i].l_object_gr; + } + RETURN(0); } + /* Retrieve object striping information. * - * @lmmu is a pointer to an in-core struct with lmm_ost_count indicating + * @lump is a pointer to an in-core struct with lmm_ost_count indicating * the maximum number of OST indices which will fit in the user buffer. - * lmm_magic must be LOV_MAGIC. + * lmm_magic must be LOV_USER_MAGIC. */ -int lov_getstripe(struct lustre_handle *conn, struct lov_stripe_md *lsm, - struct lov_mds_md *lmmu) +int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, + struct lov_user_md *lump) { - struct lov_mds_md lmm, *lmmk = NULL; + struct lov_user_md lum; + struct lov_mds_md *lmmk = NULL; int rc, lmm_size; ENTRY; if (!lsm) RETURN(-ENODATA); - rc = copy_from_user(&lmm, lmmu, sizeof(lmm)); + rc = copy_from_user(&lum, lump, sizeof(lum)); if (rc) RETURN(-EFAULT); - if (lmm.lmm_magic != LOV_MAGIC) + if (lum.lmm_magic != LOV_USER_MAGIC) RETURN(-EINVAL); - rc = lov_packmd(conn, &lmmk, lsm); + rc = lov_packmd(exp, &lmmk, lsm); if (rc < 0) RETURN(rc); - /* Bug 1185 FIXME: convert lmmk to big-endian before copy to userspace */ lmm_size = rc; rc = 0; + /* FIXME: Bug 1185 - copy fields properly when structs change */ + LASSERT(sizeof(lum) == sizeof(*lmmk)); + LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lmmk->lmm_objects[0])); + /* User wasn't expecting this many OST entries */ - if (lmm.lmm_ost_count < lmmk->lmm_ost_count) + if (lum.lmm_stripe_count == 0) { + if (copy_to_user(lump, lmmk, sizeof(lum))) + rc = -EFAULT; + } else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) { rc = -EOVERFLOW; - else if (copy_to_user(lmmu, lmmk, lmm_size)) + } else if (copy_to_user(lump, lmmk, lmm_size)) { rc = -EFAULT; + } - obd_free_diskmd (conn, &lmmk); + obd_free_diskmd(exp, &lmmk); RETURN(rc); }