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 | |
| 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')
| -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 c57ae92ebda..28c585ffc8a 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 | } |
