source: trunk/target/linux/generic-2.6/patches-2.6.27/065-rootfs_split.patch @ 12987

Last change on this file since 12987 was 12987, checked in by juhosg, 8 years ago

[kernel] refresh patches against 2.6.27 final

File size: 15.2 KB
  • drivers/mtd/Kconfig

    a b config MTD_PARTITIONS 
    4545          devices. Partitioning on NFTL 'devices' is a different - that's the 
    4646          'normal' form of partitioning used on a block device. 
    4747 
     48config MTD_ROOTFS_ROOT_DEV 
     49        bool "Automatically set 'rootfs' partition to be root filesystem" 
     50        depends on MTD_PARTITIONS 
     51        default y 
     52 
     53config MTD_ROOTFS_SPLIT 
     54        bool "Automatically split 'rootfs' partition for squashfs" 
     55        depends on MTD_PARTITIONS 
     56        default y 
     57 
    4858config MTD_REDBOOT_PARTS 
    4959        tristate "RedBoot partition table parsing" 
    5060        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/squashfs_fs.h> 
     22#include <linux/root_dev.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: 
    489491        return slave; 
    490492} 
    491493 
     494#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     495#define ROOTFS_SPLIT_NAME "rootfs_data" 
     496#define ROOTFS_REMOVED_NAME "<removed>" 
     497static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     498{ 
     499        char buf[512]; 
     500        struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; 
     501        int len, ret; 
     502 
     503        ret = master->read(master, offset, sizeof(*sb), &len, buf); 
     504        if (ret || (len != sizeof(*sb))) { 
     505                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     506                        "from \"%s\"\n", master->name); 
     507                return -EINVAL; 
     508        } 
     509 
     510        if (*((u32 *) buf) != SQUASHFS_MAGIC) { 
     511                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     512                        master->name); 
     513                *split_offset = 0; 
     514                return 0; 
     515        } 
     516 
     517        if (sb->bytes_used <= 0) { 
     518                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     519                        master->name); 
     520                *split_offset = 0; 
     521                return 0; 
     522        } 
     523 
     524        len = (u32) sb->bytes_used; 
     525        len += (offset & 0x000fffff); 
     526        len +=  (master->erasesize - 1); 
     527        len &= ~(master->erasesize - 1); 
     528        len -= (offset & 0x000fffff); 
     529        *split_offset = offset + len; 
     530 
     531        return 0; 
     532} 
     533 
     534static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part, 
     535                int index) 
     536{ 
     537        struct mtd_partition *dpart; 
     538        struct mtd_part *slave = NULL; 
     539        int split_offset = 0; 
     540        int ret; 
     541 
     542        ret = split_squashfs(master, part->offset, &split_offset); 
     543        if (ret) 
     544                return ret; 
     545 
     546        if (split_offset <= 0) 
     547                return 0; 
     548 
     549        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     550        if (dpart == NULL) { 
     551                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     552                        ROOTFS_SPLIT_NAME); 
     553                return -ENOMEM; 
     554        } 
     555 
     556        memcpy(dpart, part, sizeof(*part)); 
     557        dpart->name = (unsigned char *)&dpart[1]; 
     558        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     559 
     560        dpart->size -= split_offset - dpart->offset; 
     561        dpart->offset = split_offset; 
     562 
     563        if (dpart == NULL) 
     564                return 1; 
     565 
     566        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n", 
     567                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     568 
     569        slave = add_one_partition(master, dpart, index, split_offset); 
     570        if (!slave) { 
     571                kfree(dpart); 
     572                return -ENOMEM; 
     573        } 
     574        rpart->split = &slave->mtd; 
     575 
     576        return 0; 
     577} 
     578 
     579static int refresh_rootfs_split(struct mtd_info *mtd) 
     580{ 
     581        struct mtd_partition tpart; 
     582        struct mtd_part *part; 
     583        char *name; 
     584        int index = 0; 
     585        int offset, size; 
     586        int ret; 
     587 
     588        part = PART(mtd); 
     589 
     590        /* check for the new squashfs offset first */ 
     591        ret = split_squashfs(part->master, part->offset, &offset); 
     592        if (ret) 
     593                return ret; 
     594 
     595        if ((offset > 0) && !mtd->split) { 
     596                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     597                /* if we don't have a rootfs split partition, create a new one */ 
     598                tpart.name = (char *) mtd->name; 
     599                tpart.size = mtd->size; 
     600                tpart.offset = part->offset; 
     601 
     602                /* find the index of the last partition */ 
     603                if (!list_empty(&mtd_partitions)) 
     604                        index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1; 
     605 
     606                return split_rootfs_data(part->master, &part->mtd, &tpart, index); 
     607        } else if ((offset > 0) && mtd->split) { 
     608                /* update the offsets of the existing partition */ 
     609                size = mtd->size + part->offset - offset; 
     610 
     611                part = PART(mtd->split); 
     612                part->offset = offset; 
     613                part->mtd.size = size; 
     614                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     615                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     616                        part->offset, part->mtd.size); 
     617                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     618                strcpy(name, ROOTFS_SPLIT_NAME); 
     619                part->mtd.name = name; 
     620        } else if ((offset <= 0) && mtd->split) { 
     621                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     622 
     623                /* mark existing partition as removed */ 
     624                part = PART(mtd->split); 
     625                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     626                strcpy(name, ROOTFS_REMOVED_NAME); 
     627                part->mtd.name = name; 
     628                part->offset = 0; 
     629                part->mtd.size = 0; 
     630        } 
     631 
     632        return 0; 
     633} 
     634#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     635 
    492636/* 
    493637 * This function, given a master MTD object and a partition table, creates 
    494638 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    502646{ 
    503647        struct mtd_part *slave; 
    504648        u_int32_t cur_offset = 0; 
    505         int i; 
     649        int i, j, ret; 
    506650 
    507651        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    508652 
    509         for (i = 0; i < nbparts; i++) { 
    510                 slave = add_one_partition(master, parts + i, i, cur_offset); 
     653        for (i = 0, j = 0; i < nbparts; i++) { 
     654                slave = add_one_partition(master, parts + i, j++, cur_offset); 
    511655                if (!slave) 
    512656                        return -ENOMEM; 
     657 
     658                if (!strcmp(parts[i].name, "rootfs") && slave->registered) { 
     659#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     660                        if (ROOT_DEV == 0) { 
     661                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     662                                        "set to be root filesystem\n"); 
     663                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     664                        } 
     665#endif 
     666#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     667                        ret = split_rootfs_data(master, &slave->mtd, &parts[i], j); 
     668                        if (ret == 0) 
     669                                j++; 
     670#endif 
     671                } 
    513672                cur_offset = slave->offset + slave->mtd.size; 
    514673        } 
    515674 
    int add_mtd_partitions(struct mtd_info * 
    517676} 
    518677EXPORT_SYMBOL(add_mtd_partitions); 
    519678 
     679int refresh_mtd_partitions(struct mtd_info *mtd) 
     680{ 
     681        int ret = 0; 
     682 
     683        if (IS_PART(mtd)) { 
     684                struct mtd_part *part; 
     685                struct mtd_info *master; 
     686 
     687                part = PART(mtd); 
     688                master = part->master; 
     689                if (master->refresh_device) 
     690                        ret = master->refresh_device(master); 
     691        } 
     692 
     693        if (!ret && mtd->refresh_device) 
     694                ret = mtd->refresh_device(mtd); 
     695 
     696#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     697        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     698                refresh_rootfs_split(mtd); 
     699#endif 
     700 
     701        return 0; 
     702} 
     703EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     704 
    520705static DEFINE_SPINLOCK(part_parser_lock); 
    521706static LIST_HEAD(part_parsers); 
    522707 
  • 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); 
     249 
     250        read_lock(&dev->bdev_mutex); 
     251        if (dev->blkdev) 
     252                sync_blockdev(dev->blkdev); 
     253        read_unlock(&dev->bdev_mutex); 
     254 
    214255        return; 
    215256} 
    216257 
    static void block2mtd_free_device(struct 
    231272        kfree(dev); 
    232273} 
    233274 
    234  
    235 /* FIXME: ensure that mtd->size % erase_size == 0 */ 
    236 static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) 
     275static int _open_bdev(struct block2mtd_dev *dev) 
    237276{ 
    238277        struct block_device *bdev; 
    239278        struct block2mtd_dev *dev; 
    240279        struct mtd_partition *part; 
    241280        char *name; 
    242281 
    243         if (!devname) 
    244                 return NULL; 
    245  
    246         dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 
    247         if (!dev) 
    248                 return NULL; 
    249  
    250282        /* Get a handle on the device */ 
    251         bdev = open_bdev_excl(devname, O_RDWR, NULL); 
     283        bdev = open_bdev_excl(dev->devname, O_RDWR, NULL); 
    252284#ifndef MODULE 
    253285        if (IS_ERR(bdev)) { 
    254286 
    255287                /* We might not have rootfs mounted at this point. Try 
    256288                   to resolve the device name by other means. */ 
    257289 
    258                 dev_t devt = name_to_dev_t(devname); 
     290                dev_t devt = name_to_dev_t(dev->devname); 
    259291                if (devt) { 
    260292                        bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 
    261293                } 
    static struct block2mtd_dev *add_device( 
    263295#endif 
    264296 
    265297        if (IS_ERR(bdev)) { 
    266                 ERROR("error: cannot open device %s", devname); 
    267                 goto devinit_err; 
     298                ERROR("error: cannot open device %s", dev->devname); 
     299                return 1; 
    268300        } 
    269301        dev->blkdev = bdev; 
    270302 
    271303        if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { 
    272304                ERROR("attempting to use an MTD device as a block device"); 
    273                 goto devinit_err; 
     305                return 1; 
    274306        } 
    275307 
     308        return 0; 
     309} 
     310 
     311static void _close_bdev(struct block2mtd_dev *dev) 
     312{ 
     313        struct block_device *bdev; 
     314 
     315        if (!dev->blkdev) 
     316                return; 
     317 
     318        bdev = dev->blkdev; 
     319        invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); 
     320        close_bdev_excl(dev->blkdev); 
     321        dev->blkdev = NULL; 
     322} 
     323 
     324static void block2mtd_free_device(struct block2mtd_dev *dev) 
     325{ 
     326        if (!dev) 
     327                return; 
     328 
     329        kfree(dev->mtd.name); 
     330        _close_bdev(dev); 
     331        kfree(dev); 
     332} 
     333 
     334 
     335static int block2mtd_refresh(struct mtd_info *mtd) 
     336{ 
     337        struct block2mtd_dev *dev = mtd->priv; 
     338        struct block_device *bdev; 
     339        dev_t devt; 
     340        int err = 0; 
     341 
     342        /* no other mtd function can run at this point */ 
     343        write_lock(&dev->bdev_mutex); 
     344 
     345        /* get the device number for the whole disk */ 
     346        devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0); 
     347 
     348        /* close the old block device */ 
     349        _close_bdev(dev); 
     350 
     351        /* open the whole disk, issue a partition rescan, then */ 
     352        bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 
     353        if (!bdev || !bdev->bd_disk) 
     354                err = -EINVAL; 
     355        else { 
     356                err = rescan_partitions(bdev->bd_disk, bdev); 
     357        } 
     358        if (bdev) 
     359                close_bdev_excl(bdev); 
     360 
     361        /* try to open the partition block device again */ 
     362        _open_bdev(dev); 
     363        write_unlock(&dev->bdev_mutex); 
     364 
     365        return err; 
     366} 
     367 
     368/* FIXME: ensure that mtd->size % erase_size == 0 */ 
     369static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname) 
     370{ 
     371        struct block2mtd_dev *dev; 
     372        struct mtd_partition *part; 
     373 
     374        if (!devname) 
     375                return NULL; 
     376 
     377        dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL); 
     378        if (!dev) 
     379                return NULL; 
     380 
     381        strcpy(dev->devname, devname); 
     382 
     383        if (_open_bdev(dev)) 
     384                goto devinit_err; 
     385 
    276386        mutex_init(&dev->write_mutex); 
     387        rwlock_init(&dev->bdev_mutex); 
    277388 
    278389        if (!mtdname) 
    279390                mtdname = devname; 
    static struct block2mtd_dev *add_device( 
    297408        dev->mtd.read = block2mtd_read; 
    298409        dev->mtd.priv = dev; 
    299410        dev->mtd.owner = THIS_MODULE; 
     411        dev->mtd.refresh_device = block2mtd_refresh; 
    300412 
    301413        part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); 
    302414        part->name = dev->mtd.name; 
  • drivers/mtd/mtdchar.c

    a b  
    1616 
    1717#include <linux/mtd/mtd.h> 
    1818#include <linux/mtd/compatmac.h> 
     19#include <linux/mtd/partitions.h> 
    1920 
    2021#include <asm/uaccess.h> 
    2122 
    static int mtd_ioctl(struct inode *inode 
    771772                file->f_pos = 0; 
    772773                break; 
    773774        } 
     775#ifdef CONFIG_MTD_PARTITIONS 
     776        case MTDREFRESH: 
     777        { 
     778                ret = refresh_mtd_partitions(mtd); 
     779                break; 
     780        } 
     781#endif 
    774782 
    775783        default: 
    776784                ret = -ENOTTY; 
  • include/linux/mtd/mtd.h

    a b struct mtd_oob_ops { 
    9696        uint8_t         *oobbuf; 
    9797}; 
    9898 
     99struct mtd_info; 
    99100struct mtd_info { 
    100101        u_char type; 
    101102        u_int32_t flags; 
    struct mtd_info { 
    211212        struct module *owner; 
    212213        int usecount; 
    213214 
     215        int (*refresh_device)(struct mtd_info *mtd); 
     216        struct mtd_info *split; 
     217 
    214218        /* If the driver is something smart, like UBI, it may need to maintain 
    215219         * its own reference counting. The below functions are only for driver. 
    216220         * 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        u_int32_t size;                 /* partition size */ 
    struct mtd_partition { 
    4142        u_int32_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 { 
    9393#define ECCGETLAYOUT            _IOR('M', 17, struct nand_ecclayout) 
    9494#define ECCGETSTATS             _IOR('M', 18, struct mtd_ecc_stats) 
    9595#define MTDFILEMODE             _IO('M', 19) 
     96#define MTDREFRESH              _IO('M', 23) 
    9697 
    9798/* 
    9899 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.