123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- From 978c4c79935a375cb16d94e8114d96fee013c288 Mon Sep 17 00:00:00 2001
- From: Lidong Chen <lidong.chen@oracle.com>
- Date: Mon, 16 Dec 2024 20:22:39 +0000
- Subject: [PATCH] fs/jfs: Use full 40 bits offset and address for a data extent
- An extent's logical offset and address are represented as a 40-bit value
- split into two parts: the most significant 8 bits and the least
- significant 32 bits. Currently the JFS code uses only the least
- significant 32 bits value for offsets and addresses assuming the data
- size will never exceed the 32-bit range. This approach ignores the most
- significant 8 bits potentially leading to incorrect offsets and
- addresses for larger values. The patch fixes it by incorporating the
- most significant 8 bits into the calculation to get the full 40-bits
- value for offsets and addresses.
- https://jfs.sourceforge.net/project/pub/jfslayout.pdf
- "off1,off2 is a 40-bit field, containing the logical offset of the first
- block in the extent.
- ...
- addr1,addr2 is a 40-bit field, containing the address of the extent."
- Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
- Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
- Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
- Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
- Upstream: bd999310fe67f35a66de3bfa2836da91589d04ef
- Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
- ---
- grub-core/fs/jfs.c | 41 +++++++++++++++++++++++++++++------------
- 1 file changed, 29 insertions(+), 12 deletions(-)
- diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
- index 88fb884df..2bde48d45 100644
- --- a/grub-core/fs/jfs.c
- +++ b/grub-core/fs/jfs.c
- @@ -265,6 +265,20 @@ static grub_dl_t my_mod;
-
- static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino);
-
- +/*
- + * An extent's offset, physical and logical, is represented as a 40-bit value.
- + * This 40-bit value is split into two parts:
- + * - offset1: the most signficant 8 bits of the offset,
- + * - offset2: the least significant 32 bits of the offset.
- + *
- + * This function calculates and returns the 64-bit offset of an extent.
- + */
- +static grub_uint64_t
- +get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2)
- +{
- + return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2));
- +}
- +
- static grub_int64_t
- getblk (struct grub_jfs_treehead *treehead,
- struct grub_jfs_tree_extent *extents,
- @@ -274,22 +288,25 @@ getblk (struct grub_jfs_treehead *treehead,
- {
- int found = -1;
- int i;
- + grub_uint64_t ext_offset, ext_blk;
-
- for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
- i < max_extents; i++)
- {
- + ext_offset = get_ext_offset (extents[i].offset1, extents[i].offset2);
- + ext_blk = get_ext_offset (extents[i].extent.blk1, extents[i].extent.blk2);
- +
- if (treehead->flags & GRUB_JFS_TREE_LEAF)
- {
- /* Read the leafnode. */
- - if (grub_le_to_cpu32 (extents[i].offset2) <= blk
- + if (ext_offset <= blk
- && ((grub_le_to_cpu16 (extents[i].extent.length))
- + (extents[i].extent.length2 << 16)
- - + grub_le_to_cpu32 (extents[i].offset2)) > blk)
- - return (blk - grub_le_to_cpu32 (extents[i].offset2)
- - + grub_le_to_cpu32 (extents[i].extent.blk2));
- + + ext_offset) > blk)
- + return (blk - ext_offset + ext_blk);
- }
- else
- - if (blk >= grub_le_to_cpu32 (extents[i].offset2))
- + if (blk >= ext_offset)
- found = i;
- }
-
- @@ -307,10 +324,9 @@ getblk (struct grub_jfs_treehead *treehead,
- return -1;
-
- if (!grub_disk_read (data->disk,
- - ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
- - << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- - - GRUB_DISK_SECTOR_BITS), 0,
- - sizeof (*tree), (char *) tree))
- + (grub_disk_addr_t) ext_blk
- + << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS),
- + 0, sizeof (*tree), (char *) tree))
- {
- if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
- grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
- @@ -361,7 +377,7 @@ grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino,
- sizeof (iag_inodes), &iag_inodes))
- return grub_errno;
-
- - inoblk = grub_le_to_cpu32 (iag_inodes[inoext].blk2);
- + inoblk = get_ext_offset (iag_inodes[inoext].blk1, iag_inodes[inoext].blk2);
- inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
- - GRUB_DISK_SECTOR_BITS);
- inoblk += inonum;
- @@ -490,7 +506,8 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
- return 0;
- }
-
- - blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
- + blk = get_ext_offset (de[inode->dir.header.sorted[0]].ex.blk1,
- + de[inode->dir.header.sorted[0]].ex.blk2);
- blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
-
- /* Read in the nodes until we are on the leaf node level. */
- @@ -508,7 +525,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
-
- de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
- index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
- - blk = (grub_le_to_cpu32 (de[index].ex.blk2)
- + blk = (get_ext_offset (de[index].ex.blk1, de[index].ex.blk2)
- << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- - GRUB_DISK_SECTOR_BITS));
- } while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
- --
- 2.50.1
|