We cannot modify file->f_mapping->backing_dev_info, because it will corrupt
backing device of device node inode, since file->f_mapping is equal to
inode->i_mapping (see __dentry_open() in fs/open.c).
Let's introduce separate inode for MTD device with appropriate backing
device.
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
Acked-by: Jan Kara <jack@suse.cz>
---
Changelog
v2 -> v3:
- Rebase to mtd.git.
v1 -> v2:
- Fix error handling based on comments by Jan Kara.
---
drivers/mtd/mtdchar.c | 77 ++++++++++++++++++++++++++++++++++++++++++-----
drivers/mtd/mtdcore.c | 3 ++
include/linux/mtd/mtd.h | 3 ++
3 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index c355491..a2bb3ce 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -15,12 +15,15 @@
#include <linux/smp_lock.h>
#include <linux/backing-dev.h>
#include <linux/compat.h>
+#include <linux/mount.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
#include <asm/uaccess.h>
+#define MTD_INODE_FS_MAGIC 0x11307854
+static struct vfsmount *mtd_inode_mnt __read_mostly;
/*
* Data structure to hold the pointer to the mtd device as well
@@ -85,11 +88,30 @@ static int mtd_open(struct inode *inode, struct file *file)
goto out;
}
- if (mtd->backing_dev_info)
- file->f_mapping->backing_dev_info = mtd->backing_dev_info;
+ if (!mtd->inode) {
+ mtd->inode = new_inode(mtd_inode_mnt->mnt_sb);
+ if (!mtd->inode) {
+ put_mtd_device(mtd);
+ ret = -ENOMEM;
+ goto out;
+ }
+ mtd->inode->i_mode = S_IFCHR;
+ mtd->inode->i_rdev = inode->i_rdev;
+ if (mtd->backing_dev_info) {
+ mtd->inode->i_data.backing_dev_info =
+ mtd->backing_dev_info;
+ }
+ }
+
+ spin_lock(&inode_lock);
+ __iget(mtd->inode);
+ spin_unlock(&inode_lock);
+
+ file->f_mapping = mtd->inode->i_mapping;
/* You can't open it RW if it's not a writeable device */
if ((file->f_mode & ...