Skip to content
This repository has been archived by the owner on Jun 28, 2023. It is now read-only.

Commit

Permalink
disk: speed up blocklist (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
a1ive committed Feb 26, 2020
1 parent 7e8f6d6 commit c3a7633
Show file tree
Hide file tree
Showing 22 changed files with 138 additions and 33 deletions.
12 changes: 10 additions & 2 deletions grub-core/commands/blocklist.c
Expand Up @@ -135,8 +135,16 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
file->read_hook = read_blocklist;
file->read_hook_data = &ctx;

while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
if (file->fs && file->fs->fast_blocklist)
{
file->blocklist = 1;
grub_file_read (file, 0, file->size);
}
else
{
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
}

if (ctx.num_sectors > 0)
print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx);
Expand Down
12 changes: 10 additions & 2 deletions grub-core/commands/stat.c
Expand Up @@ -116,8 +116,16 @@ grub_cmd_stat (grub_extcmd_context_t ctxt, int argc, char **args)
{
file->read_hook = read_block_contig;
file->read_hook_data = &file_block;
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
if (file->fs && file->fs->fast_blocklist)
{
file->blocklist = 1;
grub_file_read (file, 0, file->size);
}
else
{
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
}
if (!state[STAT_QUIET].set)
grub_printf ("File is%scontiguous.\nNumber of fragments: %d\n",
(file_block.num > 1)? " NOT ":" ", file_block.num);
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/affs.c
Expand Up @@ -531,7 +531,7 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
(struct grub_affs_data *) file->data;

return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
file->read_hook, file->read_hook_data,
file->read_hook, file->read_hook_data, 0,
file->offset, len, buf, grub_affs_read_block,
grub_be_to_cpu32 (data->diropen.di.size),
data->log_blocksize, 0);
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/ext2.c
Expand Up @@ -572,7 +572,7 @@ grub_ext2_read_file (grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_ext2_read_block,
grub_cpu_to_le32 (node->inode.size)
| (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/f2fs.c
Expand Up @@ -915,7 +915,7 @@ grub_f2fs_read_file (grub_fshelp_node_t node,
}

return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_f2fs_get_block,
filesize,
F2FS_BLK_SEC_BITS, 0);
Expand Down
25 changes: 14 additions & 11 deletions grub-core/fs/fat.c
Expand Up @@ -450,7 +450,7 @@ grub_fat_mount (grub_disk_t disk)

static grub_ssize_t
grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_disk_read_hook_t read_hook, void *read_hook_data, int blocklist,
grub_off_t offset, grub_size_t len, char *buf)
{
grub_size_t size;
Expand All @@ -468,7 +468,8 @@ grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,
if (size > len)
size = len;

if (grub_disk_read (disk, node->data->root_sector, offset, size, buf))
if (grub_disk_read_ex (disk,
node->data->root_sector, offset, size, buf, blocklist))
return -1;

return size;
Expand All @@ -485,8 +486,8 @@ grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,

disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;
grub_disk_read (disk, sector + (offset >> GRUB_DISK_SECTOR_BITS),
offset & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
grub_disk_read_ex (disk, sector + (offset >> GRUB_DISK_SECTOR_BITS),
offset & (GRUB_DISK_SECTOR_SIZE - 1), len, buf, blocklist);
disk->read_hook = 0;
if (grub_errno)
return -1;
Expand Down Expand Up @@ -577,13 +578,14 @@ grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,

disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;
grub_disk_read (disk, sector, offset, size, buf);
grub_disk_read_ex (disk, sector, offset, size, buf, blocklist);
disk->read_hook = 0;
if (grub_errno)
return -1;

len -= size;
buf += size;
if (buf)
buf += size;
ret += size;
logical_cluster++;
offset = 0;
Expand Down Expand Up @@ -646,7 +648,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node,

ctxt->offset += sizeof (dir);

if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (dir),
if (grub_fat_read_data (node->disk, node, 0, 0, 0, ctxt->offset, sizeof (dir),
(char *) &dir)
!= sizeof (dir))
break;
Expand All @@ -668,7 +670,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node,
{
struct grub_fat_dir_entry sec;
ctxt->offset += sizeof (sec);
if (grub_fat_read_data (node->disk, node, 0, 0,
if (grub_fat_read_data (node->disk, node, 0, 0, 0,
ctxt->offset, sizeof (sec), (char *) &sec)
!= sizeof (sec))
break;
Expand Down Expand Up @@ -747,7 +749,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node,
ctxt->offset += sizeof (ctxt->dir);

/* Read a directory entry. */
if (grub_fat_read_data (node->disk, node, 0, 0,
if (grub_fat_read_data (node->disk, node, 0, 0, 0,
ctxt->offset, sizeof (ctxt->dir),
(char *) &ctxt->dir)
!= sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
Expand Down Expand Up @@ -1040,7 +1042,7 @@ static grub_ssize_t
grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
{
return grub_fat_read_data (file->device->disk, file->data,
file->read_hook, file->read_hook_data,
file->read_hook, file->read_hook_data, file->blocklist,
file->offset, len, buf);
}

Expand Down Expand Up @@ -1085,7 +1087,7 @@ grub_fat_label (grub_device_t device, char **label)
{
offset += sizeof (dir);

if (grub_fat_read_data (disk, &root, 0, 0,
if (grub_fat_read_data (disk, &root, 0, 0, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
Expand Down Expand Up @@ -1244,6 +1246,7 @@ static struct grub_fs grub_fat_fs =
#endif
.blocklist_install = 1,
#endif
.fast_blocklist = 1,
.next = 0
};

Expand Down
6 changes: 3 additions & 3 deletions grub-core/fs/fshelp.c
Expand Up @@ -352,7 +352,7 @@ grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode,
blocks have a size of LOG2BLOCKSIZE (in log2). */
grub_ssize_t
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_disk_read_hook_t read_hook, void *read_hook_data, int blocklist,
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),
Expand Down Expand Up @@ -413,8 +413,8 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;

grub_disk_read (disk, blknr + blocks_start, skipfirst,
blockend, buf);
grub_disk_read_ex (disk, blknr + blocks_start, skipfirst,
blockend, buf, blocklist);
disk->read_hook = 0;
if (grub_errno)
return -1;
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/hfsplus.c
Expand Up @@ -216,7 +216,7 @@ grub_hfsplus_read_file (grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_hfsplus_read_block,
node->size,
node->data->log2blksize - GRUB_DISK_SECTOR_BITS,
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/lynxfs.c
Expand Up @@ -253,7 +253,7 @@ grub_lynxfs_read_file(grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file(node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf,
grub_lynxfs_read_block,
grub_be_to_cpu32(node->inode.i_size),
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/nilfs2.c
Expand Up @@ -644,7 +644,7 @@ grub_nilfs2_read_file (grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_nilfs2_read_block,
grub_le_to_cpu64 (node->inode.i_size),
LOG2_NILFS2_BLOCK_SIZE (node->data), 0);
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/ntfs.c
Expand Up @@ -435,7 +435,7 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
}

grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
read_hook, read_hook_data, ofs, len,
read_hook, read_hook_data, 0, ofs, len,
(char *) dest,
grub_ntfs_read_block, ofs + len,
ctx->comp.log_spc, 0);
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/qnx4.c
Expand Up @@ -217,7 +217,7 @@ grub_qnx4_read_file(grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file(node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf,
grub_qnx4_get_block,
grub_le_to_cpu32(node->inode.raw.di_size),
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/qnx6.c
Expand Up @@ -399,7 +399,7 @@ grub_qnx6_read_file(grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file(node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf,
grub_qnx6_get_block,
grub_le_to_cpu32(node->inode.raw.di_size),
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/sfs.c
Expand Up @@ -354,7 +354,7 @@ grub_sfs_read_file (grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_sfs_read_block,
node->size, node->data->log_blocksize, 0);
}
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/udf.c
Expand Up @@ -619,7 +619,7 @@ grub_udf_read_file (grub_fshelp_node_t node,
}

return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_udf_read_block,
U64 (node->block.fe.file_size),
node->data->lbshift, 0);
Expand Down
2 changes: 1 addition & 1 deletion grub-core/fs/xfs.c
Expand Up @@ -622,7 +622,7 @@ grub_xfs_read_file (grub_fshelp_node_t node,
grub_off_t pos, grub_size_t len, char *buf, grub_uint32_t header_size)
{
return grub_fshelp_read_file (node->data->disk, node,
read_hook, read_hook_data,
read_hook, read_hook_data, 0,
pos, len, buf, grub_xfs_read_block,
grub_be_to_cpu64 (node->inode.size) + header_size,
node->data->sblock.log2_bsize
Expand Down
69 changes: 69 additions & 0 deletions grub-core/kern/disk.c
Expand Up @@ -532,6 +532,75 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
return grub_errno;
}

grub_err_t
grub_disk_read_ex (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, void *buf, int blocklist)
{
unsigned real_offset;

if (! blocklist)
return grub_disk_read (disk, sector, offset, size, buf);

if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
return grub_errno;

real_offset = offset;
while (size)
{
char tmp_buf[GRUB_DISK_SECTOR_SIZE];
grub_size_t len;

if ((real_offset != 0) || (size < GRUB_DISK_SECTOR_SIZE))
{
len = GRUB_DISK_SECTOR_SIZE - real_offset;
if (len > size)
len = size;

if (buf)
{
if ((disk->dev->disk_read) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
break;
grub_memcpy (buf, tmp_buf + real_offset, len);
}

if (disk->read_hook)
(disk->read_hook) (sector, real_offset, len, disk->read_hook_data);

sector++;
real_offset = 0;
}
else
{
grub_size_t n;

len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
n = size >> GRUB_DISK_SECTOR_BITS;

if ((buf) &&
((disk->dev->disk_read) (disk, sector, n, buf) != GRUB_ERR_NONE))
break;

if (disk->read_hook)
{
while (n)
{
(disk->read_hook) (sector++, 0, GRUB_DISK_SECTOR_SIZE,
disk->read_hook_data);
n--;
}
}
else
sector += n;
}

if (buf)
buf = (char *) buf + len;
size -= len;
}

return grub_errno;
}

grub_uint64_t
grub_disk_get_size (grub_disk_t disk)
{
Expand Down
13 changes: 11 additions & 2 deletions grub-core/kern/fs.c
Expand Up @@ -335,8 +335,17 @@ grub_blocklist_convert (grub_file_t file)
c.part_start = grub_partition_get_start (file->device->disk->partition);
file->read_hook = read_blocklist;
file->read_hook_data = &c;
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
if (file->fs && file->fs->fast_blocklist)
{
file->blocklist = 1;
grub_file_read (file, 0, file->size);
file->blocklist = 0;
}
else
{
while (grub_file_read (file, buf, sizeof (buf)) > 0)
;
}
file->read_hook = 0;
if ((grub_errno) || (c.total_size != file->size))
{
Expand Down
5 changes: 5 additions & 0 deletions include/grub/disk.h
Expand Up @@ -202,6 +202,11 @@ grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk,
grub_off_t offset,
grub_size_t size,
void *buf);
grub_err_t EXPORT_FUNC(grub_disk_read_ex) (grub_disk_t disk,
grub_disk_addr_t sector,
grub_off_t offset,
grub_size_t size,
void *buf, int blocklist);
grub_err_t grub_disk_write (grub_disk_t disk,
grub_disk_addr_t sector,
grub_off_t offset,
Expand Down
2 changes: 2 additions & 0 deletions include/grub/file.h
Expand Up @@ -170,6 +170,8 @@ struct grub_file

/* Caller-specific data passed to the read hook. */
void *read_hook_data;

int blocklist;
};
typedef struct grub_file *grub_file_t;

Expand Down
1 change: 1 addition & 0 deletions include/grub/fs.h
Expand Up @@ -96,6 +96,7 @@ struct grub_fs
/* Whether blocklist installs have a chance to work. */
int blocklist_install;
#endif
int fast_blocklist;
};
typedef struct grub_fs *grub_fs_t;

Expand Down
2 changes: 1 addition & 1 deletion include/grub/fshelp.h
Expand Up @@ -81,7 +81,7 @@ EXPORT_FUNC(grub_fshelp_find_file_lookup) (const char *path,
grub_ssize_t
EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook,
void *read_hook_data,
void *read_hook_data, int blocklist,
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),
Expand Down

1 comment on commit c3a7633

@a1ive
Copy link
Owner Author

@a1ive a1ive commented on c3a7633 Feb 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#33

Please sign in to comment.