Correct befs block counting logic.
* grub-core/fs/afs.c (GRUB_AFS_BLOCKS_PER_DI_RUN): Replaced with... (GRUB_AFS_LOG_BLOCKS_PER_DI_RUN): ... this. (GRUB_AFS_BLOCKRUN_LOG_SIZE): New definition. (grub_afs_read_inode): Use block_shift. (RANGE_SHIFT): New definition. (grub_afs_read_block): Account for RANGE_SHIFT, emit errors on unexpected conditions, use shifts and appropriate types. (GRUB_MOD_INIT): Check the value of GRUB_AFS_BLOCKRUN_LOG_SIZE.
This commit is contained in:
parent
6563f63dfd
commit
ad03fe768e
2 changed files with 54 additions and 26 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2011-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Correct befs block counting logic.
|
||||||
|
|
||||||
|
* grub-core/fs/afs.c (GRUB_AFS_BLOCKS_PER_DI_RUN): Replaced with...
|
||||||
|
(GRUB_AFS_LOG_BLOCKS_PER_DI_RUN): ... this.
|
||||||
|
(GRUB_AFS_BLOCKRUN_LOG_SIZE): New definition.
|
||||||
|
(grub_afs_read_inode): Use block_shift.
|
||||||
|
(RANGE_SHIFT): New definition.
|
||||||
|
(grub_afs_read_block): Account for RANGE_SHIFT, emit errors on
|
||||||
|
unexpected conditions, use shifts and appropriate types.
|
||||||
|
(GRUB_MOD_INIT): Check the value of GRUB_AFS_BLOCKRUN_LOG_SIZE.
|
||||||
|
|
||||||
2011-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
2011-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/disk/raid.c (scan_devices): Check partition.
|
* grub-core/disk/raid.c (scan_devices): Check partition.
|
||||||
|
|
|
@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GRUB_AFS_DIRECT_BLOCK_COUNT 12
|
#define GRUB_AFS_DIRECT_BLOCK_COUNT 12
|
||||||
#define GRUB_AFS_BLOCKS_PER_DI_RUN 4
|
#define GRUB_AFS_LOG_BLOCKS_PER_DI_RUN 2
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
#ifdef MODE_BFS
|
||||||
#define GRUB_AFS_SBLOCK_SECTOR 1
|
#define GRUB_AFS_SBLOCK_SECTOR 1
|
||||||
|
@ -103,6 +103,7 @@ typedef grub_uint64_t grub_afs_off_t;
|
||||||
typedef grub_uint64_t grub_afs_bigtime;
|
typedef grub_uint64_t grub_afs_bigtime;
|
||||||
typedef grub_uint64_t grub_afs_bvalue_t;
|
typedef grub_uint64_t grub_afs_bvalue_t;
|
||||||
|
|
||||||
|
#define GRUB_AFS_BLOCKRUN_LOG_SIZE 3
|
||||||
struct grub_afs_blockrun
|
struct grub_afs_blockrun
|
||||||
{
|
{
|
||||||
grub_uint32_t group;
|
grub_uint32_t group;
|
||||||
|
@ -262,8 +263,7 @@ grub_afs_read_inode (struct grub_afs_data *data,
|
||||||
grub_uint64_t ino, struct grub_afs_inode *inode)
|
grub_uint64_t ino, struct grub_afs_inode *inode)
|
||||||
{
|
{
|
||||||
return grub_disk_read (data->disk,
|
return grub_disk_read (data->disk,
|
||||||
ino *
|
ino << (data->sblock.block_shift - GRUB_DISK_SECTOR_BITS),
|
||||||
(data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, data->sblock.block_size, inode);
|
0, data->sblock.block_size, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,13 +340,19 @@ grub_afs_read_attribute (grub_fshelp_node_t node,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODE_BFS
|
||||||
|
#define RANGE_SHIFT sb->block_shift
|
||||||
|
#else
|
||||||
|
#define RANGE_SHIFT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
static grub_disk_addr_t
|
static grub_disk_addr_t
|
||||||
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
{
|
{
|
||||||
struct grub_afs_sblock *sb = &node->data->sblock;
|
struct grub_afs_sblock *sb = &node->data->sblock;
|
||||||
struct grub_afs_datastream *ds = &node->inode.stream;
|
struct grub_afs_datastream *ds = &node->inode.stream;
|
||||||
|
|
||||||
if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range))
|
if ((fileblock << RANGE_SHIFT) < grub_afs_to_cpu64 (ds->max_direct_range))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -356,21 +362,24 @@ grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
|
return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
|
||||||
fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
|
fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
|
||||||
}
|
}
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "incorrect direct blocks");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range))
|
else if ((fileblock << RANGE_SHIFT)
|
||||||
|
< grub_afs_to_cpu64 (ds->max_indirect_range))
|
||||||
{
|
{
|
||||||
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
|
grub_size_t ptrs_per_blk = (1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE));
|
||||||
struct grub_afs_blockrun indir[ptrs_per_blk];
|
struct grub_afs_blockrun indir[ptrs_per_blk];
|
||||||
grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
|
grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fileblock -= grub_afs_to_cpu64 (ds->max_direct_range);
|
fileblock -= grub_afs_to_cpu64 (ds->max_direct_range) >> RANGE_SHIFT;
|
||||||
for (i = 0; i < ds->indirect.len; i++, blk++)
|
for (i = 0; i < ds->indirect.len; i++, blk++)
|
||||||
{
|
{
|
||||||
int j;
|
grub_size_t j;
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
if (grub_disk_read (node->data->disk,
|
||||||
blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
|
blk << (sb->block_shift - GRUB_DISK_SECTOR_BITS),
|
||||||
0, sizeof (indir),
|
0, sizeof (indir),
|
||||||
indir))
|
indir))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -383,37 +392,38 @@ grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
fileblock -= grub_afs_to_cpu16 (indir[j].len);
|
fileblock -= grub_afs_to_cpu16 (indir[j].len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "incorrect indirect blocks");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else if ((fileblock << RANGE_SHIFT) < grub_afs_to_cpu64 (ds->max_double_indirect_range))
|
||||||
{
|
{
|
||||||
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
|
grub_size_t ptrs_per_blk = (1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE));
|
||||||
struct grub_afs_blockrun indir[ptrs_per_blk];
|
struct grub_afs_blockrun indir[ptrs_per_blk];
|
||||||
|
grub_disk_addr_t off, dptr, dblk, idptr, idblk;
|
||||||
/* ([idblk][idptr]) ([dblk][dptr]) [blk] */
|
/* ([idblk][idptr]) ([dblk][dptr]) [blk] */
|
||||||
int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range);
|
|
||||||
|
|
||||||
int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
|
fileblock -= grub_afs_to_cpu64 (ds->max_indirect_range) >> RANGE_SHIFT;
|
||||||
int dblk_size = dptr_size * ptrs_per_blk;
|
|
||||||
int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
|
|
||||||
int idblk_size = idptr_size * ptrs_per_blk;
|
|
||||||
|
|
||||||
int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
|
/* Divisions and modulo fixed number are optimised by compiler. */
|
||||||
int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
|
off = fileblock & ((1 << GRUB_AFS_LOG_BLOCKS_PER_DI_RUN) - 1);
|
||||||
int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
|
dptr = fileblock >> GRUB_AFS_LOG_BLOCKS_PER_DI_RUN;
|
||||||
int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
|
dblk = dptr >> (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE);
|
||||||
int idblk = (cur_pos / idblk_size);
|
dptr &= ((1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)) - 1);
|
||||||
|
idptr = dblk >> GRUB_AFS_LOG_BLOCKS_PER_DI_RUN;
|
||||||
|
dblk &= ((1 << GRUB_AFS_LOG_BLOCKS_PER_DI_RUN) - 1);
|
||||||
|
idblk = idptr >> (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE);
|
||||||
|
idptr &= ((1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)) - 1);
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
if (grub_disk_read (node->data->disk,
|
||||||
(grub_afs_run_to_num (sb, &ds->double_indirect)
|
(grub_afs_run_to_num (sb, &ds->double_indirect)
|
||||||
+ idblk) *
|
+ idblk) << (sb->block_shift - GRUB_DISK_SECTOR_BITS),
|
||||||
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, sizeof (indir),
|
0, sizeof (indir),
|
||||||
indir))
|
indir))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
if (grub_disk_read (node->data->disk,
|
||||||
(grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
|
(grub_afs_run_to_num (sb, &indir[idptr]) + dblk)
|
||||||
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
|
<< (sb->block_shift - GRUB_DISK_SECTOR_BITS),
|
||||||
0, sizeof (indir),
|
0, sizeof (indir),
|
||||||
indir))
|
indir))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -421,6 +431,9 @@ grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
return grub_afs_run_to_num (sb, &indir[dptr]) + off;
|
return grub_afs_run_to_num (sb, &indir[dptr]) + off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
"triple-indirect on " GRUB_AFS_FSNAME " isn't supported");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,6 +850,8 @@ GRUB_MOD_INIT (afs_be)
|
||||||
GRUB_MOD_INIT (afs)
|
GRUB_MOD_INIT (afs)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT ((1 << GRUB_AFS_BLOCKRUN_LOG_SIZE)
|
||||||
|
== sizeof (struct grub_afs_blockrun));
|
||||||
grub_fs_register (&grub_afs_fs);
|
grub_fs_register (&grub_afs_fs);
|
||||||
my_mod = mod;
|
my_mod = mod;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue