Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package parti for openSUSE:Factory checked in at 2026-03-19 17:38:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/parti (Old) and /work/SRC/openSUSE:Factory/.parti.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "parti" Thu Mar 19 17:38:30 2026 rev:20 rq:1341017 version:2.11 Changes: -------- --- /work/SRC/openSUSE:Factory/parti/parti.changes 2025-05-14 17:01:10.911178618 +0200 +++ /work/SRC/openSUSE:Factory/.parti.new.8177/parti.changes 2026-03-19 17:39:15.322478383 +0100 @@ -1,0 +2,7 @@ +Wed Mar 18 17:49:42 UTC 2026 - [email protected] + +- merge gh#wfeldt/parti#24 +- greatly speed up internal disk data handling +- 2.11 + +-------------------------------------------------------------------- Old: ---- parti-2.10.tar.xz New: ---- parti-2.11.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ parti.spec ++++++ --- /var/tmp/diff_new_pack.rsQlZJ/_old 2026-03-19 17:39:15.806498438 +0100 +++ /var/tmp/diff_new_pack.rsQlZJ/_new 2026-03-19 17:39:15.810498604 +0100 @@ -18,7 +18,7 @@ Name: parti -Version: 2.10 +Version: 2.11 Release: 0 Summary: Show partition table information License: GPL-3.0-only ++++++ parti-2.10.tar.xz -> parti-2.11.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-2.10/VERSION new/parti-2.11/VERSION --- old/parti-2.10/VERSION 2025-05-13 18:30:52.000000000 +0200 +++ new/parti-2.11/VERSION 2026-03-18 18:49:42.000000000 +0100 @@ -1 +1 @@ -2.10 +2.11 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-2.10/changelog new/parti-2.11/changelog --- old/parti-2.10/changelog 2025-05-13 18:30:52.000000000 +0200 +++ new/parti-2.11/changelog 2026-03-18 18:49:42.000000000 +0100 @@ -1,3 +1,7 @@ +2026-03-18: 2.11 + - merge gh#wfeldt/parti#24 + - greatly speed up internal disk data handling + 2025-05-13: 2.10 - merge gh#wfeldt/parti#23 - fix build for older gcc versions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-2.10/disk.c new/parti-2.11/disk.c --- old/parti-2.10/disk.c 2025-05-13 18:30:52.000000000 +0200 +++ new/parti-2.11/disk.c 2026-03-18 18:49:42.000000000 +0100 @@ -23,19 +23,21 @@ int disk_read(disk_t *disk, void *buffer, uint64_t block_nr, unsigned count) { - unsigned factor = disk->block_size / disk->chunk_size; + unsigned factor = disk->block_size / DISK_CHUNK_SIZE; // fprintf(stderr, "read: %llu - %u (factor = %u)\n", (unsigned long long) block_nr, count, factor); + uint64_t chunk_nr = block_nr * factor; + count *= factor; - block_nr *= factor; - for(unsigned u = 0; u < count; u++, block_nr++, buffer += disk->chunk_size) { - // fprintf(stderr, "read request: disk %u, addr %08"PRIx64"\n", disk->index, block_nr * disk->chunk_size); - if(!disk_cache_read(disk, buffer, block_nr)) { - int err = disk_read_single(disk, buffer, block_nr); + for(unsigned u = 0; u < count; u++, chunk_nr++, buffer += DISK_CHUNK_SIZE) { + // fprintf(stderr, "read request: disk %u, addr %08"PRIx64"\n", disk->index, chunk_nr * DISK_CHUNK_SIZE); + if(disk_cache_read(disk, &(disk_chunk_t) { .nr = chunk_nr, .data = buffer })) { + int err = disk_read_single(disk, buffer, chunk_nr); + if(err) return err; + err = disk_cache_store(disk, &(disk_chunk_t) { .nr = chunk_nr, .data = buffer }); if(err) return err; - disk_cache_store(disk, buffer, block_nr); } } @@ -46,15 +48,15 @@ int disk_read_single(disk_t *disk, void *buffer, uint64_t block_nr) { if(disk->fd == -1) { - // fprintf(stderr, "cache miss: disk %u, addr %08"PRIx64"\n", disk->index, block_nr * disk->chunk_size); - memset(buffer, 0, disk->chunk_size); + // fprintf(stderr, "cache miss: disk %u, addr %08"PRIx64"\n", disk->index, block_nr * DISK_CHUNK_SIZE); + memset(buffer, 0, DISK_CHUNK_SIZE); return 0; } // fprintf(stderr, "read: %llu[%llu]\n", (unsigned long long) block_nr, (unsigned long long) disk->size); - off_t offset = block_nr * disk->chunk_size; + off_t offset = block_nr * DISK_CHUNK_SIZE; if(lseek(disk->fd, offset, SEEK_SET) != offset) { fprintf(stderr, "sector %"PRIu64" not found\n", block_nr); @@ -62,7 +64,7 @@ return 2; } - if(read(disk->fd, buffer, disk->chunk_size) != disk->chunk_size) { + if(read(disk->fd, buffer, DISK_CHUNK_SIZE) != DISK_CHUNK_SIZE) { fprintf(stderr, "error reading sector %"PRIu64"\n", block_nr); return 3; @@ -72,30 +74,96 @@ } -int disk_cache_read(disk_t *disk, void *buffer, uint64_t chunk_nr) +int disk_cache_read(disk_t *disk, disk_chunk_t *chunk) { - for(disk_data_t *disk_data = disk->data; disk_data; disk_data = disk_data->next) { - if(disk_data->chunk_nr == chunk_nr) { - memcpy(buffer, disk_data->data, disk->chunk_size); - return 1; + if(!chunk || !chunk->data || chunk->nr == UINT64_MAX) return 1; + + int match; + unsigned u = disk_find_chunk(disk, chunk->nr, &match); + + if(!match) return 2; + + memcpy(chunk->data, disk->chunks.list[u].data, DISK_CHUNK_SIZE); + + return 0; +} + + +int disk_cache_store(disk_t *disk, disk_chunk_t *chunk) +{ + if(!chunk || !chunk->data || chunk->nr == UINT64_MAX) return 1; + + int match; + unsigned u = disk_find_chunk(disk, chunk->nr, &match); + + if(!match) { + if(disk->chunks.len >= DISK_MAX_CHUNKS) return 2; + void *buffer = malloc(DISK_CHUNK_SIZE); + if(!buffer) return 3; + memcpy(buffer, chunk->data, DISK_CHUNK_SIZE); + disk->chunks.len++; + if(disk->chunks.len > disk->chunks.max) { + disk->chunks.max += DISK_CHUNKS_EXTRA; + disk->chunks.list = realloc(disk->chunks.list, disk->chunks.max * sizeof (disk_chunk_t)); + if(disk->chunks.list == NULL) { + free(buffer); + disk->chunks.len = disk->chunks.max = 0; + return 4; + } } + if(u + 1 < disk->chunks.len) { + memmove(disk->chunks.list + u + 1, disk->chunks.list + u, sizeof (disk_chunk_t) * (disk->chunks.len - u - 1)); + } + disk->chunks.list[u].nr = chunk->nr; + disk->chunks.list[u].data = buffer; } return 0; } -void disk_cache_store(disk_t *disk, void *buffer, uint64_t chunk_nr) +// Binary search. +// If matched, return value is index that matched. +// If no match, return value is position at which to insert new value (may +// point at position right after end of the list). +unsigned disk_find_chunk(disk_t *disk, uint64_t chunk_nr, int *match) { - // fprintf(stderr, "cache store: disk %u, addr %08"PRIx64"\n", disk->index, chunk_nr * disk->chunk_size); - disk_data_t *disk_data = calloc(1, sizeof *disk_data); + *match = 0; + + disk_chunk_t *chunk_list = disk->chunks.list; + + unsigned u_start = 0; + unsigned u_end = disk->chunks.len; + unsigned u = 0; - disk_data->chunk_nr = chunk_nr; - disk_data->data = malloc(disk->chunk_size); - memcpy(disk_data->data, buffer, disk->chunk_size); + while(u_end > u_start) { + u = (u_end + u_start) / 2; + + int64_t i = chunk_nr - chunk_list[u].nr; + + if(i == 0) { + *match = 1; + break; + } + + if(u_end == u_start + 1) { + if(i > 0) u++; + break; + } - disk_data->next = disk->data; - disk->data = disk_data; + if(i > 0) { + if(u_end == u + 1) { + if(i > 0) u++; + break; + } + u_start = u; + } + else { + u_end = u; + } + } + + return u; } @@ -113,16 +181,9 @@ fprintf(f, "# disk %u, size = %"PRIu64"\n", disk->index, disk->size_in_bytes); - uint64_t chunk_nr = 0; - disk_data_t *disk_data; - - do { - disk_data = disk_cache_search(disk, &chunk_nr); - if(disk_data) { - disk_cache_dump(disk, disk_data, f); - } + for(unsigned u = 0; u < disk->chunks.len; u++) { + disk_cache_dump(disk, disk->chunks.list + u, f); } - while(chunk_nr != UINT64_MAX); if(f != stdout) fclose(f); @@ -132,23 +193,16 @@ int disk_to_fd(disk_t *disk, uint64_t offset) { - uint64_t chunk_nr = 0; - disk_data_t *disk_data; - int fd = syscall(SYS_memfd_create, "", 0); if(fd == -1) return 0; - do { - disk_data = disk_cache_search(disk, &chunk_nr); - if(disk_data) { - if(disk_data->chunk_nr * disk->chunk_size >= offset) { - lseek(fd, disk_data->chunk_nr * disk->chunk_size - offset, SEEK_SET); - write(fd, disk_data->data, disk->chunk_size); - } + for(unsigned u = 0; u < disk->chunks.len; u++) { + if(disk->chunks.list[u].nr * DISK_CHUNK_SIZE >= offset) { + lseek(fd, disk->chunks.list[u].nr * DISK_CHUNK_SIZE - offset, SEEK_SET); + write(fd, disk->chunks.list[u].data, DISK_CHUNK_SIZE); } } - while(chunk_nr != UINT64_MAX); lseek(fd, 0, SEEK_SET); @@ -156,19 +210,21 @@ } -void disk_cache_dump(disk_t *disk, disk_data_t *disk_data, FILE *file) +int disk_cache_dump(disk_t *disk, disk_chunk_t *chunk, FILE *file) { + if(!file) return 1; + uint8_t all_zeros[16] = {}; - uint8_t *data = disk_data->data; + uint8_t *data = chunk->data; uint64_t max_addr = disk->size_in_bytes - 1; unsigned address_digits = 0; while(max_addr >>= 4) address_digits++; if(address_digits < 4) address_digits = 4; - for(unsigned u = 0; u < disk->chunk_size; u += 16) { + for(unsigned u = 0; u < DISK_CHUNK_SIZE; u += 16) { if(memcmp(data + u, &all_zeros, 16)) { - fprintf(file, "%0*"PRIx64" ", address_digits, disk_data->chunk_nr * disk->chunk_size + u); + fprintf(file, "%0*"PRIx64" ", address_digits, chunk->nr * DISK_CHUNK_SIZE + u); for(unsigned u1 = 0; u1 < 16; u1++) { fprintf(file, " %02x", data[u + u1]); } @@ -179,28 +235,8 @@ fprintf(file, "\n"); } } -} - - -disk_data_t *disk_cache_search(disk_t *disk, uint64_t *chunk_nr) -{ - disk_data_t *disk_data_found = NULL; - uint64_t next_chunk_nr = UINT64_MAX; - - if(*chunk_nr == next_chunk_nr) return NULL; - for(disk_data_t *disk_data = disk->data; disk_data; disk_data = disk_data->next) { - if(disk_data->chunk_nr == *chunk_nr) { - disk_data_found = disk_data; - } - if(disk_data->chunk_nr > *chunk_nr && disk_data->chunk_nr < next_chunk_nr) { - next_chunk_nr = disk_data->chunk_nr; - } - } - - *chunk_nr = next_chunk_nr; - - return disk_data_found; + return 0; } @@ -231,7 +267,7 @@ void disk_init(char *file_name) { struct stat sbuf; - disk_t disk = { .chunk_size = 512, .block_size = 512 }; + disk_t disk = { .block_size = DISK_CHUNK_SIZE }; disk.fd = open(file_name, O_RDONLY | O_LARGEFILE); @@ -264,7 +300,7 @@ disk_t disk = { .fd = -1 }; - uint8_t chunk[512]; + uint8_t buffer[DISK_CHUNK_SIZE]; uint64_t current_chunk_nr = UINT64_MAX; while(getline(&line, &line_len, file) > 0) { @@ -275,14 +311,14 @@ uint8_t line_data[16]; if(sscanf(line, "# disk %u, size = %"SCNu64"", &index, &size) == 2) { if(disk.name) { - if(current_chunk_nr != UINT64_MAX) disk_cache_store(&disk, chunk, current_chunk_nr); + if(current_chunk_nr != UINT64_MAX) disk_cache_store(&disk, &(disk_chunk_t) { .nr = current_chunk_nr, .data = buffer }); disk_add_to_list(&disk); disk = (disk_t) { .index = disk_list_size }; current_chunk_nr = UINT64_MAX; } asprintf(&disk.name, "%s#%u", file_name, index); disk.size_in_bytes = size; - disk.chunk_size = disk.block_size = 512; + disk.block_size = DISK_CHUNK_SIZE; } else if( sscanf(line, @@ -296,15 +332,13 @@ !(addr & 0xf) && addr <= disk.size_in_bytes + 16 ) { - // fprintf(stderr, "XXX %08"PRIx64" %02x %02x\n", addr, line_data[0], line_data[1]); - uint64_t chunk_nr = addr / disk.chunk_size; - // fprintf(stderr, "ZZZ chunk_nr %"PRIu64", current_chunk_nr %"PRIu64"\n", chunk_nr, current_chunk_nr); + uint64_t chunk_nr = addr / DISK_CHUNK_SIZE; if(chunk_nr != current_chunk_nr) { - if(current_chunk_nr != UINT64_MAX) disk_cache_store(&disk, chunk, current_chunk_nr); + if(current_chunk_nr != UINT64_MAX) disk_cache_store(&disk, &(disk_chunk_t) { .nr = current_chunk_nr, .data = buffer }); current_chunk_nr = chunk_nr; - memset(chunk, 0, sizeof chunk); + memset(buffer, 0, sizeof buffer); } - memcpy(chunk + (addr % disk.chunk_size), line_data, 16); + memcpy(buffer + (addr % DISK_CHUNK_SIZE), line_data, 16); } else { fprintf(stderr, "%s: line %u: invalid import data: %s\n", file_name, line_nr, line); @@ -315,7 +349,7 @@ free(line); if(disk.name) { - if(current_chunk_nr != UINT64_MAX) disk_cache_store(&disk, chunk, current_chunk_nr); + if(current_chunk_nr != UINT64_MAX) disk_cache_store(&disk, &(disk_chunk_t) { .nr = current_chunk_nr, .data = buffer }); disk_add_to_list(&disk); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-2.10/disk.h new/parti-2.11/disk.h --- old/parti-2.10/disk.h 2025-05-13 18:30:52.000000000 +0200 +++ new/parti-2.11/disk.h 2026-03-18 18:49:42.000000000 +0100 @@ -1,10 +1,16 @@ #include <json-c/json.h> -typedef struct disk_data_s { - struct disk_data_s *next; - uint64_t chunk_nr; +// internal block size, fixed +#define DISK_CHUNK_SIZE 512 +// resize internal chunk list by that amount, if needed +#define DISK_CHUNKS_EXTRA 256 +// maximum number of chunks to store in internal cache (cache size = 512 MiB) +#define DISK_MAX_CHUNKS 1024*1024 + +typedef struct { + uint64_t nr; uint8_t *data; -} disk_data_t; +} disk_chunk_t; typedef struct { char *name; @@ -14,11 +20,13 @@ unsigned sectors; unsigned cylinders; uint64_t size_in_bytes; - unsigned chunk_size; unsigned block_size; unsigned grub_used:1; unsigned isolinux_used:1; - disk_data_t *data; + struct { + disk_chunk_t *list; + unsigned len, max; + } chunks; json_object *json_disk; json_object *json_current; } disk_t; @@ -29,10 +37,11 @@ int disk_read(disk_t *disk, void *buf, uint64_t sector, unsigned cnt); int disk_read_single(disk_t *disk, void *buffer, uint64_t block_nr); -int disk_cache_read(disk_t *disk, void *buffer, uint64_t chunk_nr); -void disk_cache_dump(disk_t *disk, disk_data_t *disk_data, FILE *file); -void disk_cache_store(disk_t *disk, void *buffer, uint64_t chunk_nr); -disk_data_t *disk_cache_search(disk_t *disk, uint64_t *chunk_nr); +int disk_cache_read(disk_t *disk, disk_chunk_t *chunk); +int disk_cache_store(disk_t *disk, disk_chunk_t *chunk); +int disk_cache_dump(disk_t *disk, disk_chunk_t *chunk, FILE *file); + +unsigned disk_find_chunk(disk_t *disk, uint64_t chunk_nr, int *match); int disk_export(disk_t *disk, char *file_name); int disk_to_fd(disk_t *disk, uint64_t offset);
