diff options
author | Roman Tereshonkov <roman.tereshonkov@nokia.com> | 2010-09-17 13:31:42 +0300 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-10-25 00:48:49 +0100 |
commit | d0f7959e2b708d775c3b6b53cc6a8abb8ff0a00b (patch) | |
tree | ccb0dc2fdcc6b0611fe1b19faaa841ff4430fd2b | |
parent | 5daa7b21496aebf057c12be03038e7220e33353b (diff) |
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>
-rw-r--r-- | drivers/mtd/mtdchar.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 5895de7018d4..b7ed09c57903 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -30,8 +30,9 @@ #include <linux/backing-dev.h> #include <linux/compat.h> #include <linux/mount.h> - +#include <linux/blkpg.h> #include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> #include <linux/mtd/map.h> #include <asm/uaccess.h> @@ -510,6 +511,45 @@ static int shrink_ecclayout(const struct nand_ecclayout *from, 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) { 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; } +#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: 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, 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); } |