@@ -541,6 +541,21 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
lum_size = sizeof(struct lmv_user_md);
break;
}
+ case LOV_USER_MAGIC_SPECIFIC: {
+ struct lov_user_md_v3 *v3 =
+ (struct lov_user_md_v3 *)lump;
+ if (v3->lmm_stripe_count > LOV_MAX_STRIPE_COUNT)
+ return -EINVAL;
+ if (lump->lmm_magic !=
+ cpu_to_le32(LOV_USER_MAGIC_SPECIFIC)) {
+ lustre_swab_lov_user_md_v3(v3);
+ lustre_swab_lov_user_md_objects(v3->lmm_objects,
+ v3->lmm_stripe_count);
+ }
+ lum_size = lov_user_md_size(v3->lmm_stripe_count,
+ LOV_USER_MAGIC_SPECIFIC);
+ break;
+ }
default: {
CDEBUG(D_IOCTL,
"bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n",
@@ -695,6 +710,16 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
if (cpu_to_le32(LMV_USER_MAGIC) != LMV_USER_MAGIC)
lustre_swab_lmv_user_md((struct lmv_user_md *)lmm);
break;
+ case LOV_USER_MAGIC_SPECIFIC: {
+ struct lov_user_md_v3 *v3 = (struct lov_user_md_v3 *)lmm;
+
+ if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) {
+ lustre_swab_lov_user_md_v3(v3);
+ lustre_swab_lov_user_md_objects(v3->lmm_objects,
+ v3->lmm_stripe_count);
+ }
+ }
+ break;
default:
CERROR("unknown magic: %lX\n", (unsigned long)lmm->lmm_magic);
rc = -EPROTO;
@@ -1230,35 +1255,51 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
case LL_IOC_LOV_SETSTRIPE_NEW:
case LL_IOC_LOV_SETSTRIPE: {
- struct lov_user_md_v3 lumv3;
- struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
+ struct lov_user_md_v3 *lumv3 = NULL;
+ struct lov_user_md_v1 lumv1;
+ struct lov_user_md_v1 *lumv1_ptr = &lumv1;
struct lov_user_md_v1 __user *lumv1p = (void __user *)arg;
struct lov_user_md_v3 __user *lumv3p = (void __user *)arg;
+ int lum_size;
int set_default = 0;
BUILD_BUG_ON(sizeof(struct lov_user_md_v3) <=
sizeof(struct lov_comp_md_v1));
- BUILD_BUG_ON(sizeof(lumv3) != sizeof(*lumv3p));
- BUILD_BUG_ON(sizeof(lumv3.lmm_objects[0]) !=
- sizeof(lumv3p->lmm_objects[0]));
+ BUILD_BUG_ON(sizeof(*lumv3) != sizeof(*lumv3p));
/* first try with v1 which is smaller than v3 */
- if (copy_from_user(lumv1, lumv1p, sizeof(*lumv1)))
+ if (copy_from_user(&lumv1, lumv1p, sizeof(lumv1)))
return -EFAULT;
- if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) {
- if (copy_from_user(&lumv3, lumv3p, sizeof(lumv3)))
- return -EFAULT;
- if (lumv3.lmm_magic != LOV_USER_MAGIC_V3)
- return -EINVAL;
- }
-
if (is_root_inode(inode))
set_default = 1;
- /* in v1 and v3 cases lumv1 points to data */
- rc = ll_dir_setstripe(inode, lumv1, set_default);
+ switch (lumv1.lmm_magic) {
+ case LOV_USER_MAGIC_V3:
+ case LOV_USER_MAGIC_SPECIFIC:
+ lum_size = ll_lov_user_md_size(&lumv1);
+ if (lum_size < 0)
+ return lum_size;
+ lumv3 = kzalloc(lum_size, GFP_NOFS);
+ if (!lumv3)
+ return -ENOMEM;
+ if (copy_from_user(lumv3, lumv3p, lum_size)) {
+ rc = -EFAULT;
+ goto out;
+ }
+ lumv1_ptr = (struct lov_user_md_v1 *)lumv3;
+ break;
+ case LOV_USER_MAGIC_V1:
+ break;
+ default:
+ rc = -ENOTSUPP;
+ goto out;
+ }
+ /* in v1 and v3 cases lumv1 points to data */
+ rc = ll_dir_setstripe(inode, lumv1_ptr, set_default);
+out:
+ kfree(lumv3);
return rc;
}
case LL_IOC_LMV_GETSTRIPE: {