Example #1
0
static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
			   struct lov_stripe_md **lsmp,
			   struct lov_user_md *lump)
{
	struct obd_device *obd = class_exp2obd(exp);
	struct lov_obd *lov = &obd->u.lov;
	char buffer[sizeof(struct lov_user_md_v3)];
	struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)&buffer[0];
	struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&buffer[0];
	int lmm_magic;
	__u16 stripe_count;
	int rc;
	int cplen = 0;

	rc = lov_lum_swab_if_needed(lumv3, &lmm_magic, lump);
	if (rc)
		return rc;

	/* in the rest of the tests, as *lumv1 and lumv3 have the same
	 * fields, we use lumv1 to avoid code duplication */

	if (lumv1->lmm_pattern == 0) {
		lumv1->lmm_pattern = lov->desc.ld_pattern ?
			lov->desc.ld_pattern : LOV_PATTERN_RAID0;
	}

	if (lov_pattern(lumv1->lmm_pattern) != LOV_PATTERN_RAID0) {
		CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n",
		       lumv1->lmm_pattern);
		return -EINVAL;
	}

	/* 64kB is the largest common page size we see (ia64), and matches the
	 * check in lfs */
	if (lumv1->lmm_stripe_size & (LOV_MIN_STRIPE_SIZE - 1)) {
		CDEBUG(D_IOCTL, "stripe size %u not multiple of %u, fixing\n",
		       lumv1->lmm_stripe_size, LOV_MIN_STRIPE_SIZE);
		lumv1->lmm_stripe_size = LOV_MIN_STRIPE_SIZE;
	}

	if ((lumv1->lmm_stripe_offset >= lov->desc.ld_tgt_count) &&
	    (lumv1->lmm_stripe_offset !=
	     (typeof(lumv1->lmm_stripe_offset))(-1))) {
		CDEBUG(D_IOCTL, "stripe offset %u > number of OSTs %u\n",
		       lumv1->lmm_stripe_offset, lov->desc.ld_tgt_count);
		return -EINVAL;
	}
	stripe_count = lov_get_stripecnt(lov, lmm_magic,
					 lumv1->lmm_stripe_count);

	if (max_lmm_size) {
		int max_stripes = (max_lmm_size -
				   lov_mds_md_size(0, lmm_magic)) /
				   sizeof(struct lov_ost_data_v1);
		if (unlikely(max_stripes < stripe_count)) {
			CDEBUG(D_IOCTL, "stripe count reset from %d to %d\n",
			       stripe_count, max_stripes);
			stripe_count = max_stripes;
		}
	}

	if (lmm_magic == LOV_USER_MAGIC_V3) {
		struct pool_desc *pool;

		/* In the function below, .hs_keycmp resolves to
		 * pool_hashkey_keycmp() */
		/* coverity[overrun-buffer-val] */
		pool = lov_find_pool(lov, lumv3->lmm_pool_name);
		if (pool != NULL) {
			if (lumv3->lmm_stripe_offset !=
			    (typeof(lumv3->lmm_stripe_offset))(-1)) {
				rc = lov_check_index_in_pool(
					lumv3->lmm_stripe_offset, pool);
				if (rc < 0) {
					lov_pool_putref(pool);
					return -EINVAL;
				}
			}

			if (stripe_count > pool_tgt_count(pool))
				stripe_count = pool_tgt_count(pool);

			lov_pool_putref(pool);
		}
	}

	if (lumv1->lmm_pattern & LOV_PATTERN_F_RELEASED)
		stripe_count = 0;

	rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic);

	if (rc >= 0) {
		(*lsmp)->lsm_oinfo[0]->loi_ost_idx = lumv1->lmm_stripe_offset;
		(*lsmp)->lsm_stripe_size = lumv1->lmm_stripe_size;
		if (lmm_magic == LOV_USER_MAGIC_V3) {
			cplen = strlcpy((*lsmp)->lsm_pool_name,
					lumv3->lmm_pool_name,
					sizeof((*lsmp)->lsm_pool_name));
			if (cplen >= sizeof((*lsmp)->lsm_pool_name))
				rc = -E2BIG;
		}
		rc = 0;
	}

	return rc;
}
Example #2
0
static int __lov_setstripe(struct obd_export *exp, int max_lmm_size,
                           struct lov_stripe_md **lsmp,
                           struct lov_user_md *lump)
{
    struct obd_device *obd = class_exp2obd(exp);
    struct lov_obd *lov = &obd->u.lov;
    char buffer[sizeof(struct lov_user_md_v3)];
    struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)&buffer[0];
    struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&buffer[0];
    int lmm_magic;
    int stripe_count;
    int rc;
    ENTRY;

    if (cfs_copy_from_user(lumv3, lump, sizeof(struct lov_user_md_v1)))
        RETURN(-EFAULT);

    lmm_magic = lumv1->lmm_magic;

    if (lmm_magic == __swab32(LOV_USER_MAGIC_V1)) {
        lustre_swab_lov_user_md_v1(lumv1);
        lmm_magic = LOV_USER_MAGIC_V1;
    } else if (lmm_magic == LOV_USER_MAGIC_V3) {
        if (cfs_copy_from_user(lumv3, lump, sizeof(*lumv3)))
            RETURN(-EFAULT);
    } else if (lmm_magic == __swab32(LOV_USER_MAGIC_V3)) {
        if (cfs_copy_from_user(lumv3, lump, sizeof(*lumv3)))
            RETURN(-EFAULT);
        lustre_swab_lov_user_md_v3(lumv3);
        lmm_magic = LOV_USER_MAGIC_V3;
    } else if (lmm_magic != LOV_USER_MAGIC_V1) {
        CDEBUG(D_IOCTL,
               "bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n",
               lmm_magic, LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3);
        RETURN(-EINVAL);
    }

    /* in the rest of the tests, as *lumv1 and lumv3 have the same
     * fields, we use lumv1 to avoid code duplication */

    if (lumv1->lmm_pattern == 0) {
        lumv1->lmm_pattern = lov->desc.ld_pattern ?
                             lov->desc.ld_pattern : LOV_PATTERN_RAID0;
    }

    if (lumv1->lmm_pattern != LOV_PATTERN_RAID0) {
        CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n",
               lumv1->lmm_pattern);
        RETURN(-EINVAL);
    }

    /* 64kB is the largest common page size we see (ia64), and matches the
     * check in lfs */
    if (lumv1->lmm_stripe_size & (LOV_MIN_STRIPE_SIZE - 1)) {
        CDEBUG(D_IOCTL, "stripe size %u not multiple of %u, fixing\n",
               lumv1->lmm_stripe_size, LOV_MIN_STRIPE_SIZE);
        lumv1->lmm_stripe_size = LOV_MIN_STRIPE_SIZE;
    }

    if ((lumv1->lmm_stripe_offset >= lov->desc.ld_tgt_count) &&
            (lumv1->lmm_stripe_offset !=
             (typeof(lumv1->lmm_stripe_offset))(-1))) {
        CDEBUG(D_IOCTL, "stripe offset %u > number of OSTs %u\n",
               lumv1->lmm_stripe_offset, lov->desc.ld_tgt_count);
        RETURN(-EINVAL);
    }
    stripe_count = lov_get_stripecnt(lov, lumv1->lmm_stripe_count);

    if (max_lmm_size) {
        int max_stripes = (max_lmm_size -
                           lov_mds_md_size(0, lmm_magic)) /
                          sizeof(struct lov_ost_data_v1);
        if (unlikely(max_stripes < stripe_count)) {
            CDEBUG(D_IOCTL, "stripe count reset from %d to %d\n",
                   stripe_count, max_stripes);
            stripe_count = max_stripes;
        }
    }

    if (lmm_magic == LOV_USER_MAGIC_V3) {
        struct pool_desc *pool;

        pool = lov_find_pool(lov, lumv3->lmm_pool_name);
        if (pool != NULL) {
            if (lumv3->lmm_stripe_offset !=
                    (typeof(lumv3->lmm_stripe_offset))(-1)) {
                rc = lov_check_index_in_pool(
                         lumv3->lmm_stripe_offset, pool);
                if (rc < 0) {
                    lov_pool_putref(pool);
                    RETURN(-EINVAL);
                }
            }

            if (stripe_count > pool_tgt_count(pool))
                stripe_count = pool_tgt_count(pool);

            lov_pool_putref(pool);
        }
    }

    rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic);

    if (rc >= 0) {
        (*lsmp)->lsm_oinfo[0]->loi_ost_idx = lumv1->lmm_stripe_offset;
        (*lsmp)->lsm_stripe_size = lumv1->lmm_stripe_size;
        if (lmm_magic == LOV_USER_MAGIC_V3)
            strncpy((*lsmp)->lsm_pool_name, lumv3->lmm_pool_name,
                    LOV_MAXPOOLNAME);
        rc = 0;
    }

    RETURN(rc);
}