From a5fb2fb2faa520dabb8b3515918f725678d3ed80 Mon Sep 17 00:00:00 2001 From: Jianhui Zhao Date: Tue, 16 May 2023 18:19:30 +0800 Subject: [PATCH] kernel: block: support partition split Signed-off-by: Jianhui Zhao --- .../9999-support-partition-split.patch | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 target/linux/generic/hack-5.4/9999-support-partition-split.patch diff --git a/target/linux/generic/hack-5.4/9999-support-partition-split.patch b/target/linux/generic/hack-5.4/9999-support-partition-split.patch new file mode 100644 index 0000000000..8e0026c216 --- /dev/null +++ b/target/linux/generic/hack-5.4/9999-support-partition-split.patch @@ -0,0 +1,186 @@ +Index: linux-5.4.188/block/Kconfig +=================================================================== +--- linux-5.4.188.orig/block/Kconfig ++++ linux-5.4.188/block/Kconfig +@@ -105,6 +105,9 @@ config BLK_DEV_THROTTLING_LOW + + Note, this is an experimental interface and could be changed someday. + ++config PARTITION_SPLIT ++ bool "Openwrt Block device partition rootfs split" ++ + config BLK_CMDLINE_PARSER + bool "Block device command line partition parser" + ---help--- +Index: linux-5.4.188/block/Makefile +=================================================================== +--- linux-5.4.188.orig/block/Makefile ++++ linux-5.4.188/block/Makefile +@@ -36,3 +36,4 @@ obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-deb + obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o + obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o + obj-$(CONFIG_BLK_PM) += blk-pm.o ++obj-$(CONFIG_PARTITION_SPLIT) += partition-split.o +Index: linux-5.4.188/block/partition-generic.c +=================================================================== +--- linux-5.4.188.orig/block/partition-generic.c ++++ linux-5.4.188/block/partition-generic.c +@@ -21,6 +21,10 @@ + + #include "partitions/check.h" + ++#ifdef CONFIG_PARTITION_SPLIT ++#include "partition-split.h" ++#endif ++ + #ifdef CONFIG_BLK_DEV_MD + extern void md_autodetect_dev(dev_t dev); + #endif +@@ -569,6 +573,9 @@ rescan: + highest = p; + + disk_expand_part_tbl(disk, highest); ++#ifdef CONFIG_PARTITION_SPLIT ++ partition_split(bdev, state); ++#endif + + /* add partitions */ + for (p = 1; p < state->limit; p++) { +Index: linux-5.4.188/block/partition-split.c +=================================================================== +--- /dev/null ++++ linux-5.4.188/block/partition-split.c +@@ -0,0 +1,111 @@ ++#include ++#include ++#include ++#include "partitions/check.h" ++#include "partition-split.h" ++ ++void print_sblock_value(char *buf) ++{ ++ int i, j; ++ for (i = 0; i < sizeof(struct squashfs_sblock);) { ++ for (j = 0; j < 16; j++) { ++ printk("%02x ", buf[i]); ++ i++; ++ } ++ printk("\n"); ++ } ++} ++ ++unsigned char *fs_read_super_block(struct block_device *bdev, sector_t from, Sector *sector) ++{ ++ if (from >= get_capacity(bdev->bd_disk)) { ++ return NULL; ++ } ++ return read_dev_sector(bdev, from, sector); ++} ++ ++ ++int get_squashfs_len(struct block_device *bdev, sector_t from, size_t *squashfs_len) ++{ ++ struct squashfs_sblock sb; ++ unsigned char *buf; ++ Sector sector; ++ size_t retlen; ++ ++ buf = fs_read_super_block(bdev, from, §or); ++ if (!buf) { ++ printk("failed to get super\n"); ++ return -EIO; ++ } ++ memcpy((void *)&sb, buf, sizeof(sb)); ++ put_dev_sector(sector); ++ ++ if (le32_to_cpu(sb.s_magic) != SQUASHFS_MAGIC) { ++ printk("no squashfs found in\n"); ++ //print_sblock_value((char *)&sb); ++ return -EINVAL; ++ } ++ ++ retlen = le64_to_cpu(sb.bytes_used); ++ if (retlen <= 0) { ++ printk("squashfs is empty in \n"); ++ return -ENODEV; ++ } ++ ++ *squashfs_len = retlen; ++ return 0; ++} ++ ++static int find_part_by_lable(struct parsed_partitions *state, const char *lable) ++{ ++ int p; ++ /* add partitions */ ++ for (p = 1; p < state->limit; p++) { ++ if (!strcmp(state->parts[p].info.volname, lable)) ++ return p; ++ } ++ return 0; ++} ++ ++int partition_split(struct block_device *bdev, struct parsed_partitions *state) ++{ ++ int p, insert; ++ size_t sqfs_size; ++ sector_t new_size, new_from; ++ struct partition_meta_info *info; ++ char tmp[sizeof(info->volname) + 4]; ++ ++ p = find_part_by_lable(state, ROOTFS_PART); ++ if (p == 0) ++ return 0; ++ if (get_squashfs_len(bdev, state->parts[p].from, &sqfs_size)) ++ return 0; ++ ++ sqfs_size = (sqfs_size + (ALING_SQFS - 1)) & ~(ALING_SQFS - 1); //squashfs 64k对齐 ++ ++ //计算新分区大小和起始位置 ++ ++ new_size = state->parts[p].size - (sqfs_size >> 9); ++ new_from = state->parts[p].from + (sqfs_size >> 9); ++ ++ for (insert = 1; insert < state->limit; insert++) { ++ if (!state->parts[insert].size) ++ break; ++ } ++ ++ if (insert >= state->limit) ++ return 0; ++ ++ //追加一个新分区并设置相关信息 ++ put_partition(state, insert, new_from, new_size); ++ ++ info = &state->parts[insert].info; ++ ++ strncpy(info->volname, ROOTFS_PART_DATA, strlen(ROOTFS_PART_DATA) + 1); ++ snprintf(tmp, sizeof(tmp), "(%s)", info->volname); ++ strlcat(state->pp_buf, tmp, PAGE_SIZE); ++ ++ state->parts[insert].has_info = true; ++ return 0; ++ ++} +Index: linux-5.4.188/block/partition-split.h +=================================================================== +--- /dev/null ++++ linux-5.4.188/block/partition-split.h +@@ -0,0 +1,17 @@ ++#ifndef __PARTITION_SPLIT_H ++#define __PARTITION_SPLIT_H ++ ++#define ROOTFS_PART "rootfs" ++#define ROOTFS_PART_DATA "rootfs_data" ++ ++#define ALING_SQFS 0X10000 ++ ++struct squashfs_sblock { ++ __le32 s_magic; ++ __le32 pad0[9]; ++ __le64 bytes_used; ++}; ++ ++extern int partition_split(struct block_device *bdev, struct parsed_partitions *state); ++ ++#endif -- 2.34.1