# HG changeset patch # User Paul Boddie # Date 1715360438 -7200 # Node ID 5c24477f91bf754ef0397f5b4554db6faf9f981b # Parent bbb065eae48318fbae56af1ca5754ac73499918f Added the retention of the current data position in pipe endpoints, allowing endpoints to be transferred to other programs and initialised appropriately. Renamed the populated_size parameter in the flush operation to indicate that a more general position is being sent, this being a populated size in a writing context and the current reading position in a reading context. diff -r bbb065eae483 -r 5c24477f91bf docs/wiki/Components --- a/docs/wiki/Components Fri May 10 14:49:52 2024 +0200 +++ b/docs/wiki/Components Fri May 10 19:00:38 2024 +0200 @@ -404,11 +404,13 @@ operation: {{{ -current_region(out offset_t populated_size, out offset_t size) +current_region(inout offset_t position, out offset_t populated_size, out offset_t size) }}} -This provides details of the populated size (or amount of written data) in a -region along with the size of the region. +This provides details of the recorded access position in a region, the +populated size (or amount of written data) in a region along with the size of +the region. For a writing endpoint, the position and populated size will be +the same. Navigation to the next available region of the pipe is performed using the following operation: diff -r bbb065eae483 -r 5c24477f91bf libfsclient/include/fsclient/file.h --- a/libfsclient/include/fsclient/file.h Fri May 10 14:49:52 2024 +0200 +++ b/libfsclient/include/fsclient/file.h Fri May 10 19:00:38 2024 +0200 @@ -162,7 +162,7 @@ /* Pipe region operations. */ -long pipe_current(file_t *pipe); +long pipe_current(file_t *pipe, int sync); long pipe_next(file_t *pipe); long pipe_written(file_t *pipe, offset_t size); diff -r bbb065eae483 -r 5c24477f91bf libfsclient/lib/src/client.cc --- a/libfsclient/lib/src/client.cc Fri May 10 14:49:52 2024 +0200 +++ b/libfsclient/lib/src/client.cc Fri May 10 19:00:38 2024 +0200 @@ -209,7 +209,7 @@ if (file->object_flags & OBJECT_SUPPORTS_MMAP) return client_mmap(file, client_tell(file), count, 0, 0, file_region_flags(file->flags)); - else if (pipe_current(file)) + else if (pipe_current(file, 0)) return NULL; } @@ -305,17 +305,16 @@ return stream; } -/* Initialise the stream data position to the end of any existing data. */ +/* Initialise the stream data position to the end of any existing data for an + output stream. For an input stream, initialise the position to the end of + consumed data, preserving any unconsumed data. */ long client_sync_stream(file_t *file) { - long err = client_current_region(file); + if (!client_opened(file)) + return -L4_EINVAL; - if (err) - return err; - - file->data_current = file->data_end; - return err; + return pipe_current(file, 1); } @@ -558,24 +557,15 @@ -/* Obtain the current region of a pipe. */ +/* Obtain the current region of a pipe, updating the extent of populated data + and only changing the current position if no populated data exists. */ long client_current_region(file_t *file) { if (!client_opened(file)) return -L4_EINVAL; - long err = pipe_current(file); - - if (err) - return err; - - /* Handle any case where the current region has been exhausted. */ - - if (!file_populated_span(file)) - file->data_current = 0; - - return L4_EOK; + return pipe_current(file, 0); } @@ -616,13 +606,7 @@ if (!client_opened(file)) return -L4_EINVAL; - long err = pipe_next(file); - - if (err) - return err; - - file->data_current = 0; - return L4_EOK; + return pipe_next(file); } diff -r bbb065eae483 -r 5c24477f91bf libfsclient/lib/src/file.cc --- a/libfsclient/lib/src/file.cc Fri May 10 14:49:52 2024 +0200 +++ b/libfsclient/lib/src/file.cc Fri May 10 19:00:38 2024 +0200 @@ -680,16 +680,27 @@ /* Access the current region for a pipe endpoint. */ -long pipe_current(file_t *pipe) +long pipe_current(file_t *pipe, int sync) { client_Pipe _pipe(pipe->ref); - long err = _pipe.current_region(&pipe->data_end, &pipe->size); + offset_t data_current; + long err = _pipe.current_region(&data_current, &pipe->data_end, &pipe->size); if (err) return err; pipe->end_pos = pipe->size; + /* Obtain the current position if synchronising position state. */ + + if (sync) + pipe->data_current = data_current; + + /* Handle any case where the current region has been exhausted. */ + + if (!file_populated_span(pipe)) + pipe->data_current = 0; + /* Attach memory if necessary. */ if (pipe->memory == NULL) @@ -720,6 +731,7 @@ return err; pipe->end_pos = pipe->size; + pipe->data_current = 0; pipe->memory = NULL; err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory); diff -r bbb065eae483 -r 5c24477f91bf libfsserver/include/fsserver/file_pager.h --- a/libfsserver/include/fsserver/file_pager.h Fri May 10 14:49:52 2024 +0200 +++ b/libfsserver/include/fsserver/file_pager.h Fri May 10 19:00:38 2024 +0200 @@ -1,7 +1,7 @@ /* * File-specific pager functionality. * - * Copyright (C) 2021, 2022, 2023 Paul Boddie + * Copyright (C) 2021, 2022, 2023, 2024 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 @@ -63,7 +63,7 @@ /* File methods. */ - virtual long flush(offset_t populated_size, offset_t *size); + virtual long flush(offset_t position, offset_t *size); virtual long reopen(flags_t flags, offset_t *size, l4_cap_idx_t *file, object_flags_t *object_flags); diff -r bbb065eae483 -r 5c24477f91bf libfsserver/include/fsserver/pager.h --- a/libfsserver/include/fsserver/pager.h Fri May 10 14:49:52 2024 +0200 +++ b/libfsserver/include/fsserver/pager.h Fri May 10 19:00:38 2024 +0200 @@ -1,7 +1,7 @@ /* * Generic pager functionality. * - * Copyright (C) 2021, 2022 Paul Boddie + * Copyright (C) 2021, 2022, 2024 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 @@ -53,7 +53,7 @@ /* File methods. */ - virtual long flush(offset_t populated_size, offset_t *size); + virtual long flush(offset_t position, offset_t *size); virtual long resize(offset_t *size); diff -r bbb065eae483 -r 5c24477f91bf libfsserver/include/fsserver/pipe_pager.h --- a/libfsserver/include/fsserver/pipe_pager.h Fri May 10 14:49:52 2024 +0200 +++ b/libfsserver/include/fsserver/pipe_pager.h Fri May 10 19:00:38 2024 +0200 @@ -35,6 +35,7 @@ protected: PipePaging *_paging; bool _writing; + offset_t _data_current; l4_cap_idx_t _notifier = L4_INVALID_CAP; /* Helper methods. */ @@ -65,13 +66,13 @@ virtual long closed(int *closed); - virtual long current_region(offset_t *populated_size, offset_t *size); + virtual long current_region(offset_t *position, offset_t *populated_size, offset_t *size); virtual long next_region(offset_t *populated_size, offset_t *size); /* Flushing/synchronisation. */ - virtual long flush(offset_t populated_size, offset_t *size); + virtual long flush(offset_t position, offset_t *size); /* Notification methods. */ diff -r bbb065eae483 -r 5c24477f91bf libfsserver/lib/files/file_pager.cc --- a/libfsserver/lib/files/file_pager.cc Fri May 10 14:49:52 2024 +0200 +++ b/libfsserver/lib/files/file_pager.cc Fri May 10 19:00:38 2024 +0200 @@ -1,7 +1,7 @@ /* * File-specific pager functionality. * - * Copyright (C) 2021, 2022, 2023 Paul Boddie + * Copyright (C) 2021, 2022, 2023, 2024 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 @@ -64,9 +64,9 @@ /* File-specific operations. */ -long FilePager::flush(offset_t populated_size, offset_t *size) +long FilePager::flush(offset_t position, offset_t *size) { - long err = Pager::flush(populated_size, size); + long err = Pager::flush(position, size); if (_resized) { diff -r bbb065eae483 -r 5c24477f91bf libfsserver/lib/generic/pager.cc --- a/libfsserver/lib/generic/pager.cc Fri May 10 14:49:52 2024 +0200 +++ b/libfsserver/lib/generic/pager.cc Fri May 10 19:00:38 2024 +0200 @@ -1,7 +1,7 @@ /* * Generic pager functionality. * - * Copyright (C) 2021, 2022, 2023 Paul Boddie + * Copyright (C) 2021, 2022, 2023, 2024 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 @@ -59,9 +59,9 @@ /* Flush data to the file. */ -long Pager::flush(offset_t populated_size, offset_t *size) +long Pager::flush(offset_t position, offset_t *size) { - _mapper->flush_all(_start, populated_size); + _mapper->flush_all(_start, position); *size = _mapper->get_data_size(); return L4_EOK; diff -r bbb065eae483 -r 5c24477f91bf libfsserver/lib/pipes/pipe_pager.cc --- a/libfsserver/lib/pipes/pipe_pager.cc Fri May 10 14:49:52 2024 +0200 +++ b/libfsserver/lib/pipes/pipe_pager.cc Fri May 10 19:00:38 2024 +0200 @@ -36,6 +36,10 @@ _size = _paging->region_size(); + /* Initialise any recorded position in the region. */ + + _data_current = 0; + /* Obtain any initial page mapper, this having been set up in the paging coordinator. */ @@ -92,10 +96,13 @@ /* Return details of the current region. */ -long PipePager::current_region(offset_t *populated_size, offset_t *size) +long PipePager::current_region(offset_t *position, offset_t *populated_size, offset_t *size) { if (_mapper != NULL) { + if (position != NULL) + *position = _data_current; + *populated_size = _mapper->get_data_size(); *size = _size; return L4_EOK; @@ -124,8 +131,9 @@ return pipe_error(); _mapper = mapper; + _data_current = 0; - return current_region(populated_size, size); + return current_region(NULL, populated_size, size); } long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) @@ -143,8 +151,9 @@ return pipe_error(); _mapper = mapper; + _data_current = 0; - return current_region(populated_size, size); + return current_region(NULL, populated_size, size); } long PipePager::pipe_error() @@ -157,12 +166,19 @@ -/* Update the populated size of a pipe region and notify the other endpoint. */ +/* Update the consumed or populated size of a pipe region and notify the other + endpoint. The consumed size is recorded to allow pipes to be shared between + programs. */ -long PipePager::flush(offset_t populated_size, offset_t *size) +long PipePager::flush(offset_t position, offset_t *size) { - if (_writing && (_mapper != NULL)) - _mapper->set_data_size(populated_size); + if (_mapper != NULL) + { + _data_current = position; + + if (_writing) + _mapper->set_data_size(position); + } *size = _size; diff -r bbb065eae483 -r 5c24477f91bf libsystypes/idl/flush.idl --- a/libsystypes/idl/flush.idl Fri May 10 14:49:52 2024 +0200 +++ b/libsystypes/idl/flush.idl Fri May 10 19:00:38 2024 +0200 @@ -4,7 +4,9 @@ interface Flush { - /* Flush data and update the size, if appropriate. */ + /* Flush data and update the size, if appropriate. When writing, the position + indicates the populated size of the object; when reading, the position + indicates the point from which data is being consumed by a client. */ - [opcode(5)] void flush(in offset_t populated_size, out offset_t size); + [opcode(5)] void flush(in offset_t position, out offset_t size); }; diff -r bbb065eae483 -r 5c24477f91bf libsystypes/idl/pipe.idl --- a/libsystypes/idl/pipe.idl Fri May 10 14:49:52 2024 +0200 +++ b/libsystypes/idl/pipe.idl Fri May 10 19:00:38 2024 +0200 @@ -6,7 +6,7 @@ { /* Obtain details of the current region of shared memory. */ - [opcode(16)] void current_region(out offset_t populated_size, out offset_t size); + [opcode(16)] void current_region(inout offset_t position, out offset_t populated_size, out offset_t size); /* Advance to the next region of shared memory, indicating and obtaining the populated limit of the region and obtaining the region size. */