X-Git-Url: http://bbs.cooldavid.org/git/?a=blobdiff_plain;f=drivers%2Fmtd%2Fmtdchar.c;h=3eff1e562ad3c96ca168432b829d8dca5f36abea;hb=67577927e8d7a1f4b09b4992df640eadc6aacb36;hp=1d981a5c1b137bd6a522934092b1fb741349cbc1;hpb=0ceacf36e9c41859a6072342d27cf6e60776c523;p=net-next-2.6.git diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 1d981a5c1b1..3eff1e562ad 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -26,17 +26,19 @@ #include #include #include -#include +#include #include #include #include - +#include #include +#include #include #include #define MTD_INODE_FS_MAGIC 0x11307854 +static DEFINE_MUTEX(mtd_mutex); static struct vfsmount *mtd_inode_mnt __read_mostly; /* @@ -90,7 +92,7 @@ static int mtd_open(struct inode *inode, struct file *file) if ((file->f_mode & FMODE_WRITE) && (minor & 1)) return -EACCES; - lock_kernel(); + mutex_lock(&mtd_mutex); mtd = get_mtd_device(NULL, devnum); if (IS_ERR(mtd)) { @@ -138,7 +140,7 @@ static int mtd_open(struct inode *inode, struct file *file) file->private_data = mfi; out: - unlock_kernel(); + mutex_unlock(&mtd_mutex); return ret; } /* mtd_open */ @@ -510,6 +512,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; @@ -546,6 +587,9 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) if (get_user(ur_idx, &(ur->regionindex))) return -EFAULT; + if (ur_idx >= mtd->numeraseregions) + return -EINVAL; + kr = &(mtd->eraseregions[ur_idx]); if (put_user(kr->offset, &(ur->offset)) @@ -897,6 +941,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; } @@ -908,9 +968,9 @@ static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) { int ret; - lock_kernel(); + mutex_lock(&mtd_mutex); ret = mtd_ioctl(file, cmd, arg); - unlock_kernel(); + mutex_unlock(&mtd_mutex); return ret; } @@ -934,7 +994,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, void __user *argp = compat_ptr(arg); int ret = 0; - lock_kernel(); + mutex_lock(&mtd_mutex); switch (cmd) { case MEMWRITEOOB32: @@ -969,7 +1029,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, ret = mtd_ioctl(file, cmd, (unsigned long)argp); } - unlock_kernel(); + mutex_unlock(&mtd_mutex); return ret; } @@ -1075,7 +1135,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); }