source: trunk/target/linux/generic/patches-2.6.38/065-rootfs_split.patch @ 26194

Last change on this file since 26194 was 26194, checked in by nbd, 6 years ago

kernel: refresh 2.6.38 patches for final release

File size: 15.5 KB
  • drivers/mtd/Kconfig

    a b config MTD_PARTITIONS 
    5555 
    5656if MTD_PARTITIONS 
    5757 
     58config MTD_ROOTFS_ROOT_DEV 
     59        bool "Automatically set 'rootfs' partition to be root filesystem" 
     60        depends on MTD_PARTITIONS 
     61        default y 
     62 
     63config MTD_ROOTFS_SPLIT 
     64        bool "Automatically split 'rootfs' partition for squashfs" 
     65        depends on MTD_PARTITIONS 
     66        default y 
     67 
    5868config MTD_REDBOOT_PARTS 
    5969        tristate "RedBoot partition table parsing" 
    6070        ---help--- 
  • drivers/mtd/mtdpart.c

    a b  
    2929#include <linux/kmod.h> 
    3030#include <linux/mtd/mtd.h> 
    3131#include <linux/mtd/partitions.h> 
     32#include <linux/root_dev.h> 
     33#include <linux/magic.h> 
    3234#include <linux/err.h> 
    3335 
    3436/* Our partition linked list */ 
    struct mtd_part { 
    4850 * the pointer to that structure with this macro. 
    4951 */ 
    5052#define PART(x)  ((struct mtd_part *)(x)) 
    51  
     53#define IS_PART(mtd) (mtd->read == part_read) 
    5254 
    5355/* 
    5456 * MTD methods which simply translate the effective address and pass through 
    int mtd_del_partition(struct mtd_info *m 
    636638} 
    637639EXPORT_SYMBOL_GPL(mtd_del_partition); 
    638640 
     641#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     642#define ROOTFS_SPLIT_NAME "rootfs_data" 
     643#define ROOTFS_REMOVED_NAME "<removed>" 
     644 
     645struct squashfs_super_block { 
     646        __le32 s_magic; 
     647        __le32 pad0[9]; 
     648        __le64 bytes_used; 
     649}; 
     650 
     651 
     652static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     653{ 
     654        struct squashfs_super_block sb; 
     655        int len, ret; 
     656 
     657        ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); 
     658        if (ret || (len != sizeof(sb))) { 
     659                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     660                        "from \"%s\"\n", master->name); 
     661                return -EINVAL; 
     662        } 
     663 
     664        if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { 
     665                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     666                        master->name); 
     667                *split_offset = 0; 
     668                return 0; 
     669        } 
     670 
     671        if (le64_to_cpu((sb.bytes_used)) <= 0) { 
     672                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     673                        master->name); 
     674                *split_offset = 0; 
     675                return 0; 
     676        } 
     677 
     678        len = (u32) le64_to_cpu(sb.bytes_used); 
     679        len += (offset & 0x000fffff); 
     680        len +=  (master->erasesize - 1); 
     681        len &= ~(master->erasesize - 1); 
     682        len -= (offset & 0x000fffff); 
     683        *split_offset = offset + len; 
     684 
     685        return 0; 
     686} 
     687 
     688static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part) 
     689{ 
     690        struct mtd_partition *dpart; 
     691        struct mtd_part *slave = NULL; 
     692        int ret, split_offset = 0; 
     693 
     694        ret = split_squashfs(master, part->offset, &split_offset); 
     695        if (ret) 
     696                return ret; 
     697 
     698        if (split_offset <= 0) 
     699                return 0; 
     700 
     701        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     702        if (dpart == NULL) { 
     703                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     704                        ROOTFS_SPLIT_NAME); 
     705                return -ENOMEM; 
     706        } 
     707 
     708        memcpy(dpart, part, sizeof(*part)); 
     709        dpart->name = (unsigned char *)&dpart[1]; 
     710        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     711 
     712        dpart->size -= split_offset - dpart->offset; 
     713        dpart->offset = split_offset; 
     714 
     715        if (dpart == NULL) 
     716                return 1; 
     717 
     718        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     719                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     720 
     721        slave = allocate_partition(master, dpart, 0, split_offset); 
     722        if (IS_ERR(slave)) 
     723                return PTR_ERR(slave); 
     724        mutex_lock(&mtd_partitions_mutex); 
     725        list_add(&slave->list, &mtd_partitions); 
     726        mutex_unlock(&mtd_partitions_mutex); 
     727 
     728        add_mtd_device(&slave->mtd); 
     729 
     730        rpart->split = &slave->mtd; 
     731 
     732        return 0; 
     733} 
     734 
     735static int refresh_rootfs_split(struct mtd_info *mtd) 
     736{ 
     737        struct mtd_partition tpart; 
     738        struct mtd_part *part; 
     739        char *name; 
     740        //int index = 0; 
     741        int offset, size; 
     742        int ret; 
     743 
     744        part = PART(mtd); 
     745 
     746        /* check for the new squashfs offset first */ 
     747        ret = split_squashfs(part->master, part->offset, &offset); 
     748        if (ret) 
     749                return ret; 
     750 
     751        if ((offset > 0) && !mtd->split) { 
     752                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     753                /* if we don't have a rootfs split partition, create a new one */ 
     754                tpart.name = (char *) mtd->name; 
     755                tpart.size = mtd->size; 
     756                tpart.offset = part->offset; 
     757 
     758                return split_rootfs_data(part->master, &part->mtd, &tpart); 
     759        } else if ((offset > 0) && mtd->split) { 
     760                /* update the offsets of the existing partition */ 
     761                size = mtd->size + part->offset - offset; 
     762 
     763                part = PART(mtd->split); 
     764                part->offset = offset; 
     765                part->mtd.size = size; 
     766                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     767                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     768                        (u32) part->offset, (u32) part->mtd.size); 
     769                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     770                strcpy(name, ROOTFS_SPLIT_NAME); 
     771                part->mtd.name = name; 
     772        } else if ((offset <= 0) && mtd->split) { 
     773                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     774 
     775                /* mark existing partition as removed */ 
     776                part = PART(mtd->split); 
     777                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     778                strcpy(name, ROOTFS_REMOVED_NAME); 
     779                part->mtd.name = name; 
     780                part->offset = 0; 
     781                part->mtd.size = 0; 
     782        } 
     783 
     784        return 0; 
     785} 
     786#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     787 
    639788/* 
    640789 * This function, given a master MTD object and a partition table, creates 
    641790 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    652801        struct mtd_part *slave; 
    653802        uint64_t cur_offset = 0; 
    654803        int i; 
     804#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     805        int ret; 
     806#endif 
    655807 
    656808        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    657809 
    int add_mtd_partitions(struct mtd_info * 
    666818 
    667819                add_mtd_device(&slave->mtd); 
    668820 
     821                if (!strcmp(parts[i].name, "rootfs")) { 
     822#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     823                        if (ROOT_DEV == 0) { 
     824                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     825                                        "set to be root filesystem\n"); 
     826                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     827                        } 
     828#endif 
     829#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     830                        ret = split_rootfs_data(master, &slave->mtd, &parts[i]); 
     831                        /* if (ret == 0) 
     832                         *      j++; */ 
     833#endif 
     834                } 
     835 
    669836                cur_offset = slave->offset + slave->mtd.size; 
    670837        } 
    671838 
    int add_mtd_partitions(struct mtd_info * 
    673840} 
    674841EXPORT_SYMBOL(add_mtd_partitions); 
    675842 
     843int refresh_mtd_partitions(struct mtd_info *mtd) 
     844{ 
     845        int ret = 0; 
     846 
     847        if (IS_PART(mtd)) { 
     848                struct mtd_part *part; 
     849                struct mtd_info *master; 
     850 
     851                part = PART(mtd); 
     852                master = part->master; 
     853                if (master->refresh_device) 
     854                        ret = master->refresh_device(master); 
     855        } 
     856 
     857        if (!ret && mtd->refresh_device) 
     858                ret = mtd->refresh_device(mtd); 
     859 
     860#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     861        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     862                refresh_rootfs_split(mtd); 
     863#endif 
     864 
     865        return 0; 
     866} 
     867EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     868 
    676869static DEFINE_SPINLOCK(part_parser_lock); 
    677870static LIST_HEAD(part_parsers); 
    678871 
  • 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 
    93101                instr->state = MTD_ERASE_DONE; 
    94102 
    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; 
     249        read_lock(&dev->bdev_mutex); 
     250        if (dev->blkdev) 
    213251        sync_blockdev(dev->blkdev); 
     252        read_unlock(&dev->bdev_mutex); 
     253 
    214254        return; 
    215255} 
    216256 
    217257 
     258static int _open_bdev(struct block2mtd_dev *dev) 
     259{ 
     260        const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; 
     261        struct block_device *bdev; 
     262 
     263        /* Get a handle on the device */ 
     264        bdev = blkdev_get_by_path(dev->devname, mode, dev); 
     265#ifndef MODULE 
     266        if (IS_ERR(bdev)) { 
     267 
     268                /* We might not have rootfs mounted at this point. Try 
     269                   to resolve the device name by other means. */ 
     270 
     271                dev_t devt = name_to_dev_t(dev->devname); 
     272                if (devt) 
     273                        bdev = blkdev_get_by_dev(devt, mode, dev); 
     274        } 
     275#endif 
     276 
     277        if (IS_ERR(bdev)) { 
     278                ERROR("error: cannot open device %s", dev->devname); 
     279                return 1; 
     280        } 
     281        dev->blkdev = bdev; 
     282 
     283        if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { 
     284                ERROR("attempting to use an MTD device as a block device"); 
     285                return 1; 
     286        } 
     287 
     288        return 0; 
     289} 
     290 
     291static void _close_bdev(struct block2mtd_dev *dev) 
     292{ 
     293        struct block_device *bdev; 
     294 
     295        if (!dev->blkdev) 
     296                return; 
     297 
     298        bdev = dev->blkdev; 
     299        invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1); 
     300        blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); 
     301        dev->blkdev = NULL; 
     302} 
     303 
    218304static void block2mtd_free_device(struct block2mtd_dev *dev) 
    219305{ 
    220306        if (!dev) 
    221307                return; 
    222308 
    223309        kfree(dev->mtd.name); 
    224  
    225         if (dev->blkdev) { 
    226                 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 
    227                                         0, -1); 
    228                 blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); 
    229         } 
    230  
     310        _close_bdev(dev); 
    231311        kfree(dev); 
    232312} 
    233313 
    234314 
    235 /* FIXME: ensure that mtd->size % erase_size == 0 */ 
    236 static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) 
     315static int block2mtd_refresh(struct mtd_info *mtd) 
    237316{ 
    238         const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; 
     317        struct block2mtd_dev *dev = mtd->priv; 
    239318        struct block_device *bdev; 
     319        dev_t devt; 
     320        int err = 0; 
     321 
     322        /* no other mtd function can run at this point */ 
     323        write_lock(&dev->bdev_mutex); 
     324 
     325        /* get the device number for the whole disk */ 
     326        devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0); 
     327 
     328        /* close the old block device */ 
     329        _close_bdev(dev); 
     330 
     331        /* open the whole disk, issue a partition rescan, then */ 
     332        bdev = blkdev_get_by_dev(devt, FMODE_WRITE | FMODE_READ); 
     333        if (!bdev || !bdev->bd_disk) 
     334                err = -EINVAL; 
     335#ifndef CONFIG_MTD_BLOCK2MTD_MODULE 
     336        else 
     337                err = rescan_partitions(bdev->bd_disk, bdev); 
     338#endif 
     339        if (bdev) 
     340                blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); 
     341 
     342        /* try to open the partition block device again */ 
     343        _open_bdev(dev); 
     344        write_unlock(&dev->bdev_mutex); 
     345 
     346        return err; 
     347} 
     348 
     349/* FIXME: ensure that mtd->size % erase_size == 0 */ 
     350static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname) 
     351{ 
    240352        struct block2mtd_dev *dev; 
    241353        struct mtd_partition *part; 
    242354        char *name; 
    static struct block2mtd_dev *add_device( 
    244356        if (!devname) 
    245357                return NULL; 
    246358 
    247         dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); 
     359        dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL); 
    248360        if (!dev) 
    249361                return NULL; 
    250362 
    251         /* Get a handle on the device */ 
    252         bdev = blkdev_get_by_path(devname, mode, dev); 
    253 #ifndef MODULE 
    254         if (IS_ERR(bdev)) { 
    255  
    256                 /* We might not have rootfs mounted at this point. Try 
    257                    to resolve the device name by other means. */ 
     363        strcpy(dev->devname, devname); 
    258364 
    259                 dev_t devt = name_to_dev_t(devname); 
    260                 if (devt) 
    261                         bdev = blkdev_get_by_dev(devt, mode, dev); 
    262         } 
    263 #endif 
    264  
    265         if (IS_ERR(bdev)) { 
    266                 ERROR("error: cannot open device %s", devname); 
     365        if (_open_bdev(dev)) 
    267366                goto devinit_err; 
    268         } 
    269         dev->blkdev = bdev; 
    270  
    271         if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { 
    272                 ERROR("attempting to use an MTD device as a block device"); 
    273                 goto devinit_err; 
    274         } 
    275367 
    276368        mutex_init(&dev->write_mutex); 
     369        rwlock_init(&dev->bdev_mutex); 
    277370 
    278371        /* Setup the MTD structure */ 
    279372        /* make the name contain the block device in */ 
    static struct block2mtd_dev *add_device( 
    298391        dev->mtd.read = block2mtd_read; 
    299392        dev->mtd.priv = dev; 
    300393        dev->mtd.owner = THIS_MODULE; 
     394        dev->mtd.refresh_device = block2mtd_refresh; 
    301395 
    302396        part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); 
    303397        part->name = dev->mtd.name; 
  • drivers/mtd/mtdchar.c

    a b static int mtd_ioctl(struct file *file,  
    841841                file->f_pos = 0; 
    842842                break; 
    843843        } 
     844#ifdef CONFIG_MTD_PARTITIONS 
     845        case MTDREFRESH: 
     846        { 
     847                ret = refresh_mtd_partitions(mtd); 
     848                break; 
     849        } 
     850#endif 
    844851 
    845852        case OTPGETREGIONCOUNT: 
    846853        case OTPGETREGIONINFO: 
  • include/linux/mtd/mtd.h

    a b struct nand_ecclayout { 
    125125        struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; 
    126126}; 
    127127 
     128struct mtd_info; 
    128129struct mtd_info { 
    129130        u_char type; 
    130131        uint32_t flags; 
    struct mtd_info { 
    277278        struct device dev; 
    278279        int usecount; 
    279280 
     281        int (*refresh_device)(struct mtd_info *mtd); 
     282        struct mtd_info *split; 
     283 
    280284        /* If the driver is something smart, like UBI, it may need to maintain 
    281285         * its own reference counting. The below functions are only for driver. 
    282286         * 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 { 
    127127#define MEMWRITEOOB64           _IOWR('M', 21, struct mtd_oob_buf64) 
    128128#define MEMREADOOB64            _IOWR('M', 22, struct mtd_oob_buf64) 
    129129#define MEMISLOCKED             _IOR('M', 23, struct erase_info_user) 
     130#define MTDREFRESH              _IO('M', 23) 
    130131 
    131132/* 
    132133 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.