Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6:
[JFFS2] Fix obsoletion of metadata nodes in jffs2_add_tn_to_tree()
[MTD] Fix error checking after get_mtd_device() in get_sb_mtd functions
[JFFS2] Fix buffer length calculations in jffs2_get_inode_nodes()
[JFFS2] Fix potential memory leak of dead xattrs on unmount.
[JFFS2] Fix BUG() caused by failing to discard xattrs on deleted files.
[MTD] generalise the handling of MTD-specific superblocks
[MTD] [MAPS] don't force uclinux mtd map to be root dev

+304 -189
+1 -2
drivers/mtd/Makefile
··· 1 1 # 2 2 # Makefile for the memory technology device drivers. 3 3 # 4 - # $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $ 5 4 6 5 # Core functionality. 7 - mtd-y := mtdcore.o 6 + mtd-y := mtdcore.o mtdsuper.o 8 7 mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o 9 8 obj-$(CONFIG_MTD) += $(mtd-y) 10 9
-5
drivers/mtd/maps/uclinux.c
··· 16 16 #include <linux/kernel.h> 17 17 #include <linux/fs.h> 18 18 #include <linux/major.h> 19 - #include <linux/root_dev.h> 20 19 #include <linux/mtd/mtd.h> 21 20 #include <linux/mtd/map.h> 22 21 #include <linux/mtd/partitions.h> ··· 87 88 88 89 uclinux_ram_mtdinfo = mtd; 89 90 add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS); 90 - 91 - printk("uclinux[mtd]: set %s to be root filesystem\n", 92 - uclinux_romfs[0].name); 93 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0); 94 91 95 92 return(0); 96 93 }
+232
drivers/mtd/mtdsuper.c
··· 1 + /* MTD-based superblock management 2 + * 3 + * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved. 4 + * Written by: David Howells <dhowells@redhat.com> 5 + * David Woodhouse <dwmw2@infradead.org> 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; either version 10 + * 2 of the License, or (at your option) any later version. 11 + */ 12 + 13 + #include <linux/mtd/super.h> 14 + #include <linux/namei.h> 15 + #include <linux/ctype.h> 16 + 17 + /* 18 + * compare superblocks to see if they're equivalent 19 + * - they are if the underlying MTD device is the same 20 + */ 21 + static int get_sb_mtd_compare(struct super_block *sb, void *_mtd) 22 + { 23 + struct mtd_info *mtd = _mtd; 24 + 25 + if (sb->s_mtd == mtd) { 26 + DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n", 27 + mtd->index, mtd->name); 28 + return 1; 29 + } 30 + 31 + DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n", 32 + sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name); 33 + return 0; 34 + } 35 + 36 + /* 37 + * mark the superblock by the MTD device it is using 38 + * - set the device number to be the correct MTD block device for pesuperstence 39 + * of NFS exports 40 + */ 41 + static int get_sb_mtd_set(struct super_block *sb, void *_mtd) 42 + { 43 + struct mtd_info *mtd = _mtd; 44 + 45 + sb->s_mtd = mtd; 46 + sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index); 47 + return 0; 48 + } 49 + 50 + /* 51 + * get a superblock on an MTD-backed filesystem 52 + */ 53 + static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, 54 + const char *dev_name, void *data, 55 + struct mtd_info *mtd, 56 + int (*fill_super)(struct super_block *, void *, int), 57 + struct vfsmount *mnt) 58 + { 59 + struct super_block *sb; 60 + int ret; 61 + 62 + sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd); 63 + if (IS_ERR(sb)) 64 + goto out_error; 65 + 66 + if (sb->s_root) 67 + goto already_mounted; 68 + 69 + /* fresh new superblock */ 70 + DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n", 71 + mtd->index, mtd->name); 72 + 73 + ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 74 + if (ret < 0) { 75 + up_write(&sb->s_umount); 76 + deactivate_super(sb); 77 + return ret; 78 + } 79 + 80 + /* go */ 81 + sb->s_flags |= MS_ACTIVE; 82 + return simple_set_mnt(mnt, sb); 83 + 84 + /* new mountpoint for an already mounted superblock */ 85 + already_mounted: 86 + DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n", 87 + mtd->index, mtd->name); 88 + ret = simple_set_mnt(mnt, sb); 89 + goto out_put; 90 + 91 + out_error: 92 + ret = PTR_ERR(sb); 93 + out_put: 94 + put_mtd_device(mtd); 95 + return ret; 96 + } 97 + 98 + /* 99 + * get a superblock on an MTD-backed filesystem by MTD device number 100 + */ 101 + static int get_sb_mtd_nr(struct file_system_type *fs_type, int flags, 102 + const char *dev_name, void *data, int mtdnr, 103 + int (*fill_super)(struct super_block *, void *, int), 104 + struct vfsmount *mnt) 105 + { 106 + struct mtd_info *mtd; 107 + 108 + mtd = get_mtd_device(NULL, mtdnr); 109 + if (IS_ERR(mtd)) { 110 + DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr); 111 + return PTR_ERR(mtd); 112 + } 113 + 114 + return get_sb_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super, 115 + mnt); 116 + } 117 + 118 + /* 119 + * set up an MTD-based superblock 120 + */ 121 + int get_sb_mtd(struct file_system_type *fs_type, int flags, 122 + const char *dev_name, void *data, 123 + int (*fill_super)(struct super_block *, void *, int), 124 + struct vfsmount *mnt) 125 + { 126 + struct nameidata nd; 127 + int mtdnr, ret; 128 + 129 + if (!dev_name) 130 + return -EINVAL; 131 + 132 + DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name); 133 + 134 + /* the preferred way of mounting in future; especially when 135 + * CONFIG_BLOCK=n - we specify the underlying MTD device by number or 136 + * by name, so that we don't require block device support to be present 137 + * in the kernel. */ 138 + if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { 139 + if (dev_name[3] == ':') { 140 + struct mtd_info *mtd; 141 + 142 + /* mount by MTD device name */ 143 + DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n", 144 + dev_name + 4); 145 + 146 + for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { 147 + mtd = get_mtd_device(NULL, mtdnr); 148 + if (!IS_ERR(mtd)) { 149 + if (!strcmp(mtd->name, dev_name + 4)) 150 + return get_sb_mtd_aux( 151 + fs_type, flags, 152 + dev_name, data, mtd, 153 + fill_super, mnt); 154 + 155 + put_mtd_device(mtd); 156 + } 157 + } 158 + 159 + printk(KERN_NOTICE "MTD:" 160 + " MTD device with name \"%s\" not found.\n", 161 + dev_name + 4); 162 + 163 + } else if (isdigit(dev_name[3])) { 164 + /* mount by MTD device number name */ 165 + char *endptr; 166 + 167 + mtdnr = simple_strtoul(dev_name + 3, &endptr, 0); 168 + if (!*endptr) { 169 + /* It was a valid number */ 170 + DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n", 171 + mtdnr); 172 + return get_sb_mtd_nr(fs_type, flags, 173 + dev_name, data, 174 + mtdnr, fill_super, mnt); 175 + } 176 + } 177 + } 178 + 179 + /* try the old way - the hack where we allowed users to mount 180 + * /dev/mtdblock$(n) but didn't actually _use_ the blockdev 181 + */ 182 + ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); 183 + 184 + DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n", 185 + ret, nd.dentry ? nd.dentry->d_inode : NULL); 186 + 187 + if (ret) 188 + return ret; 189 + 190 + ret = -EINVAL; 191 + 192 + if (!S_ISBLK(nd.dentry->d_inode->i_mode)) 193 + goto out; 194 + 195 + if (nd.mnt->mnt_flags & MNT_NODEV) { 196 + ret = -EACCES; 197 + goto out; 198 + } 199 + 200 + if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) 201 + goto not_an_MTD_device; 202 + 203 + mtdnr = iminor(nd.dentry->d_inode); 204 + path_release(&nd); 205 + 206 + return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, 207 + mnt); 208 + 209 + not_an_MTD_device: 210 + if (!(flags & MS_SILENT)) 211 + printk(KERN_NOTICE 212 + "MTD: Attempt to mount non-MTD device \"%s\"\n", 213 + dev_name); 214 + out: 215 + path_release(&nd); 216 + return ret; 217 + 218 + } 219 + 220 + EXPORT_SYMBOL_GPL(get_sb_mtd); 221 + 222 + /* 223 + * destroy an MTD-based superblock 224 + */ 225 + void kill_mtd_super(struct super_block *sb) 226 + { 227 + generic_shutdown_super(sb); 228 + put_mtd_device(sb->s_mtd); 229 + sb->s_mtd = NULL; 230 + } 231 + 232 + EXPORT_SYMBOL_GPL(kill_mtd_super);
+16 -6
fs/jffs2/readinode.c
··· 229 229 check anyway. */ 230 230 if (!tn->fn->size) { 231 231 if (rii->mdata_tn) { 232 - /* We had a candidate mdata node already */ 233 - dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); 234 - jffs2_kill_tn(c, rii->mdata_tn); 232 + if (rii->mdata_tn->version < tn->version) { 233 + /* We had a candidate mdata node already */ 234 + dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); 235 + jffs2_kill_tn(c, rii->mdata_tn); 236 + } else { 237 + dbg_readinode("kill new mdata with ver %d (older than existing %d\n", 238 + tn->version, rii->mdata_tn->version); 239 + jffs2_kill_tn(c, tn); 240 + return 0; 241 + } 235 242 } 236 243 rii->mdata_tn = tn; 237 244 dbg_readinode("keep new mdata with ver %d\n", tn->version); ··· 1051 1044 1052 1045 case JFFS2_NODETYPE_DIRENT: 1053 1046 1054 - if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { 1047 + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) && 1048 + len < sizeof(struct jffs2_raw_dirent)) { 1055 1049 err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); 1056 1050 if (unlikely(err)) 1057 1051 goto free_out; ··· 1066 1058 1067 1059 case JFFS2_NODETYPE_INODE: 1068 1060 1069 - if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { 1061 + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) && 1062 + len < sizeof(struct jffs2_raw_inode)) { 1070 1063 err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); 1071 1064 if (unlikely(err)) 1072 1065 goto free_out; ··· 1080 1071 break; 1081 1072 1082 1073 default: 1083 - if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { 1074 + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) && 1075 + len < sizeof(struct jffs2_unknown_node)) { 1084 1076 err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); 1085 1077 if (unlikely(err)) 1086 1078 goto free_out;
+19 -175
fs/jffs2/super.c
··· 19 19 #include <linux/mount.h> 20 20 #include <linux/jffs2.h> 21 21 #include <linux/pagemap.h> 22 - #include <linux/mtd/mtd.h> 22 + #include <linux/mtd/super.h> 23 23 #include <linux/ctype.h> 24 24 #include <linux/namei.h> 25 25 #include "compr.h" ··· 75 75 .sync_fs = jffs2_sync_fs, 76 76 }; 77 77 78 - static int jffs2_sb_compare(struct super_block *sb, void *data) 78 + /* 79 + * fill in the superblock 80 + */ 81 + static int jffs2_fill_super(struct super_block *sb, void *data, int silent) 79 82 { 80 - struct jffs2_sb_info *p = data; 81 - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 82 - 83 - /* The superblocks are considered to be equivalent if the underlying MTD 84 - device is the same one */ 85 - if (c->mtd == p->mtd) { 86 - D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); 87 - return 1; 88 - } else { 89 - D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", 90 - c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); 91 - return 0; 92 - } 93 - } 94 - 95 - static int jffs2_sb_set(struct super_block *sb, void *data) 96 - { 97 - struct jffs2_sb_info *p = data; 98 - 99 - /* For persistence of NFS exports etc. we use the same s_dev 100 - each time we mount the device, don't just use an anonymous 101 - device */ 102 - sb->s_fs_info = p; 103 - p->os_priv = sb; 104 - sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index); 105 - 106 - return 0; 107 - } 108 - 109 - static int jffs2_get_sb_mtd(struct file_system_type *fs_type, 110 - int flags, const char *dev_name, 111 - void *data, struct mtd_info *mtd, 112 - struct vfsmount *mnt) 113 - { 114 - struct super_block *sb; 115 83 struct jffs2_sb_info *c; 116 - int ret; 84 + 85 + D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():" 86 + " New superblock for device %d (\"%s\")\n", 87 + sb->s_mtd->index, sb->s_mtd->name)); 117 88 118 89 c = kzalloc(sizeof(*c), GFP_KERNEL); 119 90 if (!c) 120 91 return -ENOMEM; 121 - c->mtd = mtd; 122 92 123 - sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); 93 + c->mtd = sb->s_mtd; 94 + c->os_priv = sb; 95 + sb->s_fs_info = c; 124 96 125 - if (IS_ERR(sb)) 126 - goto out_error; 127 - 128 - if (sb->s_root) { 129 - /* New mountpoint for JFFS2 which is already mounted */ 130 - D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", 131 - mtd->index, mtd->name)); 132 - ret = simple_set_mnt(mnt, sb); 133 - goto out_put; 134 - } 135 - 136 - D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", 137 - mtd->index, mtd->name)); 138 - 139 - /* Initialize JFFS2 superblock locks, the further initialization will be 140 - * done later */ 97 + /* Initialize JFFS2 superblock locks, the further initialization will 98 + * be done later */ 141 99 init_MUTEX(&c->alloc_sem); 142 100 init_MUTEX(&c->erase_free_sem); 143 101 init_waitqueue_head(&c->erase_wait); ··· 104 146 spin_lock_init(&c->inocache_lock); 105 147 106 148 sb->s_op = &jffs2_super_operations; 107 - sb->s_flags = flags | MS_NOATIME; 149 + sb->s_flags = sb->s_flags | MS_NOATIME; 108 150 sb->s_xattr = jffs2_xattr_handlers; 109 151 #ifdef CONFIG_JFFS2_FS_POSIX_ACL 110 152 sb->s_flags |= MS_POSIXACL; 111 153 #endif 112 - ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 113 - 114 - if (ret) { 115 - /* Failure case... */ 116 - up_write(&sb->s_umount); 117 - deactivate_super(sb); 118 - return ret; 119 - } 120 - 121 - sb->s_flags |= MS_ACTIVE; 122 - return simple_set_mnt(mnt, sb); 123 - 124 - out_error: 125 - ret = PTR_ERR(sb); 126 - out_put: 127 - kfree(c); 128 - put_mtd_device(mtd); 129 - 130 - return ret; 131 - } 132 - 133 - static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type, 134 - int flags, const char *dev_name, 135 - void *data, int mtdnr, 136 - struct vfsmount *mnt) 137 - { 138 - struct mtd_info *mtd; 139 - 140 - mtd = get_mtd_device(NULL, mtdnr); 141 - if (IS_ERR(mtd)) { 142 - D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); 143 - return PTR_ERR(mtd); 144 - } 145 - 146 - return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); 154 + return jffs2_do_fill_super(sb, data, silent); 147 155 } 148 156 149 157 static int jffs2_get_sb(struct file_system_type *fs_type, 150 158 int flags, const char *dev_name, 151 159 void *data, struct vfsmount *mnt) 152 160 { 153 - int err; 154 - struct nameidata nd; 155 - int mtdnr; 156 - 157 - if (!dev_name) 158 - return -EINVAL; 159 - 160 - D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); 161 - 162 - /* The preferred way of mounting in future; especially when 163 - CONFIG_BLK_DEV is implemented - we specify the underlying 164 - MTD device by number or by name, so that we don't require 165 - block device support to be present in the kernel. */ 166 - 167 - /* FIXME: How to do the root fs this way? */ 168 - 169 - if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { 170 - /* Probably mounting without the blkdev crap */ 171 - if (dev_name[3] == ':') { 172 - struct mtd_info *mtd; 173 - 174 - /* Mount by MTD device name */ 175 - D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); 176 - for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { 177 - mtd = get_mtd_device(NULL, mtdnr); 178 - if (!IS_ERR(mtd)) { 179 - if (!strcmp(mtd->name, dev_name+4)) 180 - return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); 181 - put_mtd_device(mtd); 182 - } 183 - } 184 - printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); 185 - } else if (isdigit(dev_name[3])) { 186 - /* Mount by MTD device number name */ 187 - char *endptr; 188 - 189 - mtdnr = simple_strtoul(dev_name+3, &endptr, 0); 190 - if (!*endptr) { 191 - /* It was a valid number */ 192 - D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); 193 - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); 194 - } 195 - } 196 - } 197 - 198 - /* Try the old way - the hack where we allowed users to mount 199 - /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ 200 - 201 - err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); 202 - 203 - D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", 204 - err, nd.dentry->d_inode)); 205 - 206 - if (err) 207 - return err; 208 - 209 - err = -EINVAL; 210 - 211 - if (!S_ISBLK(nd.dentry->d_inode->i_mode)) 212 - goto out; 213 - 214 - if (nd.mnt->mnt_flags & MNT_NODEV) { 215 - err = -EACCES; 216 - goto out; 217 - } 218 - 219 - if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { 220 - if (!(flags & MS_SILENT)) 221 - printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", 222 - dev_name); 223 - goto out; 224 - } 225 - 226 - mtdnr = iminor(nd.dentry->d_inode); 227 - path_release(&nd); 228 - 229 - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); 230 - 231 - out: 232 - path_release(&nd); 233 - return err; 161 + return get_sb_mtd(fs_type, flags, dev_name, data, jffs2_fill_super, 162 + mnt); 234 163 } 235 164 236 165 static void jffs2_put_super (struct super_block *sb) ··· 152 307 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 153 308 if (!(sb->s_flags & MS_RDONLY)) 154 309 jffs2_stop_garbage_collect_thread(c); 155 - generic_shutdown_super(sb); 156 - put_mtd_device(c->mtd); 310 + kill_mtd_super(sb); 157 311 kfree(c); 158 312 } 159 313
+5 -1
fs/jffs2/xattr.c
··· 754 754 list_del(&xd->xindex); 755 755 jffs2_free_xattr_datum(xd); 756 756 } 757 + list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { 758 + list_del(&xd->xindex); 759 + jffs2_free_xattr_datum(xd); 760 + } 757 761 } 758 762 759 763 #define XREF_TMPHASH_SIZE (128) ··· 829 825 ref->xd and ref->ic are not valid yet. */ 830 826 xd = jffs2_find_xattr_datum(c, ref->xid); 831 827 ic = jffs2_get_ino_cache(c, ref->ino); 832 - if (!xd || !ic) { 828 + if (!xd || !ic || !ic->nlink) { 833 829 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", 834 830 ref->ino, ref->xid, ref->xseqno); 835 831 ref->xseqno |= XREF_DELETE_MARKER;
+1
include/linux/fs.h
··· 938 938 struct list_head s_files; 939 939 940 940 struct block_device *s_bdev; 941 + struct mtd_info *s_mtd; 941 942 struct list_head s_instances; 942 943 struct quota_info s_dquot; /* Diskquota specific options */ 943 944
+30
include/linux/mtd/super.h
··· 1 + /* MTD-based superblock handling 2 + * 3 + * Copyright © 2006 Red Hat, Inc. All Rights Reserved. 4 + * Written by David Howells (dhowells@redhat.com) 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the License, or (at your option) any later version. 10 + */ 11 + 12 + #ifndef __MTD_SUPER_H__ 13 + #define __MTD_SUPER_H__ 14 + 15 + #ifdef __KERNEL__ 16 + 17 + #include <linux/mtd/mtd.h> 18 + #include <linux/fs.h> 19 + #include <linux/mount.h> 20 + 21 + extern int get_sb_mtd(struct file_system_type *fs_type, int flags, 22 + const char *dev_name, void *data, 23 + int (*fill_super)(struct super_block *, void *, int), 24 + struct vfsmount *mnt); 25 + extern void kill_mtd_super(struct super_block *sb); 26 + 27 + 28 + #endif /* __KERNEL__ */ 29 + 30 + #endif /* __MTD_SUPER_H__ */