#define LOV_MAGIC_JOIN_V1      (0x0BD20000 | LOV_MAGIC_MAGIC)
 #define LOV_MAGIC_V3           (0x0BD30000 | LOV_MAGIC_MAGIC)
 #define LOV_MAGIC_MIGRATE      (0x0BD40000 | LOV_MAGIC_MAGIC)
+/* reserved for specifying OSTs */
+#define LOV_MAGIC_SPECIFIC     (0x0BD50000 | LOV_MAGIC_MAGIC)
 #define LOV_MAGIC              LOV_MAGIC_V1
 
 /*
 
 #define LL_FILE_LOCKLESS_IO     0x00000010 /* server-side locks with cio */
 #define LL_FILE_RMTACL   0x00000020
 
-#define LOV_USER_MAGIC_V1 0x0BD10BD0
-#define LOV_USER_MAGIC    LOV_USER_MAGIC_V1
-#define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0
-#define LOV_USER_MAGIC_V3 0x0BD30BD0
+#define LOV_USER_MAGIC_V1      0x0BD10BD0
+#define LOV_USER_MAGIC         LOV_USER_MAGIC_V1
+#define LOV_USER_MAGIC_JOIN_V1 0x0BD20BD0
+#define LOV_USER_MAGIC_V3      0x0BD30BD0
+/* 0x0BD40BD0 is occupied by LOV_MAGIC_MIGRATE */
+#define LOV_USER_MAGIC_SPECIFIC        0x0BD50BD0      /* for specific OSTs */
 
 #define LMV_USER_MAGIC    0x0CD30CD0    /*default lmv magic*/
 
 
 static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic)
 {
-       if (lmm_magic == LOV_USER_MAGIC_V3)
-               return sizeof(struct lov_user_md_v3) +
-                               stripes * sizeof(struct lov_user_ost_data_v1);
-       else
+       if (lmm_magic == LOV_USER_MAGIC_V1)
                return sizeof(struct lov_user_md_v1) +
                                stripes * sizeof(struct lov_user_ost_data_v1);
+       return sizeof(struct lov_user_md_v3) +
+              stripes * sizeof(struct lov_user_ost_data_v1);
 }
 
 /* Compile with -D_LARGEFILE64_SOURCE or -D_GNU_SOURCE (or #define) to
 
 static int ll_lov_setstripe(struct inode *inode, struct file *file,
                            unsigned long arg)
 {
-       struct lov_user_md_v3 lumv3;
-       struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
-       struct lov_user_md_v1 __user *lumv1p = (void __user *)arg;
-       struct lov_user_md_v3 __user *lumv3p = (void __user *)arg;
+       struct lov_user_md __user *lum = (struct lov_user_md __user *)arg;
+       struct lov_user_md *klum;
        int lum_size, rc;
        __u64 flags = FMODE_WRITE;
 
-       /* first try with v1 which is smaller than v3 */
-       lum_size = sizeof(struct lov_user_md_v1);
-       if (copy_from_user(lumv1, lumv1p, lum_size))
-               return -EFAULT;
-
-       if (lumv1->lmm_magic == LOV_USER_MAGIC_V3) {
-               lum_size = sizeof(struct lov_user_md_v3);
-               if (copy_from_user(&lumv3, lumv3p, lum_size))
-                       return -EFAULT;
-       }
+       rc = ll_copy_user_md(lum, &klum);
+       if (rc < 0)
+               return rc;
 
-       rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, lumv1,
+       lum_size = rc;
+       rc = ll_lov_setstripe_ea_info(inode, file->f_path.dentry, flags, klum,
                                      lum_size);
        cl_lov_delay_create_clear(&file->f_flags);
        if (rc == 0) {
                struct lov_stripe_md *lsm;
                __u32 gen;
 
-               put_user(0, &lumv1p->lmm_stripe_count);
+               put_user(0, &lum->lmm_stripe_count);
 
                ll_layout_refresh(inode, &gen);
                lsm = ccc_inode_lsm_get(inode);
                rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode),
-                                  0, lsm, (void __user *)arg);
+                                  0, lsm, lum);
                ccc_inode_lsm_put(inode, lsm);
        }
+
+       kfree(klum);
        return rc;
 }
 
 
 char *ll_get_fsname(struct super_block *sb, char *buf, int buflen);
 void ll_compute_rootsquash_state(struct ll_sb_info *sbi);
 void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req);
+ssize_t ll_copy_user_md(const struct lov_user_md __user *md,
+                       struct lov_user_md **kbuf);
+
+/* Compute expected user md size when passing in a md from user space */
+static inline ssize_t ll_lov_user_md_size(const struct lov_user_md *lum)
+{
+       switch (lum->lmm_magic) {
+       case LOV_USER_MAGIC_V1:
+               return sizeof(struct lov_user_md_v1);
+       case LOV_USER_MAGIC_V3:
+               return sizeof(struct lov_user_md_v3);
+       case LOV_USER_MAGIC_SPECIFIC:
+               if (lum->lmm_stripe_count > LOV_MAX_STRIPE_COUNT)
+                       return -EINVAL;
+
+               return lov_user_md_size(lum->lmm_stripe_count,
+                                       LOV_USER_MAGIC_SPECIFIC);
+       }
+       return -EINVAL;
+}
 
 /* llite/llite_nfs.c */
 extern const struct export_operations lustre_export_operations;
 
                free_page((unsigned long)buf);
 }
 
+ssize_t ll_copy_user_md(const struct lov_user_md __user *md,
+                       struct lov_user_md **kbuf)
+{
+       struct lov_user_md lum;
+       ssize_t lum_size;
+
+       if (copy_from_user(&lum, md, sizeof(lum))) {
+               lum_size = -EFAULT;
+               goto no_kbuf;
+       }
+
+       lum_size = ll_lov_user_md_size(&lum);
+       if (lum_size < 0)
+               goto no_kbuf;
+
+       *kbuf = kzalloc(lum_size, GFP_NOFS);
+       if (!*kbuf) {
+               lum_size = -ENOMEM;
+               goto no_kbuf;
+       }
+
+       if (copy_from_user(*kbuf, md, lum_size) != 0) {
+               kfree(*kbuf);
+               *kbuf = NULL;
+               lum_size = -EFAULT;
+       }
+no_kbuf:
+       return lum_size;
+}
+
 /*
  * Compute llite root squash state after a change of root squash
  * configuration setting or add/remove of a lnet nid
 
 
                if (lump && S_ISREG(inode->i_mode)) {
                        __u64 it_flags = FMODE_WRITE;
-                       int lum_size = (lump->lmm_magic == LOV_USER_MAGIC_V1) ?
-                               sizeof(*lump) : sizeof(struct lov_user_md_v3);
+                       int lum_size;
+
+                       lum_size = ll_lov_user_md_size(lump);
+                       if (lum_size < 0 || size < lum_size)
+                               return 0; /* b=10667: ignore error */
 
                        rc = ll_lov_setstripe_ea_info(inode, dentry, it_flags,
                                                      lump, lum_size);
-                       /* b10667: rc always be 0 here for now */
+                       /* b=10667: rc always be 0 here for now */
                        rc = 0;
                } else if (S_ISDIR(inode->i_mode)) {
                        rc = ll_dir_setstripe(inode, lump, 0);
 
                        stripe_count = 0;
                }
        } else {
-               /* No need to allocate more than maximum supported stripes.
-                * Anyway, this is pretty inaccurate since ld_tgt_count now
-                * represents max index and we should rely on the actual number
-                * of OSTs instead
+               /*
+                * To calculate maximum easize by active targets at present,
+                * which is exactly the maximum easize to be seen by LOV
                 */
-               stripe_count = lov_mds_md_max_stripe_count(
-                       lov->lov_ocd.ocd_max_easize, lmm_magic);
-
-               if (stripe_count > lov->desc.ld_tgt_count)
-                       stripe_count = lov->desc.ld_tgt_count;
+               stripe_count = lov->desc.ld_active_tgt_count;
        }
 
        /* XXX LOV STACKING call into osc for sizes */
                rc = -EFAULT;
                goto out_set;
        }
-       if ((lum.lmm_magic != LOV_USER_MAGIC) &&
-           (lum.lmm_magic != LOV_USER_MAGIC_V3)) {
+       if (lum.lmm_magic != LOV_USER_MAGIC_V1 &&
+           lum.lmm_magic != LOV_USER_MAGIC_V3 &&
+           lum.lmm_magic != LOV_USER_MAGIC_SPECIFIC) {
                rc = -EINVAL;
                goto out_set;
        }
 
 }
 EXPORT_SYMBOL(lustre_swab_lmv_user_md);
 
-static void print_lum(struct lov_user_md *lum)
-{
-       CDEBUG(D_OTHER, "lov_user_md %p:\n", lum);
-       CDEBUG(D_OTHER, "\tlmm_magic: %#x\n", lum->lmm_magic);
-       CDEBUG(D_OTHER, "\tlmm_pattern: %#x\n", lum->lmm_pattern);
-       CDEBUG(D_OTHER, "\tlmm_object_id: %llu\n", lmm_oi_id(&lum->lmm_oi));
-       CDEBUG(D_OTHER, "\tlmm_object_gr: %llu\n", lmm_oi_seq(&lum->lmm_oi));
-       CDEBUG(D_OTHER, "\tlmm_stripe_size: %#x\n", lum->lmm_stripe_size);
-       CDEBUG(D_OTHER, "\tlmm_stripe_count: %#x\n", lum->lmm_stripe_count);
-       CDEBUG(D_OTHER, "\tlmm_stripe_offset/lmm_layout_gen: %#x\n",
-              lum->lmm_stripe_offset);
-}
-
 static void lustre_swab_lmm_oi(struct ost_id *oi)
 {
        __swab64s(&oi->oi.oi_id);
        __swab32s(&lum->lmm_stripe_size);
        __swab16s(&lum->lmm_stripe_count);
        __swab16s(&lum->lmm_stripe_offset);
-       print_lum(lum);
 }
 
 void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum)