2008-05-20 Bean <bean123ch@gmail.com>

* fs/fshelp.c (grub_fshelp_map_block): New function.
	(grub_fshelp_find_file): Use 64-bit type for pos and block address.
	Use `>>' and `&' operator to avoid 64-bit divide and modulo.

	* include/grub/fshelp.h (grub_fshelp_journal_type): New enum.
	(GRUB_FSHELP_JOURNAL_UNUSED_MAPPING): New macro.
	(grub_fshelp_journal): New structure.
	(grub_fshelp_map_block): New function prototype.
	(grub_fshelp_read_file): Use grub_disk_addr_t as block type.
	(grub_fshelp_map_block): Likewise.

	* fs/ext2.c (EXT3_FEATURE_COMPAT_HAS_JOURNAL): New macro.
	(EXT3_JOURNAL_MAGIC_NUMBER): Likewise.
	(EXT3_JOURNAL_DESCRIPTOR_BLOCK): Likewise.
	(EXT3_JOURNAL_COMMIT_BLOCK): Likewise.
	(EXT3_JOURNAL_SUPERBLOCK_V1): Likewise.
	(EXT3_JOURNAL_SUPERBLOCK_V2): Likewise.
	(EXT3_JOURNAL_REVOKE_BLOCK): Likewise.
	(EXT3_JOURNAL_FLAG_ESCAPE): Likewise.
	(EXT3_JOURNAL_FLAG_SAME_UUID): Likewise.
	(EXT3_JOURNAL_FLAG_DELETED): Likewise.
	(EXT3_JOURNAL_FLAG_LAST_TAG): Likewise.
	(grub_ext2_sblock): New members for journal support.
	(grub_ext3_journal_header): New structure.
	(grub_ext3_journal_revoke_header): Likewise.
	(grub_ext3_journal_block_tag): Likewise.
	(grub_ext3_journal_sblock): Likewise.
	(grub_fshelp_node): New members logfile and journal.
	(grub_ext2_read_block): Change block type to grub_disk_addr_t. Use
	grub_fshelp_map_block to get real block number.
	(grub_ext2_blockgroup): Use grub_fshelp_map_block to get real block
	number.
	(grub_ext2_read_inode): Likewise.
	(grub_ext3_get_journal): New function.
	(grub_read_inode): Initialize journal using grub_ext3_get_journal.
	(grub_ext2_close): Release memory used by journal.

	* fs/reiserfs.c (REISERFS_MAGIC_STRING): Changed to "ReIsEr".
	(REISERFS_MAGIC_DESC_BLOCK): New macro.
	(grub_reiserfs_transaction_header): Renamed to
	grub_reiserfs_description_block, replace field data with real_blocks.
	(grub_reiserfs_commit_block): New structure.
	(grub_reiserfs_data): New member journal.
	(grub_reiserfs_get_item): Use grub_fshelp_map_block to get real block
	number.
	(grub_reiserfs_read_symlink): Likewise.
	(grub_reiserfs_iterate_dir): Likewise.
	(grub_reiserfs_open): Likewise.
	(grub_reiserfs_read): Likewise.
	(grub_reiserfs_get_journal): New function.
	(grub_reiserfs_mount): Use "ReIsEr" as super block magic, as there are
	three varieties ReIsErFs, ReIsEr2Fs and ReIsEr3Fs. Initialize journal
	using grub_reiserfs_get_journal.
	(grub_reiserfs_close): Release memory used by journal.

	* fs/affs.c (grub_affs_read_block): Change block type to
	grub_disk_addr_t. Use grub_divmod64 to do 64-bit division.

	* fs/afs.c (grub_afs_read_block): Change block type to grub_disk_addr_t.

	* fs/hfsplus.c (grub_hfsplus_read_block): Likewise.

	* fs/ntfs.c (grub_ntfs_read_block): Likewise.

	* fs/udf.c (grub_udf_read_block): Change block type to
	grub_disk_addr_t. Use type cast to avoid warning.

	* fs/xfs.c (grub_xfs_read_block): Likewise.
This commit is contained in:
bean 2008-05-20 05:00:53 +00:00
parent b7c6bed50e
commit 887d2619bf
12 changed files with 575 additions and 83 deletions

View file

@ -72,7 +72,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
void free_node (grub_fshelp_node_t node)
{
if (node != rootnode && node != currroot)
if (node != rootnode && node != currroot)
grub_free (node);
}
@ -223,25 +223,26 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
grub_ssize_t
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf,
int (*get_block) (grub_fshelp_node_t node, int block),
unsigned offset,
unsigned length),
grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
grub_off_t filesize, int log2blocksize)
{
int i;
int blockcnt;
grub_disk_addr_t i, blockcnt;
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
/* Adjust LEN so it we can't read past the end of the file. */
if (len > filesize)
len = filesize;
if (pos + len > filesize)
len = filesize - pos;
blockcnt = ((len + pos) + blocksize - 1) / blocksize;
blockcnt = ((len + pos) + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
for (i = pos / blocksize; i < blockcnt; i++)
for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
{
int blknr;
int blockoff = pos % blocksize;
grub_disk_addr_t blknr;
int blockoff = pos & (blocksize - 1);
int blockend = blocksize;
int skipfirst = 0;
@ -255,7 +256,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) % blocksize;
blockend = (len + pos) & (blocksize - 1);
/* The last portion is exactly blocksize. */
if (! blockend)
@ -263,7 +264,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
}
/* First block. */
if (i == pos / blocksize)
if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
{
skipfirst = blockoff;
blockend -= skipfirst;
@ -310,3 +311,30 @@ grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow)
return GRUB_ERR_NONE;
}
grub_disk_addr_t
grub_fshelp_map_block (grub_fshelp_journal_t log, grub_disk_addr_t block)
{
int map_block;
if (! log)
return block;
for (map_block = log->num_mappings - 1; map_block >= 0; map_block--)
{
if (log->mapping[map_block] == block)
break;
}
if (map_block < 0)
return block;
map_block += log->start_block;
if (map_block >= log->last_block)
map_block -= log->last_block - log->first_block;
if (log->type == GRUB_FSHELP_JOURNAL_TYPE_BLOCK)
return log->blkno + map_block;
else
return log->get_block (log->node, map_block);
}