source: trunk/target/linux/generic/patches-2.6.39/400-rootfs_split.patch @ 28893

Last change on this file since 28893 was 28893, checked in by jogo, 5 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: 9.0 KB
  • drivers/mtd/Kconfig

    a b config MTD_PARTITIONS 
    4747 
    4848if MTD_PARTITIONS 
    4949 
     50config MTD_ROOTFS_ROOT_DEV 
     51        bool "Automatically set 'rootfs' partition to be root filesystem" 
     52        depends on MTD_PARTITIONS 
     53        default y 
     54 
     55config MTD_ROOTFS_SPLIT 
     56        bool "Automatically split 'rootfs' partition for squashfs" 
     57        depends on MTD_PARTITIONS 
     58        default y 
     59 
    5060config MTD_REDBOOT_PARTS 
    5161        tristate "RedBoot partition table parsing" 
    5262        ---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        struct mtd_part *spart; 
     693        int ret, split_offset = 0; 
     694 
     695        spart = PART(rpart); 
     696        ret = split_squashfs(master, spart->offset, &split_offset); 
     697        if (ret) 
     698                return ret; 
     699 
     700        if (split_offset <= 0) 
     701                return 0; 
     702 
     703        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     704        if (dpart == NULL) { 
     705                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     706                        ROOTFS_SPLIT_NAME); 
     707                return -ENOMEM; 
     708        } 
     709 
     710        memcpy(dpart, part, sizeof(*part)); 
     711        dpart->name = (unsigned char *)&dpart[1]; 
     712        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     713 
     714        dpart->size = rpart->size - (split_offset - spart->offset); 
     715        dpart->offset = split_offset; 
     716 
     717        if (dpart == NULL) 
     718                return 1; 
     719 
     720        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     721                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     722 
     723        slave = allocate_partition(master, dpart, 0, split_offset); 
     724        if (IS_ERR(slave)) 
     725                return PTR_ERR(slave); 
     726        mutex_lock(&mtd_partitions_mutex); 
     727        list_add(&slave->list, &mtd_partitions); 
     728        mutex_unlock(&mtd_partitions_mutex); 
     729 
     730        add_mtd_device(&slave->mtd); 
     731 
     732        rpart->split = &slave->mtd; 
     733 
     734        return 0; 
     735} 
     736 
     737static int refresh_rootfs_split(struct mtd_info *mtd) 
     738{ 
     739        struct mtd_partition tpart; 
     740        struct mtd_part *part; 
     741        char *name; 
     742        //int index = 0; 
     743        int offset, size; 
     744        int ret; 
     745 
     746        part = PART(mtd); 
     747 
     748        /* check for the new squashfs offset first */ 
     749        ret = split_squashfs(part->master, part->offset, &offset); 
     750        if (ret) 
     751                return ret; 
     752 
     753        if ((offset > 0) && !mtd->split) { 
     754                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     755                /* if we don't have a rootfs split partition, create a new one */ 
     756                tpart.name = (char *) mtd->name; 
     757                tpart.size = mtd->size; 
     758                tpart.offset = part->offset; 
     759 
     760                return split_rootfs_data(part->master, &part->mtd, &tpart); 
     761        } else if ((offset > 0) && mtd->split) { 
     762                /* update the offsets of the existing partition */ 
     763                size = mtd->size + part->offset - offset; 
     764 
     765                part = PART(mtd->split); 
     766                part->offset = offset; 
     767                part->mtd.size = size; 
     768                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     769                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     770                        (u32) part->offset, (u32) part->mtd.size); 
     771                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     772                strcpy(name, ROOTFS_SPLIT_NAME); 
     773                part->mtd.name = name; 
     774        } else if ((offset <= 0) && mtd->split) { 
     775                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     776 
     777                /* mark existing partition as removed */ 
     778                part = PART(mtd->split); 
     779                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     780                strcpy(name, ROOTFS_REMOVED_NAME); 
     781                part->mtd.name = name; 
     782                part->offset = 0; 
     783                part->mtd.size = 0; 
     784        } 
     785 
     786        return 0; 
     787} 
     788#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     789 
    639790/* 
    640791 * This function, given a master MTD object and a partition table, creates 
    641792 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    652803        struct mtd_part *slave; 
    653804        uint64_t cur_offset = 0; 
    654805        int i; 
     806#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     807        int ret; 
     808#endif 
    655809 
    656810        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    657811 
    int add_mtd_partitions(struct mtd_info * 
    666820 
    667821                add_mtd_device(&slave->mtd); 
    668822 
     823                if (!strcmp(parts[i].name, "rootfs")) { 
     824#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     825                        if (ROOT_DEV == 0) { 
     826                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     827                                        "set to be root filesystem\n"); 
     828                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     829                        } 
     830#endif 
     831#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     832                        ret = split_rootfs_data(master, &slave->mtd, &parts[i]); 
     833                        /* if (ret == 0) 
     834                         *      j++; */ 
     835#endif 
     836                } 
     837 
    669838                cur_offset = slave->offset + slave->mtd.size; 
    670839        } 
    671840 
    int add_mtd_partitions(struct mtd_info * 
    673842} 
    674843EXPORT_SYMBOL(add_mtd_partitions); 
    675844 
     845int refresh_mtd_partitions(struct mtd_info *mtd) 
     846{ 
     847        int ret = 0; 
     848 
     849        if (IS_PART(mtd)) { 
     850                struct mtd_part *part; 
     851                struct mtd_info *master; 
     852 
     853                part = PART(mtd); 
     854                master = part->master; 
     855                if (master->refresh_device) 
     856                        ret = master->refresh_device(master); 
     857        } 
     858 
     859        if (!ret && mtd->refresh_device) 
     860                ret = mtd->refresh_device(mtd); 
     861 
     862#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     863        if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) 
     864                refresh_rootfs_split(mtd); 
     865#endif 
     866 
     867        return 0; 
     868} 
     869EXPORT_SYMBOL_GPL(refresh_mtd_partitions); 
     870 
    676871static DEFINE_SPINLOCK(part_parser_lock); 
    677872static LIST_HEAD(part_parsers); 
    678873 
  • drivers/mtd/mtdchar.c

    a b static int mtd_ioctl(struct file *file, 
    956956                break; 
    957957        } 
    958958#endif 
     959#ifdef CONFIG_MTD_PARTITIONS 
     960        case MTDREFRESH: 
     961        { 
     962                ret = refresh_mtd_partitions(mtd); 
     963                break; 
     964        } 
     965#endif 
    959966 
    960967        default: 
    961968                ret = -ENOTTY; 
  • 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', 50) 
    130131 
    131132/* 
    132133 * Obsolete legacy interface. Keep it in order not to break userspace 
Note: See TracBrowser for help on using the repository browser.