source: trunk/target/linux/generic/patches-2.6.36/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.5 KB
  • drivers/mtd/Kconfig

    a b config MTD_PARTITIONS 
    5353          devices. Partitioning on NFTL 'devices' is a different - that's the 
    5454          'normal' form of partitioning used on a block device. 
    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  
    2929#include <linux/kmod.h> 
    3030#include <linux/mtd/mtd.h> 
    3131#include <linux/mtd/partitions.h> 
     32#include <linux/root_dev.h> 
     33#include <linux/magic.h> 
    3234 
    3335/* Our partition linked list */ 
    3436static LIST_HEAD(mtd_partitions); 
    struct mtd_part { 
    4648 * the pointer to that structure with this macro. 
    4749 */ 
    4850#define PART(x)  ((struct mtd_part *)(x)) 
    49  
     51#define IS_PART(mtd) (mtd->read == part_read) 
    5052 
    5153/* 
    5254 * MTD methods which simply translate the effective address and pass through 
    out_register: 
    524526        return slave; 
    525527} 
    526528 
     529#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     530#define ROOTFS_SPLIT_NAME "rootfs_data" 
     531#define ROOTFS_REMOVED_NAME "<removed>" 
     532 
     533struct squashfs_super_block { 
     534        __le32 s_magic; 
     535        __le32 pad0[9]; 
     536        __le64 bytes_used; 
     537}; 
     538 
     539 
     540static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     541{ 
     542        struct squashfs_super_block sb; 
     543        int len, ret; 
     544 
     545        ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); 
     546        if (ret || (len != sizeof(sb))) { 
     547                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     548                        "from \"%s\"\n", master->name); 
     549                return -EINVAL; 
     550        } 
     551 
     552        if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { 
     553                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     554                        master->name); 
     555                *split_offset = 0; 
     556                return 0; 
     557        } 
     558 
     559        if (le64_to_cpu((sb.bytes_used)) <= 0) { 
     560                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     561                        master->name); 
     562                *split_offset = 0; 
     563                return 0; 
     564        } 
     565 
     566        len = (u32) le64_to_cpu(sb.bytes_used); 
     567        len += (offset & 0x000fffff); 
     568        len +=  (master->erasesize - 1); 
     569        len &= ~(master->erasesize - 1); 
     570        len -= (offset & 0x000fffff); 
     571        *split_offset = offset + len; 
     572 
     573        return 0; 
     574} 
     575 
     576static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part) 
     577{ 
     578        struct mtd_partition *dpart; 
     579        struct mtd_part *slave = NULL; 
     580        struct mtd_part *spart; 
     581        int split_offset = 0; 
     582        int ret; 
     583 
     584        spart = PART(rpart); 
     585        ret = split_squashfs(master, spart->offset, &split_offset); 
     586        if (ret) 
     587                return ret; 
     588 
     589        if (split_offset <= 0) 
     590                return 0; 
     591 
     592        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     593        if (dpart == NULL) { 
     594                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     595                        ROOTFS_SPLIT_NAME); 
     596                return -ENOMEM; 
     597        } 
     598 
     599        memcpy(dpart, part, sizeof(*part)); 
     600        dpart->name = (unsigned char *)&dpart[1]; 
     601        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     602 
     603        dpart->size = rpart->size - (split_offset - spart->offset); 
     604        dpart->offset = split_offset; 
     605 
     606        if (dpart == NULL) 
     607                return 1; 
     608 
     609        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     610                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     611 
     612        slave = add_one_partition(master, dpart, 0, split_offset); 
     613        if (!slave) { 
     614                kfree(dpart); 
     615                return -ENOMEM; 
     616        } 
     617        rpart->split = &slave->mtd; 
     618 
     619        return 0; 
     620} 
     621 
     622static int refresh_rootfs_split(struct mtd_info *mtd) 
     623{ 
     624        struct mtd_partition tpart; 
     625        struct mtd_part *part; 
     626        char *name; 
     627        //int index = 0; 
     628        int offset, size; 
     629        int ret; 
     630 
     631        part = PART(mtd); 
     632 
     633        /* check for the new squashfs offset first */ 
     634        ret = split_squashfs(part->master, part->offset, &offset); 
     635        if (ret) 
     636                return ret; 
     637 
     638        if ((offset > 0) && !mtd->split) { 
     639                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     640                /* if we don't have a rootfs split partition, create a new one */ 
     641                tpart.name = (char *) mtd->name; 
     642                tpart.size = mtd->size; 
     643                tpart.offset = part->offset; 
     644 
     645                return split_rootfs_data(part->master, &part->mtd, &tpart); 
     646        } else if ((offset > 0) && mtd->split) { 
     647                /* update the offsets of the existing partition */ 
     648                size = mtd->size + part->offset - offset; 
     649 
     650                part = PART(mtd->split); 
     651                part->offset = offset; 
     652                part->mtd.size = size; 
     653                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     654                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     655                        (u32) part->offset, (u32) part->mtd.size); 
     656                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     657                strcpy(name, ROOTFS_SPLIT_NAME); 
     658                part->mtd.name = name; 
     659        } else if ((offset <= 0) && mtd->split) { 
     660                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     661 
     662                /* mark existing partition as removed */ 
     663                part = PART(mtd->split); 
     664                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     665                strcpy(name, ROOTFS_REMOVED_NAME); 
     666                part->mtd.name = name; 
     667                part->offset = 0; 
     668                part->mtd.size = 0; 
     669        } 
     670 
     671        return 0; 
     672} 
     673#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     674 
    527675/* 
    528676 * This function, given a master MTD object and a partition table, creates 
    529677 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    539685{ 
    540686        struct mtd_part *slave; 
    541687        uint64_t cur_offset = 0; 
    542         int i; 
     688        int i, ret; 
    543689 
    544690        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    545691 
    int add_mtd_partitions(struct mtd_info * 
    547693                slave = add_one_partition(master, parts + i, i, cur_offset); 
    548694                if (!slave) 
    549695                        return -ENOMEM; 
     696 
     697                if (!strcmp(parts[i].name, "rootfs")) { 
     698#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     699                        if (ROOT_DEV == 0) { 
     700                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     701                                        "set to be root filesystem\n"); 
     702                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     703                        } 
     704#endif 
     705#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     706                        ret = split_rootfs_data(master, &slave->mtd, &parts[i]); 
     707                        /* if (ret == 0) 
     708                                j++; */ 
     709#endif 
     710                } 
    550711                cur_offset = slave->offset + slave->mtd.size; 
    551712        } 
    552713 
    int add_mtd_partitions(struct mtd_info * 
    554715} 
    555716EXPORT_SYMBOL(add_mtd_partitions); 
    556717 
     718int refresh_mtd_partitions(struct mtd_info *mtd) 
     719{ 
     720        int ret = 0; 
     721 
     722        if (IS_PART(mtd)) { 
     723                struct mtd_part *part; 
     724                struct mtd_info *master; 
     725 
     726                part = PART(mtd); 
     727                master = part->master; 
     728                if (master->refresh_device) 
     729                        ret = master->refresh_device(master); 
     730        } 
     731 
     732        if (!ret && mtd->refresh_device) 
     733                ret = mtd->refresh_device(mtd); 
     734 
     735#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     736        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     737                refresh_rootfs_split(mtd); 
     738#endif 
     739 
     740        return 0; 
     741} 
     742EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     743 
    557744static DEFINE_SPINLOCK(part_parser_lock); 
    558745static LIST_HEAD(part_parsers); 
    559746 
  • drivers/mtd/devices/block2mtd.c

    a b struct block2mtd_dev { 
    3030        struct block_device *blkdev; 
    3131        struct mtd_info mtd; 
    3232        struct mutex write_mutex; 
     33        rwlock_t bdev_mutex; 
     34        char devname[0]; 
    3335}; 
    3436 
    3537 
    static int block2mtd_erase(struct mtd_in 
    8284        size_t len = instr->len; 
    8385        int err; 
    8486 
     87        read_lock(&dev->bdev_mutex); 
     88        if (!dev->blkdev) { 
     89                err = -EINVAL; 
     90                goto done; 
     91        } 
     92 
    8593        instr->state = MTD_ERASING; 
    8694        mutex_lock(&dev->write_mutex); 
    8795        err = _block2mtd_erase(dev, from, len); 
    static int block2mtd_erase(struct mtd_in 
    94102 
    95103        instr->state = MTD_ERASE_DONE; 
    96104        mtd_erase_callback(instr); 
     105 
     106done: 
     107        read_unlock(&dev->bdev_mutex); 
     108 
    97109        return err; 
    98110} 
    99111 
    static int block2mtd_read(struct mtd_inf 
    105117        struct page *page; 
    106118        int index = from >> PAGE_SHIFT; 
    107119        int offset = from & (PAGE_SIZE-1); 
    108         int cpylen; 
     120        int cpylen, err = 0; 
     121 
     122        read_lock(&dev->bdev_mutex); 
     123        if (!dev->blkdev || (from > mtd->size)) { 
     124                err = -EINVAL; 
     125                goto done; 
     126        } 
    109127 
    110         if (from > mtd->size) 
    111                 return -EINVAL; 
    112128        if (from + len > mtd->size) 
    113129                len = mtd->size - from; 
    114130 
    static int block2mtd_read(struct mtd_inf 
    123139                len = len - cpylen; 
    124140 
    125141                page = page_read(dev->blkdev->bd_inode->i_mapping, index); 
    126                 if (!page) 
    127                         return -ENOMEM; 
    128                 if (IS_ERR(page)) 
    129                         return PTR_ERR(page); 
     142                if (!page) { 
     143                        err = -ENOMEM; 
     144                        goto done; 
     145                } 
     146                if (IS_ERR(page)) { 
     147                        err = PTR_ERR(page); 
     148                        goto done; 
     149                } 
    130150 
    131151                memcpy(buf, page_address(page) + offset, cpylen); 
    132152                page_cache_release(page); 
    static int block2mtd_read(struct mtd_inf 
    137157                offset = 0; 
    138158                index++; 
    139159        } 
    140         return 0; 
     160 
     161done: 
     162        read_unlock(&dev->bdev_mutex); 
     163        return err; 
    141164} 
    142165 
    143166 
    static int block2mtd_write(struct mtd_in 
    189212                size_t *retlen, const u_char *buf) 
    190213{ 
    191214        struct block2mtd_dev *dev = mtd->priv; 
    192         int err; 
     215        int err = 0; 
     216 
     217        read_lock(&dev->bdev_mutex); 
     218        if (!dev->blkdev) { 
     219                err = -EINVAL; 
     220                goto done; 
     221        } 
    193222 
    194223        if (!len) 
    195                 return 0; 
    196         if (to >= mtd->size) 
    197                 return -ENOSPC; 
     224                goto done; 
     225 
     226        if (to >= mtd->size) { 
     227                err = -ENOSPC; 
     228                goto done; 
     229        } 
     230 
    198231        if (to + len > mtd->size) 
    199232                len = mtd->size - to; 
    200233 
    static int block2mtd_write(struct mtd_in 
    203236        mutex_unlock(&dev->write_mutex); 
    204237        if (err > 0) 
    205238                err = 0; 
     239 
     240done: 
     241        read_unlock(&dev->bdev_mutex); 
    206242        return err; 
    207243} 
    208244 
    static int block2mtd_write(struct mtd_in 
    211247static void block2mtd_sync(struct mtd_info *mtd) 
    212248{ 
    213249        struct block2mtd_dev *dev = mtd->priv; 
    214         sync_blockdev(dev->blkdev); 
    215         return; 
    216 } 
    217  
    218  
    219 static void block2mtd_free_device(struct block2mtd_dev *dev) 
    220 { 
    221         if (!dev) 
    222                 return; 
    223  
    224         kfree(dev->mtd.name); 
    225250 
    226         if (dev->blkdev) { 
    227                 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 
    228                                         0, -1); 
    229                 close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); 
    230         } 
     251        read_lock(&dev->bdev_mutex); 
     252        if (dev->blkdev) 
     253                sync_blockdev(dev->blkdev); 
     254        read_unlock(&dev->bdev_mutex); 
    231255 
    232         kfree(dev); 
     256        return; 
    233257} 
    234258 
    235259 
    236 /* FIXME: ensure that mtd->size % erase_size == 0 */ 
    237 static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) 
     260static int _open_bdev(struct block2mtd_dev *dev) 
    238261{ 
    239262        struct block_device *bdev; 
    240         struct block2mtd_dev *dev; 
    241         struct mtd_partition *part; 
    242         char *name; 
    243  
    244         if (!devname) 
    245                 return NULL; 
    246  
    247         dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 
    248         if (!dev) 
    249                 return NULL; 
    250263 
    251264        /* Get a handle on the device */ 
    252         bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL); 
     265        bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL); 
    253266#ifndef MODULE 
    254267        if (IS_ERR(bdev)) { 
    255268 
    256269                /* We might not have rootfs mounted at this point. Try 
    257270                   to resolve the device name by other means. */ 
    258271 
    259                 dev_t devt = name_to_dev_t(devname); 
     272                dev_t devt = name_to_dev_t(dev->devname); 
    260273                if (devt) { 
    261274                        bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 
    262275                } 
    static struct block2mtd_dev *add_device( 
    264277#endif 
    265278 
    266279        if (IS_ERR(bdev)) { 
    267                 ERROR("error: cannot open device %s", devname); 
    268                 goto devinit_err; 
     280                ERROR("error: cannot open device %s", dev->devname); 
     281                return 1; 
    269282        } 
    270283        dev->blkdev = bdev; 
    271284 
    272285        if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { 
    273286                ERROR("attempting to use an MTD device as a block device"); 
    274                 goto devinit_err; 
     287                return 1; 
    275288        } 
    276289 
     290        return 0; 
     291} 
     292 
     293static void _close_bdev(struct block2mtd_dev *dev) 
     294{ 
     295        struct block_device *bdev; 
     296 
     297        if (!dev->blkdev) 
     298                return; 
     299 
     300        bdev = dev->blkdev; 
     301        invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); 
     302        close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); 
     303        dev->blkdev = NULL; 
     304} 
     305 
     306static void block2mtd_free_device(struct block2mtd_dev *dev) 
     307{ 
     308        if (!dev) 
     309                return; 
     310 
     311        kfree(dev->mtd.name); 
     312        _close_bdev(dev); 
     313        kfree(dev); 
     314} 
     315 
     316 
     317static int block2mtd_refresh(struct mtd_info *mtd) 
     318{ 
     319        struct block2mtd_dev *dev = mtd->priv; 
     320        struct block_device *bdev; 
     321        dev_t devt; 
     322        int err = 0; 
     323 
     324        /* no other mtd function can run at this point */ 
     325        write_lock(&dev->bdev_mutex); 
     326 
     327        /* get the device number for the whole disk */ 
     328        devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0); 
     329 
     330        /* close the old block device */ 
     331        _close_bdev(dev); 
     332 
     333        /* open the whole disk, issue a partition rescan, then */ 
     334        bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 
     335        if (!bdev || !bdev->bd_disk) 
     336                err = -EINVAL; 
     337#ifndef CONFIG_MTD_BLOCK2MTD_MODULE 
     338        else 
     339                err = rescan_partitions(bdev->bd_disk, bdev); 
     340#endif 
     341        if (bdev) 
     342                close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE); 
     343 
     344        /* try to open the partition block device again */ 
     345        _open_bdev(dev); 
     346        write_unlock(&dev->bdev_mutex); 
     347 
     348        return err; 
     349} 
     350 
     351/* FIXME: ensure that mtd->size % erase_size == 0 */ 
     352static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname) 
     353{ 
     354        struct block2mtd_dev *dev; 
     355        struct mtd_partition *part; 
     356        char *name; 
     357 
     358        if (!devname) 
     359                return NULL; 
     360 
     361        dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL); 
     362        if (!dev) 
     363                return NULL; 
     364 
     365        strcpy(dev->devname, devname); 
     366 
     367        if (_open_bdev(dev)) 
     368                goto devinit_err; 
     369 
    277370        mutex_init(&dev->write_mutex); 
     371        rwlock_init(&dev->bdev_mutex); 
    278372 
    279373        /* Setup the MTD structure */ 
    280374        /* make the name contain the block device in */ 
    static struct block2mtd_dev *add_device( 
    299393        dev->mtd.read = block2mtd_read; 
    300394        dev->mtd.priv = dev; 
    301395        dev->mtd.owner = THIS_MODULE; 
     396        dev->mtd.refresh_device = block2mtd_refresh; 
    302397 
    303398        part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); 
    304399        part->name = dev->mtd.name; 
  • drivers/mtd/mtdchar.c

    a b  
    3030#include <linux/backing-dev.h> 
    3131#include <linux/compat.h> 
    3232#include <linux/mount.h> 
     33#include <linux/mtd/partitions.h> 
    3334 
    3435#include <linux/mtd/mtd.h> 
    3536#include <linux/mtd/map.h> 
    static int mtd_ioctl(struct file *file,  
    854855                file->f_pos = 0; 
    855856                break; 
    856857        } 
     858#ifdef CONFIG_MTD_PARTITIONS 
     859        case MTDREFRESH: 
     860        { 
     861                ret = refresh_mtd_partitions(mtd); 
     862                break; 
     863        } 
     864#endif 
    857865 
    858866        default: 
    859867                ret = -ENOTTY; 
  • include/linux/mtd/mtd.h

    a b struct mtd_oob_ops { 
    110110        uint8_t         *oobbuf; 
    111111}; 
    112112 
     113struct mtd_info; 
    113114struct mtd_info { 
    114115        u_char type; 
    115116        uint32_t flags; 
    struct mtd_info { 
    251252        struct device dev; 
    252253        int usecount; 
    253254 
     255        int (*refresh_device)(struct mtd_info *mtd); 
     256        struct mtd_info *split; 
     257 
    254258        /* If the driver is something smart, like UBI, it may need to maintain 
    255259         * its own reference counting. The below functions are only for driver. 
    256260         * 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 */ 
    4041        uint64_t offset;                /* offset within the master MTD space */ 
    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)*/ 
     44        int (*refresh_partition)(struct mtd_info *); 
    4345}; 
    4446 
    4547#define MTDPART_OFS_NXTBLK      (-2) 
    struct mtd_info; 
    5153 
    5254int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); 
    5355int del_mtd_partitions(struct mtd_info *); 
     56int refresh_mtd_partitions(struct mtd_info *); 
    5457 
    5558/* 
    5659 * Functions dealing with the various ways of partitioning the space 
  • include/mtd/mtd-abi.h

    a b struct otp_info { 
    126126#define MEMWRITEOOB64           _IOWR('M', 21, struct mtd_oob_buf64) 
    127127#define MEMREADOOB64            _IOWR('M', 22, struct mtd_oob_buf64) 
    128128#define MEMISLOCKED             _IOR('M', 23, struct erase_info_user) 
     129#define MTDREFRESH              _IO('M', 50) 
    129130 
    130131/* 
    131132 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.