Blame view
drivers/mtd/mtdsuper.c
5.53 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 |
* 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> |
f3bcc0179 mtd: Add export.h... |
17 |
#include <linux/export.h> |
acaebfd8a [MTD] generalise ... |
18 |
#include <linux/ctype.h> |
6de940025 Fix JFFS2 sync si... |
19 |
#include <linux/slab.h> |
f83c3838b mtd: Move major n... |
20 |
#include <linux/major.h> |
fa06052d6 mtd: Convert to d... |
21 |
#include <linux/backing-dev.h> |
acaebfd8a [MTD] generalise ... |
22 23 24 25 26 27 28 29 30 31 |
/* * 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) { |
289c05222 mtd: replace DEBU... |
32 33 |
pr_debug("MTDSB: Match on device %d (\"%s\") ", |
acaebfd8a [MTD] generalise ... |
34 35 36 |
mtd->index, mtd->name); return 1; } |
289c05222 mtd: replace DEBU... |
37 38 |
pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\") ", |
acaebfd8a [MTD] generalise ... |
39 40 41 |
sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name); return 0; } |
fa06052d6 mtd: Convert to d... |
42 |
extern struct backing_dev_info *mtd_bdi; |
acaebfd8a [MTD] generalise ... |
43 44 45 46 47 48 49 50 51 52 53 |
/* * 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); |
fa06052d6 mtd: Convert to d... |
54 |
sb->s_bdi = bdi_get(mtd_bdi); |
fa06052d6 mtd: Convert to d... |
55 |
|
acaebfd8a [MTD] generalise ... |
56 57 58 59 60 61 |
return 0; } /* * get a superblock on an MTD-backed filesystem */ |
848b83a59 convert get_sb_mt... |
62 |
static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags, |
acaebfd8a [MTD] generalise ... |
63 64 |
const char *dev_name, void *data, struct mtd_info *mtd, |
848b83a59 convert get_sb_mt... |
65 |
int (*fill_super)(struct super_block *, void *, int)) |
acaebfd8a [MTD] generalise ... |
66 67 68 |
{ struct super_block *sb; int ret; |
9249e17fe VFS: Pass mount f... |
69 |
sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, flags, mtd); |
acaebfd8a [MTD] generalise ... |
70 71 72 73 74 75 76 |
if (IS_ERR(sb)) goto out_error; if (sb->s_root) goto already_mounted; /* fresh new superblock */ |
289c05222 mtd: replace DEBU... |
77 78 |
pr_debug("MTDSB: New superblock for device %d (\"%s\") ", |
acaebfd8a [MTD] generalise ... |
79 80 81 82 |
mtd->index, mtd->name); ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (ret < 0) { |
6f5bbff9a Convert obvious p... |
83 |
deactivate_locked_super(sb); |
848b83a59 convert get_sb_mt... |
84 |
return ERR_PTR(ret); |
acaebfd8a [MTD] generalise ... |
85 86 87 88 |
} /* go */ sb->s_flags |= MS_ACTIVE; |
848b83a59 convert get_sb_mt... |
89 |
return dget(sb->s_root); |
acaebfd8a [MTD] generalise ... |
90 91 92 |
/* new mountpoint for an already mounted superblock */ already_mounted: |
289c05222 mtd: replace DEBU... |
93 94 |
pr_debug("MTDSB: Device %d (\"%s\") is already mounted ", |
acaebfd8a [MTD] generalise ... |
95 |
mtd->index, mtd->name); |
848b83a59 convert get_sb_mt... |
96 97 |
put_mtd_device(mtd); return dget(sb->s_root); |
acaebfd8a [MTD] generalise ... |
98 99 |
out_error: |
acaebfd8a [MTD] generalise ... |
100 |
put_mtd_device(mtd); |
848b83a59 convert get_sb_mt... |
101 |
return ERR_CAST(sb); |
acaebfd8a [MTD] generalise ... |
102 103 104 105 106 |
} /* * get a superblock on an MTD-backed filesystem by MTD device number */ |
848b83a59 convert get_sb_mt... |
107 |
static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags, |
acaebfd8a [MTD] generalise ... |
108 |
const char *dev_name, void *data, int mtdnr, |
848b83a59 convert get_sb_mt... |
109 |
int (*fill_super)(struct super_block *, void *, int)) |
acaebfd8a [MTD] generalise ... |
110 111 112 113 |
{ struct mtd_info *mtd; mtd = get_mtd_device(NULL, mtdnr); |
718ea8361 [MTD] Fix error c... |
114 |
if (IS_ERR(mtd)) { |
289c05222 mtd: replace DEBU... |
115 116 |
pr_debug("MTDSB: Device #%u doesn't appear to exist ", mtdnr); |
848b83a59 convert get_sb_mt... |
117 |
return ERR_CAST(mtd); |
acaebfd8a [MTD] generalise ... |
118 |
} |
848b83a59 convert get_sb_mt... |
119 |
return mount_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super); |
acaebfd8a [MTD] generalise ... |
120 121 122 123 124 |
} /* * set up an MTD-based superblock */ |
848b83a59 convert get_sb_mt... |
125 |
struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, |
acaebfd8a [MTD] generalise ... |
126 |
const char *dev_name, void *data, |
848b83a59 convert get_sb_mt... |
127 |
int (*fill_super)(struct super_block *, void *, int)) |
acaebfd8a [MTD] generalise ... |
128 |
{ |
f1136d022 [MTD] Fix !CONFIG... |
129 |
#ifdef CONFIG_BLOCK |
d5686b444 [PATCH] switch mt... |
130 |
struct block_device *bdev; |
f1136d022 [MTD] Fix !CONFIG... |
131 132 133 |
int ret, major; #endif int mtdnr; |
acaebfd8a [MTD] generalise ... |
134 135 |
if (!dev_name) |
848b83a59 convert get_sb_mt... |
136 |
return ERR_PTR(-EINVAL); |
acaebfd8a [MTD] generalise ... |
137 |
|
289c05222 mtd: replace DEBU... |
138 139 |
pr_debug("MTDSB: dev_name \"%s\" ", dev_name); |
acaebfd8a [MTD] generalise ... |
140 141 142 143 144 145 146 147 148 149 |
/* 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 */ |
289c05222 mtd: replace DEBU... |
150 151 |
pr_debug("MTDSB: mtd:%%s, name \"%s\" ", |
acaebfd8a [MTD] generalise ... |
152 |
dev_name + 4); |
677c2aec8 mtd: Use get_mtd_... |
153 154 |
mtd = get_mtd_device_nm(dev_name + 4); if (!IS_ERR(mtd)) |
848b83a59 convert get_sb_mt... |
155 |
return mount_mtd_aux( |
677c2aec8 mtd: Use get_mtd_... |
156 157 |
fs_type, flags, dev_name, data, mtd, |
848b83a59 convert get_sb_mt... |
158 |
fill_super); |
acaebfd8a [MTD] generalise ... |
159 160 161 162 163 164 165 166 167 168 169 170 171 |
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 */ |
289c05222 mtd: replace DEBU... |
172 173 |
pr_debug("MTDSB: mtd%%d, mtdnr %d ", |
acaebfd8a [MTD] generalise ... |
174 |
mtdnr); |
848b83a59 convert get_sb_mt... |
175 |
return mount_mtd_nr(fs_type, flags, |
acaebfd8a [MTD] generalise ... |
176 |
dev_name, data, |
848b83a59 convert get_sb_mt... |
177 |
mtdnr, fill_super); |
acaebfd8a [MTD] generalise ... |
178 179 180 |
} } } |
f1136d022 [MTD] Fix !CONFIG... |
181 |
#ifdef CONFIG_BLOCK |
acaebfd8a [MTD] generalise ... |
182 183 184 |
/* 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... |
185 186 187 |
bdev = lookup_bdev(dev_name); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); |
289c05222 mtd: replace DEBU... |
188 189 |
pr_debug("MTDSB: lookup_bdev() returned %d ", ret); |
848b83a59 convert get_sb_mt... |
190 |
return ERR_PTR(ret); |
acaebfd8a [MTD] generalise ... |
191 |
} |
289c05222 mtd: replace DEBU... |
192 193 |
pr_debug("MTDSB: lookup_bdev() returned 0 "); |
acaebfd8a [MTD] generalise ... |
194 |
|
d5686b444 [PATCH] switch mt... |
195 |
ret = -EINVAL; |
acaebfd8a [MTD] generalise ... |
196 |
|
f1136d022 [MTD] Fix !CONFIG... |
197 |
major = MAJOR(bdev->bd_dev); |
d5686b444 [PATCH] switch mt... |
198 199 |
mtdnr = MINOR(bdev->bd_dev); bdput(bdev); |
acaebfd8a [MTD] generalise ... |
200 |
|
f1136d022 [MTD] Fix !CONFIG... |
201 202 |
if (major != MTD_BLOCK_MAJOR) goto not_an_MTD_device; |
848b83a59 convert get_sb_mt... |
203 |
return mount_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super); |
acaebfd8a [MTD] generalise ... |
204 205 |
not_an_MTD_device: |
f1136d022 [MTD] Fix !CONFIG... |
206 |
#endif /* CONFIG_BLOCK */ |
acaebfd8a [MTD] generalise ... |
207 208 209 210 211 |
if (!(flags & MS_SILENT)) printk(KERN_NOTICE "MTD: Attempt to mount non-MTD device \"%s\" ", dev_name); |
848b83a59 convert get_sb_mt... |
212 |
return ERR_PTR(-EINVAL); |
acaebfd8a [MTD] generalise ... |
213 |
} |
848b83a59 convert get_sb_mt... |
214 |
EXPORT_SYMBOL_GPL(mount_mtd); |
acaebfd8a [MTD] generalise ... |
215 216 217 218 219 220 221 222 223 224 225 226 |
/* * 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); |