1.1 --- a/dstest_block_client.cc Wed Mar 17 00:10:47 2021 +0100
1.2 +++ b/dstest_block_client.cc Thu Mar 18 00:59:55 2021 +0100
1.3 @@ -33,6 +33,24 @@
1.4
1.5
1.6
1.7 +static void show(file_t *file, unsigned long step, unsigned long sample)
1.8 +{
1.9 + /* Allocate a buffer for sampling from the file. */
1.10 +
1.11 + char buf[sample + 1];
1.12 +
1.13 + for (unsigned long offset = 0; offset < file_populated_span(file); offset += step)
1.14 + {
1.15 + unsigned long remaining = file_populated_span(file) - offset;
1.16 + unsigned long sample_remaining = remaining < sample ? remaining : sample;
1.17 +
1.18 + printf("%ld bytes from %p...\n", sample_remaining, (file->memory + offset));
1.19 + strncpy(buf, (file->memory + offset), sample_remaining);
1.20 + buf[sample_remaining] = '\0';
1.21 + printf("%s\n", buf);
1.22 + }
1.23 +}
1.24 +
1.25 int main(int argc, char *argv[])
1.26 {
1.27 if (argc < 4)
1.28 @@ -47,10 +65,6 @@
1.29 unsigned long step = atoi(argv[2]);
1.30 unsigned long sample = atoi(argv[3]);
1.31
1.32 - /* Allocate a buffer for sampling from the file. */
1.33 -
1.34 - char buf[sample + 1];
1.35 -
1.36 /* Obtain access to the filesystem. */
1.37
1.38 l4_cap_idx_t server = l4re_env_get_cap("server");
1.39 @@ -76,16 +90,39 @@
1.40 return 1;
1.41 }
1.42
1.43 + show(&file, step, sample);
1.44 +
1.45 + /* Resizing must occur before writing beyond the end of file. Otherwise, the
1.46 + data may get discarded if the supporting flexpage needs to be flushed. */
1.47 +
1.48 + offset_t new_region = round(file_populated_span(&file), page(1));
1.49 +
1.50 + printf("Resize to %ld...\n", new_region + file_populated_span(&file));
1.51 +
1.52 + err = file_resize(&file, new_region + file_populated_span(&file));
1.53 +
1.54 + if (err)
1.55 + {
1.56 + printf("Could not resize file: %s\n", l4sys_errtostr(err));
1.57 + return 1;
1.58 + }
1.59 +
1.60 + printf("Resized file...\n");
1.61 +
1.62 + /* Copy the sampled data to another file region. */
1.63 +
1.64 + printf("Copy data to %ld...\n", new_region);
1.65 +
1.66 for (unsigned long offset = 0; offset < file_populated_span(&file); offset += step)
1.67 {
1.68 - unsigned long remaining = file_populated_span(&file) - offset;
1.69 - unsigned long sample_remaining = remaining < sample ? remaining : sample;
1.70 + memcpy(file.memory + new_region + offset, file.memory + offset, sample);
1.71 + if (step > sample)
1.72 + memset(file.memory + new_region + offset + sample, 0, step - sample);
1.73 + }
1.74
1.75 - printf("%ld bytes from %p...\n", sample_remaining, (file.memory + offset));
1.76 - strncpy(buf, (file.memory + offset), sample_remaining);
1.77 - buf[sample_remaining] = '\0';
1.78 - printf("%s\n", buf);
1.79 - }
1.80 + show(&file, step, sample);
1.81 +
1.82 + printf("File shown.\n");
1.83
1.84 return 0;
1.85 }
2.1 --- a/file.cc Wed Mar 17 00:10:47 2021 +0100
2.2 +++ b/file.cc Thu Mar 18 00:59:55 2021 +0100
2.3 @@ -25,6 +25,7 @@
2.4 #include <string.h>
2.5
2.6 #include "dataspace_client.h"
2.7 +#include "file_client.h"
2.8 #include "opener_client.h"
2.9 #include "opener_context_client.h"
2.10 #include "mapped_file_client.h"
2.11 @@ -128,6 +129,33 @@
2.12 return ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory);
2.13 }
2.14
2.15 +/* Resize a file. */
2.16 +
2.17 +long file_resize(file_t *file, offset_t size)
2.18 +{
2.19 + client_File _file(file->ref);
2.20 + offset_t file_size = size;
2.21 + long err = _file.resize(&file_size);
2.22 +
2.23 + if (!err)
2.24 + {
2.25 + /* Determine the extent of the file in this region. */
2.26 +
2.27 + if (file_size > file->end_pos)
2.28 + file->data_end = file_span(file);
2.29 + else
2.30 + file->data_end = file_size - file->start_pos;
2.31 +
2.32 + /* Update the file size locally. */
2.33 +
2.34 + file->size = file_size;
2.35 + }
2.36 +
2.37 + return err;
2.38 +}
2.39 +
2.40 +
2.41 +
2.42 /* Return the amount of data in the mapped region for the given file. */
2.43
2.44 offset_t file_populated_span(file_t *file)
3.1 --- a/file.h Wed Mar 17 00:10:47 2021 +0100
3.2 +++ b/file.h Thu Mar 18 00:59:55 2021 +0100
3.3 @@ -63,9 +63,13 @@
3.4 long file_context_open(file_t *file, file_t *context);
3.5 void file_init(file_t *file);
3.6
3.7 -/* File access region operations. */
3.8 +/* File and region operations. */
3.9
3.10 long file_mmap(file_t *file, offset_t position, offset_t length);
3.11 +long file_resize(file_t *file, offset_t size);
3.12 +
3.13 +/* File and region properties. */
3.14 +
3.15 offset_t file_populated_span(file_t *file);
3.16 offset_t file_span(file_t *file);
3.17
4.1 --- a/file_pager.cc Wed Mar 17 00:10:47 2021 +0100
4.2 +++ b/file_pager.cc Thu Mar 18 00:59:55 2021 +0100
4.3 @@ -24,6 +24,11 @@
4.4 return Pager::flush(populated_size, size);
4.5 }
4.6
4.7 +long FilePager::resize(offset_t *size)
4.8 +{
4.9 + return Pager::resize(size);
4.10 +}
4.11 +
4.12 long FilePager::mmap(offset_t position, offset_t length, offset_t *start_pos, offset_t *end_pos, offset_t *data_end)
4.13 {
4.14 /* Set the limits of the paged region. */
5.1 --- a/file_pager.h Wed Mar 17 00:10:47 2021 +0100
5.2 +++ b/file_pager.h Thu Mar 18 00:59:55 2021 +0100
5.3 @@ -25,6 +25,8 @@
5.4
5.5 virtual long flush(offset_t populated_size, offset_t *size);
5.6
5.7 + virtual long resize(offset_t *size);
5.8 +
5.9 /* Pager and mapped file methods. */
5.10
5.11 virtual long map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region);
6.1 --- a/files/block_file_accessor.cc Wed Mar 17 00:10:47 2021 +0100
6.2 +++ b/files/block_file_accessor.cc Thu Mar 18 00:59:55 2021 +0100
6.3 @@ -45,13 +45,44 @@
6.4 fclose(fp);
6.5 }
6.6
6.7 +/* Update the size of the file. */
6.8 +
6.9 +void BlockFileAccessor::set_size(offset_t size)
6.10 +{
6.11 + void *new_data = realloc(_data, size);
6.12 +
6.13 + if (new_data != NULL)
6.14 + {
6.15 + _data = (char *) new_data;
6.16 +
6.17 + if (size > _size)
6.18 + memset(_data + _size, 0, size - _size);
6.19 +
6.20 + Accessor::set_size(size);
6.21 + }
6.22 +}
6.23 +
6.24 /* Data transfer methods. */
6.25
6.26 void BlockFileAccessor::fill(Flexpage *flexpage)
6.27 {
6.28 offset_t filepos = flexpage->base_offset;
6.29 offset_t addr = flexpage->base_addr;
6.30 - offset_t populated_size = std::min(flexpage->size, _size - filepos);
6.31 + offset_t populated_size;
6.32 +
6.33 + /* Filling completely beyond the end of file should produce an empty
6.34 + flexpage. This could potentially be a shared read-only flexpage that
6.35 + would be replaced by an independent writable flexpage if ever written. */
6.36 +
6.37 + if (filepos > _size)
6.38 + {
6.39 + memset((void *) addr, 0, flexpage->size);
6.40 + return;
6.41 + }
6.42 +
6.43 + /* Otherwise, fill the populated portion of a flexpage. */
6.44 +
6.45 + populated_size = std::min(flexpage->size, _size - filepos);
6.46
6.47 /* Tag the region with file state. */
6.48
6.49 @@ -71,7 +102,17 @@
6.50 {
6.51 offset_t addr = flexpage->base_addr;
6.52 offset_t filepos = flexpage->base_offset;
6.53 - offset_t populated_size = std::min(flexpage->size, _size - filepos);
6.54 + offset_t populated_size;
6.55 +
6.56 + /* Flushing completely beyond the end of file should discard the
6.57 + flexpage. */
6.58 +
6.59 + if (filepos > _size)
6.60 + return;
6.61 +
6.62 + /* Otherwise, only the populated portion of a flexpage should be flushed. */
6.63 +
6.64 + populated_size = std::min(flexpage->size, _size - filepos);
6.65
6.66 /* Remove the file state tag from the region. */
6.67
7.1 --- a/files/block_file_accessor.h Wed Mar 17 00:10:47 2021 +0100
7.2 +++ b/files/block_file_accessor.h Thu Mar 18 00:59:55 2021 +0100
7.3 @@ -13,6 +13,8 @@
7.4 public:
7.5 explicit BlockFileAccessor(const char *path, fileid_t fileid);
7.6
7.7 + virtual void set_size(offset_t size);
7.8 +
7.9 /* Data transfer methods. */
7.10
7.11 virtual void fill(Flexpage *flexpage);
8.1 --- a/pager.cc Wed Mar 17 00:10:47 2021 +0100
8.2 +++ b/pager.cc Thu Mar 18 00:59:55 2021 +0100
8.3 @@ -19,19 +19,19 @@
8.4
8.5 long Pager::flush(offset_t populated_size, offset_t *size)
8.6 {
8.7 - offset_t limit = _start + populated_size;
8.8 - offset_t file_size = _mapper->get_data_size();
8.9 + _mapper->flush_all(_start, populated_size);
8.10
8.11 - /* Extend the file if the populated size of the region goes beyond the
8.12 - current size. */
8.13 + *size = _mapper->get_data_size();
8.14 + return L4_EOK;
8.15 +}
8.16
8.17 - if (limit > file_size)
8.18 - {
8.19 - file_size = limit;
8.20 - _mapper->set_data_size(file_size);
8.21 - }
8.22 +/* Resize the underlying file. */
8.23
8.24 - *size = file_size;
8.25 +long Pager::resize(offset_t *size)
8.26 +{
8.27 + _mapper->set_data_size(*size);
8.28 +
8.29 + *size = _mapper->get_data_size();
8.30 return L4_EOK;
8.31 }
8.32
9.1 --- a/pager.h Wed Mar 17 00:10:47 2021 +0100
9.2 +++ b/pager.h Thu Mar 18 00:59:55 2021 +0100
9.3 @@ -33,6 +33,8 @@
9.4
9.5 virtual long flush(offset_t populated_size, offset_t *size);
9.6
9.7 + virtual long resize(offset_t *size);
9.8 +
9.9 /* Mapped file methods. */
9.10
9.11 virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, offset_t *end_pos, offset_t *data_end);