mtd: add BLKPG API based repartition support

Add support for mtd repartition based on the block
device BLKPG interface:
BLKPG_ADD_PARTITION - for partition creation;
BLKPG_DEL_PARTITION - for partition delete

The usage is based on BLKPG ioctl called with
struct blkpg_ioctl_arg argument which includes the
reference to struct blkpg_partition discribing the
partition offset and length.

Disadvantage: there is no implementation for mtd
flags control. The flags are always borrowed from
the master device.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov@nokia.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
Roman Tereshonkov 2010-09-17 13:31:42 +03:00 committed by David Woodhouse
parent 5daa7b2149
commit d0f7959e2b

View File

@ -30,8 +30,9 @@
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/blkpg.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -510,6 +511,45 @@ static int shrink_ecclayout(const struct nand_ecclayout *from,
return 0; return 0;
} }
#ifdef CONFIG_MTD_PARTITIONS
static int mtd_blkpg_ioctl(struct mtd_info *mtd,
struct blkpg_ioctl_arg __user *arg)
{
struct blkpg_ioctl_arg a;
struct blkpg_partition p;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
/* Only master mtd device must be used to control partitions */
if (!mtd_is_master(mtd))
return -EINVAL;
if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
return -EFAULT;
if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
return -EFAULT;
switch (a.op) {
case BLKPG_ADD_PARTITION:
return mtd_add_partition(mtd, p.devname, p.start, p.length);
case BLKPG_DEL_PARTITION:
if (p.pno < 0)
return -EINVAL;
return mtd_del_partition(mtd, p.pno);
default:
return -EINVAL;
}
}
#endif
static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
{ {
struct mtd_file_info *mfi = file->private_data; struct mtd_file_info *mfi = file->private_data;
@ -900,6 +940,22 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
break; break;
} }
#ifdef CONFIG_MTD_PARTITIONS
case BLKPG:
{
ret = mtd_blkpg_ioctl(mtd,
(struct blkpg_ioctl_arg __user *)arg);
break;
}
case BLKRRPART:
{
/* No reread partition feature. Just return ok */
ret = 0;
break;
}
#endif
default: default:
ret = -ENOTTY; ret = -ENOTTY;
} }
@ -1078,7 +1134,7 @@ static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data, const char *dev_name, void *data,
struct vfsmount *mnt) struct vfsmount *mnt)
{ {
return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC,
mnt); mnt);
} }