source: trunk/target/linux/generic/patches-2.6.35/065-rootfs_split.patch @ 22540

Last change on this file since 22540 was 22540, checked in by florian, 6 years ago

[kernel] refresh 2.6.35 patches

File size: 15.4 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  
    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 { 
    3537 * the pointer to that structure with this macro. 
    3638 */ 
    3739#define PART(x)  ((struct mtd_part *)(x)) 
    38  
     40#define IS_PART(mtd) (mtd->read == part_read) 
    3941 
    4042/* 
    4143 * MTD methods which simply translate the effective address and pass through 
    out_register: 
    503505        return slave; 
    504506} 
    505507 
     508#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     509#define ROOTFS_SPLIT_NAME "rootfs_data" 
     510#define ROOTFS_REMOVED_NAME "<removed>" 
     511 
     512struct squashfs_super_block { 
     513        __le32 s_magic; 
     514        __le32 pad0[9]; 
     515        __le64 bytes_used; 
     516}; 
     517 
     518 
     519static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     520{ 
     521        struct squashfs_super_block sb; 
     522        int len, ret; 
     523 
     524        ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); 
     525        if (ret || (len != sizeof(sb))) { 
     526                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     527                        "from \"%s\"\n", master->name); 
     528                return -EINVAL; 
     529        } 
     530 
     531        if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { 
     532                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     533                        master->name); 
     534                *split_offset = 0; 
     535                return 0; 
     536        } 
     537 
     538        if (le64_to_cpu((sb.bytes_used)) <= 0) { 
     539                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     540                        master->name); 
     541                *split_offset = 0; 
     542                return 0; 
     543        } 
     544 
     545        len = (u32) le64_to_cpu(sb.bytes_used); 
     546        len += (offset & 0x000fffff); 
     547        len +=  (master->erasesize - 1); 
     548        len &= ~(master->erasesize - 1); 
     549        len -= (offset & 0x000fffff); 
     550        *split_offset = offset + len; 
     551 
     552        return 0; 
     553} 
     554 
     555static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part) 
     556{ 
     557        struct mtd_partition *dpart; 
     558        struct mtd_part *slave = NULL; 
     559        int split_offset = 0; 
     560        int ret; 
     561 
     562        ret = split_squashfs(master, part->offset, &split_offset); 
     563        if (ret) 
     564                return ret; 
     565 
     566        if (split_offset <= 0) 
     567                return 0; 
     568 
     569        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     570        if (dpart == NULL) { 
     571                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     572                        ROOTFS_SPLIT_NAME); 
     573                return -ENOMEM; 
     574        } 
     575 
     576        memcpy(dpart, part, sizeof(*part)); 
     577        dpart->name = (unsigned char *)&dpart[1]; 
     578        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     579 
     580        dpart->size -= split_offset - dpart->offset; 
     581        dpart->offset = split_offset; 
     582 
     583        if (dpart == NULL) 
     584                return 1; 
     585 
     586        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     587                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     588 
     589        slave = add_one_partition(master, dpart, 0, split_offset); 
     590        if (!slave) { 
     591                kfree(dpart); 
     592                return -ENOMEM; 
     593        } 
     594        rpart->split = &slave->mtd; 
     595 
     596        return 0; 
     597} 
     598 
     599static int refresh_rootfs_split(struct mtd_info *mtd) 
     600{ 
     601        struct mtd_partition tpart; 
     602        struct mtd_part *part; 
     603        char *name; 
     604        //int index = 0; 
     605        int offset, size; 
     606        int ret; 
     607 
     608        part = PART(mtd); 
     609 
     610        /* check for the new squashfs offset first */ 
     611        ret = split_squashfs(part->master, part->offset, &offset); 
     612        if (ret) 
     613                return ret; 
     614 
     615        if ((offset > 0) && !mtd->split) { 
     616                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     617                /* if we don't have a rootfs split partition, create a new one */ 
     618                tpart.name = (char *) mtd->name; 
     619                tpart.size = mtd->size; 
     620                tpart.offset = part->offset; 
     621 
     622                return split_rootfs_data(part->master, &part->mtd, &tpart); 
     623        } else if ((offset > 0) && mtd->split) { 
     624                /* update the offsets of the existing partition */ 
     625                size = mtd->size + part->offset - offset; 
     626 
     627                part = PART(mtd->split); 
     628                part->offset = offset; 
     629                part->mtd.size = size; 
     630                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     631                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     632                        (u32) part->offset, (u32) part->mtd.size); 
     633                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     634                strcpy(name, ROOTFS_SPLIT_NAME); 
     635                part->mtd.name = name; 
     636        } else if ((offset <= 0) && mtd->split) { 
     637                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     638 
     639                /* mark existing partition as removed */ 
     640                part = PART(mtd->split); 
     641                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     642                strcpy(name, ROOTFS_REMOVED_NAME); 
     643                part->mtd.name = name; 
     644                part->offset = 0; 
     645                part->mtd.size = 0; 
     646        } 
     647 
     648        return 0; 
     649} 
     650#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     651 
    506652/* 
    507653 * This function, given a master MTD object and a partition table, creates 
    508654 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    518664{ 
    519665        struct mtd_part *slave; 
    520666        uint64_t cur_offset = 0; 
    521         int i; 
     667        int i, ret; 
    522668 
    523669        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    524670 
    int add_mtd_partitions(struct mtd_info * 
    526672                slave = add_one_partition(master, parts + i, i, cur_offset); 
    527673                if (!slave) 
    528674                        return -ENOMEM; 
     675 
     676                if (!strcmp(parts[i].name, "rootfs")) { 
     677#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     678                        if (ROOT_DEV == 0) { 
     679                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     680                                        "set to be root filesystem\n"); 
     681                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     682                        } 
     683#endif 
     684#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     685                        ret = split_rootfs_data(master, &slave->mtd, &parts[i]); 
     686                        /* if (ret == 0) 
     687                                j++; */ 
     688#endif 
     689                } 
    529690                cur_offset = slave->offset + slave->mtd.size; 
    530691        } 
    531692 
    int add_mtd_partitions(struct mtd_info * 
    533694} 
    534695EXPORT_SYMBOL(add_mtd_partitions); 
    535696 
     697int refresh_mtd_partitions(struct mtd_info *mtd) 
     698{ 
     699        int ret = 0; 
     700 
     701        if (IS_PART(mtd)) { 
     702                struct mtd_part *part; 
     703                struct mtd_info *master; 
     704 
     705                part = PART(mtd); 
     706                master = part->master; 
     707                if (master->refresh_device) 
     708                        ret = master->refresh_device(master); 
     709        } 
     710 
     711        if (!ret && mtd->refresh_device) 
     712                ret = mtd->refresh_device(mtd); 
     713 
     714#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     715        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     716                refresh_rootfs_split(mtd); 
     717#endif 
     718 
     719        return 0; 
     720} 
     721EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     722 
    536723static DEFINE_SPINLOCK(part_parser_lock); 
    537724static LIST_HEAD(part_parsers); 
    538725 
  • 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  
    1919 
    2020#include <linux/mtd/mtd.h> 
    2121#include <linux/mtd/compatmac.h> 
     22#include <linux/mtd/partitions.h> 
    2223 
    2324#include <asm/uaccess.h> 
    2425 
    static int mtd_ioctl(struct file *file, 
    826827                file->f_pos = 0; 
    827828                break; 
    828829        } 
     830#ifdef CONFIG_MTD_PARTITIONS 
     831        case MTDREFRESH: 
     832        { 
     833                ret = refresh_mtd_partitions(mtd); 
     834                break; 
     835        } 
     836#endif 
    829837 
    830838        default: 
    831839                ret = -ENOTTY; 
  • include/linux/mtd/mtd.h

    a b struct mtd_oob_ops { 
    9898        uint8_t         *oobbuf; 
    9999}; 
    100100 
     101struct mtd_info; 
    101102struct mtd_info { 
    102103        u_char type; 
    103104        uint32_t flags; 
    struct mtd_info { 
    238239        struct device dev; 
    239240        int usecount; 
    240241 
     242        int (*refresh_device)(struct mtd_info *mtd); 
     243        struct mtd_info *split; 
     244 
    241245        /* If the driver is something smart, like UBI, it may need to maintain 
    242246         * its own reference counting. The below functions are only for driver. 
    243247         * 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 { 
    110110#define MEMERASE64              _IOW('M', 20, struct erase_info_user64) 
    111111#define MEMWRITEOOB64           _IOWR('M', 21, struct mtd_oob_buf64) 
    112112#define MEMREADOOB64            _IOWR('M', 22, struct mtd_oob_buf64) 
     113#define MTDREFRESH              _IO('M', 23) 
    113114 
    114115/* 
    115116 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.