Exemple #1
0
/* compute object size given "stripeno" and the ost size */
obd_size lov_stripe_size(struct lov_stripe_md *lsm, obd_size ost_size,
                         int stripeno)
{
        unsigned long ssize = lsm->lsm_stripe_size;
        unsigned long stripe_size;
        obd_off swidth;
        obd_size lov_size;
        int magic = lsm->lsm_magic;
        ENTRY;

        if (ost_size == 0)
                RETURN(0);

        LASSERT(lsm_op_find(magic) != NULL);
        lsm_op_find(magic)->lsm_stripe_by_index(lsm, &stripeno, NULL, &swidth);

	/* lov_do_div64(a, b) returns a % b, and a = a / b */
	stripe_size = lov_do_div64(ost_size, ssize);
	if (stripe_size)
		lov_size = ost_size * swidth + stripeno * ssize + stripe_size;
	else
		lov_size = (ost_size - 1) * swidth + (stripeno + 1) * ssize;

        RETURN(lov_size);
}
static int lov_verify_lmm(void *lmm, int lmm_bytes, __u16 *stripe_count)
{
	int rc;

	if (lsm_op_find(le32_to_cpu(*(__u32 *)lmm)) == NULL) {
		char *buffer;
		int sz;

		CERROR("bad disk LOV MAGIC: 0x%08X; dumping LMM (size=%d):\n",
		       le32_to_cpu(*(__u32 *)lmm), lmm_bytes);
		sz = lmm_bytes * 2 + 1;
		OBD_ALLOC_LARGE(buffer, sz);
		if (buffer != NULL) {
			int i;

			for (i = 0; i < lmm_bytes; i++)
				sprintf(buffer+2*i, "%.2X", ((char *)lmm)[i]);
			buffer[sz - 1] = '\0';
			CERROR("%s\n", buffer);
			OBD_FREE_LARGE(buffer, sz);
		}
		return -EINVAL;
	}
	rc = lsm_op_find(le32_to_cpu(*(__u32 *)lmm))->lsm_lmm_verify(lmm,
				     lmm_bytes, stripe_count);
	return rc;
}
/* Unpack LOV object metadata from disk storage.  It is packed in LE byte
 * order and is opaque to the networking layer.
 */
struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, struct lov_mds_md *lmm,
				   size_t lmm_size)
{
	struct lov_stripe_md *lsm;
	u16 stripe_count;
	u32 pattern;
	u32 magic;
	int rc;

	rc = lov_verify_lmm(lmm, lmm_size, &stripe_count);
	if (rc)
		return ERR_PTR(rc);

	magic = le32_to_cpu(lmm->lmm_magic);
	pattern = le32_to_cpu(lmm->lmm_pattern);

	lsm = lov_lsm_alloc(stripe_count, pattern, magic);
	if (IS_ERR(lsm))
		return lsm;

	LASSERT(lsm_op_find(magic));
	rc = lsm_op_find(magic)->lsm_unpackmd(lov, lsm, lmm);
	if (rc) {
		lov_free_memmd(&lsm);
		return ERR_PTR(rc);
	}

	return lsm;
}
Exemple #4
0
void lov_free_memmd(struct lov_stripe_md **lsmp)
{
    struct lov_stripe_md *lsm = *lsmp;

    LASSERT(lsm_op_find(lsm->lsm_magic) != NULL);
    lsm_op_find(lsm->lsm_magic)->lsm_free(lsm);

    *lsmp = NULL;
}
Exemple #5
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, lsm_size;
        __u16 stripe_count;
        __u32 magic;
	__u32 pattern;
        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);
                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;
        }

        /* 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);
        }

        lsm_size = lov_alloc_memmd(lsmp, stripe_count, pattern, magic);
        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);

        LASSERT(lsm_op_find(magic) != NULL);
        rc = lsm_op_find(magic)->lsm_unpackmd(lov, *lsmp, lmm);
        if (rc) {
                lov_free_memmd(lsmp);
                RETURN(rc);
        }

        RETURN(lsm_size);
}
Exemple #6
0
int lov_free_memmd(struct lov_stripe_md **lsmp)
{
	struct lov_stripe_md *lsm = *lsmp;
	int refc;

	*lsmp = NULL;
	LASSERT(cfs_atomic_read(&lsm->lsm_refc) > 0);
	if ((refc = cfs_atomic_dec_return(&lsm->lsm_refc)) == 0) {
		LASSERT(lsm_op_find(lsm->lsm_magic) != NULL);
		lsm_op_find(lsm->lsm_magic)->lsm_free(lsm);
	}
	return refc;
}
Exemple #7
0
static int lov_verify_lmm(void *lmm, int lmm_bytes, __u16 *stripe_count)
{
	int rc;

	if (!lsm_op_find(le32_to_cpu(*(__u32 *)lmm))) {
		CERROR("bad disk LOV MAGIC: 0x%08X; dumping LMM (size=%d):\n",
		       le32_to_cpu(*(__u32 *)lmm), lmm_bytes);
		CERROR("%*phN\n", lmm_bytes, lmm);
		return -EINVAL;
	}
	rc = lsm_op_find(le32_to_cpu(*(__u32 *)lmm))->lsm_lmm_verify(lmm,
								     lmm_bytes,
								  stripe_count);
	return rc;
}
Exemple #8
0
/* compute which stripe number "lov_off" will be written into */
int lov_stripe_number(struct lov_stripe_md *lsm, obd_off lov_off)
{
	unsigned long ssize  = lsm->lsm_stripe_size;
	obd_off stripe_off, swidth;
	int magic = lsm->lsm_magic;

	LASSERT(lsm_op_find(magic) != NULL);
	lsm_op_find(magic)->lsm_stripe_by_offset(lsm, NULL, &lov_off, &swidth);

	stripe_off = lov_do_div64(lov_off, swidth);

	/* Puts stripe_off/ssize result into stripe_off */
	lov_do_div64(stripe_off, ssize);

	return stripe_off;
}
Exemple #9
0
int lov_free_memmd(struct lov_stripe_md **lsmp)
{
	struct lov_stripe_md *lsm = *lsmp;
	int refc;

	*lsmp = NULL;
	LASSERT(atomic_read(&lsm->lsm_refc) > 0);
	refc = atomic_dec_return(&lsm->lsm_refc);
	if (refc == 0)
		lsm_op_find(lsm->lsm_magic)->lsm_free(lsm);

	return refc;
}
/* Given a whole-file size and a stripe number, give the file size which
 * corresponds to the individual object of that stripe.
 *
 * This behaves basically in the same was as lov_stripe_offset, except that
 * file sizes falling before the beginning of a stripe are clamped to the end
 * of the previous stripe, not the beginning of the next:
 *
 *                                               S
 * ---------------------------------------------------------------------
 * |    0    |     1     |     2     |    0    |     1     |     2     |
 * ---------------------------------------------------------------------
 *
 * if clamped to stripe 2 becomes:
 *
 *                                   S
 * ---------------------------------------------------------------------
 * |    0    |     1     |     2     |    0    |     1     |     2     |
 * ---------------------------------------------------------------------
 */
loff_t lov_size_to_stripe(struct lov_stripe_md *lsm, u64 file_size,
			  int stripeno)
{
	unsigned long ssize  = lsm->lsm_stripe_size;
	loff_t stripe_off;
	loff_t this_stripe;
	loff_t swidth;
	u32 magic = lsm->lsm_magic;

        if (file_size == OBD_OBJECT_EOF)
                return OBD_OBJECT_EOF;

        LASSERT(lsm_op_find(magic) != NULL);
        lsm_op_find(magic)->lsm_stripe_by_index(lsm, &stripeno, &file_size,
                                                &swidth);

	/* lov_do_div64(a, b) returns a % b, and a = a / b */
	stripe_off = lov_do_div64(file_size, swidth);

	this_stripe = (loff_t)stripeno * ssize;
        if (stripe_off < this_stripe) {
                /* Move to end of previous stripe, or zero */
                if (file_size > 0) {
                        file_size--;
                        stripe_off = ssize;
                } else {
                        stripe_off = 0;
                }
        } else {
                stripe_off -= this_stripe;

                if (stripe_off >= ssize) {
                        /* Clamp to end of this stripe */
                        stripe_off = ssize;
                }
        }

        return (file_size * ssize + stripe_off);
}
/* we have an offset in file backed by an lov and want to find out where
 * that offset lands in our given stripe of the file.  for the easy
 * case where the offset is within the stripe, we just have to scale the
 * offset down to make it relative to the stripe instead of the lov.
 *
 * the harder case is what to do when the offset doesn't intersect the
 * stripe.  callers will want start offsets clamped ahead to the start
 * of the nearest stripe in the file.  end offsets similarly clamped to the
 * nearest ending byte of a stripe in the file:
 *
 * all this function does is move offsets to the nearest region of the
 * stripe, and it does its work "mod" the full length of all the stripes.
 * consider a file with 3 stripes:
 *
 *             S                                              E
 * ---------------------------------------------------------------------
 * |    0    |     1     |     2     |    0    |     1     |     2     |
 * ---------------------------------------------------------------------
 *
 * to find stripe 1's offsets for S and E, it divides by the full stripe
 * width and does its math in the context of a single set of stripes:
 *
 *             S         E
 * -----------------------------------
 * |    0    |     1     |     2     |
 * -----------------------------------
 *
 * it'll notice that E is outside stripe 1 and clamp it to the end of the
 * stripe, then multiply it back out by lov_off to give the real offsets in
 * the stripe:
 *
 *   S                   E
 * ---------------------------------------------------------------------
 * |    1    |     1     |     1     |    1    |     1     |     1     |
 * ---------------------------------------------------------------------
 *
 * it would have done similarly and pulled S forward to the start of a 1
 * stripe if, say, S had landed in a 0 stripe.
 *
 * this rounding isn't always correct.  consider an E lov offset that lands
 * on a 0 stripe, the "mod stripe width" math will pull it forward to the
 * start of a 1 stripe, when in fact it wanted to be rounded back to the end
 * of a previous 1 stripe.  this logic is handled by callers and this is why:
 *
 * this function returns < 0 when the offset was "before" the stripe and
 * was moved forward to the start of the stripe in question;  0 when it
 * falls in the stripe and no shifting was done; > 0 when the offset
 * was outside the stripe and was pulled back to its final byte. */
int lov_stripe_offset(struct lov_stripe_md *lsm, loff_t lov_off, int stripeno,
		      loff_t *obdoff)
{
	unsigned long ssize  = lsm->lsm_stripe_size;
	loff_t stripe_off;
	loff_t this_stripe;
	loff_t swidth;
	u32 magic = lsm->lsm_magic;
        int ret = 0;

        if (lov_off == OBD_OBJECT_EOF) {
                *obdoff = OBD_OBJECT_EOF;
                return 0;
        }

        LASSERT(lsm_op_find(magic) != NULL);
        lsm_op_find(magic)->lsm_stripe_by_index(lsm, &stripeno, &lov_off,
                                                &swidth);

	/* lov_do_div64(a, b) returns a % b, and a = a / b */
	stripe_off = lov_do_div64(lov_off, swidth);

	this_stripe = (loff_t)stripeno * ssize;
        if (stripe_off < this_stripe) {
                stripe_off = 0;
                ret = -1;
        } else {
                stripe_off -= this_stripe;

                if (stripe_off >= ssize) {
                        stripe_off = ssize;
                        ret = 1;
                }
        }

        *obdoff = lov_off * ssize + stripe_off;
        return ret;
}
/* Unpack LOV object metadata from disk storage.  It is packed in LE byte
 * order and is opaque to the networking layer.
 */
struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, void *buf,
				   size_t buf_size)
{
	const struct lsm_operations *op;
	struct lov_stripe_md *lsm;
	u32 magic;
	ENTRY;

	if (buf_size < sizeof(magic))
		RETURN(ERR_PTR(-EINVAL));

	magic = le32_to_cpu(*(u32 *)buf);
	op = lsm_op_find(magic);
	if (op == NULL)
		RETURN(ERR_PTR(-EINVAL));

	lsm = op->lsm_unpackmd(lov, buf, buf_size);

	RETURN(lsm);
}