* grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset.
(GRUB_XFS_INO_AGBITS): Make into inline function. (GRUB_XFS_INO_INOINAG): Likewise. (GRUB_XFS_INO_AG): Likewise. (GRUB_XFS_FSB_TO_BLOCK): Likewise. (GRUB_XFS_EXTENT_OFFSET): Likewise. (GRUB_XFS_EXTENT_BLOCK): Likewise. (GRUB_XFS_EXTENT_SIZE): Likewise. (GRUB_XFS_ROUND_TO_DIRENT): Likewise. (GRUB_XFS_NEXT_DIRENT): Likewise. (grub_xfs_read_block): Rewrite the btree parsing. Fixes invalid BMAP. (grub_xfs_read_file): Fix offset type.
This commit is contained in:
parent
8bcebcb8e4
commit
3b619ae116
2 changed files with 94 additions and 32 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
||||||
|
2011-10-16 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset.
|
||||||
|
(GRUB_XFS_INO_AGBITS): Make into inline function.
|
||||||
|
(GRUB_XFS_INO_INOINAG): Likewise.
|
||||||
|
(GRUB_XFS_INO_AG): Likewise.
|
||||||
|
(GRUB_XFS_FSB_TO_BLOCK): Likewise.
|
||||||
|
(GRUB_XFS_EXTENT_OFFSET): Likewise.
|
||||||
|
(GRUB_XFS_EXTENT_BLOCK): Likewise.
|
||||||
|
(GRUB_XFS_EXTENT_SIZE): Likewise.
|
||||||
|
(GRUB_XFS_ROUND_TO_DIRENT): Likewise.
|
||||||
|
(GRUB_XFS_NEXT_DIRENT): Likewise.
|
||||||
|
(grub_xfs_read_block): Rewrite the btree parsing. Fixes invalid BMAP.
|
||||||
|
(grub_xfs_read_file): Fix offset type.
|
||||||
|
|
||||||
2011-10-15 Robert Millan <rmh@gnu.org>
|
2011-10-15 Robert Millan <rmh@gnu.org>
|
||||||
|
|
||||||
* util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs.
|
* util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs.
|
||||||
|
|
|
@ -120,7 +120,9 @@ struct grub_xfs_inode
|
||||||
grub_uint64_t nblocks;
|
grub_uint64_t nblocks;
|
||||||
grub_uint32_t extsize;
|
grub_uint32_t extsize;
|
||||||
grub_uint32_t nextents;
|
grub_uint32_t nextents;
|
||||||
grub_uint8_t unused3[20];
|
grub_uint16_t unused3;
|
||||||
|
grub_uint8_t fork_offset;
|
||||||
|
grub_uint8_t unused4[17];
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
char raw[156];
|
char raw[156];
|
||||||
|
@ -154,7 +156,7 @@ struct grub_xfs_data
|
||||||
grub_disk_t disk;
|
grub_disk_t disk;
|
||||||
int pos;
|
int pos;
|
||||||
int bsize;
|
int bsize;
|
||||||
int agsize;
|
grub_uint32_t agsize;
|
||||||
struct grub_fshelp_node diropen;
|
struct grub_fshelp_node diropen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,33 +170,67 @@ static grub_dl_t my_mod;
|
||||||
#define FILETYPE_INO_DIRECTORY 0040000
|
#define FILETYPE_INO_DIRECTORY 0040000
|
||||||
#define FILETYPE_INO_SYMLINK 0120000
|
#define FILETYPE_INO_SYMLINK 0120000
|
||||||
|
|
||||||
#define GRUB_XFS_INO_AGBITS(data) \
|
static inline int
|
||||||
((data)->sblock.log2_agblk + (data)->sblock.log2_inop)
|
GRUB_XFS_INO_AGBITS(struct grub_xfs_data *data)
|
||||||
#define GRUB_XFS_INO_INOINAG(data, ino) \
|
{
|
||||||
(grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1))
|
return ((data)->sblock.log2_agblk + (data)->sblock.log2_inop);
|
||||||
#define GRUB_XFS_INO_AG(data,ino) \
|
}
|
||||||
(grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data))
|
|
||||||
|
|
||||||
#define GRUB_XFS_FSB_TO_BLOCK(data, fsb) \
|
static inline grub_uint64_t
|
||||||
(((fsb) >> (data)->sblock.log2_agblk) * (data)->agsize \
|
GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
|
||||||
+ ((fsb) & ((1LL << (data)->sblock.log2_agblk) - 1)))
|
grub_uint64_t ino)
|
||||||
|
{
|
||||||
|
return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \
|
static inline grub_uint64_t
|
||||||
((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \
|
GRUB_XFS_INO_AG (struct grub_xfs_data *data,
|
||||||
| grub_be_to_cpu32 (exts[ex][1]) >> 9)
|
grub_uint64_t ino)
|
||||||
|
{
|
||||||
|
return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data));
|
||||||
|
}
|
||||||
|
|
||||||
#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \
|
static inline grub_disk_addr_t
|
||||||
((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \
|
GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb)
|
||||||
& (0x1ff)) << 43 \
|
{
|
||||||
| (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \
|
return ((fsb >> data->sblock.log2_agblk) * data->agsize
|
||||||
| grub_be_to_cpu32 (exts[ex][3]) >> 21)
|
+ (fsb & ((1LL << data->sblock.log2_agblk) - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
#define GRUB_XFS_EXTENT_SIZE(exts,ex) \
|
static inline grub_uint64_t
|
||||||
(grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1))
|
GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex)
|
||||||
|
{
|
||||||
|
return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23
|
||||||
|
| grub_be_to_cpu32 (exts[ex][1]) >> 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline grub_uint64_t
|
||||||
|
GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex)
|
||||||
|
{
|
||||||
|
return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1])
|
||||||
|
& (0x1ff)) << 43
|
||||||
|
| (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11
|
||||||
|
| grub_be_to_cpu32 (exts[ex][3]) >> 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline grub_uint64_t
|
||||||
|
GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex)
|
||||||
|
{
|
||||||
|
return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
GRUB_XFS_ROUND_TO_DIRENT (int pos)
|
||||||
|
{
|
||||||
|
return ((((pos) + 8 - 1) / 8) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
GRUB_XFS_NEXT_DIRENT (int pos, int len)
|
||||||
|
{
|
||||||
|
return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2);
|
||||||
|
}
|
||||||
|
|
||||||
#define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8)
|
|
||||||
#define GRUB_XFS_NEXT_DIRENT(pos,len) \
|
|
||||||
(pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2)
|
|
||||||
|
|
||||||
static inline grub_uint64_t
|
static inline grub_uint64_t
|
||||||
grub_xfs_inode_block (struct grub_xfs_data *data,
|
grub_xfs_inode_block (struct grub_xfs_data *data,
|
||||||
|
@ -250,13 +286,23 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
if (node->inode.format == XFS_INODE_FORMAT_BTREE)
|
if (node->inode.format == XFS_INODE_FORMAT_BTREE)
|
||||||
{
|
{
|
||||||
grub_uint64_t *keys;
|
grub_uint64_t *keys;
|
||||||
|
int recoffset;
|
||||||
|
|
||||||
leaf = grub_malloc (node->data->sblock.bsize);
|
leaf = grub_malloc (node->data->bsize);
|
||||||
if (leaf == 0)
|
if (leaf == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
|
nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
|
||||||
keys = &node->inode.data.btree.keys[0];
|
keys = &node->inode.data.btree.keys[0];
|
||||||
|
if (node->inode.fork_offset)
|
||||||
|
recoffset = (node->inode.fork_offset
|
||||||
|
- ((char *) &node->inode.data.btree.keys - (char *) &node->inode))
|
||||||
|
/ (2 * sizeof (grub_uint64_t));
|
||||||
|
else
|
||||||
|
recoffset = ((1 << node->data->sblock.log2_inode)
|
||||||
|
- ((char *) &node->inode.data.btree.keys
|
||||||
|
- (char *) &node->inode))
|
||||||
|
/ (2 * sizeof (grub_uint64_t));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -273,12 +319,9 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
grub_free (leaf);
|
grub_free (leaf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
if (grub_disk_read (node->data->disk,
|
||||||
grub_be_to_cpu64 (keys[i - 1 + nrec])
|
GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS),
|
||||||
<< (node->data->sblock.log2_bsize
|
0, node->data->bsize, leaf))
|
||||||
- GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, node->data->sblock.bsize, leaf))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
|
if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
|
||||||
|
@ -290,7 +333,11 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
|
|
||||||
nrec = grub_be_to_cpu16 (leaf->numrecs);
|
nrec = grub_be_to_cpu16 (leaf->numrecs);
|
||||||
keys = &leaf->keys[0];
|
keys = &leaf->keys[0];
|
||||||
} while (leaf->level);
|
recoffset = ((node->data->bsize - ((char *) &leaf->keys
|
||||||
|
- (char *) leaf))
|
||||||
|
/ (2 * sizeof (grub_uint64_t)));
|
||||||
|
}
|
||||||
|
while (leaf->level);
|
||||||
exts = (grub_xfs_extent *) keys;
|
exts = (grub_xfs_extent *) keys;
|
||||||
}
|
}
|
||||||
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
|
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
|
||||||
|
@ -336,7 +383,7 @@ static grub_ssize_t
|
||||||
grub_xfs_read_file (grub_fshelp_node_t node,
|
grub_xfs_read_file (grub_fshelp_node_t node,
|
||||||
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
||||||
unsigned offset, unsigned length),
|
unsigned offset, unsigned length),
|
||||||
int pos, grub_size_t len, char *buf)
|
grub_off_t pos, grub_size_t len, char *buf)
|
||||||
{
|
{
|
||||||
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
||||||
pos, len, buf, grub_xfs_read_block,
|
pos, len, buf, grub_xfs_read_block,
|
||||||
|
|
Loading…
Reference in a new issue