linux/drivers/mtd/devices/block2mtd.c
<<
>>
Prefs
   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 */
  38struct block2mtd_dev {
  39        struct list_head list;
  40        struct block_device *blkdev;
  41        struct mtd_info mtd;
  42        struct mutex write_mutex;
  43};
  44
  45
  46/* Static info about the MTD, used in cleanup_module */
  47static LIST_HEAD(blkmtd_device_list);
  48
  49
  50static 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 */
  56static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
  57{
  58        struct address_space *mapping = dev->blkdev->bd_inode->i_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(page))
  68                        return PTR_ERR(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}
  87static 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, from, len);
  96        mutex_unlock(&dev->write_mutex);
  97        if (err)
  98                pr_err("erase failed err = %d\n", err);
  99
 100        return err;
 101}
 102
 103
 104static 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 page *page;
 109        pgoff_t index = from >> PAGE_SHIFT;
 110        int offset = from & (PAGE_SIZE-1);
 111        int cpylen;
 112
 113        while (len) {
 114                if ((offset + len) > PAGE_SIZE)
 115                        cpylen = PAGE_SIZE - offset;    // multiple pages
 116                else
 117                        cpylen = len;   // this page
 118                len = len - cpylen;
 119
 120                page = page_read(dev->blkdev->bd_inode->i_mapping, index);
 121                if (IS_ERR(page))
 122                        return PTR_ERR(page);
 123
 124                memcpy(buf, page_address(page) + offset, cpylen);
 125                put_page(page);
 126
 127                if (retlen)
 128                        *retlen += cpylen;
 129                buf += cpylen;
 130                offset = 0;
 131                index++;
 132        }
 133        return 0;
 134}
 135
 136
 137/* write data to the underlying device */
 138static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
 139                loff_t to, size_t len, size_t *retlen)
 140{
 141        struct page *page;
 142        struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
 143        pgoff_t index = to >> PAGE_SHIFT;       // page index
 144        int offset = to & ~PAGE_MASK;   // page offset
 145        int cpylen;
 146
 147        while (len) {
 148                if ((offset+len) > PAGE_SIZE)
 149                        cpylen = PAGE_SIZE - offset;    // multiple pages
 150                else
 151                        cpylen = len;                   // this page
 152                len = len - cpylen;
 153
 154                page = page_read(mapping, index);
 155                if (IS_ERR(page))
 156                        return PTR_ERR(page);
 157
 158                if (memcmp(page_address(page)+offset, buf, cpylen)) {
 159                        lock_page(page);
 160                        memcpy(page_address(page) + offset, buf, cpylen);
 161                        set_page_dirty(page);
 162                        unlock_page(page);
 163                        balance_dirty_pages_ratelimited(mapping);
 164                }
 165                put_page(page);
 166
 167                if (retlen)
 168                        *retlen += cpylen;
 169
 170                buf += cpylen;
 171                offset = 0;
 172                index++;
 173        }
 174        return 0;
 175}
 176
 177
 178static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
 179                size_t *retlen, const u_char *buf)
 180{
 181        struct block2mtd_dev *dev = mtd->priv;
 182        int err;
 183
 184        mutex_lock(&dev->write_mutex);
 185        err = _block2mtd_write(dev, buf, to, len, retlen);
 186        mutex_unlock(&dev->write_mutex);
 187        if (err > 0)
 188                err = 0;
 189        return err;
 190}
 191
 192
 193/* sync the device - wait until the write queue is empty */
 194static void block2mtd_sync(struct mtd_info *mtd)
 195{
 196        struct block2mtd_dev *dev = mtd->priv;
 197        sync_blockdev(dev->blkdev);
 198        return;
 199}
 200
 201
 202static void block2mtd_free_device(struct block2mtd_dev *dev)
 203{
 204        if (!dev)
 205                return;
 206
 207        kfree(dev->mtd.name);
 208
 209        if (dev->blkdev) {
 210                invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
 211                                        0, -1);
 212                blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 213        }
 214
 215        kfree(dev);
 216}
 217
 218
 219static struct block2mtd_dev *add_device(char *devname, int erase_size,
 220                char *label, int timeout)
 221{
 222#ifndef MODULE
 223        int i;
 224#endif
 225        const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 226        struct block_device *bdev;
 227        struct block2mtd_dev *dev;
 228        char *name;
 229
 230        if (!devname)
 231                return NULL;
 232
 233        dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
 234        if (!dev)
 235                return NULL;
 236
 237        /* Get a handle on the device */
 238        bdev = blkdev_get_by_path(devname, mode, dev);
 239
 240#ifndef MODULE
 241        /*
 242         * We might not have the root device mounted at this point.
 243         * Try to resolve the device name by other means.
 244         */
 245        for (i = 0; IS_ERR(bdev) && i <= timeout; i++) {
 246                dev_t devt;
 247
 248                if (i)
 249                        /*
 250                         * Calling wait_for_device_probe in the first loop
 251                         * was not enough, sleep for a bit in subsequent
 252                         * go-arounds.
 253                         */
 254                        msleep(1000);
 255                wait_for_device_probe();
 256
 257                devt = name_to_dev_t(devname);
 258                if (!devt)
 259                        continue;
 260                bdev = blkdev_get_by_dev(devt, mode, dev);
 261        }
 262#endif
 263
 264        if (IS_ERR(bdev)) {
 265                pr_err("error: cannot open device %s\n", devname);
 266                goto err_free_block2mtd;
 267        }
 268        dev->blkdev = bdev;
 269
 270        if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 271                pr_err("attempting to use an MTD device as a block device\n");
 272                goto err_free_block2mtd;
 273        }
 274
 275        if ((long)dev->blkdev->bd_inode->i_size % erase_size) {
 276                pr_err("erasesize must be a divisor of device size\n");
 277                goto err_free_block2mtd;
 278        }
 279
 280        mutex_init(&dev->write_mutex);
 281
 282        /* Setup the MTD structure */
 283        /* make the name contain the block device in */
 284        if (!label)
 285                name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
 286        else
 287                name = kstrdup(label, GFP_KERNEL);
 288        if (!name)
 289                goto err_destroy_mutex;
 290
 291        dev->mtd.name = name;
 292
 293        dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 294        dev->mtd.erasesize = erase_size;
 295        dev->mtd.writesize = 1;
 296        dev->mtd.writebufsize = PAGE_SIZE;
 297        dev->mtd.type = MTD_RAM;
 298        dev->mtd.flags = MTD_CAP_RAM;
 299        dev->mtd._erase = block2mtd_erase;
 300        dev->mtd._write = block2mtd_write;
 301        dev->mtd._sync = block2mtd_sync;
 302        dev->mtd._read = block2mtd_read;
 303        dev->mtd.priv = dev;
 304        dev->mtd.owner = THIS_MODULE;
 305
 306        if (mtd_device_register(&dev->mtd, NULL, 0)) {
 307                /* Device didn't get added, so free the entry */
 308                goto err_destroy_mutex;
 309        }
 310
 311        list_add(&dev->list, &blkmtd_device_list);
 312        pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
 313                dev->mtd.index,
 314                label ? label : dev->mtd.name + strlen("block2mtd: "),
 315                dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 316        return dev;
 317
 318err_destroy_mutex:
 319        mutex_destroy(&dev->write_mutex);
 320err_free_block2mtd:
 321        block2mtd_free_device(dev);
 322        return NULL;
 323}
 324
 325
 326/* This function works similar to reguler strtoul.  In addition, it
 327 * allows some suffixes for a more human-readable number format:
 328 * ki, Ki, kiB, KiB     - multiply result with 1024
 329 * Mi, MiB              - multiply result with 1024^2
 330 * Gi, GiB              - multiply result with 1024^3
 331 */
 332static int ustrtoul(const char *cp, char **endp, unsigned int base)
 333{
 334        unsigned long result = simple_strtoul(cp, endp, base);
 335        switch (**endp) {
 336        case 'G' :
 337                result *= 1024;
 338                fallthrough;
 339        case 'M':
 340                result *= 1024;
 341                fallthrough;
 342        case 'K':
 343        case 'k':
 344                result *= 1024;
 345        /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
 346                if ((*endp)[1] == 'i') {
 347                        if ((*endp)[2] == 'B')
 348                                (*endp) += 3;
 349                        else
 350                                (*endp) += 2;
 351                }
 352        }
 353        return result;
 354}
 355
 356
 357static int parse_num(size_t *num, const char *token)
 358{
 359        char *endp;
 360        size_t n;
 361
 362        n = (size_t) ustrtoul(token, &endp, 0);
 363        if (*endp)
 364                return -EINVAL;
 365
 366        *num = n;
 367        return 0;
 368}
 369
 370
 371static inline void kill_final_newline(char *str)
 372{
 373        char *newline = strrchr(str, '\n');
 374        if (newline && !newline[1])
 375                *newline = 0;
 376}
 377
 378
 379#ifndef MODULE
 380static int block2mtd_init_called = 0;
 381/* 80 for device, 12 for erase size */
 382static char block2mtd_paramline[80 + 12];
 383#endif
 384
 385static int block2mtd_setup2(const char *val)
 386{
 387        /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
 388        char buf[80 + 12 + 80 + 8];
 389        char *str = buf;
 390        char *token[BLOCK2MTD_PARAM_MAX_COUNT];
 391        char *name;
 392        char *label = NULL;
 393        size_t erase_size = PAGE_SIZE;
 394        unsigned long timeout = MTD_DEFAULT_TIMEOUT;
 395        int i, ret;
 396
 397        if (strnlen(val, sizeof(buf)) >= sizeof(buf)) {
 398                pr_err("parameter too long\n");
 399                return 0;
 400        }
 401
 402        strcpy(str, val);
 403        kill_final_newline(str);
 404
 405        for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT; i++)
 406                token[i] = strsep(&str, ",");
 407
 408        if (str) {
 409                pr_err("too many arguments\n");
 410                return 0;
 411        }
 412
 413        if (!token[0]) {
 414                pr_err("no argument\n");
 415                return 0;
 416        }
 417
 418        name = token[0];
 419        if (strlen(name) + 1 > 80) {
 420                pr_err("device name too long\n");
 421                return 0;
 422        }
 423
 424        /* Optional argument when custom label is used */
 425        if (token[1] && strlen(token[1])) {
 426                ret = parse_num(&erase_size, token[1]);
 427                if (ret) {
 428                        pr_err("illegal erase size\n");
 429                        return 0;
 430                }
 431        }
 432
 433        if (token[2]) {
 434                label = token[2];
 435                pr_info("Using custom MTD label '%s' for dev %s\n", label, name);
 436        }
 437
 438        add_device(name, erase_size, label, timeout);
 439
 440        return 0;
 441}
 442
 443
 444static int block2mtd_setup(const char *val, const struct kernel_param *kp)
 445{
 446#ifdef MODULE
 447        return block2mtd_setup2(val);
 448#else
 449        /* If more parameters are later passed in via
 450           /sys/module/block2mtd/parameters/block2mtd
 451           and block2mtd_init() has already been called,
 452           we can parse the argument now. */
 453
 454        if (block2mtd_init_called)
 455                return block2mtd_setup2(val);
 456
 457        /* During early boot stage, we only save the parameters
 458           here. We must parse them later: if the param passed
 459           from kernel boot command line, block2mtd_setup() is
 460           called so early that it is not possible to resolve
 461           the device (even kmalloc() fails). Deter that work to
 462           block2mtd_setup2(). */
 463
 464        strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline));
 465
 466        return 0;
 467#endif
 468}
 469
 470
 471module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
 472MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"");
 473
 474static int __init block2mtd_init(void)
 475{
 476        int ret = 0;
 477
 478#ifndef MODULE
 479        if (strlen(block2mtd_paramline))
 480                ret = block2mtd_setup2(block2mtd_paramline);
 481        block2mtd_init_called = 1;
 482#endif
 483
 484        return ret;
 485}
 486
 487
 488static void block2mtd_exit(void)
 489{
 490        struct list_head *pos, *next;
 491
 492        /* Remove the MTD devices */
 493        list_for_each_safe(pos, next, &blkmtd_device_list) {
 494                struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
 495                block2mtd_sync(&dev->mtd);
 496                mtd_device_unregister(&dev->mtd);
 497                mutex_destroy(&dev->write_mutex);
 498                pr_info("mtd%d: [%s] removed\n",
 499                        dev->mtd.index,
 500                        dev->mtd.name + strlen("block2mtd: "));
 501                list_del(&dev->list);
 502                block2mtd_free_device(dev);
 503        }
 504}
 505
 506late_initcall(block2mtd_init);
 507module_exit(block2mtd_exit);
 508
 509MODULE_LICENSE("GPL");
 510MODULE_AUTHOR("Joern Engel <joern@lazybastard.org>");
 511MODULE_DESCRIPTION("Emulate an MTD using a block device");
 512