X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/ee0eb80db00fde857692fb8df1bd48d522e1475e..5f47b607c0e361a0b720304c0edba43d721475be:/target/linux/generic-2.6/patches-2.6.29/065-rootfs_split.patch diff --git a/target/linux/generic-2.6/patches-2.6.29/065-rootfs_split.patch b/target/linux/generic-2.6/patches-2.6.29/065-rootfs_split.patch index bae962193..172eb0f19 100644 --- a/target/linux/generic-2.6/patches-2.6.29/065-rootfs_split.patch +++ b/target/linux/generic-2.6/patches-2.6.29/065-rootfs_split.patch @@ -1,7 +1,268 @@ -diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3/drivers/mtd/devices/block2mtd.c ---- linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c 2009-03-09 05:13:51.000000000 +0100 -+++ linux-2.6.29-rc3/drivers/mtd/devices/block2mtd.c 2009-03-09 18:18:49.000000000 +0100 -@@ -28,6 +28,8 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -53,6 +53,16 @@ config MTD_TESTS + should normally be compiled as kernel modules. The modules perform + various checks and verifications when loaded. + ++config MTD_ROOTFS_ROOT_DEV ++ bool "Automatically set 'rootfs' partition to be root filesystem" ++ depends on MTD_PARTITIONS ++ default y ++ ++config MTD_ROOTFS_SPLIT ++ bool "Automatically split 'rootfs' partition for squashfs" ++ depends on MTD_PARTITIONS ++ default y ++ + config MTD_REDBOOT_PARTS + tristate "RedBoot partition table parsing" + depends on MTD_PARTITIONS +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -18,6 +18,8 @@ + #include + #include + #include ++#include ++#include + + /* Our partition linked list */ + static LIST_HEAD(mtd_partitions); +@@ -37,7 +39,7 @@ struct mtd_part { + * the pointer to that structure with this macro. + */ + #define PART(x) ((struct mtd_part *)(x)) +- ++#define IS_PART(mtd) (mtd->read == part_read) + + /* + * MTD methods which simply translate the effective address and pass through +@@ -489,6 +491,156 @@ out_register: + return slave; + } + ++#ifdef CONFIG_MTD_ROOTFS_SPLIT ++#define ROOTFS_SPLIT_NAME "rootfs_data" ++#define ROOTFS_REMOVED_NAME "" ++ ++struct squashfs_super_block { ++ __le32 s_magic; ++ __le32 pad0[9]; ++ __le64 bytes_used; ++}; ++ ++ ++static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) ++{ ++ char buf[512]; ++ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; ++ int len, ret; ++ ++ ret = master->read(master, offset, sizeof(*sb), &len, buf); ++ if (ret || (len != sizeof(*sb))) { ++ printk(KERN_ALERT "split_squashfs: error occured while reading " ++ "from \"%s\"\n", master->name); ++ return -EINVAL; ++ } ++ ++ if (*((u32 *) buf) != SQUASHFS_MAGIC) { ++ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", ++ master->name); ++ *split_offset = 0; ++ return 0; ++ } ++ ++ if (sb->bytes_used <= 0) { ++ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", ++ master->name); ++ *split_offset = 0; ++ return 0; ++ } ++ ++ len = (u32) sb->bytes_used; ++ len += (offset & 0x000fffff); ++ len += (master->erasesize - 1); ++ len &= ~(master->erasesize - 1); ++ len -= (offset & 0x000fffff); ++ *split_offset = offset + len; ++ ++ return 0; ++} ++ ++static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part, ++ int index) ++{ ++ struct mtd_partition *dpart; ++ struct mtd_part *slave = NULL; ++ int split_offset = 0; ++ int ret; ++ ++ ret = split_squashfs(master, part->offset, &split_offset); ++ if (ret) ++ return ret; ++ ++ if (split_offset <= 0) ++ return 0; ++ ++ dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); ++ if (dpart == NULL) { ++ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", ++ ROOTFS_SPLIT_NAME); ++ return -ENOMEM; ++ } ++ ++ memcpy(dpart, part, sizeof(*part)); ++ dpart->name = (unsigned char *)&dpart[1]; ++ strcpy(dpart->name, ROOTFS_SPLIT_NAME); ++ ++ dpart->size -= split_offset - dpart->offset; ++ dpart->offset = split_offset; ++ ++ if (dpart == NULL) ++ return 1; ++ ++ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n", ++ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); ++ ++ slave = add_one_partition(master, dpart, index, split_offset); ++ if (!slave) { ++ kfree(dpart); ++ return -ENOMEM; ++ } ++ rpart->split = &slave->mtd; ++ ++ return 0; ++} ++ ++static int refresh_rootfs_split(struct mtd_info *mtd) ++{ ++ struct mtd_partition tpart; ++ struct mtd_part *part; ++ char *name; ++ int index = 0; ++ int offset, size; ++ int ret; ++ ++ part = PART(mtd); ++ ++ /* check for the new squashfs offset first */ ++ ret = split_squashfs(part->master, part->offset, &offset); ++ if (ret) ++ return ret; ++ ++ if ((offset > 0) && !mtd->split) { ++ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); ++ /* if we don't have a rootfs split partition, create a new one */ ++ tpart.name = (char *) mtd->name; ++ tpart.size = mtd->size; ++ tpart.offset = part->offset; ++ ++ /* find the index of the last partition */ ++ if (!list_empty(&mtd_partitions)) ++ index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1; ++ ++ return split_rootfs_data(part->master, &part->mtd, &tpart, index); ++ } else if ((offset > 0) && mtd->split) { ++ /* update the offsets of the existing partition */ ++ size = mtd->size + part->offset - offset; ++ ++ part = PART(mtd->split); ++ part->offset = offset; ++ part->mtd.size = size; ++ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", ++ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), ++ (u32) part->offset, (u32) part->mtd.size); ++ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); ++ strcpy(name, ROOTFS_SPLIT_NAME); ++ part->mtd.name = name; ++ } else if ((offset <= 0) && mtd->split) { ++ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); ++ ++ /* mark existing partition as removed */ ++ part = PART(mtd->split); ++ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); ++ strcpy(name, ROOTFS_REMOVED_NAME); ++ part->mtd.name = name; ++ part->offset = 0; ++ part->mtd.size = 0; ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_MTD_ROOTFS_SPLIT */ ++ + /* + * This function, given a master MTD object and a partition table, creates + * and registers slave MTD objects which are bound to the master according to +@@ -502,14 +654,29 @@ int add_mtd_partitions(struct mtd_info * + { + struct mtd_part *slave; + uint64_t cur_offset = 0; +- int i; ++ int i, j, ret; + + printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); + +- for (i = 0; i < nbparts; i++) { +- slave = add_one_partition(master, parts + i, i, cur_offset); ++ for (i = 0, j = 0; i < nbparts; i++) { ++ slave = add_one_partition(master, parts + i, j++, cur_offset); + if (!slave) + return -ENOMEM; ++ ++ if (!strcmp(parts[i].name, "rootfs") && slave->registered) { ++#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV ++ if (ROOT_DEV == 0) { ++ printk(KERN_NOTICE "mtd: partition \"rootfs\" " ++ "set to be root filesystem\n"); ++ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); ++ } ++#endif ++#ifdef CONFIG_MTD_ROOTFS_SPLIT ++ ret = split_rootfs_data(master, &slave->mtd, &parts[i], j); ++ if (ret == 0) ++ j++; ++#endif ++ } + cur_offset = slave->offset + slave->mtd.size; + } + +@@ -517,6 +684,32 @@ int add_mtd_partitions(struct mtd_info * + } + EXPORT_SYMBOL(add_mtd_partitions); + ++int refresh_mtd_partitions(struct mtd_info *mtd) ++{ ++ int ret = 0; ++ ++ if (IS_PART(mtd)) { ++ struct mtd_part *part; ++ struct mtd_info *master; ++ ++ part = PART(mtd); ++ master = part->master; ++ if (master->refresh_device) ++ ret = master->refresh_device(master); ++ } ++ ++ if (!ret && mtd->refresh_device) ++ ret = mtd->refresh_device(mtd); ++ ++#ifdef CONFIG_MTD_ROOTFS_SPLIT ++ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) ++ refresh_rootfs_split(mtd); ++#endif ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(refresh_mtd_partitions); ++ + static DEFINE_SPINLOCK(part_parser_lock); + static LIST_HEAD(part_parsers); + +--- a/drivers/mtd/devices/block2mtd.c ++++ b/drivers/mtd/devices/block2mtd.c +@@ -29,6 +29,8 @@ struct block2mtd_dev { struct block_device *blkdev; struct mtd_info mtd; struct mutex write_mutex; @@ -10,7 +271,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 }; -@@ -80,6 +82,12 @@ +@@ -81,6 +83,12 @@ static int block2mtd_erase(struct mtd_in size_t len = instr->len; int err; @@ -23,7 +284,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 instr->state = MTD_ERASING; mutex_lock(&dev->write_mutex); err = _block2mtd_erase(dev, from, len); -@@ -92,6 +100,10 @@ +@@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); @@ -34,7 +295,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 return err; } -@@ -103,10 +115,14 @@ +@@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf struct page *page; int index = from >> PAGE_SHIFT; int offset = from & (PAGE_SIZE-1); @@ -52,7 +313,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 if (from + len > mtd->size) len = mtd->size - from; -@@ -121,10 +137,14 @@ +@@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf len = len - cpylen; page = page_read(dev->blkdev->bd_inode->i_mapping, index); @@ -71,7 +332,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 memcpy(buf, page_address(page) + offset, cpylen); page_cache_release(page); -@@ -135,7 +155,10 @@ +@@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf offset = 0; index++; } @@ -83,7 +344,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 } -@@ -187,12 +210,22 @@ +@@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in size_t *retlen, const u_char *buf) { struct block2mtd_dev *dev = mtd->priv; @@ -110,7 +371,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 if (to + len > mtd->size) len = mtd->size - to; -@@ -201,6 +234,9 @@ +@@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in mutex_unlock(&dev->write_mutex); if (err > 0) err = 0; @@ -120,7 +381,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 return err; } -@@ -209,30 +245,15 @@ +@@ -210,52 +246,29 @@ static int block2mtd_write(struct mtd_in static void block2mtd_sync(struct mtd_info *mtd) { struct block2mtd_dev *dev = mtd->priv; @@ -128,37 +389,44 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 - return; -} - -+ read_lock(&dev->bdev_mutex); -+ if (dev->blkdev) -+ sync_blockdev(dev->blkdev); -+ read_unlock(&dev->bdev_mutex); - +- -static void block2mtd_free_device(struct block2mtd_dev *dev) -{ - if (!dev) - return; - - kfree(dev->mtd.name); -- + - if (dev->blkdev) { - invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, - 0, -1); - close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); - } -- ++ read_lock(&dev->bdev_mutex); ++ if (dev->blkdev) ++ sync_blockdev(dev->blkdev); ++ read_unlock(&dev->bdev_mutex); + - kfree(dev); + return; } -- + -/* FIXME: ensure that mtd->size % erase_size == 0 */ --static struct block2mtd_dev *add_device(char *devname, int erase_size) +-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname) +static int _open_bdev(struct block2mtd_dev *dev) { struct block_device *bdev; - struct block2mtd_dev *dev; -@@ -246,14 +267,14 @@ - return NULL; +- struct block2mtd_dev *dev; +- struct mtd_partition *part; +- char *name; +- +- if (!devname) +- return NULL; +- +- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL); +- if (!dev) +- return NULL; /* Get a handle on the device */ - bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL); @@ -174,7 +442,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 if (devt) { bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); } -@@ -261,17 +282,97 @@ +@@ -263,17 +276,97 @@ static struct block2mtd_dev *add_device( #endif if (IS_ERR(bdev)) { @@ -273,39 +541,18 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/devices/block2mtd.c linux-2.6.29-rc3 mutex_init(&dev->write_mutex); + rwlock_init(&dev->bdev_mutex); - /* Setup the MTD structure */ - /* make the name contain the block device in */ -@@ -295,6 +396,7 @@ + if (!mtdname) + mtdname = devname; +@@ -297,6 +390,7 @@ static struct block2mtd_dev *add_device( dev->mtd.read = block2mtd_read; dev->mtd.priv = dev; dev->mtd.owner = THIS_MODULE; + dev->mtd.refresh_device = block2mtd_refresh; - if (add_mtd_device(&dev->mtd)) { - /* Device didnt get added, so free the entry */ -diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/Kconfig linux-2.6.29-rc3/drivers/mtd/Kconfig ---- linux-2.6.29-rc3.orig/drivers/mtd/Kconfig 2009-03-09 05:13:51.000000000 +0100 -+++ linux-2.6.29-rc3/drivers/mtd/Kconfig 2009-03-09 18:10:48.000000000 +0100 -@@ -53,6 +53,16 @@ - should normally be compiled as kernel modules. The modules perform - various checks and verifications when loaded. - -+config MTD_ROOTFS_ROOT_DEV -+ bool "Automatically set 'rootfs' partition to be root filesystem" -+ depends on MTD_PARTITIONS -+ default y -+ -+config MTD_ROOTFS_SPLIT -+ bool "Automatically split 'rootfs' partition for squashfs" -+ depends on MTD_PARTITIONS -+ default y -+ - config MTD_REDBOOT_PARTS - tristate "RedBoot partition table parsing" - depends on MTD_PARTITIONS -diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/mtdchar.c linux-2.6.29-rc3/drivers/mtd/mtdchar.c ---- linux-2.6.29-rc3.orig/drivers/mtd/mtdchar.c 2009-03-09 05:13:51.000000000 +0100 -+++ linux-2.6.29-rc3/drivers/mtd/mtdchar.c 2009-03-09 18:10:48.000000000 +0100 + part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); + part->name = dev->mtd.name; +--- a/drivers/mtd/mtdchar.c ++++ b/drivers/mtd/mtdchar.c @@ -16,6 +16,7 @@ #include @@ -314,7 +561,7 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/mtdchar.c linux-2.6.29-rc3/drivers/m #include -@@ -773,6 +774,13 @@ +@@ -773,6 +774,13 @@ static int mtd_ioctl(struct inode *inode file->f_pos = 0; break; } @@ -328,246 +575,9 @@ diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/mtdchar.c linux-2.6.29-rc3/drivers/m default: ret = -ENOTTY; -diff -ruN linux-2.6.29-rc3.orig/drivers/mtd/mtdpart.c linux-2.6.29-rc3/drivers/mtd/mtdpart.c ---- linux-2.6.29-rc3.orig/drivers/mtd/mtdpart.c 2009-03-09 05:13:51.000000000 +0100 -+++ linux-2.6.29-rc3/drivers/mtd/mtdpart.c 2009-03-09 18:29:58.000000000 +0100 -@@ -18,6 +18,8 @@ - #include - #include - #include -+#include -+#include - - /* Our partition linked list */ - static LIST_HEAD(mtd_partitions); -@@ -37,7 +39,7 @@ - * the pointer to that structure with this macro. - */ - #define PART(x) ((struct mtd_part *)(x)) -- -+#define IS_PART(mtd) (mtd->read == part_read) - - /* - * MTD methods which simply translate the effective address and pass through -@@ -489,6 +491,148 @@ - return slave; - } - -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+#define ROOTFS_SPLIT_NAME "rootfs_data" -+#define ROOTFS_REMOVED_NAME "" -+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) -+{ -+ char buf[512]; -+ struct squashfs_super_block *sb = (struct squashfs_super_block *) buf; -+ int len, ret; -+ -+ ret = master->read(master, offset, sizeof(*sb), &len, buf); -+ if (ret || (len != sizeof(*sb))) { -+ printk(KERN_ALERT "split_squashfs: error occured while reading " -+ "from \"%s\"\n", master->name); -+ return -EINVAL; -+ } -+ -+ if (*((u32 *) buf) != SQUASHFS_MAGIC) { -+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n", -+ master->name); -+ *split_offset = 0; -+ return 0; -+ } -+ -+ if (sb->bytes_used <= 0) { -+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n", -+ master->name); -+ *split_offset = 0; -+ return 0; -+ } -+ -+ len = (u32) sb->bytes_used; -+ len += (offset & 0x000fffff); -+ len += (master->erasesize - 1); -+ len &= ~(master->erasesize - 1); -+ len -= (offset & 0x000fffff); -+ *split_offset = offset + len; -+ -+ return 0; -+} -+ -+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part, -+ int index) -+{ -+ struct mtd_partition *dpart; -+ struct mtd_part *slave = NULL; -+ int split_offset = 0; -+ int ret; -+ -+ ret = split_squashfs(master, part->offset, &split_offset); -+ if (ret) -+ return ret; -+ -+ if (split_offset <= 0) -+ return 0; -+ -+ dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL); -+ if (dpart == NULL) { -+ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n", -+ ROOTFS_SPLIT_NAME); -+ return -ENOMEM; -+ } -+ -+ memcpy(dpart, part, sizeof(*part)); -+ dpart->name = (unsigned char *)&dpart[1]; -+ strcpy(dpart->name, ROOTFS_SPLIT_NAME); -+ -+ dpart->size -= split_offset - dpart->offset; -+ dpart->offset = split_offset; -+ -+ if (dpart == NULL) -+ return 1; -+ -+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n", -+ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size); -+ -+ slave = add_one_partition(master, dpart, index, split_offset); -+ if (!slave) { -+ kfree(dpart); -+ return -ENOMEM; -+ } -+ rpart->split = &slave->mtd; -+ -+ return 0; -+} -+ -+static int refresh_rootfs_split(struct mtd_info *mtd) -+{ -+ struct mtd_partition tpart; -+ struct mtd_part *part; -+ char *name; -+ int index = 0; -+ int offset, size; -+ int ret; -+ -+ part = PART(mtd); -+ -+ /* check for the new squashfs offset first */ -+ ret = split_squashfs(part->master, part->offset, &offset); -+ if (ret) -+ return ret; -+ -+ if ((offset > 0) && !mtd->split) { -+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name); -+ /* if we don't have a rootfs split partition, create a new one */ -+ tpart.name = (char *) mtd->name; -+ tpart.size = mtd->size; -+ tpart.offset = part->offset; -+ -+ /* find the index of the last partition */ -+ if (!list_empty(&mtd_partitions)) -+ index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1; -+ -+ return split_rootfs_data(part->master, &part->mtd, &tpart, index); -+ } else if ((offset > 0) && mtd->split) { -+ /* update the offsets of the existing partition */ -+ size = mtd->size + part->offset - offset; -+ -+ part = PART(mtd->split); -+ part->offset = offset; -+ part->mtd.size = size; -+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n", -+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"), -+ part->offset, part->mtd.size); -+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); -+ strcpy(name, ROOTFS_SPLIT_NAME); -+ part->mtd.name = name; -+ } else if ((offset <= 0) && mtd->split) { -+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name); -+ -+ /* mark existing partition as removed */ -+ part = PART(mtd->split); -+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL); -+ strcpy(name, ROOTFS_REMOVED_NAME); -+ part->mtd.name = name; -+ part->offset = 0; -+ part->mtd.size = 0; -+ } -+ -+ return 0; -+} -+#endif /* CONFIG_MTD_ROOTFS_SPLIT */ -+ - /* - * This function, given a master MTD object and a partition table, creates - * and registers slave MTD objects which are bound to the master according to -@@ -502,14 +646,29 @@ - { - struct mtd_part *slave; - uint64_t cur_offset = 0; -- int i; -+ int i, j, ret; - - printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); - -- for (i = 0; i < nbparts; i++) { -- slave = add_one_partition(master, parts + i, i, cur_offset); -+ for (i = 0, j = 0; i < nbparts; i++) { -+ slave = add_one_partition(master, parts + i, j++, cur_offset); - if (!slave) - return -ENOMEM; -+ -+ if (!strcmp(parts[i].name, "rootfs") && slave->registered) { -+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV -+ if (ROOT_DEV == 0) { -+ printk(KERN_NOTICE "mtd: partition \"rootfs\" " -+ "set to be root filesystem\n"); -+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index); -+ } -+#endif -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+ ret = split_rootfs_data(master, &slave->mtd, &parts[i], j); -+ if (ret == 0) -+ j++; -+#endif -+ } - cur_offset = slave->offset + slave->mtd.size; - } - -@@ -517,6 +676,32 @@ - } - EXPORT_SYMBOL(add_mtd_partitions); - -+int refresh_mtd_partitions(struct mtd_info *mtd) -+{ -+ int ret = 0; -+ -+ if (IS_PART(mtd)) { -+ struct mtd_part *part; -+ struct mtd_info *master; -+ -+ part = PART(mtd); -+ master = part->master; -+ if (master->refresh_device) -+ ret = master->refresh_device(master); -+ } -+ -+ if (!ret && mtd->refresh_device) -+ ret = mtd->refresh_device(mtd); -+ -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs")) -+ refresh_rootfs_split(mtd); -+#endif -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(refresh_mtd_partitions); -+ - static DEFINE_SPINLOCK(part_parser_lock); - static LIST_HEAD(part_parsers); - -diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/mtd.h linux-2.6.29-rc3/include/linux/mtd/mtd.h ---- linux-2.6.29-rc3.orig/include/linux/mtd/mtd.h 2009-03-09 05:13:58.000000000 +0100 -+++ linux-2.6.29-rc3/include/linux/mtd/mtd.h 2009-03-09 18:10:48.000000000 +0100 -@@ -100,6 +100,7 @@ +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -100,6 +100,7 @@ struct mtd_oob_ops { uint8_t *oobbuf; }; @@ -575,7 +585,7 @@ diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/mtd.h linux-2.6.29-rc3/include struct mtd_info { u_char type; uint32_t flags; -@@ -225,6 +226,9 @@ +@@ -225,6 +226,9 @@ struct mtd_info { struct module *owner; int usecount; @@ -585,9 +595,8 @@ diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/mtd.h linux-2.6.29-rc3/include /* If the driver is something smart, like UBI, it may need to maintain * its own reference counting. The below functions are only for driver. * The driver may register its callbacks. These callbacks are not -diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h linux-2.6.29-rc3/include/linux/mtd/partitions.h ---- linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h 2009-03-09 05:13:58.000000000 +0100 -+++ linux-2.6.29-rc3/include/linux/mtd/partitions.h 2009-03-09 18:10:48.000000000 +0100 +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h @@ -34,6 +34,7 @@ * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). */ @@ -596,7 +605,7 @@ diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h linux-2.6.29-rc3/ struct mtd_partition { char *name; /* identifier string */ uint64_t size; /* partition size */ -@@ -41,6 +42,7 @@ +@@ -41,6 +42,7 @@ struct mtd_partition { uint32_t mask_flags; /* master MTD flags to mask out for this partition */ struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ struct mtd_info **mtdp; /* pointer to store the MTD object */ @@ -604,7 +613,7 @@ diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h linux-2.6.29-rc3/ }; #define MTDPART_OFS_NXTBLK (-2) -@@ -50,6 +52,7 @@ +@@ -50,6 +52,7 @@ struct mtd_partition { int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); int del_mtd_partitions(struct mtd_info *); @@ -612,10 +621,9 @@ diff -ruN linux-2.6.29-rc3.orig/include/linux/mtd/partitions.h linux-2.6.29-rc3/ /* * Functions dealing with the various ways of partitioning the space -diff -ruN linux-2.6.29-rc3.orig/include/mtd/mtd-abi.h linux-2.6.29-rc3/include/mtd/mtd-abi.h ---- linux-2.6.29-rc3.orig/include/mtd/mtd-abi.h 2009-03-09 05:13:57.000000000 +0100 -+++ linux-2.6.29-rc3/include/mtd/mtd-abi.h 2009-03-09 18:10:48.000000000 +0100 -@@ -93,6 +93,7 @@ +--- a/include/mtd/mtd-abi.h ++++ b/include/mtd/mtd-abi.h +@@ -93,6 +93,7 @@ struct otp_info { #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) #define MTDFILEMODE _IO('M', 19)