source: trunk/target/linux/generic/patches-2.6.31/065-rootfs_split.patch @ 26705

Last change on this file since 26705 was 26705, checked in by nbd, 5 years ago

rootfs_split: Allow using MTDPART_OFS_APPEND macro for offset of rootfs.

Use offset from struct mtd_part instead of struct mtd_partition for defining
the new partitions. This enables the usage of MTDPART_OFS_APPEND macro in
struct mtd_partition.

Signed-off-by: Jochen Friedrich <jochen@…>

File size: 15.4 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 { 
    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: 
    502504        return slave; 
    503505} 
    504506 
     507#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     508#define ROOTFS_SPLIT_NAME "rootfs_data" 
     509#define ROOTFS_REMOVED_NAME "<removed>" 
     510 
     511struct squashfs_super_block { 
     512        __le32 s_magic; 
     513        __le32 pad0[9]; 
     514        __le64 bytes_used; 
     515}; 
     516 
     517 
     518static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     519{ 
     520        struct squashfs_super_block sb; 
     521        int len, ret; 
     522 
     523        ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); 
     524        if (ret || (len != sizeof(sb))) { 
     525                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     526                        "from \"%s\"\n", master->name); 
     527                return -EINVAL; 
     528        } 
     529 
     530        if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { 
     531                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     532                        master->name); 
     533                *split_offset = 0; 
     534                return 0; 
     535        } 
     536 
     537        if (le64_to_cpu((sb.bytes_used)) <= 0) { 
     538                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     539                        master->name); 
     540                *split_offset = 0; 
     541                return 0; 
     542        } 
     543 
     544        len = (u32) le64_to_cpu(sb.bytes_used); 
     545        len += (offset & 0x000fffff); 
     546        len +=  (master->erasesize - 1); 
     547        len &= ~(master->erasesize - 1); 
     548        len -= (offset & 0x000fffff); 
     549        *split_offset = offset + len; 
     550 
     551        return 0; 
     552} 
     553 
     554static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part) 
     555{ 
     556        struct mtd_partition *dpart; 
     557        struct mtd_part *slave = NULL; 
     558        struct mtd_part *spart; 
     559        int split_offset = 0; 
     560        int ret; 
     561 
     562        spart = PART(rpart); 
     563        ret = split_squashfs(master, spart->offset, &split_offset); 
     564        if (ret) 
     565                return ret; 
     566 
     567        if (split_offset <= 0) 
     568                return 0; 
     569 
     570        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     571        if (dpart == NULL) { 
     572                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     573                        ROOTFS_SPLIT_NAME); 
     574                return -ENOMEM; 
     575        } 
     576 
     577        memcpy(dpart, part, sizeof(*part)); 
     578        dpart->name = (unsigned char *)&dpart[1]; 
     579        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     580 
     581        dpart->size = rpart->size - (split_offset - spart->offset); 
     582        dpart->offset = split_offset; 
     583 
     584        if (dpart == NULL) 
     585                return 1; 
     586 
     587        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     588                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     589 
     590        slave = add_one_partition(master, dpart, 0, split_offset); 
     591        if (!slave) { 
     592                kfree(dpart); 
     593                return -ENOMEM; 
     594        } 
     595        rpart->split = &slave->mtd; 
     596 
     597        return 0; 
     598} 
     599 
     600static int refresh_rootfs_split(struct mtd_info *mtd) 
     601{ 
     602        struct mtd_partition tpart; 
     603        struct mtd_part *part; 
     604        char *name; 
     605        //int index = 0; 
     606        int offset, size; 
     607        int ret; 
     608 
     609        part = PART(mtd); 
     610 
     611        /* check for the new squashfs offset first */ 
     612        ret = split_squashfs(part->master, part->offset, &offset); 
     613        if (ret) 
     614                return ret; 
     615 
     616        if ((offset > 0) && !mtd->split) { 
     617                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     618                /* if we don't have a rootfs split partition, create a new one */ 
     619                tpart.name = (char *) mtd->name; 
     620                tpart.size = mtd->size; 
     621                tpart.offset = part->offset; 
     622 
     623                return split_rootfs_data(part->master, &part->mtd, &tpart); 
     624        } else if ((offset > 0) && mtd->split) { 
     625                /* update the offsets of the existing partition */ 
     626                size = mtd->size + part->offset - offset; 
     627 
     628                part = PART(mtd->split); 
     629                part->offset = offset; 
     630                part->mtd.size = size; 
     631                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     632                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     633                        (u32) part->offset, (u32) part->mtd.size); 
     634                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     635                strcpy(name, ROOTFS_SPLIT_NAME); 
     636                part->mtd.name = name; 
     637        } else if ((offset <= 0) && mtd->split) { 
     638                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     639 
     640                /* mark existing partition as removed */ 
     641                part = PART(mtd->split); 
     642                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     643                strcpy(name, ROOTFS_REMOVED_NAME); 
     644                part->mtd.name = name; 
     645                part->offset = 0; 
     646                part->mtd.size = 0; 
     647        } 
     648 
     649        return 0; 
     650} 
     651#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     652 
    505653/* 
    506654 * This function, given a master MTD object and a partition table, creates 
    507655 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    517665{ 
    518666        struct mtd_part *slave; 
    519667        uint64_t cur_offset = 0; 
    520         int i; 
     668        int i, ret; 
    521669 
    522670        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    523671 
    int add_mtd_partitions(struct mtd_info * 
    525673                slave = add_one_partition(master, parts + i, i, cur_offset); 
    526674                if (!slave) 
    527675                        return -ENOMEM; 
     676 
     677                if (!strcmp(parts[i].name, "rootfs")) { 
     678#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     679                        if (ROOT_DEV == 0) { 
     680                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     681                                        "set to be root filesystem\n"); 
     682                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     683                        } 
     684#endif 
     685#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     686                        ret = split_rootfs_data(master, &slave->mtd, &parts[i]); 
     687                        /* if (ret == 0) 
     688                                j++; */ 
     689#endif 
     690                } 
    528691                cur_offset = slave->offset + slave->mtd.size; 
    529692        } 
    530693 
    int add_mtd_partitions(struct mtd_info * 
    532695} 
    533696EXPORT_SYMBOL(add_mtd_partitions); 
    534697 
     698int refresh_mtd_partitions(struct mtd_info *mtd) 
     699{ 
     700        int ret = 0; 
     701 
     702        if (IS_PART(mtd)) { 
     703                struct mtd_part *part; 
     704                struct mtd_info *master; 
     705 
     706                part = PART(mtd); 
     707                master = part->master; 
     708                if (master->refresh_device) 
     709                        ret = master->refresh_device(master); 
     710        } 
     711 
     712        if (!ret && mtd->refresh_device) 
     713                ret = mtd->refresh_device(mtd); 
     714 
     715#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     716        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     717                refresh_rootfs_split(mtd); 
     718#endif 
     719 
     720        return 0; 
     721} 
     722EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     723 
    535724static DEFINE_SPINLOCK(part_parser_lock); 
    536725static LIST_HEAD(part_parsers); 
    537726 
  • 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  
    1818 
    1919#include <linux/mtd/mtd.h> 
    2020#include <linux/mtd/compatmac.h> 
     21#include <linux/mtd/partitions.h> 
    2122 
    2223#include <asm/uaccess.h> 
    2324 
    static int mtd_ioctl(struct inode *inode 
    814815                file->f_pos = 0; 
    815816                break; 
    816817        } 
     818#ifdef CONFIG_MTD_PARTITIONS 
     819        case MTDREFRESH: 
     820        { 
     821                ret = refresh_mtd_partitions(mtd); 
     822                break; 
     823        } 
     824#endif 
    817825 
    818826        default: 
    819827                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 */ 
    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.