source: trunk/target/linux/generic/patches-3.0/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_TESTS 
    3333          should normally be compiled as kernel modules. The modules perform 
    3434          various checks and verifications when loaded. 
    3535 
     36config MTD_ROOTFS_ROOT_DEV 
     37        bool "Automatically set 'rootfs' partition to be root filesystem" 
     38        default y 
     39 
     40config MTD_ROOTFS_SPLIT 
     41        bool "Automatically split 'rootfs' partition for squashfs" 
     42        default y 
     43 
    3644config MTD_REDBOOT_PARTS 
    3745        tristate "RedBoot partition table parsing" 
    3846        ---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#include "mtdcore.h" 
    struct mtd_part { 
    5052 * the pointer to that structure with this macro. 
    5153 */ 
    5254#define PART(x)  ((struct mtd_part *)(x)) 
    53  
     55#define IS_PART(mtd) (mtd->read == part_read) 
    5456 
    5557/* 
    5658 * MTD methods which simply translate the effective address and pass through 
    int mtd_del_partition(struct mtd_info *m 
    637639} 
    638640EXPORT_SYMBOL_GPL(mtd_del_partition); 
    639641 
     642#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     643#define ROOTFS_SPLIT_NAME "rootfs_data" 
     644#define ROOTFS_REMOVED_NAME "<removed>" 
     645 
     646struct squashfs_super_block { 
     647        __le32 s_magic; 
     648        __le32 pad0[9]; 
     649        __le64 bytes_used; 
     650}; 
     651 
     652 
     653static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) 
     654{ 
     655        struct squashfs_super_block sb; 
     656        int len, ret; 
     657 
     658        ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); 
     659        if (ret || (len != sizeof(sb))) { 
     660                printk(KERN_ALERT "split_squashfs: error occured while reading " 
     661                        "from \"%s\"\n", master->name); 
     662                return -EINVAL; 
     663        } 
     664 
     665        if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) { 
     666                printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", 
     667                        master->name); 
     668                *split_offset = 0; 
     669                return 0; 
     670        } 
     671 
     672        if (le64_to_cpu((sb.bytes_used)) <= 0) { 
     673                printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", 
     674                        master->name); 
     675                *split_offset = 0; 
     676                return 0; 
     677        } 
     678 
     679        len = (u32) le64_to_cpu(sb.bytes_used); 
     680        len += (offset & 0x000fffff); 
     681        len +=  (master->erasesize - 1); 
     682        len &= ~(master->erasesize - 1); 
     683        len -= (offset & 0x000fffff); 
     684        *split_offset = offset + len; 
     685 
     686        return 0; 
     687} 
     688 
     689static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part) 
     690{ 
     691        struct mtd_partition *dpart; 
     692        struct mtd_part *slave = NULL; 
     693        struct mtd_part *spart; 
     694        int ret, split_offset = 0; 
     695 
     696        spart = PART(rpart); 
     697        ret = split_squashfs(master, spart->offset, &split_offset); 
     698        if (ret) 
     699                return ret; 
     700 
     701        if (split_offset <= 0) 
     702                return 0; 
     703 
     704        dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); 
     705        if (dpart == NULL) { 
     706                printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", 
     707                        ROOTFS_SPLIT_NAME); 
     708                return -ENOMEM; 
     709        } 
     710 
     711        memcpy(dpart, part, sizeof(*part)); 
     712        dpart->name = (unsigned char *)&dpart[1]; 
     713        strcpy(dpart->name, ROOTFS_SPLIT_NAME); 
     714 
     715        dpart->size = rpart->size - (split_offset - spart->offset); 
     716        dpart->offset = split_offset; 
     717 
     718        if (dpart == NULL) 
     719                return 1; 
     720 
     721        printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", 
     722                ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); 
     723 
     724        slave = allocate_partition(master, dpart, 0, split_offset); 
     725        if (IS_ERR(slave)) 
     726                return PTR_ERR(slave); 
     727        mutex_lock(&mtd_partitions_mutex); 
     728        list_add(&slave->list, &mtd_partitions); 
     729        mutex_unlock(&mtd_partitions_mutex); 
     730 
     731        add_mtd_device(&slave->mtd); 
     732 
     733        rpart->split = &slave->mtd; 
     734 
     735        return 0; 
     736} 
     737 
     738static int refresh_rootfs_split(struct mtd_info *mtd) 
     739{ 
     740        struct mtd_partition tpart; 
     741        struct mtd_part *part; 
     742        char *name; 
     743        //int index = 0; 
     744        int offset, size; 
     745        int ret; 
     746 
     747        part = PART(mtd); 
     748 
     749        /* check for the new squashfs offset first */ 
     750        ret = split_squashfs(part->master, part->offset, &offset); 
     751        if (ret) 
     752                return ret; 
     753 
     754        if ((offset > 0) && !mtd->split) { 
     755                printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); 
     756                /* if we don't have a rootfs split partition, create a new one */ 
     757                tpart.name = (char *) mtd->name; 
     758                tpart.size = mtd->size; 
     759                tpart.offset = part->offset; 
     760 
     761                return split_rootfs_data(part->master, &part->mtd, &tpart); 
     762        } else if ((offset > 0) && mtd->split) { 
     763                /* update the offsets of the existing partition */ 
     764                size = mtd->size + part->offset - offset; 
     765 
     766                part = PART(mtd->split); 
     767                part->offset = offset; 
     768                part->mtd.size = size; 
     769                printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", 
     770                        __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), 
     771                        (u32) part->offset, (u32) part->mtd.size); 
     772                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     773                strcpy(name, ROOTFS_SPLIT_NAME); 
     774                part->mtd.name = name; 
     775        } else if ((offset <= 0) && mtd->split) { 
     776                printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); 
     777 
     778                /* mark existing partition as removed */ 
     779                part = PART(mtd->split); 
     780                name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); 
     781                strcpy(name, ROOTFS_REMOVED_NAME); 
     782                part->mtd.name = name; 
     783                part->offset = 0; 
     784                part->mtd.size = 0; 
     785        } 
     786 
     787        return 0; 
     788} 
     789#endif /* CONFIG_MTD_ROOTFS_SPLIT */ 
     790 
    640791/* 
    641792 * This function, given a master MTD object and a partition table, creates 
    642793 * and registers slave MTD objects which are bound to the master according to 
    int add_mtd_partitions(struct mtd_info * 
    653804        struct mtd_part *slave; 
    654805        uint64_t cur_offset = 0; 
    655806        int i; 
     807#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     808        int ret; 
     809#endif 
    656810 
    657811        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); 
    658812 
    int add_mtd_partitions(struct mtd_info * 
    667821 
    668822                add_mtd_device(&slave->mtd); 
    669823 
     824                if (!strcmp(parts[i].name, "rootfs")) { 
     825#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV 
     826                        if (ROOT_DEV == 0) { 
     827                                printk(KERN_NOTICE "mtd: partition \"rootfs\" " 
     828                                        "set to be root filesystem\n"); 
     829                                ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); 
     830                        } 
     831#endif 
     832#ifdef CONFIG_MTD_ROOTFS_SPLIT 
     833                        ret = split_rootfs_data(master, &slave->mtd, &parts[i]); 
     834                        /* if (ret == 0) 
     835                         *      j++; */ 
     836#endif 
     837                } 
     838 
    670839                cur_offset = slave->offset + slave->mtd.size; 
    671840        } 
    672841 
    673842        return 0; 
    674843} 
    675844 
     845int mtd_device_refresh(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(mtd_device_refresh); 
     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, 
    948948                break; 
    949949        } 
    950950 
     951        case MTDREFRESH: 
     952        { 
     953                ret = mtd_device_refresh(mtd); 
     954                break; 
     955        } 
     956 
    951957        default: 
    952958                ret = -ENOTTY; 
    953959        } 
  • 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 
    struct mtd_partition; 
    327331extern int mtd_device_register(struct mtd_info *master, 
    328332                               const struct mtd_partition *parts, 
    329333                               int nr_parts); 
     334extern int mtd_device_refresh(struct mtd_info *master); 
    330335extern int mtd_device_unregister(struct mtd_info *master); 
    331336extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 
    332337extern int __get_mtd_device(struct mtd_info *mtd); 
  • 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) 
  • 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.