source: trunk/target/linux/generic/patches-2.6.30/065-rootfs_split.patch @ 28893

Last change on this file since 28893 was 28893, checked in by jogo, 4 years ago

target: linux: mtd: fix MTDREFRESH to an arbitrary high number

To make the ioctl number "stable", use an arbitrary high number to prevent
conflicts with new mtd ioctls that would push MTDREFRESH's number.

Also make mtd use the in-kernel mtd headers.

File size: 15.7 KB
  • drivers/mtd/Kconfig

    a b config MTD_TESTS 
    5353          should normally be compiled as kernel modules. The modules perform 
    5454          various checks and verifications when loaded. 
    5555 
     56config MTD_ROOTFS_ROOT_DEV 
     57        bool "Automatically set 'rootfs' partition to be root filesystem" 
     58        depends on MTD_PARTITIONS 
     59        default y 
     60 
     61config MTD_ROOTFS_SPLIT 
     62        bool "Automatically split 'rootfs' partition for squashfs" 
     63        depends on MTD_PARTITIONS 
     64        default y 
     65 
    5666config MTD_REDBOOT_PARTS 
    5767        tristate "RedBoot partition table parsing" 
    5868        depends on MTD_PARTITIONS 
  • drivers/mtd/mtdpart.c

    a b  
    1818#include <linux/mtd/mtd.h> 
    1919#include <linux/mtd/partitions.h> 
    2020#include <linux/mtd/compatmac.h> 
     21#include <linux/root_dev.h> 
     22#include <linux/magic.h> 
    2123 
    2224/* Our partition linked list */ 
    2325static LIST_HEAD(mtd_partitions); 
    struct mtd_part { 
    3739 * the pointer to that structure with this macro. 
    3840 */ 
    3941#define PART(x)  ((struct mtd_part *)(x)) 
    40  
     42#define IS_PART(mtd) (mtd->read == part_read) 
    4143 
    4244/* 
    4345 * MTD methods which simply translate the effective address and pass through 
    out_register: 
    512514        return slave; 
    513515} 
    514516 
     517#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     518#define ROOTFS_SPLIT_NAME "rootfs_data" 
     519#define ROOTFS_REMOVED_NAME "<removed>" 
     520 
     521struct squashfs_super_block { 
     522        __le32 s_magic; 
     523        __le32 pad0[9]; 
     524        __le64 bytes_used; 
     525}; 
     526 
     527 
     528static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     529{ 
     530        struct squashfs_super_block sb; 
     531        int len, ret; 
     532 
     533        ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); 
     534        if (ret || (len != sizeof(sb))) { 
     535                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     536                        "from \"%s\"\n", master->name); 
     537                return -EINVAL; 
     538        } 
     539 
     540        if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { 
     541                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     542                        master->name); 
     543                *split_offset = 0; 
     544                return 0; 
     545        } 
     546 
     547        if (le64_to_cpu((sb.bytes_used)) <= 0) { 
     548                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     549                        master->name); 
     550                *split_offset = 0; 
     551                return 0; 
     552        } 
     553 
     554        len = (u32) le64_to_cpu(sb.bytes_used); 
     555        len += (offset & 0x000fffff); 
     556        len +=  (master->erasesize - 1); 
     557        len &= ~(master->erasesize - 1); 
     558        len -= (offset & 0x000fffff); 
     559        *split_offset = offset + len; 
     560 
     561        return 0; 
     562} 
     563 
     564static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part, 
     565                int index) 
     566{ 
     567        struct mtd_partition *dpart; 
     568        struct mtd_part *slave = NULL; 
     569        struct mtd_part *spart; 
     570        int split_offset = 0; 
     571        int ret; 
     572 
     573        spart = PART(rpart); 
     574        ret = split_squashfs(master, spart->offset, &split_offset); 
     575        if (ret) 
     576                return ret; 
     577 
     578        if (split_offset <= 0) 
     579                return 0; 
     580 
     581        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     582        if (dpart == NULL) { 
     583                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     584                        ROOTFS_SPLIT_NAME); 
     585                return -ENOMEM; 
     586        } 
     587 
     588        memcpy(dpart, part, sizeof(*part)); 
     589        dpart->name = (unsigned char *)&dpart[1]; 
     590        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     591 
     592        dpart->size = rpart->size - (split_offset - spart->offset); 
     593        dpart->offset = split_offset; 
     594 
     595        if (dpart == NULL) 
     596                return 1; 
     597 
     598        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     599                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     600 
     601        slave = add_one_partition(master, dpart, index, split_offset); 
     602        if (!slave) { 
     603                kfree(dpart); 
     604                return -ENOMEM; 
     605        } 
     606        rpart->split = &slave->mtd; 
     607 
     608        return 0; 
     609} 
     610 
     611static int refresh_rootfs_split(struct mtd_info *mtd) 
     612{ 
     613        struct mtd_partition tpart; 
     614        struct mtd_part *part; 
     615        char *name; 
     616        int index = 0; 
     617        int offset, size; 
     618        int ret; 
     619 
     620        part = PART(mtd); 
     621 
     622        /* check for the new squashfs offset first */ 
     623        ret = split_squashfs(part->master, part->offset, &offset); 
     624        if (ret) 
     625                return ret; 
     626 
     627        if ((offset > 0) && !mtd->split) { 
     628                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     629                /* if we don't have a rootfs split partition, create a new one */ 
     630                tpart.name = (char *) mtd->name; 
     631                tpart.size = mtd->size; 
     632                tpart.offset = part->offset; 
     633 
     634                /* find the index of the last partition */ 
     635                if (!list_empty(&mtd_partitions)) 
     636                        index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1; 
     637 
     638                return split_rootfs_data(part->master, &part->mtd, &tpart, index); 
     639        } else if ((offset > 0) && mtd->split) { 
     640                /* update the offsets of the existing partition */ 
     641                size = mtd->size + part->offset - offset; 
     642 
     643                part = PART(mtd->split); 
     644                part->offset = offset; 
     645                part->mtd.size = size; 
     646                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     647                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     648                        (u32) part->offset, (u32) part->mtd.size); 
     649                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     650                strcpy(name, ROOTFS_SPLIT_NAME); 
     651                part->mtd.name = name; 
     652        } else if ((offset <= 0) && mtd->split) { 
     653                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     654 
     655                /* mark existing partition as removed */ 
     656                part = PART(mtd->split); 
     657                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     658                strcpy(name, ROOTFS_REMOVED_NAME); 
     659                part->mtd.name = name; 
     660                part->offset = 0; 
     661                part->mtd.size = 0; 
     662        } 
     663 
     664        return 0; 
     665} 
     666#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     667 
    515668/* 
    516669 * This function, given a master MTD object and a partition table, creates 
    517670 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    527680{ 
    528681        struct mtd_part *slave; 
    529682        uint64_t cur_offset = 0; 
    530         int i; 
     683        int i, j, ret; 
    531684 
    532685        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    533686 
    534         for (i = 0; i < nbparts; i++) { 
    535                 slave = add_one_partition(master, parts + i, i, cur_offset); 
     687        for (i = 0, j = 0; i < nbparts; i++) { 
     688                slave = add_one_partition(master, parts + i, j++, cur_offset); 
    536689                if (!slave) 
    537690                        return -ENOMEM; 
     691 
     692                if (!strcmp(parts[i].name, "rootfs") && slave->registered) { 
     693#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     694                        if (ROOT_DEV == 0) { 
     695                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     696                                        "set to be root filesystem\n"); 
     697                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     698                        } 
     699#endif 
     700#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     701                        ret = split_rootfs_data(master, &slave->mtd, &parts[i], j); 
     702                        if (ret == 0) 
     703                                j++; 
     704#endif 
     705                } 
    538706                cur_offset = slave->offset + slave->mtd.size; 
    539707        } 
    540708 
    int add_mtd_partitions(struct mtd_info * 
    542710} 
    543711EXPORT_SYMBOL(add_mtd_partitions); 
    544712 
     713int refresh_mtd_partitions(struct mtd_info *mtd) 
     714{ 
     715        int ret = 0; 
     716 
     717        if (IS_PART(mtd)) { 
     718                struct mtd_part *part; 
     719                struct mtd_info *master; 
     720 
     721                part = PART(mtd); 
     722                master = part->master; 
     723                if (master->refresh_device) 
     724                        ret = master->refresh_device(master); 
     725        } 
     726 
     727        if (!ret && mtd->refresh_device) 
     728                ret = mtd->refresh_device(mtd); 
     729 
     730#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     731        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     732                refresh_rootfs_split(mtd); 
     733#endif 
     734 
     735        return 0; 
     736} 
     737EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     738 
    545739static DEFINE_SPINLOCK(part_parser_lock); 
    546740static LIST_HEAD(part_parsers); 
    547741 
  • drivers/mtd/devices/block2mtd.c

    a b struct block2mtd_dev { 
    2929        struct block_device *blkdev; 
    3030        struct mtd_info mtd; 
    3131        struct mutex write_mutex; 
     32        rwlock_t bdev_mutex; 
     33        char devname[0]; 
    3234}; 
    3335 
    3436 
    static int block2mtd_erase(struct mtd_in 
    8183        size_t len = instr->len; 
    8284        int err; 
    8385 
     86        read_lock(&dev->bdev_mutex); 
     87        if (!dev->blkdev) { 
     88                err = -EINVAL; 
     89                goto done; 
     90        } 
     91 
    8492        instr->state = MTD_ERASING; 
    8593        mutex_lock(&dev->write_mutex); 
    8694        err = _block2mtd_erase(dev, from, len); 
    static int block2mtd_erase(struct mtd_in 
    93101 
    94102        instr->state = MTD_ERASE_DONE; 
    95103        mtd_erase_callback(instr); 
     104 
     105done: 
     106        read_unlock(&dev->bdev_mutex); 
     107 
    96108        return err; 
    97109} 
    98110 
    static int block2mtd_read(struct mtd_inf 
    104116        struct page *page; 
    105117        int index = from >> PAGE_SHIFT; 
    106118        int offset = from & (PAGE_SIZE-1); 
    107         int cpylen; 
     119        int cpylen, err = 0; 
     120 
     121        read_lock(&dev->bdev_mutex); 
     122        if (!dev->blkdev || (from > mtd->size)) { 
     123                err = -EINVAL; 
     124                goto done; 
     125        } 
    108126 
    109         if (from > mtd->size) 
    110                 return -EINVAL; 
    111127        if (from + len > mtd->size) 
    112128                len = mtd->size - from; 
    113129 
    static int block2mtd_read(struct mtd_inf 
    122138                len = len - cpylen; 
    123139 
    124140                page = page_read(dev->blkdev->bd_inode->i_mapping, index); 
    125                 if (!page) 
    126                         return -ENOMEM; 
    127                 if (IS_ERR(page)) 
    128                         return PTR_ERR(page); 
     141                if (!page) { 
     142                        err = -ENOMEM; 
     143                        goto done; 
     144                } 
     145                if (IS_ERR(page)) { 
     146                        err = PTR_ERR(page); 
     147                        goto done; 
     148                } 
    129149 
    130150                memcpy(buf, page_address(page) + offset, cpylen); 
    131151                page_cache_release(page); 
    static int block2mtd_read(struct mtd_inf 
    136156                offset = 0; 
    137157                index++; 
    138158        } 
    139         return 0; 
     159 
     160done: 
     161        read_unlock(&dev->bdev_mutex); 
     162        return err; 
    140163} 
    141164 
    142165 
    static int block2mtd_write(struct mtd_in 
    188211                size_t *retlen, const u_char *buf) 
    189212{ 
    190213        struct block2mtd_dev *dev = mtd->priv; 
    191         int err; 
     214        int err = 0; 
     215 
     216        read_lock(&dev->bdev_mutex); 
     217        if (!dev->blkdev) { 
     218                err = -EINVAL; 
     219                goto done; 
     220        } 
    192221 
    193222        if (!len) 
    194                 return 0; 
    195         if (to >= mtd->size) 
    196                 return -ENOSPC; 
     223                goto done; 
     224 
     225        if (to >= mtd->size) { 
     226                err = -ENOSPC; 
     227                goto done; 
     228        } 
     229 
    197230        if (to + len > mtd->size) 
    198231                len = mtd->size - to; 
    199232 
    static int block2mtd_write(struct mtd_in 
    202235        mutex_unlock(&dev->write_mutex); 
    203236        if (err > 0) 
    204237                err = 0; 
     238 
     239done: 
     240        read_unlock(&dev->bdev_mutex); 
    205241        return err; 
    206242} 
    207243 
    static int block2mtd_write(struct mtd_in 
    210246static void block2mtd_sync(struct mtd_info *mtd) 
    211247{ 
    212248        struct block2mtd_dev *dev = mtd->priv; 
    213         sync_blockdev(dev->blkdev); 
    214         return; 
    215 } 
    216  
    217  
    218 static void block2mtd_free_device(struct block2mtd_dev *dev) 
    219 { 
    220         if (!dev) 
    221                 return; 
    222  
    223         kfree(dev->mtd.name); 
    224249 
    225         if (dev->blkdev) { 
    226                 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 
    227                                         0, -1); 
    228                 close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); 
    229         } 
     250        read_lock(&dev->bdev_mutex); 
     251        if (dev->blkdev) 
     252                sync_blockdev(dev->blkdev); 
     253        read_unlock(&dev->bdev_mutex); 
    230254 
    231         kfree(dev); 
     255        return; 
    232256} 
    233257 
    234258 
    235 /* FIXME: ensure that mtd->size % erase_size == 0 */ 
    236 static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) 
     259static int _open_bdev(struct block2mtd_dev *dev) 
    237260{ 
    238261        struct block_device *bdev; 
    239         struct block2mtd_dev *dev; 
    240         struct mtd_partition *part; 
    241         char *name; 
    242  
    243         if (!devname) 
    244                 return NULL; 
    245  
    246         dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 
    247         if (!dev) 
    248                 return NULL; 
    249262 
    250263        /* Get a handle on the device */ 
    251         bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL); 
     264        bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL); 
    252265#ifndef MODULE 
    253266        if (IS_ERR(bdev)) { 
    254267 
    255268                /* We might not have rootfs mounted at this point. Try 
    256269                   to resolve the device name by other means. */ 
    257270 
    258                 dev_t devt = name_to_dev_t(devname); 
     271                dev_t devt = name_to_dev_t(dev->devname); 
    259272                if (devt) { 
    260273                        bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 
    261274                } 
    static struct block2mtd_dev *add_device( 
    263276#endif 
    264277 
    265278        if (IS_ERR(bdev)) { 
    266                 ERROR("error: cannot open device %s", devname); 
    267                 goto devinit_err; 
     279                ERROR("error: cannot open device %s", dev->devname); 
     280                return 1; 
    268281        } 
    269282        dev->blkdev = bdev; 
    270283 
    271284        if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { 
    272285                ERROR("attempting to use an MTD device as a block device"); 
    273                 goto devinit_err; 
     286                return 1; 
    274287        } 
    275288 
     289        return 0; 
     290} 
     291 
     292static void _close_bdev(struct block2mtd_dev *dev) 
     293{ 
     294        struct block_device *bdev; 
     295 
     296        if (!dev->blkdev) 
     297                return; 
     298 
     299        bdev = dev->blkdev; 
     300        invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); 
     301        close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); 
     302        dev->blkdev = NULL; 
     303} 
     304 
     305static void block2mtd_free_device(struct block2mtd_dev *dev) 
     306{ 
     307        if (!dev) 
     308                return; 
     309 
     310        kfree(dev->mtd.name); 
     311        _close_bdev(dev); 
     312        kfree(dev); 
     313} 
     314 
     315 
     316static int block2mtd_refresh(struct mtd_info *mtd) 
     317{ 
     318        struct block2mtd_dev *dev = mtd->priv; 
     319        struct block_device *bdev; 
     320        dev_t devt; 
     321        int err = 0; 
     322 
     323        /* no other mtd function can run at this point */ 
     324        write_lock(&dev->bdev_mutex); 
     325 
     326        /* get the device number for the whole disk */ 
     327        devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0); 
     328 
     329        /* close the old block device */ 
     330        _close_bdev(dev); 
     331 
     332        /* open the whole disk, issue a partition rescan, then */ 
     333        bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 
     334        if (!bdev || !bdev->bd_disk) 
     335                err = -EINVAL; 
     336#ifndef CONFIG_MTD_BLOCK2MTD_MODULE 
     337        else 
     338                err = rescan_partitions(bdev->bd_disk, bdev); 
     339#endif 
     340        if (bdev) 
     341                close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE); 
     342 
     343        /* try to open the partition block device again */ 
     344        _open_bdev(dev); 
     345        write_unlock(&dev->bdev_mutex); 
     346 
     347        return err; 
     348} 
     349 
     350/* FIXME: ensure that mtd->size % erase_size == 0 */ 
     351static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname) 
     352{ 
     353        struct block2mtd_dev *dev; 
     354        struct mtd_partition *part; 
     355        char *name; 
     356 
     357        if (!devname) 
     358                return NULL; 
     359 
     360        dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL); 
     361        if (!dev) 
     362                return NULL; 
     363 
     364        strcpy(dev->devname, devname); 
     365 
     366        if (_open_bdev(dev)) 
     367                goto devinit_err; 
     368 
    276369        mutex_init(&dev->write_mutex); 
     370        rwlock_init(&dev->bdev_mutex); 
    277371 
    278372        if (!mtdname) 
    279373                mtdname = devname; 
    static struct block2mtd_dev *add_device( 
    297391        dev->mtd.read = block2mtd_read; 
    298392        dev->mtd.priv = dev; 
    299393        dev->mtd.owner = THIS_MODULE; 
     394        dev->mtd.refresh_device = block2mtd_refresh; 
    300395 
    301396        part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); 
    302397        part->name = dev->mtd.name; 
  • drivers/mtd/mtdchar.c

    a b  
    1717 
    1818#include <linux/mtd/mtd.h> 
    1919#include <linux/mtd/compatmac.h> 
     20#include <linux/mtd/partitions.h> 
    2021 
    2122#include <asm/uaccess.h> 
    2223 
    static int mtd_ioctl(struct inode *inode 
    750751                file->f_pos = 0; 
    751752                break; 
    752753        } 
     754#ifdef CONFIG_MTD_PARTITIONS 
     755        case MTDREFRESH: 
     756        { 
     757                ret = refresh_mtd_partitions(mtd); 
     758                break; 
     759        } 
     760#endif 
    753761 
    754762        default: 
    755763                ret = -ENOTTY; 
  • include/linux/mtd/mtd.h

    a b struct mtd_oob_ops { 
    101101        uint8_t         *oobbuf; 
    102102}; 
    103103 
     104struct mtd_info; 
    104105struct mtd_info { 
    105106        u_char type; 
    106107        uint32_t flags; 
    struct mtd_info { 
    241242        struct device dev; 
    242243        int usecount; 
    243244 
     245        int (*refresh_device)(struct mtd_info *mtd); 
     246        struct mtd_info *split; 
     247 
    244248        /* If the driver is something smart, like UBI, it may need to maintain 
    245249         * its own reference counting. The below functions are only for driver. 
    246250         * The driver may register its callbacks. These callbacks are not 
  • include/linux/mtd/partitions.h

    a b  
    3434 * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). 
    3535 */ 
    3636 
     37struct mtd_partition; 
    3738struct mtd_partition { 
    3839        char *name;                     /* identifier string */ 
    3940        uint64_t size;                  /* partition size */ 
    struct mtd_partition { 
    4142        uint32_t mask_flags;            /* master MTD flags to mask out for this partition */ 
    4243        struct nand_ecclayout *ecclayout;       /* out of band layout for this partition (NAND only)*/ 
    4344        struct mtd_info **mtdp;         /* pointer to store the MTD object */ 
     45        int (*refresh_partition)(struct mtd_info *); 
    4446}; 
    4547 
    4648#define MTDPART_OFS_NXTBLK      (-2) 
    struct mtd_partition { 
    5052 
    5153int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); 
    5254int del_mtd_partitions(struct mtd_info *); 
     55int refresh_mtd_partitions(struct mtd_info *); 
    5356 
    5457/* 
    5558 * Functions dealing with the various ways of partitioning the space 
  • include/mtd/mtd-abi.h

    a b struct otp_info { 
    9595#define ECCGETLAYOUT            _IOR('M', 17, struct nand_ecclayout) 
    9696#define ECCGETSTATS             _IOR('M', 18, struct mtd_ecc_stats) 
    9797#define MTDFILEMODE             _IO('M', 19) 
     98#define MTDREFRESH              _IO('M', 50) 
    9899 
    99100/* 
    100101 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.