source: trunk/target/linux/generic/patches-3.0/400-rootfs_split.patch @ 27191

Last change on this file since 27191 was 27191, checked in by hauke, 5 years ago

linux/generic: Add support for 3.0-rc3

Also make linux identify itself properly as 3.0, not 3.0.0.

Signed-off-by: Jonas Gorski <jonas.gorski+openwrt@…>

File size: 8.6 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, 
    834834                file->f_pos = 0; 
    835835                break; 
    836836        } 
     837        case MTDREFRESH: 
     838        { 
     839                ret = mtd_device_refresh(mtd); 
     840                break; 
     841        } 
    837842 
    838843        case OTPGETREGIONCOUNT: 
    839844        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 
    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) 
Note: See TracBrowser for help on using the repository browser.