# HG changeset patch # User Paul Boddie # Date 1653345245 -7200 # Node ID e32a48700c0a70360d8106de7367baa18c258d0c # Parent 8349c51951e2cec851670601227a62042ff30db0 Introduced flexpage replication for copy-on-write support, thus allowing the memory mapping of a program's data segment with start and end region masking. diff -r 8349c51951e2 -r e32a48700c0a libexec/lib/src/segment.cc --- a/libexec/lib/src/segment.cc Sun May 22 23:46:17 2022 +0200 +++ b/libexec/lib/src/segment.cc Tue May 24 00:34:05 2022 +0200 @@ -73,30 +73,14 @@ long Segment::fill(file_t *file) { - /* NOTE: This should be replaced by copy-on-write dataspace usage. */ - - if (_flags & L4RE_RM_F_W) - { - long err = allocate(); - - if (err) - return err; - - client_seek(file, _file_offset - _region_offset, SEEK_SET); - offset_t nread = client_read(file, _buf, _region_size); - - memset(_buf, 0, _region_offset); - memset(_buf + _region_offset + _file_contents, 0, _region_size - _region_offset - _file_contents); - - if (nread < _file_contents) - return -L4_EIO; - else - return L4_EOK; - } - /* Provide the exposed file contents in a masked memory mapped region. */ - _buf = (char *) client_mmap(file, _file_offset - _region_offset, _region_size, 0, 0, _flags); + _buf = (char *) client_mmap(file, + _file_offset - _region_offset, + _region_size, + _file_offset, + _file_offset + _file_contents, + _flags); if (_buf == NULL) return -L4_EIO; diff -r 8349c51951e2 -r e32a48700c0a libfsserver/include/fsserver/pager.h --- a/libfsserver/include/fsserver/pager.h Sun May 22 23:46:17 2022 +0200 +++ b/libfsserver/include/fsserver/pager.h Tue May 24 00:34:05 2022 +0200 @@ -38,12 +38,15 @@ PageMapper *_mapper; map_flags_t _flags; + /* Support for masked regions and replicated flexpages. */ + + MemoryIncremental _memory; + /* Masked region support. */ bool _is_masked; offset_t _start_visible, _end_visible; Flexpage _start_flexpage, _end_flexpage, _zero_flexpage; - MemoryIncremental _memory; Flexpage *get_masked_flexpage(Flexpage *flexpage); @@ -52,6 +55,11 @@ void populate_region(Flexpage *flexpage, Flexpage &masked, bool has_start, bool has_end); + /* Replicated flexpage support. */ + + AccessMap _map; + Flexpage *get_replicated_flexpage(Flexpage *flexpage, map_flags_t flags); + public: explicit Pager(PageMapper *mapper, map_flags_t flags); diff -r 8349c51951e2 -r e32a48700c0a libfsserver/lib/generic/pager.cc --- a/libfsserver/lib/generic/pager.cc Sun May 22 23:46:17 2022 +0200 +++ b/libfsserver/lib/generic/pager.cc Tue May 24 00:34:05 2022 +0200 @@ -40,6 +40,7 @@ void Pager::close() { + /* NOTE: Need to deallocate any allocated regions and flexpages. */ } /* Flush data to the file. */ @@ -109,11 +110,30 @@ if (flags & (~(_flags | L4RE_DS_F_X))) return -L4_EACCESS; - Flexpage *flexpage = _mapper->get(file_offset, flags); + Flexpage *issued_flexpage = NULL, *obtained_flexpage = NULL; + + /* Obtain any replicated flexpage. + NOTE: An additional condition should be introduced to test for the + relevance of replicated flexpages. */ + + if (flags & L4RE_DS_F_W) + issued_flexpage = _map.find(file_offset); + + /* Without any replicated flexpage, obtain one for the shared, underlying + file data. */ - /* Determine if the flexpage should be masked. */ + if (issued_flexpage == NULL) + { + obtained_flexpage = _mapper->get(file_offset, flags); + + /* Determine if the flexpage should be masked. */ - Flexpage *issued_flexpage = get_masked_flexpage(flexpage); + issued_flexpage = get_masked_flexpage(obtained_flexpage); + + /* Determine if the flexpage should be replicated. */ + + issued_flexpage = get_replicated_flexpage(issued_flexpage, flags); + } /* Issue the flexpage via the IPC system. */ @@ -123,9 +143,10 @@ if (!err) err = complete_Dataspace_map(*region); - /* After the flexpage is issued, it is queued for future reuse. */ + /* After the obtained flexpage is issued, it is queued for future reuse. */ - _mapper->queue(flexpage); + if (obtained_flexpage != NULL) + _mapper->queue(obtained_flexpage); if (err) return err; @@ -151,7 +172,7 @@ return flexpage; /* Determine whether the flexpage involves the limits of the visible - region. */ + region or is beyond such limits. */ bool has_start = flexpage->supports_position(_start_visible) && flexpage->base_offset != _start_visible; @@ -165,9 +186,7 @@ return flexpage; /* Allocate and populate a region in one of the preallocated flexpages for - masked content. - NOTE: A general copy-on-write solution will maintain a collection of - flexpages. */ + masked content. */ Flexpage &masked = has_start ? _start_flexpage : has_end ? _end_flexpage : @@ -179,6 +198,7 @@ /* Associate the preallocated flexpage with the original flexpage. */ flexpage->associate(&masked); + return &masked; } @@ -229,4 +249,28 @@ memset((void *) (masked.region->start + end_offset), 0, masked.size - end_offset); } +/* Detect flexpages with replicated content, introducing separate flexpages + offering replicated content from the same region. */ + +Flexpage *Pager::get_replicated_flexpage(Flexpage *flexpage, map_flags_t flags) +{ + /* NOTE: An additional condition should be introduced to test for the + relevance of replicated flexpages. For now, detect copy-on-write + situations. */ + + if (_is_masked && (flags & L4RE_DS_F_W)) + { + Region *region = _memory.region(flexpage->size); + Flexpage *replicated = new Flexpage(region); + + replicated->reset(flexpage->base_offset); + + memcpy((void *) region->start, (const void *) flexpage->region->start, flexpage->size); + _map.insert(replicated); + return replicated; + } + else + return flexpage; +} + // vim: tabstop=4 expandtab shiftwidth=4 diff -r 8349c51951e2 -r e32a48700c0a libfsserver/lib/mapping/page_mapper.cc --- a/libfsserver/lib/mapping/page_mapper.cc Sun May 22 23:46:17 2022 +0200 +++ b/libfsserver/lib/mapping/page_mapper.cc Tue May 24 00:34:05 2022 +0200 @@ -1,7 +1,7 @@ /* * A page mapper providing memory pages to satisfy file accesses. * - * Copyright (C) 2021 Paul Boddie + * Copyright (C) 2021, 2022 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as