1 | /* |
2 | * block2mtd.c - create an mtd from a block device |
3 | * |
4 | * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk> |
5 | * Copyright (C) 2004-2006 Joern Engel <joern@wh.fh-wedel.de> |
6 | * |
7 | * Licence: GPL |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | |
12 | /* |
13 | * When the first attempt at device initialization fails, we may need to |
14 | * wait a little bit and retry. This timeout, by default 3 seconds, gives |
15 | * device time to start up. Required on BCM2708 and a few other chipsets. |
16 | */ |
17 | #define MTD_DEFAULT_TIMEOUT 3 |
18 | |
19 | #include <linux/module.h> |
20 | #include <linux/delay.h> |
21 | #include <linux/fs.h> |
22 | #include <linux/blkdev.h> |
23 | #include <linux/backing-dev.h> |
24 | #include <linux/bio.h> |
25 | #include <linux/pagemap.h> |
26 | #include <linux/list.h> |
27 | #include <linux/init.h> |
28 | #include <linux/mtd/mtd.h> |
29 | #include <linux/mutex.h> |
30 | #include <linux/mount.h> |
31 | #include <linux/slab.h> |
32 | #include <linux/major.h> |
33 | |
34 | /* Maximum number of comma-separated items in the 'block2mtd=' parameter */ |
35 | #define BLOCK2MTD_PARAM_MAX_COUNT 3 |
36 | |
37 | /* Info for the block device */ |
38 | struct block2mtd_dev { |
39 | struct list_head list; |
40 | struct file *bdev_file; |
41 | struct mtd_info mtd; |
42 | struct mutex write_mutex; |
43 | }; |
44 | |
45 | |
46 | /* Static info about the MTD, used in cleanup_module */ |
47 | static LIST_HEAD(blkmtd_device_list); |
48 | |
49 | |
50 | static struct page *page_read(struct address_space *mapping, pgoff_t index) |
51 | { |
52 | return read_mapping_page(mapping, index, NULL); |
53 | } |
54 | |
55 | /* erase a specified part of the device */ |
56 | static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) |
57 | { |
58 | struct address_space *mapping = dev->bdev_file->f_mapping; |
59 | struct page *page; |
60 | pgoff_t index = to >> PAGE_SHIFT; // page index |
61 | int pages = len >> PAGE_SHIFT; |
62 | u_long *p; |
63 | u_long *max; |
64 | |
65 | while (pages) { |
66 | page = page_read(mapping, index); |
67 | if (IS_ERR(ptr: page)) |
68 | return PTR_ERR(ptr: page); |
69 | |
70 | max = page_address(page) + PAGE_SIZE; |
71 | for (p=page_address(page); p<max; p++) |
72 | if (*p != -1UL) { |
73 | lock_page(page); |
74 | memset(page_address(page), 0xff, PAGE_SIZE); |
75 | set_page_dirty(page); |
76 | unlock_page(page); |
77 | balance_dirty_pages_ratelimited(mapping); |
78 | break; |
79 | } |
80 | |
81 | put_page(page); |
82 | pages--; |
83 | index++; |
84 | } |
85 | return 0; |
86 | } |
87 | static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) |
88 | { |
89 | struct block2mtd_dev *dev = mtd->priv; |
90 | size_t from = instr->addr; |
91 | size_t len = instr->len; |
92 | int err; |
93 | |
94 | mutex_lock(&dev->write_mutex); |
95 | err = _block2mtd_erase(dev, to: from, len); |
96 | mutex_unlock(lock: &dev->write_mutex); |
97 | if (err) |
98 | pr_err("erase failed err = %d\n" , err); |
99 | |
100 | return err; |
101 | } |
102 | |
103 | |
104 | static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, |
105 | size_t *retlen, u_char *buf) |
106 | { |
107 | struct block2mtd_dev *dev = mtd->priv; |
108 | struct address_space *mapping = dev->bdev_file->f_mapping; |
109 | struct page *page; |
110 | pgoff_t index = from >> PAGE_SHIFT; |
111 | int offset = from & (PAGE_SIZE-1); |
112 | int cpylen; |
113 | |
114 | while (len) { |
115 | if ((offset + len) > PAGE_SIZE) |
116 | cpylen = PAGE_SIZE - offset; // multiple pages |
117 | else |
118 | cpylen = len; // this page |
119 | len = len - cpylen; |
120 | |
121 | page = page_read(mapping, index); |
122 | if (IS_ERR(ptr: page)) |
123 | return PTR_ERR(ptr: page); |
124 | |
125 | memcpy(buf, page_address(page) + offset, cpylen); |
126 | put_page(page); |
127 | |
128 | if (retlen) |
129 | *retlen += cpylen; |
130 | buf += cpylen; |
131 | offset = 0; |
132 | index++; |
133 | } |
134 | return 0; |
135 | } |
136 | |
137 | |
138 | /* write data to the underlying device */ |
139 | static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, |
140 | loff_t to, size_t len, size_t *retlen) |
141 | { |
142 | struct page *page; |
143 | struct address_space *mapping = dev->bdev_file->f_mapping; |
144 | pgoff_t index = to >> PAGE_SHIFT; // page index |
145 | int offset = to & ~PAGE_MASK; // page offset |
146 | int cpylen; |
147 | |
148 | while (len) { |
149 | if ((offset+len) > PAGE_SIZE) |
150 | cpylen = PAGE_SIZE - offset; // multiple pages |
151 | else |
152 | cpylen = len; // this page |
153 | len = len - cpylen; |
154 | |
155 | page = page_read(mapping, index); |
156 | if (IS_ERR(ptr: page)) |
157 | return PTR_ERR(ptr: page); |
158 | |
159 | if (memcmp(page_address(page)+offset, q: buf, size: cpylen)) { |
160 | lock_page(page); |
161 | memcpy(page_address(page) + offset, buf, cpylen); |
162 | set_page_dirty(page); |
163 | unlock_page(page); |
164 | balance_dirty_pages_ratelimited(mapping); |
165 | } |
166 | put_page(page); |
167 | |
168 | if (retlen) |
169 | *retlen += cpylen; |
170 | |
171 | buf += cpylen; |
172 | offset = 0; |
173 | index++; |
174 | } |
175 | return 0; |
176 | } |
177 | |
178 | |
179 | static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, |
180 | size_t *retlen, const u_char *buf) |
181 | { |
182 | struct block2mtd_dev *dev = mtd->priv; |
183 | int err; |
184 | |
185 | mutex_lock(&dev->write_mutex); |
186 | err = _block2mtd_write(dev, buf, to, len, retlen); |
187 | mutex_unlock(lock: &dev->write_mutex); |
188 | if (err > 0) |
189 | err = 0; |
190 | return err; |
191 | } |
192 | |
193 | |
194 | /* sync the device - wait until the write queue is empty */ |
195 | static void block2mtd_sync(struct mtd_info *mtd) |
196 | { |
197 | struct block2mtd_dev *dev = mtd->priv; |
198 | sync_blockdev(bdev: file_bdev(bdev_file: dev->bdev_file)); |
199 | return; |
200 | } |
201 | |
202 | |
203 | static void block2mtd_free_device(struct block2mtd_dev *dev) |
204 | { |
205 | if (!dev) |
206 | return; |
207 | |
208 | kfree(objp: dev->mtd.name); |
209 | |
210 | if (dev->bdev_file) { |
211 | invalidate_mapping_pages(mapping: dev->bdev_file->f_mapping, start: 0, end: -1); |
212 | bdev_fput(bdev_file: dev->bdev_file); |
213 | } |
214 | |
215 | kfree(objp: dev); |
216 | } |
217 | |
218 | /* |
219 | * This function is marked __ref because it calls the __init marked |
220 | * early_lookup_bdev when called from the early boot code. |
221 | */ |
222 | static struct file __ref *mdtblock_early_get_bdev(const char *devname, |
223 | blk_mode_t mode, int timeout, struct block2mtd_dev *dev) |
224 | { |
225 | struct file *bdev_file = ERR_PTR(error: -ENODEV); |
226 | #ifndef MODULE |
227 | int i; |
228 | |
229 | /* |
230 | * We can't use early_lookup_bdev from a running system. |
231 | */ |
232 | if (system_state >= SYSTEM_RUNNING) |
233 | return bdev_file; |
234 | |
235 | /* |
236 | * We might not have the root device mounted at this point. |
237 | * Try to resolve the device name by other means. |
238 | */ |
239 | for (i = 0; i <= timeout; i++) { |
240 | dev_t devt; |
241 | |
242 | if (i) |
243 | /* |
244 | * Calling wait_for_device_probe in the first loop |
245 | * was not enough, sleep for a bit in subsequent |
246 | * go-arounds. |
247 | */ |
248 | msleep(msecs: 1000); |
249 | wait_for_device_probe(); |
250 | |
251 | if (!early_lookup_bdev(pathname: devname, dev: &devt)) { |
252 | bdev_file = bdev_file_open_by_dev(dev: devt, mode, holder: dev, NULL); |
253 | if (!IS_ERR(ptr: bdev_file)) |
254 | break; |
255 | } |
256 | } |
257 | #endif |
258 | return bdev_file; |
259 | } |
260 | |
261 | static struct block2mtd_dev *add_device(char *devname, int erase_size, |
262 | char *label, int timeout) |
263 | { |
264 | const blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_WRITE; |
265 | struct file *bdev_file; |
266 | struct block_device *bdev; |
267 | struct block2mtd_dev *dev; |
268 | char *name; |
269 | |
270 | if (!devname) |
271 | return NULL; |
272 | |
273 | dev = kzalloc(size: sizeof(struct block2mtd_dev), GFP_KERNEL); |
274 | if (!dev) |
275 | return NULL; |
276 | |
277 | /* Get a handle on the device */ |
278 | bdev_file = bdev_file_open_by_path(path: devname, mode, holder: dev, NULL); |
279 | if (IS_ERR(ptr: bdev_file)) |
280 | bdev_file = mdtblock_early_get_bdev(devname, mode, timeout, |
281 | dev); |
282 | if (IS_ERR(ptr: bdev_file)) { |
283 | pr_err("error: cannot open device %s\n" , devname); |
284 | goto err_free_block2mtd; |
285 | } |
286 | dev->bdev_file = bdev_file; |
287 | bdev = file_bdev(bdev_file); |
288 | |
289 | if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { |
290 | pr_err("attempting to use an MTD device as a block device\n" ); |
291 | goto err_free_block2mtd; |
292 | } |
293 | |
294 | if ((long)bdev->bd_inode->i_size % erase_size) { |
295 | pr_err("erasesize must be a divisor of device size\n" ); |
296 | goto err_free_block2mtd; |
297 | } |
298 | |
299 | mutex_init(&dev->write_mutex); |
300 | |
301 | /* Setup the MTD structure */ |
302 | /* make the name contain the block device in */ |
303 | if (!label) |
304 | name = kasprintf(GFP_KERNEL, fmt: "block2mtd: %s" , devname); |
305 | else |
306 | name = kstrdup(s: label, GFP_KERNEL); |
307 | if (!name) |
308 | goto err_destroy_mutex; |
309 | |
310 | dev->mtd.name = name; |
311 | |
312 | dev->mtd.size = bdev->bd_inode->i_size & PAGE_MASK; |
313 | dev->mtd.erasesize = erase_size; |
314 | dev->mtd.writesize = 1; |
315 | dev->mtd.writebufsize = PAGE_SIZE; |
316 | dev->mtd.type = MTD_RAM; |
317 | dev->mtd.flags = MTD_CAP_RAM; |
318 | dev->mtd._erase = block2mtd_erase; |
319 | dev->mtd._write = block2mtd_write; |
320 | dev->mtd._sync = block2mtd_sync; |
321 | dev->mtd._read = block2mtd_read; |
322 | dev->mtd.priv = dev; |
323 | dev->mtd.owner = THIS_MODULE; |
324 | |
325 | if (mtd_device_register(&dev->mtd, NULL, 0)) { |
326 | /* Device didn't get added, so free the entry */ |
327 | goto err_destroy_mutex; |
328 | } |
329 | |
330 | list_add(new: &dev->list, head: &blkmtd_device_list); |
331 | pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n" , |
332 | dev->mtd.index, |
333 | label ? label : dev->mtd.name + strlen("block2mtd: " ), |
334 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); |
335 | return dev; |
336 | |
337 | err_destroy_mutex: |
338 | mutex_destroy(lock: &dev->write_mutex); |
339 | err_free_block2mtd: |
340 | block2mtd_free_device(dev); |
341 | return NULL; |
342 | } |
343 | |
344 | |
345 | /* This function works similar to reguler strtoul. In addition, it |
346 | * allows some suffixes for a more human-readable number format: |
347 | * ki, Ki, kiB, KiB - multiply result with 1024 |
348 | * Mi, MiB - multiply result with 1024^2 |
349 | * Gi, GiB - multiply result with 1024^3 |
350 | */ |
351 | static int ustrtoul(const char *cp, char **endp, unsigned int base) |
352 | { |
353 | unsigned long result = simple_strtoul(cp, endp, base); |
354 | switch (**endp) { |
355 | case 'G' : |
356 | result *= 1024; |
357 | fallthrough; |
358 | case 'M': |
359 | result *= 1024; |
360 | fallthrough; |
361 | case 'K': |
362 | case 'k': |
363 | result *= 1024; |
364 | /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */ |
365 | if ((*endp)[1] == 'i') { |
366 | if ((*endp)[2] == 'B') |
367 | (*endp) += 3; |
368 | else |
369 | (*endp) += 2; |
370 | } |
371 | } |
372 | return result; |
373 | } |
374 | |
375 | |
376 | static int parse_num(size_t *num, const char *token) |
377 | { |
378 | char *endp; |
379 | size_t n; |
380 | |
381 | n = (size_t) ustrtoul(cp: token, endp: &endp, base: 0); |
382 | if (*endp) |
383 | return -EINVAL; |
384 | |
385 | *num = n; |
386 | return 0; |
387 | } |
388 | |
389 | |
390 | static inline void kill_final_newline(char *str) |
391 | { |
392 | char *newline = strrchr(str, '\n'); |
393 | if (newline && !newline[1]) |
394 | *newline = 0; |
395 | } |
396 | |
397 | |
398 | #ifndef MODULE |
399 | static int block2mtd_init_called = 0; |
400 | /* 80 for device, 12 for erase size */ |
401 | static char block2mtd_paramline[80 + 12]; |
402 | #endif |
403 | |
404 | static int block2mtd_setup2(const char *val) |
405 | { |
406 | /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */ |
407 | char buf[80 + 12 + 80 + 8]; |
408 | char *str = buf; |
409 | char *token[BLOCK2MTD_PARAM_MAX_COUNT]; |
410 | char *name; |
411 | char *label = NULL; |
412 | size_t erase_size = PAGE_SIZE; |
413 | unsigned long timeout = MTD_DEFAULT_TIMEOUT; |
414 | int i, ret; |
415 | |
416 | if (strnlen(p: val, maxlen: sizeof(buf)) >= sizeof(buf)) { |
417 | pr_err("parameter too long\n" ); |
418 | return 0; |
419 | } |
420 | |
421 | strcpy(p: str, q: val); |
422 | kill_final_newline(str); |
423 | |
424 | for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT; i++) |
425 | token[i] = strsep(&str, "," ); |
426 | |
427 | if (str) { |
428 | pr_err("too many arguments\n" ); |
429 | return 0; |
430 | } |
431 | |
432 | if (!token[0]) { |
433 | pr_err("no argument\n" ); |
434 | return 0; |
435 | } |
436 | |
437 | name = token[0]; |
438 | if (strlen(name) + 1 > 80) { |
439 | pr_err("device name too long\n" ); |
440 | return 0; |
441 | } |
442 | |
443 | /* Optional argument when custom label is used */ |
444 | if (token[1] && strlen(token[1])) { |
445 | ret = parse_num(num: &erase_size, token: token[1]); |
446 | if (ret) { |
447 | pr_err("illegal erase size\n" ); |
448 | return 0; |
449 | } |
450 | } |
451 | |
452 | if (token[2]) { |
453 | label = token[2]; |
454 | pr_info("Using custom MTD label '%s' for dev %s\n" , label, name); |
455 | } |
456 | |
457 | add_device(devname: name, erase_size, label, timeout); |
458 | |
459 | return 0; |
460 | } |
461 | |
462 | |
463 | static int block2mtd_setup(const char *val, const struct kernel_param *kp) |
464 | { |
465 | #ifdef MODULE |
466 | return block2mtd_setup2(val); |
467 | #else |
468 | /* If more parameters are later passed in via |
469 | /sys/module/block2mtd/parameters/block2mtd |
470 | and block2mtd_init() has already been called, |
471 | we can parse the argument now. */ |
472 | |
473 | if (block2mtd_init_called) |
474 | return block2mtd_setup2(val); |
475 | |
476 | /* During early boot stage, we only save the parameters |
477 | here. We must parse them later: if the param passed |
478 | from kernel boot command line, block2mtd_setup() is |
479 | called so early that it is not possible to resolve |
480 | the device (even kmalloc() fails). Deter that work to |
481 | block2mtd_setup2(). */ |
482 | |
483 | strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); |
484 | |
485 | return 0; |
486 | #endif |
487 | } |
488 | |
489 | |
490 | module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); |
491 | MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"" ); |
492 | |
493 | static int __init block2mtd_init(void) |
494 | { |
495 | int ret = 0; |
496 | |
497 | #ifndef MODULE |
498 | if (strlen(block2mtd_paramline)) |
499 | ret = block2mtd_setup2(val: block2mtd_paramline); |
500 | block2mtd_init_called = 1; |
501 | #endif |
502 | |
503 | return ret; |
504 | } |
505 | |
506 | |
507 | static void block2mtd_exit(void) |
508 | { |
509 | struct list_head *pos, *next; |
510 | |
511 | /* Remove the MTD devices */ |
512 | list_for_each_safe(pos, next, &blkmtd_device_list) { |
513 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); |
514 | block2mtd_sync(mtd: &dev->mtd); |
515 | mtd_device_unregister(master: &dev->mtd); |
516 | mutex_destroy(lock: &dev->write_mutex); |
517 | pr_info("mtd%d: [%s] removed\n" , |
518 | dev->mtd.index, |
519 | dev->mtd.name + strlen("block2mtd: " )); |
520 | list_del(entry: &dev->list); |
521 | block2mtd_free_device(dev); |
522 | } |
523 | } |
524 | |
525 | late_initcall(block2mtd_init); |
526 | module_exit(block2mtd_exit); |
527 | |
528 | MODULE_LICENSE("GPL" ); |
529 | MODULE_AUTHOR("Joern Engel <joern@lazybastard.org>" ); |
530 | MODULE_DESCRIPTION("Emulate an MTD using a block device" ); |
531 | |