@@ -236,7 +236,9 @@ struct ll_futimes_3 {
#define LL_IOC_SETFLAGS _IOW('f', 152, long)
#define LL_IOC_CLRFLAGS _IOW('f', 153, long)
#define LL_IOC_LOV_SETSTRIPE _IOW('f', 154, long)
+#define LL_IOC_LOV_SETSTRIPE_NEW _IOWR('f', 154, struct lov_user_md)
#define LL_IOC_LOV_GETSTRIPE _IOW('f', 155, long)
+#define LL_IOC_LOV_GETSTRIPE_NEW _IOR('f', 155, struct lov_user_md)
#define LL_IOC_LOV_SETEA _IOW('f', 156, long)
/* LL_IOC_RECREATE_OBJ 157 obsolete */
/* LL_IOC_RECREATE_FID 158 obsolete */
@@ -390,7 +390,7 @@ struct cl_object_operations {
* Object getstripe method.
*/
int (*coo_getstripe)(const struct lu_env *env, struct cl_object *obj,
- struct lov_user_md __user *lum);
+ struct lov_user_md __user *lum, size_t size);
/**
* Get FIEMAP mapping from the object.
*/
@@ -2057,7 +2057,7 @@ int cl_conf_set(const struct lu_env *env, struct cl_object *obj,
int cl_object_prune(const struct lu_env *env, struct cl_object *obj);
void cl_object_kill(const struct lu_env *env, struct cl_object *obj);
int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj,
- struct lov_user_md __user *lum);
+ struct lov_user_md __user *lum, size_t size);
int cl_object_fiemap(const struct lu_env *env, struct cl_object *obj,
struct ll_fiemap_info_key *fmkey, struct fiemap *fiemap,
size_t *buflen);
@@ -1224,6 +1224,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return rc;
}
+ 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;
@@ -1363,6 +1364,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case IOC_OBD_STATFS:
return ll_obd_statfs(inode, (void __user *)arg);
case LL_IOC_LOV_GETSTRIPE:
+ case LL_IOC_LOV_GETSTRIPE_NEW:
case LL_IOC_MDC_GETINFO:
case IOC_MDC_GETFILEINFO:
case IOC_MDC_GETFILESTRIPE: {
@@ -1405,7 +1407,8 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
if (cmd == IOC_MDC_GETFILESTRIPE ||
- cmd == LL_IOC_LOV_GETSTRIPE) {
+ cmd == LL_IOC_LOV_GETSTRIPE ||
+ cmd == LL_IOC_LOV_GETSTRIPE_NEW) {
lump = (struct lov_user_md __user *)arg;
} else {
struct lov_user_mds_data __user *lmdp;
@@ -1481,7 +1481,7 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
}
static int ll_lov_setea(struct inode *inode, struct file *file,
- unsigned long arg)
+ void __user *arg)
{
__u64 flags = MDS_OPEN_HAS_OBJS | FMODE_WRITE;
struct lov_user_md *lump;
@@ -1496,7 +1496,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file,
if (!lump)
return -ENOMEM;
- if (copy_from_user(lump, (struct lov_user_md __user *)arg, lum_size)) {
+ if (copy_from_user(lump, arg, lum_size)) {
kvfree(lump);
return -EFAULT;
}
@@ -1509,8 +1509,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file,
return rc;
}
-static int ll_file_getstripe(struct inode *inode,
- struct lov_user_md __user *lum)
+static int ll_file_getstripe(struct inode *inode, void __user *lum, size_t size)
{
struct lu_env *env;
u16 refcheck;
@@ -1520,13 +1519,13 @@ static int ll_file_getstripe(struct inode *inode,
if (IS_ERR(env))
return PTR_ERR(env);
- rc = cl_object_getstripe(env, ll_i2info(inode)->lli_clob, lum);
+ rc = cl_object_getstripe(env, ll_i2info(inode)->lli_clob, lum, size);
cl_env_put(env, &refcheck);
return rc;
}
static int ll_lov_setstripe(struct inode *inode, struct file *file,
- unsigned long arg)
+ void __user *arg)
{
struct lov_user_md __user *lum = (struct lov_user_md __user *)arg;
struct lov_user_md *klum;
@@ -1540,8 +1539,22 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file,
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) {
+ u32 gen;
+
+ rc = put_user(0, &lum->lmm_stripe_count);
+ if (rc)
+ goto out;
+ rc = ll_layout_refresh(inode, &gen);
+ if (rc)
+ goto out;
+
+ rc = ll_file_getstripe(inode, arg, lum_size);
+ }
+
+ cl_lov_delay_create_clear(&file->f_flags);
+out:
kfree(klum);
return rc;
}
@@ -2329,9 +2342,10 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
}
return 0;
case LL_IOC_LOV_SETSTRIPE:
- return ll_lov_setstripe(inode, file, arg);
+ case LL_IOC_LOV_SETSTRIPE_NEW:
+ return ll_lov_setstripe(inode, file, (void __user *) arg);
case LL_IOC_LOV_SETEA:
- return ll_lov_setea(inode, file, arg);
+ return ll_lov_setea(inode, file, (void __user *) arg);
case LL_IOC_LOV_SWAP_LAYOUTS: {
struct file *file2;
struct lustre_swap_layouts lsl;
@@ -2384,8 +2398,8 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
return rc;
}
case LL_IOC_LOV_GETSTRIPE:
- return ll_file_getstripe(inode,
- (struct lov_user_md __user *)arg);
+ case LL_IOC_LOV_GETSTRIPE_NEW:
+ return ll_file_getstripe(inode, (void __user *)arg, 0);
case FSFILT_IOC_GETFLAGS:
case FSFILT_IOC_SETFLAGS:
return ll_iocontrol(inode, file, cmd, arg);
@@ -651,8 +651,9 @@ static inline struct lov_stripe_md_entry *lov_lse(struct lov_object *lov, int i)
}
/* lov_pack.c */
-int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm,
- struct lov_user_md __user *lump);
+int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
+ struct lov_stripe_md *lsm, struct lov_user_md __user *lump,
+ size_t size);
/** @} lov */
@@ -1605,7 +1605,7 @@ static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj,
}
static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj,
- struct lov_user_md __user *lum)
+ struct lov_user_md __user *lum, size_t size)
{
struct lov_object *lov = cl2lov(obj);
struct lov_stripe_md *lsm;
@@ -1615,7 +1615,7 @@ static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj,
if (!lsm)
return -ENODATA;
- rc = lov_getstripe(env, cl2lov(obj), lsm, lum);
+ rc = lov_getstripe(env, cl2lov(obj), lsm, lum, size);
lov_lsm_put(lsm);
return rc;
}
@@ -314,12 +314,16 @@ struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, void *buf,
* @lump is a pointer to an in-core struct with lmm_ost_count indicating
* the maximum number of OST indices which will fit in the user buffer.
* lmm_magic must be LOV_USER_MAGIC.
+ *
+ * If @size > 0, User specified limited buffer size, usually the buffer is from
+ * ll_lov_setstripe(), and the buffer can only hold basic layout template info.
*/
int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
- struct lov_stripe_md *lsm, struct lov_user_md __user *lump)
+ struct lov_stripe_md *lsm, struct lov_user_md __user *lump,
+ size_t size)
{
/* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */
- struct lov_mds_md *lmmk;
+ struct lov_mds_md *lmmk, *lmm;
struct lov_user_md_v1 lum;
ssize_t lmm_size, lum_size = 0;
static bool printed;
@@ -410,15 +414,24 @@ int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
comp_md = (struct lov_mds_md *)((char *)comp_v1 +
comp_v1->lcm_entries[i].lcme_offset);
}
- if (copy_to_user(lump, comp_md, lum_size)) {
- rc = -EFAULT;
- goto out_free;
- }
+
+ lmm = comp_md;
+ lmm_size = lum_size;
} else {
- if (copy_to_user(lump, lmmk, lmmk_size)) {
- rc = -EFAULT;
- goto out_free;
- }
+ lmm = lmmk;
+ lmm_size = lmmk_size;
+ }
+ /**
+ * User specified limited buffer size, usually the buffer is
+ * from ll_lov_setstripe(), and the buffer can only hold basic
+ * layout template info.
+ */
+ if (size == 0 || size > lmm_size)
+ size = lmm_size;
+
+ if (copy_to_user(lump, lmm, size)) {
+ rc = -EFAULT;
+ goto out_free;
}
out_free:
@@ -323,7 +323,7 @@ int cl_object_prune(const struct lu_env *env, struct cl_object *obj)
* Get stripe information of this object.
*/
int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj,
- struct lov_user_md __user *uarg)
+ struct lov_user_md __user *uarg, size_t size)
{
struct lu_object_header *top;
int result = 0;
@@ -331,7 +331,8 @@ int cl_object_getstripe(const struct lu_env *env, struct cl_object *obj,
top = obj->co_lu.lo_header;
list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) {
if (obj->co_ops->coo_getstripe) {
- result = obj->co_ops->coo_getstripe(env, obj, uarg);
+ result = obj->co_ops->coo_getstripe(env, obj, uarg,
+ size);
if (result)
break;
}