linux-parisc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] bring parisc linux into the modern age by adding ext4 support to the bootloader
@ 2019-07-05 20:07 James Bottomley
  2019-07-05 20:15 ` [PATCH 1/4] iplboot: eliminate unused struct bootfs James Bottomley
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: James Bottomley @ 2019-07-05 20:07 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel, Parisc List

The parisc bootloader, palo, has understood how to read ext2/3
filesystems for decades.  However, keeping an ext2/3 partition around
simply to boot from is becoming a bit old, so add support for ext4 to
the iplboot code.  Note, this still doesn't fix ipl specific
limitations, like the inability to read a disk beyond 2GB, so you will
still need a low sector /boot partition for this.

The assumptions I've made adding ext4 are that the only additional
variables over ext2/3 are the variable group descriptor size support,
conditioned on the EXT4_FEATURE_INCOMPAT_64BIT flag and extent based
inodes conditioned on the EXT3_EXTENTS_FL (it's been renamed to
EXT4_EXTENTS_FL now in libext2fs).

Filesystem people interested in reviewing the extent handling code
probably only need look at patch 3/4 iplboot: add ext4 support

James

---

James Bottomley (4):
  iplboot: eliminate unused struct bootfs
  iplboot: update the ext2_fs.h header
  iplboot: add ext4 support
  palo: add support for formatting as ext4

 ipl/bootloader.h |  13 ---
 ipl/ext2.c       | 256 +++++++++++++++++++++++++++++++++++++++++++------------
 ipl/ext2_fs.h    |  42 ++++++++-
 iplboot          | Bin 45056 -> 45056 bytes
 palo/palo.c      |   6 +-
 5 files changed, 245 insertions(+), 72 deletions(-)

-- 
2.16.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] iplboot: eliminate unused struct bootfs
  2019-07-05 20:07 [PATCH 0/4] bring parisc linux into the modern age by adding ext4 support to the bootloader James Bottomley
@ 2019-07-05 20:15 ` James Bottomley
  2019-07-05 20:16 ` [PATCH 2/4] iplboot: update the ext2_fs.h header James Bottomley
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: James Bottomley @ 2019-07-05 20:15 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel, Parisc List

It's only used locally in ext2.c to carry the blocksize, so make
blocksize a static variable instead.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 ipl/bootloader.h | 13 ---------
 ipl/ext2.c       | 80 ++++++++++++++++++++------------------------------------
 2 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/ipl/bootloader.h b/ipl/bootloader.h
index 626ebd3..956b6ed 100644
--- a/ipl/bootloader.h
+++ b/ipl/bootloader.h
@@ -12,19 +12,6 @@
 
 #define MAX_FD 20
 
-struct bootfs {
-	int	fs_type;
-	int	blocksize;
-	
-	int	(*mount)(long dev, long partition_start, long quiet);
-
-	int	(*open)(const char *filename);
-	int	(*bread)(int fd, long blkno, long nblks, char *buf);
-	void	(*close)(int fd);
-	const char *	(*readdir)(int fd, int rewind);
-};
-
-
 /* pdc_misc.c */
 void die(const char *);
 void firmware_init(int started_wide);
diff --git a/ipl/ext2.c b/ipl/ext2.c
index 4679c13..9d198fe 100644
--- a/ipl/ext2.c
+++ b/ipl/ext2.c
@@ -26,7 +26,7 @@
 
 #define MAX_OPEN_FILES		5
 
-extern struct bootfs ext2fs;
+static int ext2_blocksize;
 
 static struct ext2_super_block sb;
 static struct ext2_group_desc *gds;
@@ -242,26 +242,26 @@ int ext2_mount(long cons_dev, long p_offset, long quiet)
 	gds = (struct ext2_group_desc *)
 	          malloc((size_t)(ngroups * sizeof(struct ext2_group_desc)));
 
-	ext2fs.blocksize = EXT2_BLOCK_SIZE(&sb);
-	if (Debug) printf("ext2 block size %d\n", ext2fs.blocksize);
+	ext2_blocksize = EXT2_BLOCK_SIZE(&sb);
+	if (Debug) printf("ext2 block size %d\n", ext2_blocksize);
 
 	/* read in the group descriptors (immediately follows superblock) */
 	cons_read(dev, gds, ngroups * sizeof(struct ext2_group_desc),
 		  partition_offset +
-                  ext2fs.blocksize * (EXT2_MIN_BLOCK_SIZE/ext2fs.blocksize + 1));
+                  ext2_blocksize * (EXT2_MIN_BLOCK_SIZE/ext2_blocksize + 1));
 	for (i = 0; i < ngroups; i++)
 	{
 	    swapgrp(&gds[i]);
 	}
 	/*
 	 * Calculate direct/indirect block limits for this file system
-	 * (blocksize dependent):
+	 * (ext2_blocksize dependent):
 	 */
-	ext2fs.blocksize = EXT2_BLOCK_SIZE(&sb);
-	if (Debug) printf("ext2 block size %d\n", ext2fs.blocksize);
+	ext2_blocksize = EXT2_BLOCK_SIZE(&sb);
+	if (Debug) printf("ext2 block size %d\n", ext2_blocksize);
 
 	directlim = EXT2_NDIR_BLOCKS - 1;
-	ptrs_per_blk = ext2fs.blocksize/sizeof(unsigned int);
+	ptrs_per_blk = ext2_blocksize/sizeof(unsigned int);
 	ind1lim = ptrs_per_blk + directlim;
 	ind2lim = (ptrs_per_blk * ptrs_per_blk) + directlim;
 
@@ -317,7 +317,7 @@ static struct ext2_inode *ext2_iget(int ino)
 	printf("group is %d\n", group);
 #endif
 	offset = partition_offset
-		+ ((long) gds[group].bg_inode_table * (long)ext2fs.blocksize)
+		+ ((long) gds[group].bg_inode_table * (long)ext2_blocksize)
 		+ (((ino - 1) % EXT2_INODES_PER_GROUP(&sb))
 		   * EXT2_INODE_SIZE(&sb));
 #ifdef DEBUG
@@ -325,7 +325,7 @@ static struct ext2_inode *ext2_iget(int ino)
 	       "(%ld + (%d * %d) + ((%d) %% %d) * %d) "
 	       "(inode %d -> table %d)\n", 
 	       sizeof(struct ext2_inode), offset, partition_offset,
-	       gds[group].bg_inode_table, ext2fs.blocksize,
+	       gds[group].bg_inode_table, ext2_blocksize,
 	       ino - 1, EXT2_INODES_PER_GROUP(&sb), EXT2_INODE_SIZE(&sb),
 	       ino, (int) (itp - inode_table));
 #endif
@@ -403,9 +403,9 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
 
 		/* Read the indirect block */
 		if (cached_iblkno != iblkno) {
-			offset = partition_offset + (long)iblkno * (long)ext2fs.blocksize;
-			if (cons_read(dev, iblkbuf, ext2fs.blocksize, offset)
-			    != ext2fs.blocksize)
+			offset = partition_offset + (long)iblkno * (long)ext2_blocksize;
+			if (cons_read(dev, iblkbuf, ext2_blocksize, offset)
+			    != ext2_blocksize)
 			{
 				printf("ext2_blkno: error on iblk read\n");
 				return 0;
@@ -430,9 +430,9 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
 
 		/* Read in the double-indirect block */
 		if (cached_diblkno != diblkno) {
-			offset = partition_offset + (long) diblkno * (long) ext2fs.blocksize;
-			if (cons_read(dev, diblkbuf, ext2fs.blocksize, offset)
-			    != ext2fs.blocksize)
+			offset = partition_offset + (long) diblkno * (long) ext2_blocksize;
+			if (cons_read(dev, diblkbuf, ext2_blocksize, offset)
+			    != ext2_blocksize)
 			{
 				printf("ext2_blkno: err reading dindr blk\n");
 				return 0;
@@ -451,9 +451,9 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
 		/* Read the indirect block */
     
 		if (cached_iblkno != iblkno) {
-			offset = partition_offset + (long) iblkno * (long) ext2fs.blocksize;
-			if (cons_read(dev, iblkbuf, ext2fs.blocksize, offset)
-			    != ext2fs.blocksize)
+			offset = partition_offset + (long) iblkno * (long) ext2_blocksize;
+			if (cons_read(dev, iblkbuf, ext2_blocksize, offset)
+			    != ext2_blocksize)
 			{
 				printf("ext2_blkno: err on iblk read\n");
 				return 0;
@@ -493,8 +493,8 @@ static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks,
 		ip, blkno, nblks, buffer);
 
 	tot_bytes = 0;
-	if ((blkno+nblks)*ext2fs.blocksize > ip->i_size)
-		nblks = (ip->i_size + ext2fs.blocksize) / ext2fs.blocksize - blkno;
+	if ((blkno+nblks)*ext2_blocksize > ip->i_size)
+		nblks = (ip->i_size + ext2_blocksize) / ext2_blocksize - blkno;
 
 	if (Debug) printf("nblks = %ld\n", nblks);
 	while (nblks) {
@@ -507,7 +507,7 @@ static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks,
 		if (Debug) printf("dev_blkno = %ld\n", dev_blkno);
 		do {
 			++blkno; ++ncontig; --nblks;
-			nbytes += ext2fs.blocksize;
+			nbytes += ext2_blocksize;
 		} while (nblks &&
 			 print_ext2_blkno(ip, blkno) == dev_blkno + ncontig);
 
@@ -518,7 +518,7 @@ static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks,
 			memset(buffer, 0, nbytes);
 		} else {
 			/* Read it for real */
-			offset = partition_offset + (long) dev_blkno* (long) ext2fs.blocksize;
+			offset = partition_offset + (long) dev_blkno* (long) ext2_blocksize;
 #ifdef DEBUG
 			printf("ext2_bread: reading %ld bytes at offset %ld\n",
 			       nbytes, offset);
@@ -557,8 +557,8 @@ static struct ext2_dir_entry_2 *ext2_readdiri(struct ext2_inode *dir_inode,
 	printf("ext2_readdiri: blkoffset %d diroffset %d len %d\n",
 		blockoffset, diroffset, dir_inode->i_size);
 #endif
-	if (blockoffset >= ext2fs.blocksize) {
-		diroffset += ext2fs.blocksize;
+	if (blockoffset >= ext2_blocksize) {
+		diroffset += ext2_blocksize;
 		if (diroffset >= dir_inode->i_size)
 			return NULL;
 #ifdef DEBUG
@@ -567,7 +567,7 @@ static struct ext2_dir_entry_2 *ext2_readdiri(struct ext2_inode *dir_inode,
 #endif
 		/* assume that this will read the whole block */
 		if (ext2_breadi(dir_inode,
-				diroffset / ext2fs.blocksize,
+				diroffset / ext2_blocksize,
 				1, blkbuf) < 0)
 			return NULL;
 		blockoffset = 0;
@@ -668,16 +668,6 @@ static struct ext2_inode *ext2_namei(const char *name)
 }
 
 
-/*
- * Read block number "blkno" from the specified file.
- */
-static int ext2_bread(int fd, long blkno, long nblks, char *buffer)
-{
-	struct ext2_inode * ip;
-	ip = &inode_table[fd].inode;
-	return ext2_breadi(ip, blkno, nblks, buffer);
-}
-
 /*
  * Note: don't mix any kind of file lookup or other I/O with this or
  * you will lose horribly (as it reuses blkbuf)
@@ -785,8 +775,8 @@ static int ext2_read(int fd, char *buf, unsigned count, unsigned devaddr)
 		fd, buf, count, devaddr);
 
 	return ext2_breadi(ip,
-		devaddr / ext2fs.blocksize,
-		count / ext2fs.blocksize,
+		devaddr / ext2_blocksize,
+		count / ext2_blocksize,
 		buf);
 }
 
@@ -795,7 +785,7 @@ static void ext2_describe(int fd, int *bufalign,
 {
     describe(dev, bufalign, blocksize);
     if (blocksize != 0)
-	*blocksize = ext2fs.blocksize;
+	*blocksize = ext2_blocksize;
 }
 
 int ext2_open(const char *filename)
@@ -830,15 +820,3 @@ void ext2_close(int fd)
 	if (&inode_table[fd].inode != root_inode)
 		ext2_iput(&inode_table[fd].inode);
 }
-
-
-struct bootfs ext2fs = {
-	.fs_type =	0,
-	.blocksize =	0,
-	.mount =	ext2_mount,
-	.open =		ext2_open,
-	.bread = 	ext2_bread,
-	.close = 	ext2_close,
-	.readdir =	ext2_readdir,
-	/* .fstat =	ext2_fstat */
-};
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] iplboot: update the ext2_fs.h header
  2019-07-05 20:07 [PATCH 0/4] bring parisc linux into the modern age by adding ext4 support to the bootloader James Bottomley
  2019-07-05 20:15 ` [PATCH 1/4] iplboot: eliminate unused struct bootfs James Bottomley
@ 2019-07-05 20:16 ` James Bottomley
  2019-07-05 20:16 ` [PATCH 3/4] iplboot: add ext4 support James Bottomley
  2019-07-05 20:17 ` [PATCH 4/4] palo: add support for formatting as ext4 James Bottomley
  3 siblings, 0 replies; 5+ messages in thread
From: James Bottomley @ 2019-07-05 20:16 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel, Parisc List

A lot has changed in libext2fs since this header was last imported,
but most of it is irrelevant to simply reading files from ext2/3, so
only import the additional changes absolutely necessary for reading
from an ext4 filesystem.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 ipl/ext2_fs.h | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/ipl/ext2_fs.h b/ipl/ext2_fs.h
index 2d1db8f..f104880 100644
--- a/ipl/ext2_fs.h
+++ b/ipl/ext2_fs.h
@@ -504,7 +504,7 @@ struct ext2_super_block {
 	__u32	s_hash_seed[4];		/* HTREE hash seed */
 	__u8	s_def_hash_version;	/* Default hash version to use */
 	__u8	s_jnl_backup_type; 	/* Default type of journal backup */
-	__u16	s_reserved_word_pad;
+	__u16	s_desc_size;
 	__u32	s_default_mount_opts;
 	__u32	s_first_meta_bg;	/* First metablock group */
 	__u32	s_mkfs_time;		/* When the filesystem was created */
@@ -565,6 +565,8 @@ struct ext2_super_block {
 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
 #define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
 #define EXT3_FEATURE_INCOMPAT_EXTENTS		0x0040
+#define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
+
 
 
 #define EXT2_FEATURE_COMPAT_SUPP	0
@@ -643,4 +645,42 @@ struct ext2_dir_entry_2 {
 #define EXT2_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT2_DIR_ROUND) & \
 					 ~EXT2_DIR_ROUND)
 
+/* from here we have additional structures from ext3_extents.h */
+
+/*
+ * this is extent on-disk structure
+ * it's used at the bottom of the tree
+ */
+struct ext3_extent {
+	__le32	ee_block;	/* first logical block extent covers */
+	__le16	ee_len;		/* number of blocks covered by extent */
+	__le16	ee_start_hi;	/* high 16 bits of physical block */
+	__le32	ee_start;	/* low 32 bigs of physical block */
+};
+
+/*
+ * this is index on-disk structure
+ * it's used at all the levels, but the bottom
+ */
+struct ext3_extent_idx {
+	__le32	ei_block;	/* index covers logical blocks from 'block' */
+	__le32	ei_leaf;	/* pointer to the physical block of the next *
+				 * level. leaf or next index could bet here */
+	__le16	ei_leaf_hi;	/* high 16 bits of physical block */
+	__le16	ei_unused;
+};
+
+/*
+ * each block (leaves and indexes), even inode-stored has header
+ */
+struct ext3_extent_header {
+	__le16	eh_magic;	/* probably will support different formats */
+	__le16	eh_entries;	/* number of valid entries */
+	__le16	eh_max;		/* capacity of store in entries */
+	__le16	eh_depth;	/* has tree real underlying blocks? */
+	__le32	eh_generation;	/* generation of the tree */
+};
+
+#define EXT3_EXT_MAGIC		0xf30a
+
 #endif	/* _LINUX_EXT2_FS_H */
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] iplboot: add ext4 support
  2019-07-05 20:07 [PATCH 0/4] bring parisc linux into the modern age by adding ext4 support to the bootloader James Bottomley
  2019-07-05 20:15 ` [PATCH 1/4] iplboot: eliminate unused struct bootfs James Bottomley
  2019-07-05 20:16 ` [PATCH 2/4] iplboot: update the ext2_fs.h header James Bottomley
@ 2019-07-05 20:16 ` James Bottomley
  2019-07-05 20:17 ` [PATCH 4/4] palo: add support for formatting as ext4 James Bottomley
  3 siblings, 0 replies; 5+ messages in thread
From: James Bottomley @ 2019-07-05 20:16 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel, Parisc List

For a read only filesystem, like iplboot, the only real additions for
ext4 are allowing for extent based inodes and a variable group size.

The current block transformation scheme simply goes from filesystem
block offset to absolute partition block employing a caching scheme
for the indirect inodes.  We can follow a similar scheme for the
extent tree based on depth, relying on the fact that linear block
loading will optimally keep the cache at a given depth until it's not
needed.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 ipl/ext2.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 173 insertions(+), 7 deletions(-)

diff --git a/ipl/ext2.c b/ipl/ext2.c
index 9d198fe..31b8469 100644
--- a/ipl/ext2.c
+++ b/ipl/ext2.c
@@ -25,6 +25,7 @@
 #include "bootloader.h"
 
 #define MAX_OPEN_FILES		5
+#define EXTENT_MAX_DEPTH	5
 
 static int ext2_blocksize;
 
@@ -32,6 +33,7 @@ static struct ext2_super_block sb;
 static struct ext2_group_desc *gds;
 static struct ext2_inode *root_inode = NULL;
 static int ngroups = 0;
+static int group_size;
 static int directlim;			/* Maximum direct blkno */
 static int ind1lim;			/* Maximum single-indir blkno */
 static int ind2lim;			/* Maximum double-indir blkno */
@@ -62,6 +64,11 @@ static struct inode_table_entry {
 #undef DEBUG
 #define Debug 0
 
+static struct ext3_extent_header *ext3_extent_header(struct ext2_inode *i)
+{
+	return (struct ext3_extent_header *)&i->i_block[0];
+}
+
 
 static void swapsb(struct ext2_super_block *sb)
 {
@@ -104,6 +111,8 @@ static void swapsb(struct ext2_super_block *sb)
     inplace(__le32_to_cpu, sb->s_feature_ro_compat);
     inplace(__le32_to_cpu, sb->s_algorithm_usage_bitmap);
 
+    inplace(__le16_to_cpu, sb->s_desc_size);
+
     /* whew! */
 }
 
@@ -119,6 +128,15 @@ static void swapgrp(struct ext2_group_desc *g)
 
 }
 
+static void swapextenthdr(struct ext3_extent_header *hdr)
+{
+		inplace(__le16_to_cpu, hdr->eh_magic);
+		inplace(__le16_to_cpu, hdr->eh_entries);
+		inplace(__le16_to_cpu, hdr->eh_max);
+		inplace(__le16_to_cpu, hdr->eh_depth);
+		inplace(__le32_to_cpu, hdr->eh_generation);
+}
+
 static void swapino(struct ext2_inode *i)
 {
 	int n;
@@ -148,8 +166,18 @@ static void swapino(struct ext2_inode *i)
 		} masix1;
 	} osd1;				/* OS dependent 1 */
 #endif
-	for (n = 0; n < EXT2_N_BLOCKS; n++) {
-		inplace(__le32_to_cpu, i->i_block[n]);
+	if ((i->i_flags & EXT3_EXTENTS_FL)) {
+		/* the extent header is in the i_block array */
+		struct ext3_extent_header *hdr = ext3_extent_header(i);
+
+		swapextenthdr(hdr);
+		if (Debug)
+			printf("ext4: extent based inode; depth %d, size %d\n",
+			       hdr->eh_depth, hdr->eh_entries);
+	} else {
+		for (n = 0; n < EXT2_N_BLOCKS; n++) {
+			inplace(__le32_to_cpu, i->i_block[n]);
+		}
 	}
 	inplace(__le32_to_cpu, i->i_generation);
 	inplace(__le32_to_cpu, i->i_file_acl);
@@ -193,6 +221,13 @@ static void swapde(struct ext2_dir_entry_2 *de)
 				de->name_len, de->name);
 }
 
+static struct ext2_group_desc *ext2_gds(int i)
+{
+	char *ptr = (char *)gds;
+
+	return (struct ext2_group_desc *)(ptr + group_size * i);
+}
+
 /*
  * Initialize an ext2 partition starting at offset P_OFFSET; this is
  * sort-of the same idea as "mounting" it.  Read in the relevant
@@ -239,8 +274,14 @@ int ext2_mount(long cons_dev, long p_offset, long quiet)
 		   EXT2_BLOCKS_PER_GROUP(&sb) - 1)
 		/ EXT2_BLOCKS_PER_GROUP(&sb);
 
-	gds = (struct ext2_group_desc *)
-	          malloc((size_t)(ngroups * sizeof(struct ext2_group_desc)));
+	if (sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+		group_size = sb.s_desc_size;
+	else
+		group_size = sizeof(struct ext2_group_desc);
+
+	printf("filesystem group size %d\n", group_size);
+
+	gds = (struct ext2_group_desc *)malloc(ngroups * group_size);
 
 	ext2_blocksize = EXT2_BLOCK_SIZE(&sb);
 	if (Debug) printf("ext2 block size %d\n", ext2_blocksize);
@@ -251,7 +292,7 @@ int ext2_mount(long cons_dev, long p_offset, long quiet)
                   ext2_blocksize * (EXT2_MIN_BLOCK_SIZE/ext2_blocksize + 1));
 	for (i = 0; i < ngroups; i++)
 	{
-	    swapgrp(&gds[i]);
+		swapgrp(ext2_gds(i));
 	}
 	/*
 	 * Calculate direct/indirect block limits for this file system
@@ -317,7 +358,7 @@ static struct ext2_inode *ext2_iget(int ino)
 	printf("group is %d\n", group);
 #endif
 	offset = partition_offset
-		+ ((long) gds[group].bg_inode_table * (long)ext2_blocksize)
+		+ ((long) ext2_gds(group)->bg_inode_table * (long)ext2_blocksize)
 		+ (((ino - 1) % EXT2_INODES_PER_GROUP(&sb))
 		   * EXT2_INODE_SIZE(&sb));
 #ifdef DEBUG
@@ -325,7 +366,7 @@ static struct ext2_inode *ext2_iget(int ino)
 	       "(%ld + (%d * %d) + ((%d) %% %d) * %d) "
 	       "(inode %d -> table %d)\n", 
 	       sizeof(struct ext2_inode), offset, partition_offset,
-	       gds[group].bg_inode_table, ext2_blocksize,
+	       ext2_gds(group)->bg_inode_table, ext2_blocksize,
 	       ino - 1, EXT2_INODES_PER_GROUP(&sb), EXT2_INODE_SIZE(&sb),
 	       ino, (int) (itp - inode_table));
 #endif
@@ -338,6 +379,18 @@ static struct ext2_inode *ext2_iget(int ino)
 
 	swapino(ip);
 	if (Debug) printinode("iget", ip);
+	if (ip->i_flags & EXT3_EXTENTS_FL) {
+		struct ext3_extent_header *hdr = ext3_extent_header(ip);
+
+		if (hdr->eh_magic != EXT3_EXT_MAGIC) {
+			printf("ext2_iget: wrong extent magic in inode\n");
+			return NULL;
+		}
+		if (hdr->eh_depth > EXTENT_MAX_DEPTH) {
+			printf("ext2_iget: file has too deep an extent tree]n");
+			return NULL;
+		}
+	}
 
 	itp->free = 0;
 	itp->inumber = ino;
@@ -366,6 +419,116 @@ static void ext2_iput(struct ext2_inode *ip)
 	itp->free = 1;
 }
 
+/*
+ * Recursive function to find the mapping of a block in the extent
+ * tree We make a load of assumptions here, firstly, since we're
+ * dealing with filesystems < 2GB we assume all the _hi elements are
+ * zero.  Secondly we assume monotonic logical block traversal for
+ * kernel/initrd loading, so the cache is static per depth in the
+ * tree.
+ */
+
+static int ext3_extent_leaf_find(struct ext3_extent_header *hdr, int blkoff)
+{
+	struct ext3_extent *leaf = (struct ext3_extent *)(hdr + 1);
+	int i;
+
+	for (i = 0; i < hdr->eh_entries; i++) {
+		__u32 block = __le32_to_cpu(leaf[i].ee_block);
+		__u16 len = __le16_to_cpu(leaf[i].ee_len);
+		__u32 start = __le32_to_cpu(leaf[i].ee_start);
+
+		if (block <= blkoff && block + len > blkoff)
+			return blkoff - block + start;
+	}
+
+	/* block is not in map: this means a hole */
+	return 0;
+}
+
+static int ext3_extent_load_find(struct ext2_inode *ip, int leaf, int d,
+				 int blkoff);
+
+static int ext3_extent_node_find(struct ext2_inode *ip,
+				 struct ext3_extent_header *hdr, int blkoff)
+{
+	struct ext3_extent_idx *node = (struct ext3_extent_idx *)(hdr + 1);
+	struct ext3_extent_idx *prev = node;
+	int i;
+	__u32 start = __le32_to_cpu(prev->ei_block);
+	__u32 leaf = __le32_to_cpu(prev->ei_leaf);
+
+	for (i = 1; i < hdr->eh_entries; i++) {
+		__u32 block = __le32_to_cpu(node[i].ei_block);
+
+		if (start <= blkoff && block > blkoff)
+			break;
+
+		prev = &node[i];
+		start = __le32_to_cpu(prev->ei_block);
+		leaf = __le32_to_cpu(prev->ei_leaf);
+	}
+
+	return ext3_extent_load_find(ip, leaf, hdr->eh_depth - 1, blkoff);
+}
+
+static int ext3_extent_load_find(struct ext2_inode *ip, int leaf, int d,
+				 int blkoff)
+{
+	static char blockbuf[EXTENT_MAX_DEPTH][EXT2_MAX_BLOCK_SIZE];
+	static int cached_blockno[EXTENT_MAX_DEPTH];
+	struct ext3_extent_header *hdr;
+
+	hdr = (struct ext3_extent_header *)blockbuf[d];
+	if (cached_blockno[d] != leaf) {
+		printf("load extent tree[%d] block at %d\n", d, leaf);
+
+		if (cons_read(dev, blockbuf[d], sizeof(blockbuf[d]),
+			      leaf * ext2_blocksize) !=
+		    sizeof(blockbuf[d])) {
+			printf("ext3_extent_load_find: read error\n");
+			return -1;
+		}
+		cached_blockno[d] = leaf;
+		swapextenthdr(hdr);
+	}
+
+	/* these checks could be done once after load, but belt and braces */
+	if (hdr->eh_magic != EXT3_EXT_MAGIC) {
+		printf("ext3_extent_load_find: wrong extent magic in block\n");
+		return -1;
+	}
+	if (hdr->eh_depth != d) {
+		printf("ext3_extent_load_find: wrong depth %d!=%d\n",
+		       hdr->eh_depth, d);
+		return -1;
+	}
+	if (sizeof(hdr) + sizeof(struct ext3_extent)*hdr->eh_entries >
+	    sizeof(blockbuf[d])) {
+		printf("ext3_extent_load_find: extent is larger than buffer\n");
+		return -1;
+	}
+
+	if (hdr->eh_depth == 0)
+		return ext3_extent_leaf_find(hdr, blkoff);
+	else
+		return ext3_extent_node_find(ip, hdr, blkoff);
+}
+
+/*
+ * Map a block using the extents tree
+ */
+static int ext3_extent_blkno(struct ext2_inode *ip, int blkoff)
+{
+	struct ext3_extent_header *hdr = ext3_extent_header(ip);
+
+
+	if (hdr->eh_depth == 0)
+		return ext3_extent_leaf_find(hdr, blkoff);
+	else
+		return ext3_extent_node_find(ip, hdr, blkoff);
+}
+
 
 /*
  * Map a block offset into a file into an absolute block number.
@@ -385,6 +548,9 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
 	int diblkno;
 	unsigned long offset;
 
+	if (ip->i_flags & EXT3_EXTENTS_FL)
+		return ext3_extent_blkno(ip, blkoff);
+
 	ilp = (unsigned int *)iblkbuf;
 	dlp = (unsigned int *)diblkbuf;
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] palo: add support for formatting as ext4
  2019-07-05 20:07 [PATCH 0/4] bring parisc linux into the modern age by adding ext4 support to the bootloader James Bottomley
                   ` (2 preceding siblings ...)
  2019-07-05 20:16 ` [PATCH 3/4] iplboot: add ext4 support James Bottomley
@ 2019-07-05 20:17 ` James Bottomley
  3 siblings, 0 replies; 5+ messages in thread
From: James Bottomley @ 2019-07-05 20:17 UTC (permalink / raw)
  To: linux-ext4, linux-fsdevel, Parisc List

Now that iplboot can read ext4 filesystem, allow palo to create them
with the palo --format-as=4 option.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 palo/palo.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/palo/palo.c b/palo/palo.c
index e088993..26da01b 100644
--- a/palo/palo.c
+++ b/palo/palo.c
@@ -506,8 +506,8 @@ do_formatted(int init, int media, const char *medianame, int partition,
 	    }
 	}
 
-	sprintf(cmd, "mke2fs %s -O^resize_inode -b %d -l %s %s", do_format == 3 ? "-j" : "",
-		EXT2_BLOCKSIZE, badblockfilename, partitionname);
+	sprintf(cmd, "mke2fs -t ext%d -O^resize_inode -b %d -l %s %s",
+		do_format, EXT2_BLOCKSIZE, badblockfilename, partitionname);
 
 	if (verbose)
 	    printf("Executing: %s\n", cmd);
@@ -868,6 +868,8 @@ main(int argc, char *argv[])
 		format_as = 2;
 	    else if(strcmp(optarg, "3") == 0)
 		format_as = 3;
+	    else if (strcmp(optarg, "4") == 0)
+		format_as = 4;
 	    else
 		error(0, argv[0]);
 	    break;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-07-05 20:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-05 20:07 [PATCH 0/4] bring parisc linux into the modern age by adding ext4 support to the bootloader James Bottomley
2019-07-05 20:15 ` [PATCH 1/4] iplboot: eliminate unused struct bootfs James Bottomley
2019-07-05 20:16 ` [PATCH 2/4] iplboot: update the ext2_fs.h header James Bottomley
2019-07-05 20:16 ` [PATCH 3/4] iplboot: add ext4 support James Bottomley
2019-07-05 20:17 ` [PATCH 4/4] palo: add support for formatting as ext4 James Bottomley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).