mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zfcpdump: drop use of mmap() for /proc/vmcore
The function copy_table_entry_write() maps/unmaps /proc/vmcore for each 64kB of the file in order to write its content to a dump partition. This requires a page allocation of order 2 in kernel (crst_table_alloc) each time a mmap() syscall is performed and which cannot always be fulfilled due to external memory fragmentation. And this in turn results in a OOM kernel panic while writing /proc/vmcore content to a dump partition. To make zfcpdump more robust in the face of such problems with page allocations of order > 0, we use a simple file read/write loop to transfer the content of /proc/vmcore to a dump partition. This solution is less efficient (by not much) than the old one with mmap() because it requires additional user space copy but we trade off here efficiency for robustness which is more important for zfcpdump. We use a statically allocated buffer to read data into from /proc/vmcore and write to a dump partition to avoid repeated use of the memory mapping kernel path which would be required for a buffer allocated dynamically at each entry of copy_table_entry_write(). Another possible and very convenient solution would be to use sendfile() which would avoid any user space copies but, unfortunately, sendfile() doesn't work with large /proc files. Example of failed mmap() call for /proc/vmcore ============================================== [ 26.568654] init invoked oom-killer: gfp_mask=0x40cc0(GFP_KERNEL|__GFP_COMP), order=2, oom_score_adj=0 [ 26.568665] CPU: 0 PID: 1 Comm: init Not tainted 6.9.0-20240504.rc6.git0.9986ea583f39.300.fc39.s390x+zfcpdump #1 [ 26.568668] Hardware name: IBM 3931 A01 704 (LPAR) [ 26.568669] Call Trace: [ 26.568671] [<000003ffe03277c6>] dump_stack_lvl+0x76/0x98 [ 26.568676] [<000003ffe00f15c8>] dump_header+0x58/0x2d0 [ 26.568680] [<000003ffe00f219a>] out_of_memory+0x252/0x348 [ 26.568683] [<000003ffe0132f3e>] __alloc_pages_slowpath.constprop.0+0x65e/0x7c0 [ 26.568686] [<000003ffe01331a4>] __alloc_pages+0x104/0x128 [ 26.568688] [<000003ffe001ab46>] crst_table_alloc+0x2e/0xa0 [ 26.568693] [<000003ffe01164c4>] __pmd_alloc+0x24/0x160 [ 26.568696] [<000003ffe0116650>] pmd_alloc+0x50/0x68 [ 26.568698] [<000003ffe0117be4>] remap_pfn_range_notrack+0x194/0x310 [ 26.568701] [<000003ffe0117d7c>] remap_pfn_range+0x1c/0x28 [ 26.568703] [<000003ffe0015442>] remap_oldmem_pfn_range+0xb2/0x108 [ 26.568705] [<000003ffe01a0544>] mmap_vmcore+0x414/0x448 [ 26.568707] [<000003ffe01937c4>] proc_reg_mmap+0x84/0xa0 [ 26.568709] [<000003ffe011f264>] mmap_region+0x22c/0x6f8 [ 26.568711] [<000003ffe011fae8>] do_mmap+0x3b8/0x410 [ 26.568713] [<000003ffe01015cc>] vm_mmap_pgoff+0x9c/0xe8 [ 26.568715] [<000003ffe011d006>] ksys_mmap_pgoff+0x8e/0xb8 [ 26.568716] [<000003ffe011d0f4>] __s390x_sys_old_mmap+0x74/0x90 [ 26.568718] [<000003ffe0341a2a>] __do_syscall+0x1aa/0x220 [ 26.568720] [<000003ffe03478b0>] system_call+0x70/0x98 [ 26.568724] Mem-Info: [ 26.568725] active_anon:1 inactive_anon:12 isolated_anon:0 active_file:83590 inactive_file:93939 isolated_file:0 unevictable:201 dirty:17845 writeback:4 slab_reclaimable:4259 slab_unreclaimable:1482 mapped:174 shmem:0 pagetables:810 sec_pagetables:0 bounce:0 kernel_misc_reclaimable:0 free:2694 free_pcp:105 free_cma:0 [ 26.568729] Node 0 active_anon:4kB inactive_anon:48kB active_file:334360kB inactive_file:375756kB unevictable:804kB isolated(anon):0kB isolated(file):0kB mapped:696kB dirty:71380kB writeback:16kB shmem:0kB writeback_tmp:0kB kernel_stack:544kB pagetables:3240kB sec_pagetables:0kB all_unreclaimable? no [ 26.568732] DMA free:10776kB boost:0kB min:3496kB low:4368kB high:5240kB reserved_highatomic:0KB active_anon:4kB inactive_anon:48kB active_file:334360kB inactive_file:375756kB unevictable:804kB writepending:71360kB present:786428kB managed:764664kB mlocked:0kB bounce:0kB free_pcp:420kB local_pcp:420kB free_cma:0kB [ 26.568735] lowmem_reserve[]: 0 0 0 [ 26.568738] DMA: 1069*4kB (UH) 757*8kB (UH) 11*16kB (H) 6*32kB (H) 1*64kB (H) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 10764kB [ 26.568747] 177773 total pagecache pages [ 26.568748] 196607 pages RAM [ 26.568748] 0 pages HighMem/MovableOnly [ 26.568749] 5441 pages reserved [ 26.568749] Tasks state (memory values in pages): [ 26.568750] [ pid ] uid tgid total_vm rss rss_anon rss_file rss_shmem pgtables_bytes swapents oom_score_adj name [ 26.568751] Out of memory and no killable processes... [ 26.568752] Kernel panic - not syncing: System is deadlocked on memory [ 26.568755] CPU: 0 PID: 1 Comm: init Not tainted 6.9.0-20240504.rc6.git0.9986ea583f39.300.fc39.s390x+zfcpdump #1 [ 26.568758] Hardware name: IBM 3931 A01 704 (LPAR) [ 26.568759] Call Trace: [ 26.568760] [<000003ffe03277c6>] dump_stack_lvl+0x76/0x98 [ 26.568763] [<000003ffe001f14e>] panic+0x10e/0x2e8 [ 26.568765] [<000003ffe00f21c8>] out_of_memory+0x280/0x348 [ 26.568768] [<000003ffe0132f3e>] __alloc_pages_slowpath.constprop.0+0x65e/0x7c0 [ 26.568771] [<000003ffe01331a4>] __alloc_pages+0x104/0x128 [ 26.568773] [<000003ffe001ab46>] crst_table_alloc+0x2e/0xa0 [ 26.568776] [<000003ffe01164c4>] __pmd_alloc+0x24/0x160 [ 26.568779] [<000003ffe0116650>] pmd_alloc+0x50/0x68 [ 26.568781] [<000003ffe0117be4>] remap_pfn_range_notrack+0x194/0x310 [ 26.568784] [<000003ffe0117d7c>] remap_pfn_range+0x1c/0x28 [ 26.568787] [<000003ffe0015442>] remap_oldmem_pfn_range+0xb2/0x108 [ 26.568789] [<000003ffe01a0544>] mmap_vmcore+0x414/0x448 [ 26.568791] [<000003ffe01937c4>] proc_reg_mmap+0x84/0xa0 [ 26.568793] [<000003ffe011f264>] mmap_region+0x22c/0x6f8 [ 26.568795] [<000003ffe011fae8>] do_mmap+0x3b8/0x410 [ 26.568797] [<000003ffe01015cc>] vm_mmap_pgoff+0x9c/0xe8 [ 26.568799] [<000003ffe011d006>] ksys_mmap_pgoff+0x8e/0xb8 [ 26.568801] [<000003ffe011d0f4>] __s390x_sys_old_mmap+0x74/0x90 [ 26.568803] [<000003ffe0341a2a>] __do_syscall+0x1aa/0x220 [ 26.568805] [<000003ffe03478b0>] system_call+0x70/0x98 Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com> Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
committed by
Steffen Eiden
parent
6d15850480
commit
b6c30404bc
@@ -24,7 +24,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -294,32 +293,38 @@ static int copy_table_init(int fd, struct copy_table *table)
|
||||
*/
|
||||
static int copy_table_entry_write(int fdin, int fdout,
|
||||
const struct copy_table_entry *entry,
|
||||
unsigned long offset)
|
||||
unsigned long disk_offset)
|
||||
{
|
||||
unsigned long buf_size, bytes_left, off;
|
||||
void *map;
|
||||
static unsigned char buf[COPY_BUF_SIZE];
|
||||
unsigned long bytes_left, count;
|
||||
ssize_t bytes_read, bytes_written;
|
||||
|
||||
if (entry->size == 0)
|
||||
return 0;
|
||||
off = entry->off;
|
||||
bytes_left = entry->size;
|
||||
if (lseek(fdout, entry->off + offset, SEEK_SET) < 0)
|
||||
if (bytes_left == 0)
|
||||
return 0;
|
||||
if (lseek(fdin, entry->off, SEEK_SET) < 0)
|
||||
return -1;
|
||||
if (lseek(fdout, disk_offset + entry->off, SEEK_SET) < 0)
|
||||
return -1;
|
||||
PRINT_TRACE("Write dump: vmcore offset=0x%016lx disk offset=0x%016lx bytes=0x%016lx\n",
|
||||
entry->off, disk_offset + entry->off, bytes_left);
|
||||
while (bytes_left > 0) {
|
||||
buf_size = MIN(COPY_BUF_SIZE, bytes_left);
|
||||
map = mmap(0, buf_size, PROT_READ, MAP_SHARED, fdin, off);
|
||||
if (map == (void *)-1) {
|
||||
PRINT_PERR("Mapping failed\n");
|
||||
count = MIN(COPY_BUF_SIZE, bytes_left);
|
||||
bytes_read = read(fdin, buf, count);
|
||||
if (bytes_read < 0) {
|
||||
PRINT_PERR("Read from /proc/vmcore failed: offset=0x%016lx bytes=0x%016lx\n",
|
||||
entry->off + entry->size - bytes_left, count);
|
||||
return -1;
|
||||
}
|
||||
if (write(fdout, map, buf_size) < 0) {
|
||||
PRINT_PERR("Write to partition failed\n");
|
||||
bytes_written = write(fdout, buf, bytes_read);
|
||||
if (bytes_written < 0) {
|
||||
PRINT_PERR("Write to partition failed: offset=0x%016lx bytes=0x%016lx\n",
|
||||
disk_offset + entry->off + entry->size - bytes_left,
|
||||
bytes_read);
|
||||
return -1;
|
||||
}
|
||||
munmap(map, buf_size);
|
||||
bytes_left -= buf_size;
|
||||
off += buf_size;
|
||||
show_progress(buf_size);
|
||||
bytes_left -= bytes_written;
|
||||
show_progress(bytes_written);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user