From 2ae44cb7946a226d0f3a31e84c79bb3c2c1e7401 Mon Sep 17 00:00:00 2001 From: Eduard Shishkin Date: Fri, 4 Dec 2020 14:21:59 +0100 Subject: [PATCH] zipl: expand interface of disk_get_blocklist_from_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit . expand interface of disk_get_blocklist_from_file() to get block pointers for a specific range of data within a file. . provide a helper function add_component_file_range() to add a specific range of data within a file as a boot component. This will be used by a later patch. Reviewed-by: Stefan Haberland Reviewed-by: Peter Oberparleiter Signed-off-by: Eduard Shishkin Signed-off-by: Jan Höppner --- zipl/include/disk.h | 6 +++++ zipl/src/bootmap.c | 28 +++++++++++++++++------ zipl/src/disk.c | 54 ++++++++++++++++++++++++++++++--------------- 3 files changed, 63 insertions(+), 25 deletions(-) diff --git a/zipl/include/disk.h b/zipl/include/disk.h index f8d477f0..40236d72 100644 --- a/zipl/include/disk.h +++ b/zipl/include/disk.h @@ -90,6 +90,11 @@ struct disk_info { definition_t targetbase; }; +struct file_range { + off_t offset; + size_t len; +}; + struct job_target_data; int disk_get_info(const char* device, struct job_target_data* target, @@ -119,6 +124,7 @@ int disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info); blocknum_t disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count, struct disk_info* info); blocknum_t disk_get_blocklist_from_file(const char* filename, + struct file_range *reg, disk_blockptr_t** blocklist, struct disk_info* pinfo); int disk_check_subchannel_set(int devno, dev_t device, char* dev_name); diff --git a/zipl/src/bootmap.c b/zipl/src/bootmap.c index 6928f1ee..da14bebf 100644 --- a/zipl/src/bootmap.c +++ b/zipl/src/bootmap.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "lib/zt_common.h" #include "lib/util_part.h" @@ -291,10 +292,11 @@ struct component_loc { }; static int -add_component_file(int fd, const char* filename, address_t load_address, - size_t trailer, void *component, int add_files, - struct disk_info* info, struct job_target_data* target, - struct component_loc *location) +add_component_file_range(int fd, const char *filename, struct file_range *reg, + address_t load_address, + size_t trailer, void *component, int add_files, + struct disk_info *info, struct job_target_data *target, + struct component_loc *location) { struct disk_info* file_info; struct component_loc loc; @@ -306,6 +308,7 @@ add_component_file(int fd, const char* filename, address_t load_address, int rc; if (add_files) { + assert(reg == NULL); /* not implemented */ /* Read file to buffer */ rc = misc_read_file(filename, &buffer, &size, 0); if (rc) { @@ -332,8 +335,8 @@ add_component_file(int fd, const char* filename, address_t load_address, return -1; } /* Get block list from existing file */ - count = disk_get_blocklist_from_file(filename, &list, - file_info); + count = disk_get_blocklist_from_file(filename, reg, + &list, file_info); disk_free_info(file_info); if (count == 0) return -1; @@ -357,6 +360,17 @@ add_component_file(int fd, const char* filename, address_t load_address, return rc; } +static int +add_component_file(int fd, const char *filename, address_t load_address, + size_t trailer, void *component, int add_files, + struct disk_info *info, struct job_target_data *target, + struct component_loc *location) +{ + return add_component_file_range(fd, filename, NULL, load_address, + trailer, component, add_files, + info, target, location); +} + static int add_component_buffer(int fd, void* buffer, size_t size, component_data data, void* component, struct disk_info* info, @@ -834,7 +848,7 @@ add_segment_program(int fd, struct job_segment_data* segment, rc = add_component_file(fd, segment->segment, segment->segment_addr, 0, VOID_ADD(table, offset), add_files, info, target, &comp_loc[0]); -if (rc) { + if (rc) { error_text("Could not add segment file '%s'", segment->segment); free(table); diff --git a/zipl/src/disk.c b/zipl/src/disk.c index b32884b4..657dbd40 100644 --- a/zipl/src/disk.c +++ b/zipl/src/disk.c @@ -23,7 +23,6 @@ #include #include #include - #include "lib/util_proc.h" #include "lib/util_sys.h" @@ -1064,19 +1063,26 @@ disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count, return last + 1; } - -/* Retrieve a list of pointers to the disk blocks that make up the file - * specified by FILENAME. Upon success, return the number of blocks and set - * BLOCKLIST to point to the uncompacted list. INFO provides information - * about the device which contains the file. Return zero otherwise. */ +/** + * Retrieve a list of pointers to the disk blocks that make up the whole + * file specified by FILENAME, or only its part specified by REG (if the + * last one is not NULL). + * Upon success, return the number of blocks and set BLOCKLIST to point to + * the uncompacted list. INFO provides information about the device which + * contains the file. Return zero otherwise + */ blocknum_t -disk_get_blocklist_from_file(const char* filename, disk_blockptr_t** blocklist, +disk_get_blocklist_from_file(const char *filename, struct file_range *reg, + disk_blockptr_t **blocklist, struct disk_info* info) { disk_blockptr_t* list; struct stat stats; int fd; - blocknum_t count; + off_t off; + size_t count; + blocknum_t blk_off; + blocknum_t blk_count; blocknum_t i; blocknum_t blocknum; @@ -1093,24 +1099,36 @@ disk_get_blocklist_from_file(const char* filename, disk_blockptr_t** blocklist, close (fd); return 0; } - /* Get number of blocks */ - count = ((blocknum_t) stats.st_size + - info->phy_block_size - 1) / info->phy_block_size; - if (count == 0) { - error_reason("Could not read empty file '%s'", filename); + if (reg) { + off = reg->offset; + count = reg->len; + } else { + off = 0; + count = stats.st_size; + } + if (off >= stats.st_size) { + error_reason("Offset %llu is outside the file '%s'", + off, filename); close(fd); return 0; } + if (off + count > (size_t)stats.st_size) + count = stats.st_size - off; + + blk_off = off / info->phy_block_size; + blk_count = ((blocknum_t) count + + info->phy_block_size - 1) / info->phy_block_size; + list = (disk_blockptr_t *) misc_malloc(sizeof(disk_blockptr_t) * - count); + blk_count); if (list == NULL) { close(fd); return 0; } - memset((void *) list, 0, sizeof(disk_blockptr_t) * count); + memset((void *) list, 0, sizeof(disk_blockptr_t) * blk_count); /* Build list */ - for (i=0; i < count; i++) { - if (disk_get_blocknum(fd, 0, i, &blocknum, info)) { + for (i = 0; i < blk_count; i++) { + if (disk_get_blocknum(fd, 0, blk_off + i, &blocknum, info)) { free(list); close(fd); return 0; @@ -1119,7 +1137,7 @@ disk_get_blocklist_from_file(const char* filename, disk_blockptr_t** blocklist, } close(fd); *blocklist = list; - return count; + return blk_count; } /* Check whether input device is in subchannel set 0.