aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-03-23 13:47:52 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-03-31 16:03:15 -0400
commit00292bbf769620dea923dbd906afd88955f7ea19 (patch)
treee13fb45d1c31e96d37213f514715bddc95bbea07 /drivers
parent22a71c3055cfcc277b7a8422d4ff256944370c24 (diff)
mtdchar: kill persistently held vfsmount
... and mtdchar_notifier along with it; just have ->drop_inode() that will unconditionally get evict them instead of dances on mtd device removal and use simple_pin_fs() instead of kern_mount() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/mtdchar.c53
1 files changed, 16 insertions, 37 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index c57ae92ebda4..28c585ffc8af 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -39,7 +39,6 @@
39#include <asm/uaccess.h> 39#include <asm/uaccess.h>
40 40
41static DEFINE_MUTEX(mtd_mutex); 41static DEFINE_MUTEX(mtd_mutex);
42static struct vfsmount *mtd_inode_mnt __read_mostly;
43 42
44/* 43/*
45 * Data structure to hold the pointer to the mtd device as well 44 * Data structure to hold the pointer to the mtd device as well
@@ -75,7 +74,9 @@ static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig)
75 return -EINVAL; 74 return -EINVAL;
76} 75}
77 76
78 77static int count;
78static struct vfsmount *mnt;
79static struct file_system_type mtd_inodefs_type;
79 80
80static int mtdchar_open(struct inode *inode, struct file *file) 81static int mtdchar_open(struct inode *inode, struct file *file)
81{ 82{
@@ -92,6 +93,10 @@ static int mtdchar_open(struct inode *inode, struct file *file)
92 if ((file->f_mode & FMODE_WRITE) && (minor & 1)) 93 if ((file->f_mode & FMODE_WRITE) && (minor & 1))
93 return -EACCES; 94 return -EACCES;
94 95
96 ret = simple_pin_fs(&mtd_inodefs_type, &mnt, &count);
97 if (ret)
98 return ret;
99
95 mutex_lock(&mtd_mutex); 100 mutex_lock(&mtd_mutex);
96 mtd = get_mtd_device(NULL, devnum); 101 mtd = get_mtd_device(NULL, devnum);
97 102
@@ -106,7 +111,7 @@ static int mtdchar_open(struct inode *inode, struct file *file)
106 goto out; 111 goto out;
107 } 112 }
108 113
109 mtd_ino = iget_locked(mtd_inode_mnt->mnt_sb, devnum); 114 mtd_ino = iget_locked(mnt->mnt_sb, devnum);
110 if (!mtd_ino) { 115 if (!mtd_ino) {
111 put_mtd_device(mtd); 116 put_mtd_device(mtd);
112 ret = -ENOMEM; 117 ret = -ENOMEM;
@@ -141,6 +146,7 @@ static int mtdchar_open(struct inode *inode, struct file *file)
141 146
142out: 147out:
143 mutex_unlock(&mtd_mutex); 148 mutex_unlock(&mtd_mutex);
149 simple_release_fs(&mnt, &count);
144 return ret; 150 return ret;
145} /* mtdchar_open */ 151} /* mtdchar_open */
146 152
@@ -162,6 +168,7 @@ static int mtdchar_close(struct inode *inode, struct file *file)
162 put_mtd_device(mtd); 168 put_mtd_device(mtd);
163 file->private_data = NULL; 169 file->private_data = NULL;
164 kfree(mfi); 170 kfree(mfi);
171 simple_release_fs(&mnt, &count);
165 172
166 return 0; 173 return 0;
167} /* mtdchar_close */ 174} /* mtdchar_close */
@@ -1175,10 +1182,15 @@ static const struct file_operations mtd_fops = {
1175#endif 1182#endif
1176}; 1183};
1177 1184
1185static const struct super_operations mtd_ops = {
1186 .drop_inode = generic_delete_inode,
1187 .statfs = simple_statfs,
1188};
1189
1178static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, 1190static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
1179 int flags, const char *dev_name, void *data) 1191 int flags, const char *dev_name, void *data)
1180{ 1192{
1181 return mount_pseudo(fs_type, "mtd_inode:", NULL, NULL, MTD_INODE_FS_MAGIC); 1193 return mount_pseudo(fs_type, "mtd_inode:", &mtd_ops, NULL, MTD_INODE_FS_MAGIC);
1182} 1194}
1183 1195
1184static struct file_system_type mtd_inodefs_type = { 1196static struct file_system_type mtd_inodefs_type = {
@@ -1187,26 +1199,6 @@ static struct file_system_type mtd_inodefs_type = {
1187 .kill_sb = kill_anon_super, 1199 .kill_sb = kill_anon_super,
1188}; 1200};
1189 1201
1190static void mtdchar_notify_add(struct mtd_info *mtd)
1191{
1192}
1193
1194static void mtdchar_notify_remove(struct mtd_info *mtd)
1195{
1196 struct inode *mtd_ino = ilookup(mtd_inode_mnt->mnt_sb, mtd->index);
1197
1198 if (mtd_ino) {
1199 /* Destroy the inode if it exists */
1200 clear_nlink(mtd_ino);
1201 iput(mtd_ino);
1202 }
1203}
1204
1205static struct mtd_notifier mtdchar_notifier = {
1206 .add = mtdchar_notify_add,
1207 .remove = mtdchar_notify_remove,
1208};
1209
1210static int __init init_mtdchar(void) 1202static int __init init_mtdchar(void)
1211{ 1203{
1212 int ret; 1204 int ret;
@@ -1224,19 +1216,8 @@ static int __init init_mtdchar(void)
1224 pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); 1216 pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret);
1225 goto err_unregister_chdev; 1217 goto err_unregister_chdev;
1226 } 1218 }
1227
1228 mtd_inode_mnt = kern_mount(&mtd_inodefs_type);
1229 if (IS_ERR(mtd_inode_mnt)) {
1230 ret = PTR_ERR(mtd_inode_mnt);
1231 pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret);
1232 goto err_unregister_filesystem;
1233 }
1234 register_mtd_user(&mtdchar_notifier);
1235
1236 return ret; 1219 return ret;
1237 1220
1238err_unregister_filesystem:
1239 unregister_filesystem(&mtd_inodefs_type);
1240err_unregister_chdev: 1221err_unregister_chdev:
1241 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); 1222 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1242 return ret; 1223 return ret;
@@ -1244,8 +1225,6 @@ err_unregister_chdev:
1244 1225
1245static void __exit cleanup_mtdchar(void) 1226static void __exit cleanup_mtdchar(void)
1246{ 1227{
1247 unregister_mtd_user(&mtdchar_notifier);
1248 kern_unmount(mtd_inode_mnt);
1249 unregister_filesystem(&mtd_inodefs_type); 1228 unregister_filesystem(&mtd_inodefs_type);
1250 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); 1229 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1251} 1230}