Blame view
drivers/mtd/mtdsuper.c
5.43 KB
acaebfd8a [MTD] generalise ... |
1 2 3 |
/* MTD-based superblock management * * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved. |
a1452a377 mtd: Update copyr... |
4 5 |
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org> * |
acaebfd8a [MTD] generalise ... |
6 7 8 9 10 11 12 13 14 15 16 17 |
* Written by: David Howells <dhowells@redhat.com> * David Woodhouse <dwmw2@infradead.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/mtd/super.h> #include <linux/namei.h> #include <linux/ctype.h> |
6de940025 Fix JFFS2 sync si... |
18 |
#include <linux/slab.h> |
acaebfd8a [MTD] generalise ... |
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
/* * compare superblocks to see if they're equivalent * - they are if the underlying MTD device is the same */ static int get_sb_mtd_compare(struct super_block *sb, void *_mtd) { struct mtd_info *mtd = _mtd; if (sb->s_mtd == mtd) { DEBUG(2, "MTDSB: Match on device %d (\"%s\") ", mtd->index, mtd->name); return 1; } DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\") ", sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name); return 0; } /* * mark the superblock by the MTD device it is using * - set the device number to be the correct MTD block device for pesuperstence * of NFS exports */ static int get_sb_mtd_set(struct super_block *sb, void *_mtd) { struct mtd_info *mtd = _mtd; sb->s_mtd = mtd; sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index); |
6de940025 Fix JFFS2 sync si... |
52 |
sb->s_bdi = mtd->backing_dev_info; |
acaebfd8a [MTD] generalise ... |
53 54 55 56 57 58 |
return 0; } /* * get a superblock on an MTD-backed filesystem */ |
848b83a59 convert get_sb_mt... |
59 |
static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags, |
acaebfd8a [MTD] generalise ... |
60 61 |
const char *dev_name, void *data, struct mtd_info *mtd, |
848b83a59 convert get_sb_mt... |
62 |
int (*fill_super)(struct super_block *, void *, int)) |
acaebfd8a [MTD] generalise ... |
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
{ struct super_block *sb; int ret; sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd); if (IS_ERR(sb)) goto out_error; if (sb->s_root) goto already_mounted; /* fresh new superblock */ DEBUG(1, "MTDSB: New superblock for device %d (\"%s\") ", mtd->index, mtd->name); |
48440e893 [MTD] Initialise ... |
78 |
sb->s_flags = flags; |
acaebfd8a [MTD] generalise ... |
79 80 |
ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (ret < 0) { |
6f5bbff9a Convert obvious p... |
81 |
deactivate_locked_super(sb); |
848b83a59 convert get_sb_mt... |
82 |
return ERR_PTR(ret); |
acaebfd8a [MTD] generalise ... |
83 84 85 86 |
} /* go */ sb->s_flags |= MS_ACTIVE; |
848b83a59 convert get_sb_mt... |
87 |
return dget(sb->s_root); |
acaebfd8a [MTD] generalise ... |
88 89 90 91 92 93 |
/* new mountpoint for an already mounted superblock */ already_mounted: DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted ", mtd->index, mtd->name); |
848b83a59 convert get_sb_mt... |
94 95 |
put_mtd_device(mtd); return dget(sb->s_root); |
acaebfd8a [MTD] generalise ... |
96 97 |
out_error: |
acaebfd8a [MTD] generalise ... |
98 |
put_mtd_device(mtd); |
848b83a59 convert get_sb_mt... |
99 |
return ERR_CAST(sb); |
acaebfd8a [MTD] generalise ... |
100 101 102 103 104 |
} /* * get a superblock on an MTD-backed filesystem by MTD device number */ |
848b83a59 convert get_sb_mt... |
105 |
static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags, |
acaebfd8a [MTD] generalise ... |
106 |
const char *dev_name, void *data, int mtdnr, |
848b83a59 convert get_sb_mt... |
107 |
int (*fill_super)(struct super_block *, void *, int)) |
acaebfd8a [MTD] generalise ... |
108 109 110 111 |
{ struct mtd_info *mtd; mtd = get_mtd_device(NULL, mtdnr); |
718ea8361 [MTD] Fix error c... |
112 |
if (IS_ERR(mtd)) { |
acaebfd8a [MTD] generalise ... |
113 114 |
DEBUG(0, "MTDSB: Device #%u doesn't appear to exist ", mtdnr); |
848b83a59 convert get_sb_mt... |
115 |
return ERR_CAST(mtd); |
acaebfd8a [MTD] generalise ... |
116 |
} |
848b83a59 convert get_sb_mt... |
117 |
return mount_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super); |
acaebfd8a [MTD] generalise ... |
118 119 120 121 122 |
} /* * set up an MTD-based superblock */ |
848b83a59 convert get_sb_mt... |
123 |
struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, |
acaebfd8a [MTD] generalise ... |
124 |
const char *dev_name, void *data, |
848b83a59 convert get_sb_mt... |
125 |
int (*fill_super)(struct super_block *, void *, int)) |
acaebfd8a [MTD] generalise ... |
126 |
{ |
f1136d022 [MTD] Fix !CONFIG... |
127 |
#ifdef CONFIG_BLOCK |
d5686b444 [PATCH] switch mt... |
128 |
struct block_device *bdev; |
f1136d022 [MTD] Fix !CONFIG... |
129 130 131 |
int ret, major; #endif int mtdnr; |
acaebfd8a [MTD] generalise ... |
132 133 |
if (!dev_name) |
848b83a59 convert get_sb_mt... |
134 |
return ERR_PTR(-EINVAL); |
acaebfd8a [MTD] generalise ... |
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
DEBUG(2, "MTDSB: dev_name \"%s\" ", dev_name); /* the preferred way of mounting in future; especially when * CONFIG_BLOCK=n - we specify the underlying MTD device by number or * by name, so that we don't require block device support to be present * in the kernel. */ if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { if (dev_name[3] == ':') { struct mtd_info *mtd; /* mount by MTD device name */ DEBUG(1, "MTDSB: mtd:%%s, name \"%s\" ", dev_name + 4); |
677c2aec8 mtd: Use get_mtd_... |
151 152 |
mtd = get_mtd_device_nm(dev_name + 4); if (!IS_ERR(mtd)) |
848b83a59 convert get_sb_mt... |
153 |
return mount_mtd_aux( |
677c2aec8 mtd: Use get_mtd_... |
154 155 |
fs_type, flags, dev_name, data, mtd, |
848b83a59 convert get_sb_mt... |
156 |
fill_super); |
acaebfd8a [MTD] generalise ... |
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
printk(KERN_NOTICE "MTD:" " MTD device with name \"%s\" not found. ", dev_name + 4); } else if (isdigit(dev_name[3])) { /* mount by MTD device number name */ char *endptr; mtdnr = simple_strtoul(dev_name + 3, &endptr, 0); if (!*endptr) { /* It was a valid number */ DEBUG(1, "MTDSB: mtd%%d, mtdnr %d ", mtdnr); |
848b83a59 convert get_sb_mt... |
173 |
return mount_mtd_nr(fs_type, flags, |
acaebfd8a [MTD] generalise ... |
174 |
dev_name, data, |
848b83a59 convert get_sb_mt... |
175 |
mtdnr, fill_super); |
acaebfd8a [MTD] generalise ... |
176 177 178 |
} } } |
f1136d022 [MTD] Fix !CONFIG... |
179 |
#ifdef CONFIG_BLOCK |
acaebfd8a [MTD] generalise ... |
180 181 182 |
/* try the old way - the hack where we allowed users to mount * /dev/mtdblock$(n) but didn't actually _use_ the blockdev */ |
d5686b444 [PATCH] switch mt... |
183 184 185 186 187 |
bdev = lookup_bdev(dev_name); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); DEBUG(1, "MTDSB: lookup_bdev() returned %d ", ret); |
848b83a59 convert get_sb_mt... |
188 |
return ERR_PTR(ret); |
acaebfd8a [MTD] generalise ... |
189 |
} |
d5686b444 [PATCH] switch mt... |
190 191 |
DEBUG(1, "MTDSB: lookup_bdev() returned 0 "); |
acaebfd8a [MTD] generalise ... |
192 |
|
d5686b444 [PATCH] switch mt... |
193 |
ret = -EINVAL; |
acaebfd8a [MTD] generalise ... |
194 |
|
f1136d022 [MTD] Fix !CONFIG... |
195 |
major = MAJOR(bdev->bd_dev); |
d5686b444 [PATCH] switch mt... |
196 197 |
mtdnr = MINOR(bdev->bd_dev); bdput(bdev); |
acaebfd8a [MTD] generalise ... |
198 |
|
f1136d022 [MTD] Fix !CONFIG... |
199 200 |
if (major != MTD_BLOCK_MAJOR) goto not_an_MTD_device; |
848b83a59 convert get_sb_mt... |
201 |
return mount_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super); |
acaebfd8a [MTD] generalise ... |
202 203 |
not_an_MTD_device: |
f1136d022 [MTD] Fix !CONFIG... |
204 |
#endif /* CONFIG_BLOCK */ |
acaebfd8a [MTD] generalise ... |
205 206 207 208 209 |
if (!(flags & MS_SILENT)) printk(KERN_NOTICE "MTD: Attempt to mount non-MTD device \"%s\" ", dev_name); |
848b83a59 convert get_sb_mt... |
210 |
return ERR_PTR(-EINVAL); |
acaebfd8a [MTD] generalise ... |
211 |
} |
848b83a59 convert get_sb_mt... |
212 |
EXPORT_SYMBOL_GPL(mount_mtd); |
acaebfd8a [MTD] generalise ... |
213 214 215 216 217 218 219 220 221 222 223 224 |
/* * destroy an MTD-based superblock */ void kill_mtd_super(struct super_block *sb) { generic_shutdown_super(sb); put_mtd_device(sb->s_mtd); sb->s_mtd = NULL; } EXPORT_SYMBOL_GPL(kill_mtd_super); |