hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/mtd/mtdsuper.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* MTD-based superblock management
23 *
34 * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
....@@ -5,11 +6,6 @@
56 *
67 * Written by: David Howells <dhowells@redhat.com>
78 * David Woodhouse <dwmw2@infradead.org>
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License
11
- * as published by the Free Software Foundation; either version
12
- * 2 of the License, or (at your option) any later version.
139 */
1410
1511 #include <linux/mtd/super.h>
....@@ -19,112 +15,109 @@
1915 #include <linux/slab.h>
2016 #include <linux/major.h>
2117 #include <linux/backing-dev.h>
18
+#include <linux/fs_context.h>
19
+#include "mtdcore.h"
2220
2321 /*
2422 * compare superblocks to see if they're equivalent
2523 * - they are if the underlying MTD device is the same
2624 */
27
-static int get_sb_mtd_compare(struct super_block *sb, void *_mtd)
25
+static int mtd_test_super(struct super_block *sb, struct fs_context *fc)
2826 {
29
- struct mtd_info *mtd = _mtd;
27
+ struct mtd_info *mtd = fc->sget_key;
3028
31
- if (sb->s_mtd == mtd) {
29
+ if (sb->s_mtd == fc->sget_key) {
3230 pr_debug("MTDSB: Match on device %d (\"%s\")\n",
33
- mtd->index, mtd->name);
31
+ mtd->index, mtd->name);
3432 return 1;
3533 }
3634
3735 pr_debug("MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
38
- sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
36
+ sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
3937 return 0;
4038 }
41
-
42
-extern struct backing_dev_info *mtd_bdi;
4339
4440 /*
4541 * mark the superblock by the MTD device it is using
4642 * - set the device number to be the correct MTD block device for pesuperstence
4743 * of NFS exports
4844 */
49
-static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
45
+static int mtd_set_super(struct super_block *sb, struct fs_context *fc)
5046 {
51
- struct mtd_info *mtd = _mtd;
52
-
53
- sb->s_mtd = mtd;
54
- sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
47
+ sb->s_mtd = fc->sget_key;
48
+ sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
5549 sb->s_bdi = bdi_get(mtd_bdi);
56
-
5750 return 0;
5851 }
5952
6053 /*
6154 * get a superblock on an MTD-backed filesystem
6255 */
63
-static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
64
- const char *dev_name, void *data,
65
- struct mtd_info *mtd,
66
- int (*fill_super)(struct super_block *, void *, int))
56
+static int mtd_get_sb(struct fs_context *fc,
57
+ struct mtd_info *mtd,
58
+ int (*fill_super)(struct super_block *,
59
+ struct fs_context *))
6760 {
6861 struct super_block *sb;
6962 int ret;
7063
71
- sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, flags, mtd);
64
+ fc->sget_key = mtd;
65
+ sb = sget_fc(fc, mtd_test_super, mtd_set_super);
7266 if (IS_ERR(sb))
73
- goto out_error;
67
+ return PTR_ERR(sb);
7468
75
- if (sb->s_root)
76
- goto already_mounted;
69
+ if (sb->s_root) {
70
+ /* new mountpoint for an already mounted superblock */
71
+ pr_debug("MTDSB: Device %d (\"%s\") is already mounted\n",
72
+ mtd->index, mtd->name);
73
+ put_mtd_device(mtd);
74
+ } else {
75
+ /* fresh new superblock */
76
+ pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
77
+ mtd->index, mtd->name);
7778
78
- /* fresh new superblock */
79
- pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
80
- mtd->index, mtd->name);
79
+ ret = fill_super(sb, fc);
80
+ if (ret < 0)
81
+ goto error_sb;
8182
82
- ret = fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
83
- if (ret < 0) {
84
- deactivate_locked_super(sb);
85
- return ERR_PTR(ret);
83
+ sb->s_flags |= SB_ACTIVE;
8684 }
8785
88
- /* go */
89
- sb->s_flags |= SB_ACTIVE;
90
- return dget(sb->s_root);
86
+ BUG_ON(fc->root);
87
+ fc->root = dget(sb->s_root);
88
+ return 0;
9189
92
- /* new mountpoint for an already mounted superblock */
93
-already_mounted:
94
- pr_debug("MTDSB: Device %d (\"%s\") is already mounted\n",
95
- mtd->index, mtd->name);
96
- put_mtd_device(mtd);
97
- return dget(sb->s_root);
98
-
99
-out_error:
100
- put_mtd_device(mtd);
101
- return ERR_CAST(sb);
90
+error_sb:
91
+ deactivate_locked_super(sb);
92
+ return ret;
10293 }
10394
10495 /*
10596 * get a superblock on an MTD-backed filesystem by MTD device number
10697 */
107
-static struct dentry *mount_mtd_nr(struct file_system_type *fs_type, int flags,
108
- const char *dev_name, void *data, int mtdnr,
109
- int (*fill_super)(struct super_block *, void *, int))
98
+static int mtd_get_sb_by_nr(struct fs_context *fc, int mtdnr,
99
+ int (*fill_super)(struct super_block *,
100
+ struct fs_context *))
110101 {
111102 struct mtd_info *mtd;
112103
113104 mtd = get_mtd_device(NULL, mtdnr);
114105 if (IS_ERR(mtd)) {
115
- pr_debug("MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
116
- return ERR_CAST(mtd);
106
+ errorf(fc, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
107
+ return PTR_ERR(mtd);
117108 }
118109
119
- return mount_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super);
110
+ return mtd_get_sb(fc, mtd, fill_super);
120111 }
121112
122
-/*
123
- * set up an MTD-based superblock
113
+/**
114
+ * get_tree_mtd - Get a superblock based on a single MTD device
115
+ * @fc: The filesystem context holding the parameters
116
+ * @fill_super: Helper to initialise a new superblock
124117 */
125
-struct dentry *mount_mtd(struct file_system_type *fs_type, int flags,
126
- const char *dev_name, void *data,
127
- int (*fill_super)(struct super_block *, void *, int))
118
+int get_tree_mtd(struct fs_context *fc,
119
+ int (*fill_super)(struct super_block *sb,
120
+ struct fs_context *fc))
128121 {
129122 #ifdef CONFIG_BLOCK
130123 struct block_device *bdev;
....@@ -132,46 +125,42 @@
132125 #endif
133126 int mtdnr;
134127
135
- if (!dev_name)
136
- return ERR_PTR(-EINVAL);
128
+ if (!fc->source)
129
+ return invalf(fc, "No source specified");
137130
138
- pr_debug("MTDSB: dev_name \"%s\"\n", dev_name);
131
+ pr_debug("MTDSB: dev_name \"%s\"\n", fc->source);
139132
140133 /* the preferred way of mounting in future; especially when
141134 * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
142135 * by name, so that we don't require block device support to be present
143
- * in the kernel. */
144
- if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
145
- if (dev_name[3] == ':') {
136
+ * in the kernel.
137
+ */
138
+ if (fc->source[0] == 'm' &&
139
+ fc->source[1] == 't' &&
140
+ fc->source[2] == 'd') {
141
+ if (fc->source[3] == ':') {
146142 struct mtd_info *mtd;
147143
148144 /* mount by MTD device name */
149145 pr_debug("MTDSB: mtd:%%s, name \"%s\"\n",
150
- dev_name + 4);
146
+ fc->source + 4);
151147
152
- mtd = get_mtd_device_nm(dev_name + 4);
148
+ mtd = get_mtd_device_nm(fc->source + 4);
153149 if (!IS_ERR(mtd))
154
- return mount_mtd_aux(
155
- fs_type, flags,
156
- dev_name, data, mtd,
157
- fill_super);
150
+ return mtd_get_sb(fc, mtd, fill_super);
158151
159
- printk(KERN_NOTICE "MTD:"
160
- " MTD device with name \"%s\" not found.\n",
161
- dev_name + 4);
152
+ errorf(fc, "MTD: MTD device with name \"%s\" not found",
153
+ fc->source + 4);
162154
163
- } else if (isdigit(dev_name[3])) {
155
+ } else if (isdigit(fc->source[3])) {
164156 /* mount by MTD device number name */
165157 char *endptr;
166158
167
- mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
159
+ mtdnr = simple_strtoul(fc->source + 3, &endptr, 0);
168160 if (!*endptr) {
169161 /* It was a valid number */
170
- pr_debug("MTDSB: mtd%%d, mtdnr %d\n",
171
- mtdnr);
172
- return mount_mtd_nr(fs_type, flags,
173
- dev_name, data,
174
- mtdnr, fill_super);
162
+ pr_debug("MTDSB: mtd%%d, mtdnr %d\n", mtdnr);
163
+ return mtd_get_sb_by_nr(fc, mtdnr, fill_super);
175164 }
176165 }
177166 }
....@@ -180,36 +169,29 @@
180169 /* try the old way - the hack where we allowed users to mount
181170 * /dev/mtdblock$(n) but didn't actually _use_ the blockdev
182171 */
183
- bdev = lookup_bdev(dev_name);
172
+ bdev = lookup_bdev(fc->source);
184173 if (IS_ERR(bdev)) {
185174 ret = PTR_ERR(bdev);
186
- pr_debug("MTDSB: lookup_bdev() returned %d\n", ret);
187
- return ERR_PTR(ret);
175
+ errorf(fc, "MTD: Couldn't look up '%s': %d", fc->source, ret);
176
+ return ret;
188177 }
189178 pr_debug("MTDSB: lookup_bdev() returned 0\n");
190
-
191
- ret = -EINVAL;
192179
193180 major = MAJOR(bdev->bd_dev);
194181 mtdnr = MINOR(bdev->bd_dev);
195182 bdput(bdev);
196183
197
- if (major != MTD_BLOCK_MAJOR)
198
- goto not_an_MTD_device;
184
+ if (major == MTD_BLOCK_MAJOR)
185
+ return mtd_get_sb_by_nr(fc, mtdnr, fill_super);
199186
200
- return mount_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super);
201
-
202
-not_an_MTD_device:
203187 #endif /* CONFIG_BLOCK */
204188
205
- if (!(flags & SB_SILENT))
206
- printk(KERN_NOTICE
207
- "MTD: Attempt to mount non-MTD device \"%s\"\n",
208
- dev_name);
209
- return ERR_PTR(-EINVAL);
189
+ if (!(fc->sb_flags & SB_SILENT))
190
+ errorf(fc, "MTD: Attempt to mount non-MTD device \"%s\"",
191
+ fc->source);
192
+ return -EINVAL;
210193 }
211
-
212
-EXPORT_SYMBOL_GPL(mount_mtd);
194
+EXPORT_SYMBOL_GPL(get_tree_mtd);
213195
214196 /*
215197 * destroy an MTD-based superblock