source: trunk/target/linux/generic/patches-2.6.31/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.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', 50) 
    113114 
    114115/* 
    115116 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.