All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.