diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-03-23 13:47:52 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-03-31 16:03:15 -0400 |
commit | 00292bbf769620dea923dbd906afd88955f7ea19 (patch) | |
tree | e13fb45d1c31e96d37213f514715bddc95bbea07 /drivers/mtd/mtdchar.c | |
parent | 22a71c3055cfcc277b7a8422d4ff256944370c24 (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/mtd/mtdchar.c')
-rw-r--r-- | drivers/mtd/mtdchar.c | 53 |
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 | ||
41 | static DEFINE_MUTEX(mtd_mutex); | 41 | static DEFINE_MUTEX(mtd_mutex); |
42 | static 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 | 77 | static int count; | |
78 | static struct vfsmount *mnt; | ||
79 | static struct file_system_type mtd_inodefs_type; | ||
79 | 80 | ||
80 | static int mtdchar_open(struct inode *inode, struct file *file) | 81 | static 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 | ||
142 | out: | 147 | out: |
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 | ||
1185 | static const struct super_operations mtd_ops = { | ||
1186 | .drop_inode = generic_delete_inode, | ||
1187 | .statfs = simple_statfs, | ||
1188 | }; | ||
1189 | |||
1178 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, | 1190 | static 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 | ||
1184 | static struct file_system_type mtd_inodefs_type = { | 1196 | static 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 | ||
1190 | static void mtdchar_notify_add(struct mtd_info *mtd) | ||
1191 | { | ||
1192 | } | ||
1193 | |||
1194 | static 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 | |||
1205 | static struct mtd_notifier mtdchar_notifier = { | ||
1206 | .add = mtdchar_notify_add, | ||
1207 | .remove = mtdchar_notify_remove, | ||
1208 | }; | ||
1209 | |||
1210 | static int __init init_mtdchar(void) | 1202 | static 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 | ||
1238 | err_unregister_filesystem: | ||
1239 | unregister_filesystem(&mtd_inodefs_type); | ||
1240 | err_unregister_chdev: | 1221 | err_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 | ||
1245 | static void __exit cleanup_mtdchar(void) | 1226 | static 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 | } |