1.1 --- a/libfsserver/lib/generic/pager.cc Sun May 22 23:46:17 2022 +0200
1.2 +++ b/libfsserver/lib/generic/pager.cc Tue May 24 00:34:05 2022 +0200
1.3 @@ -40,6 +40,7 @@
1.4
1.5 void Pager::close()
1.6 {
1.7 + /* NOTE: Need to deallocate any allocated regions and flexpages. */
1.8 }
1.9
1.10 /* Flush data to the file. */
1.11 @@ -109,11 +110,30 @@
1.12 if (flags & (~(_flags | L4RE_DS_F_X)))
1.13 return -L4_EACCESS;
1.14
1.15 - Flexpage *flexpage = _mapper->get(file_offset, flags);
1.16 + Flexpage *issued_flexpage = NULL, *obtained_flexpage = NULL;
1.17 +
1.18 + /* Obtain any replicated flexpage.
1.19 + NOTE: An additional condition should be introduced to test for the
1.20 + relevance of replicated flexpages. */
1.21 +
1.22 + if (flags & L4RE_DS_F_W)
1.23 + issued_flexpage = _map.find(file_offset);
1.24 +
1.25 + /* Without any replicated flexpage, obtain one for the shared, underlying
1.26 + file data. */
1.27
1.28 - /* Determine if the flexpage should be masked. */
1.29 + if (issued_flexpage == NULL)
1.30 + {
1.31 + obtained_flexpage = _mapper->get(file_offset, flags);
1.32 +
1.33 + /* Determine if the flexpage should be masked. */
1.34
1.35 - Flexpage *issued_flexpage = get_masked_flexpage(flexpage);
1.36 + issued_flexpage = get_masked_flexpage(obtained_flexpage);
1.37 +
1.38 + /* Determine if the flexpage should be replicated. */
1.39 +
1.40 + issued_flexpage = get_replicated_flexpage(issued_flexpage, flags);
1.41 + }
1.42
1.43 /* Issue the flexpage via the IPC system. */
1.44
1.45 @@ -123,9 +143,10 @@
1.46 if (!err)
1.47 err = complete_Dataspace_map(*region);
1.48
1.49 - /* After the flexpage is issued, it is queued for future reuse. */
1.50 + /* After the obtained flexpage is issued, it is queued for future reuse. */
1.51
1.52 - _mapper->queue(flexpage);
1.53 + if (obtained_flexpage != NULL)
1.54 + _mapper->queue(obtained_flexpage);
1.55
1.56 if (err)
1.57 return err;
1.58 @@ -151,7 +172,7 @@
1.59 return flexpage;
1.60
1.61 /* Determine whether the flexpage involves the limits of the visible
1.62 - region. */
1.63 + region or is beyond such limits. */
1.64
1.65 bool has_start = flexpage->supports_position(_start_visible) &&
1.66 flexpage->base_offset != _start_visible;
1.67 @@ -165,9 +186,7 @@
1.68 return flexpage;
1.69
1.70 /* Allocate and populate a region in one of the preallocated flexpages for
1.71 - masked content.
1.72 - NOTE: A general copy-on-write solution will maintain a collection of
1.73 - flexpages. */
1.74 + masked content. */
1.75
1.76 Flexpage &masked = has_start ? _start_flexpage :
1.77 has_end ? _end_flexpage :
1.78 @@ -179,6 +198,7 @@
1.79 /* Associate the preallocated flexpage with the original flexpage. */
1.80
1.81 flexpage->associate(&masked);
1.82 +
1.83 return &masked;
1.84 }
1.85
1.86 @@ -229,4 +249,28 @@
1.87 memset((void *) (masked.region->start + end_offset), 0, masked.size - end_offset);
1.88 }
1.89
1.90 +/* Detect flexpages with replicated content, introducing separate flexpages
1.91 + offering replicated content from the same region. */
1.92 +
1.93 +Flexpage *Pager::get_replicated_flexpage(Flexpage *flexpage, map_flags_t flags)
1.94 +{
1.95 + /* NOTE: An additional condition should be introduced to test for the
1.96 + relevance of replicated flexpages. For now, detect copy-on-write
1.97 + situations. */
1.98 +
1.99 + if (_is_masked && (flags & L4RE_DS_F_W))
1.100 + {
1.101 + Region *region = _memory.region(flexpage->size);
1.102 + Flexpage *replicated = new Flexpage(region);
1.103 +
1.104 + replicated->reset(flexpage->base_offset);
1.105 +
1.106 + memcpy((void *) region->start, (const void *) flexpage->region->start, flexpage->size);
1.107 + _map.insert(replicated);
1.108 + return replicated;
1.109 + }
1.110 + else
1.111 + return flexpage;
1.112 +}
1.113 +
1.114 // vim: tabstop=4 expandtab shiftwidth=4