diff options
Diffstat (limited to 'drivers/staging/lustre/lustre/lov/lov_pack.c')
-rw-r--r-- | drivers/staging/lustre/lustre/lov/lov_pack.c | 293 |
1 files changed, 110 insertions, 183 deletions
diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index be6e985..6c93d18 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -38,14 +38,17 @@ #define DEBUG_SUBSYSTEM S_LOV +#include "../include/lustre/lustre_idl.h" +#include "../include/lustre/lustre_user.h" + #include "../include/lustre_net.h" +#include "../include/lustre_swab.h" #include "../include/obd.h" #include "../include/obd_class.h" #include "../include/obd_support.h" -#include "../include/lustre/lustre_user.h" -#include "lov_internal.h" #include "lov_cl_internal.h" +#include "lov_internal.h" void lov_dump_lmm_common(int level, void *lmmp) { @@ -97,120 +100,54 @@ void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm) le16_to_cpu(lmm->lmm_stripe_count)); } -/* Pack LOV object metadata for disk storage. It is packed in LE byte - * order and is opaque to the networking layer. +/** + * Pack LOV striping metadata for disk storage format (in little + * endian byte order). * - * XXX In the future, this will be enhanced to get the EA size from the - * underlying OSC device(s) to get their EA sizes so we can stack - * LOVs properly. For now lov_mds_md_size() just assumes one u64 - * per stripe. + * This follows the getxattr() conventions. If \a buf_size is zero + * then return the size needed. If \a buf_size is too small then + * return -ERANGE. Otherwise return the size of the result. */ -int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, + size_t buf_size) { - struct lov_mds_md_v1 *lmmv1; - struct lov_mds_md_v3 *lmmv3; - __u16 stripe_count; struct lov_ost_data_v1 *lmm_objects; - int lmm_size, lmm_magic; - int i; - int cplen = 0; - - if (lsm) { - lmm_magic = lsm->lsm_magic; - } else { - if (lmmp && *lmmp) - lmm_magic = le32_to_cpu((*lmmp)->lmm_magic); - else - /* lsm == NULL and lmmp == NULL */ - lmm_magic = LOV_MAGIC; - } - - if ((lmm_magic != LOV_MAGIC_V1) && - (lmm_magic != LOV_MAGIC_V3)) { - CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", - lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); - return -EINVAL; - } - - if (lsm) { - /* If we are just sizing the EA, limit the stripe count - * to the actual number of OSTs in this filesystem. - */ - if (!lmmp) { - stripe_count = lov_get_stripecnt(lov, lmm_magic, - lsm->lsm_stripe_count); - lsm->lsm_stripe_count = stripe_count; - } else if (!lsm_is_released(lsm)) { - stripe_count = lsm->lsm_stripe_count; - } else { - stripe_count = 0; - } - } else { - /* - * To calculate maximum easize by active targets at present, - * which is exactly the maximum easize to be seen by LOV - */ - stripe_count = lov->desc.ld_active_tgt_count; - } + struct lov_mds_md_v1 *lmmv1 = buf; + struct lov_mds_md_v3 *lmmv3 = buf; + size_t lmm_size; + unsigned int i; - /* XXX LOV STACKING call into osc for sizes */ - lmm_size = lov_mds_md_size(stripe_count, lmm_magic); - - if (!lmmp) + lmm_size = lov_mds_md_size(lsm->lsm_stripe_count, lsm->lsm_magic); + if (!buf_size) return lmm_size; - if (*lmmp && !lsm) { - stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count); - lmm_size = lov_mds_md_size(stripe_count, lmm_magic); - kvfree(*lmmp); - *lmmp = NULL; - return 0; - } - - if (!*lmmp) { - *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); - if (!*lmmp) - return -ENOMEM; - } - - CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d\n", - lmm_magic, lmm_size); - - lmmv1 = *lmmp; - lmmv3 = (struct lov_mds_md_v3 *)*lmmp; - if (lmm_magic == LOV_MAGIC_V3) - lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3); - else - lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1); - - if (!lsm) - return lmm_size; + if (buf_size < lmm_size) + return -ERANGE; - /* lmmv1 and lmmv3 point to the same struct and have the + /* + * lmmv1 and lmmv3 point to the same struct and have the * same first fields */ + lmmv1->lmm_magic = cpu_to_le32(lsm->lsm_magic); lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); - lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count); + lmmv1->lmm_stripe_count = cpu_to_le16(lsm->lsm_stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); + if (lsm->lsm_magic == LOV_MAGIC_V3) { - cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, - sizeof(lmmv3->lmm_pool_name)); - if (cplen >= sizeof(lmmv3->lmm_pool_name)) - return -E2BIG; + CLASSERT(sizeof(lsm->lsm_pool_name) == + sizeof(lmmv3->lmm_pool_name)); + strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, + sizeof(lmmv3->lmm_pool_name)); lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } - for (i = 0; i < stripe_count; i++) { + for (i = 0; i < lsm->lsm_stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; - /* XXX LOV STACKING call down to osc_packmd() to do packing */ - LASSERTF(ostid_id(&loi->loi_oi) != 0, "lmm_oi "DOSTID - " stripe %u/%u idx %u\n", POSTID(&lmmv1->lmm_oi), - i, stripe_count, loi->loi_ost_idx); + ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); @@ -219,15 +156,6 @@ int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, return lmm_size; } -int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) -{ - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; - - return lov_obd_packmd(lov, lmmp, lsm); -} - /* Find the max stripecount we should use */ __u16 lov_get_stripecnt(struct lov_obd *lov, __u32 magic, __u16 stripe_count) { @@ -270,34 +198,34 @@ static int lov_verify_lmm(void *lmm, int lmm_bytes, __u16 *stripe_count) return rc; } -int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, - int pattern, int magic) +struct lov_stripe_md *lov_lsm_alloc(u16 stripe_count, u32 pattern, u32 magic) { - int i, lsm_size; + struct lov_stripe_md *lsm; + unsigned int i; - CDEBUG(D_INFO, "alloc lsm, stripe_count %d\n", stripe_count); + CDEBUG(D_INFO, "alloc lsm, stripe_count %u\n", stripe_count); - *lsmp = lsm_alloc_plain(stripe_count, &lsm_size); - if (!*lsmp) { - CERROR("can't allocate lsmp stripe_count %d\n", stripe_count); - return -ENOMEM; + lsm = lsm_alloc_plain(stripe_count); + if (!lsm) { + CERROR("cannot allocate LSM stripe_count %u\n", stripe_count); + return ERR_PTR(-ENOMEM); } - atomic_set(&(*lsmp)->lsm_refc, 1); - spin_lock_init(&(*lsmp)->lsm_lock); - (*lsmp)->lsm_magic = magic; - (*lsmp)->lsm_stripe_count = stripe_count; - (*lsmp)->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES * stripe_count; - (*lsmp)->lsm_pattern = pattern; - (*lsmp)->lsm_pool_name[0] = '\0'; - (*lsmp)->lsm_layout_gen = 0; + atomic_set(&lsm->lsm_refc, 1); + spin_lock_init(&lsm->lsm_lock); + lsm->lsm_magic = magic; + lsm->lsm_stripe_count = stripe_count; + lsm->lsm_maxbytes = LUSTRE_EXT3_STRIPE_MAXBYTES * stripe_count; + lsm->lsm_pattern = pattern; + lsm->lsm_pool_name[0] = '\0'; + lsm->lsm_layout_gen = 0; if (stripe_count > 0) - (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0; + lsm->lsm_oinfo[0]->loi_ost_idx = ~0; for (i = 0; i < stripe_count; i++) - loi_init((*lsmp)->lsm_oinfo[i]); + loi_init(lsm->lsm_oinfo[i]); - return lsm_size; + return lsm; } int lov_free_memmd(struct lov_stripe_md **lsmp) @@ -317,56 +245,34 @@ int lov_free_memmd(struct lov_stripe_md **lsmp) /* 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 lov_stripe_md *lov_unpackmd(struct lov_obd *lov, struct lov_mds_md *lmm, + size_t lmm_size) { - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; - int rc = 0, lsm_size; - __u16 stripe_count; - __u32 magic; - __u32 pattern; - - /* 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; - magic = le32_to_cpu(lmm->lmm_magic); - pattern = le32_to_cpu(lmm->lmm_pattern); - } else { - magic = LOV_MAGIC; - stripe_count = lov_get_stripecnt(lov, magic, 0); - pattern = LOV_PATTERN_RAID0; - } + struct lov_stripe_md *lsm; + u16 stripe_count; + u32 pattern; + u32 magic; + int rc; - /* If we aren't passed an lsmp struct, we just want the size */ - if (!lsmp) { - /* XXX LOV STACKING call into osc for sizes */ - LBUG(); - 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; - } + rc = lov_verify_lmm(lmm, lmm_size, &stripe_count); + if (rc) + return ERR_PTR(rc); - lsm_size = lov_alloc_memmd(lsmp, stripe_count, pattern, magic); - if (lsm_size < 0) - return lsm_size; + magic = le32_to_cpu(lmm->lmm_magic); + pattern = le32_to_cpu(lmm->lmm_pattern); - /* If we are passed a pointer but nothing to unpack, we only alloc */ - if (!lmm) - return lsm_size; + lsm = lov_lsm_alloc(stripe_count, pattern, magic); + if (IS_ERR(lsm)) + return lsm; - rc = lsm_op_find(magic)->lsm_unpackmd(lov, *lsmp, lmm); + LASSERT(lsm_op_find(magic)); + rc = lsm_op_find(magic)->lsm_unpackmd(lov, lsm, lmm); if (rc) { - lov_free_memmd(lsmp); - return rc; + lov_free_memmd(&lsm); + return ERR_PTR(rc); } - return lsm_size; + return lsm; } /* Retrieve object striping information. @@ -378,15 +284,14 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, struct lov_user_md __user *lump) { - /* - * XXX huge struct allocated on stack. - */ /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ - struct lov_obd *lov; struct lov_user_md_v3 lum; - struct lov_mds_md *lmmk = NULL; - int rc, lmmk_size, lmm_size; - int lum_size; + struct lov_mds_md *lmmk; + u32 stripe_count; + ssize_t lmm_size; + size_t lmmk_size; + size_t lum_size; + int rc; mm_segment_t seg; if (!lsm) @@ -399,6 +304,18 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, seg = get_fs(); set_fs(KERNEL_DS); + if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { + CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", + lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); + rc = -EIO; + goto out; + } + + if (!lsm_is_released(lsm)) + stripe_count = lsm->lsm_stripe_count; + else + stripe_count = 0; + /* we only need the header part from user space to get lmm_magic and * lmm_stripe_count, (the header part is common to v1 and v3) */ @@ -417,32 +334,40 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, if (lum.lmm_stripe_count && (lum.lmm_stripe_count < lsm->lsm_stripe_count)) { /* Return right size of stripe to user */ - lum.lmm_stripe_count = lsm->lsm_stripe_count; + lum.lmm_stripe_count = stripe_count; rc = copy_to_user(lump, &lum, lum_size); rc = -EOVERFLOW; goto out; } - lov = lu2lov_dev(obj->lo_cl.co_lu.lo_dev)->ld_lov; - rc = lov_obd_packmd(lov, &lmmk, lsm); - if (rc < 0) + lmmk_size = lov_mds_md_size(stripe_count, lsm->lsm_magic); + + + lmmk = libcfs_kvzalloc(lmmk_size, GFP_NOFS); + if (!lmmk) { + rc = -ENOMEM; goto out; - lmmk_size = rc; - lmm_size = rc; - rc = 0; + } + + lmm_size = lov_lsm_pack(lsm, lmmk, lmmk_size); + if (lmm_size < 0) { + rc = lmm_size; + goto out_free; + } /* FIXME: Bug 1185 - copy fields properly when structs change */ /* struct lov_user_md_v3 and struct lov_mds_md_v3 must be the same */ CLASSERT(sizeof(lum) == sizeof(struct lov_mds_md_v3)); CLASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lmmk->lmm_objects[0])); - if ((cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) && - ((lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) || - (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)))) { + if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC && + (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) || + lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V3))) { lustre_swab_lov_mds_md(lmmk); lustre_swab_lov_user_md_objects( (struct lov_user_ost_data *)lmmk->lmm_objects, lmmk->lmm_stripe_count); } + if (lum.lmm_magic == LOV_USER_MAGIC) { /* User request for v1, we need skip lmm_pool_name */ if (lmmk->lmm_magic == LOV_MAGIC_V3) { @@ -474,9 +399,11 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, ((struct lov_user_md *)lmmk)->lmm_stripe_count = lum.lmm_stripe_count; if (copy_to_user(lump, lmmk, lmm_size)) rc = -EFAULT; + else + rc = 0; out_free: - kfree(lmmk); + kvfree(lmmk); out: set_fs(seg); return rc; |