userlandfs: Ensure room for requests in port

* Add a parameter to RequestAllocator::AllocateAddress and ::AllocateData
  that allows the client to specify a minimum amount of free space that
  must remain in the port buffer.
* Make use of the new parameter in some operations that can fail
  without it.

The Port buffer can be used to store data associated with a Request.
For some file system operations, further requests must be sent through
the port (by calling AllocateRequest) after reserving port buffer
space for data. Unlike AllocateAddress and AllocateData, which can
use an area if the data is larger than the port buffer capacity,
AllocateRequest can only allocate space in the port buffer. If data
previously allocated in the port buffer happens to be large enough to
fill it, then these further AllocateRequest calls will fail.

Change-Id: If03e0afdfbd9fbc36f0e1a04b5d0a20031932b91
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8866
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Jim906
2025-01-29 17:17:16 +00:00
committed by waddlesplash
parent 83e4b8867e
commit 1c0da902ab
6 changed files with 13 additions and 12 deletions
@@ -37,10 +37,10 @@ public:
status_t AllocateAddress(Address& address, int32 size,
int32 align, void** data,
bool deferredInit = false);
bool deferredInit = false, int32 reserveForNextRequests = 0);
status_t AllocateData(Address& address, const void* data,
int32 size, int32 align,
bool deferredInit = false);
bool deferredInit = false, int32 reserveForNextRequests = 0);
status_t AllocateString(Address& address,
const char* data,
bool deferredInit = false);
@@ -2219,7 +2219,7 @@ Volume::Write(void* _node, void* cookie, off_t pos, const void* buffer,
request->node = vnode->clientNode;
request->fileCookie = cookie;
request->pos = pos;
error = allocator.AllocateData(request->buffer, buffer, size, 1);
error = allocator.AllocateData(request->buffer, buffer, size, 1, false, sizeof(DoIORequest));
if (error != B_OK)
return error;
@@ -176,7 +176,7 @@ RequestAllocator::GetRequestSize() const
// AllocateAddress
status_t
RequestAllocator::AllocateAddress(Address& address, int32 size, int32 align,
void** data, bool deferredInit)
void** data, bool deferredInit, int32 reserveForNextRequests)
{
if (fError != B_OK)
return fError;
@@ -206,8 +206,8 @@ RequestAllocator::AllocateAddress(Address& address, int32 size, int32 align,
// get the next free aligned offset in the port buffer
int32 offset = (fRequestSize + align - 1) / align * align;
// allocate the data
if (fRequestOffset + offset + size <= fPort->GetCapacity()) {
// there's enough free space in the port buffer
if (fRequestOffset + offset + size + reserveForNextRequests <= fPort->GetCapacity()) {
// there's enough free space in the port buffer for the data and any anticipated requests
fRequestSize = offset + size;
fPort->Reserve(fRequestOffset + fRequestSize);
if (deferredInit) {
@@ -273,13 +273,13 @@ RequestAllocator::AllocateAddress(Address& address, int32 size, int32 align,
// AllocateData
status_t
RequestAllocator::AllocateData(Address& address, const void* data, int32 size,
int32 align, bool deferredInit)
int32 align, bool deferredInit, int32 reserveForNextRequests)
{
status_t error = B_OK;
if (data != NULL) {
void* destination;
error = AllocateAddress(address, size, align, &destination,
deferredInit);
deferredInit, reserveForNextRequests);
if (error != B_OK)
return error;
if (size > 0) {
@@ -5,12 +5,13 @@
#include "Debug.h"
#include "Requests.h"
#define _ADD_ADDRESS(_address, _flags) { \
#define _ADD_ADDRESS(_address, _flags) do { \
if (*count >= MAX_REQUEST_ADDRESS_COUNT) \
return B_BAD_VALUE; \
infos[*count].address = &_address; \
infos[*count].flags = _flags; \
infos[(*count)++].max_size = INT32_MAX; } // TODO:...
infos[(*count)++].max_size = INT32_MAX; \
} while (0) // TODO:...
#define ADD_ADDRESS(address) _ADD_ADDRESS(address, 0)
#define ADD_STRING(address) _ADD_ADDRESS(address, ADDRESS_IS_STRING)
@@ -1259,7 +1259,7 @@ UserlandRequestHandler::_HandleRequest(ReadRequest* request)
void* buffer;
if (result == B_OK) {
result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
true);
true, sizeof(FileCacheReadRequest) + sizeof(ReceiptAckReply));
}
// execute the request
@@ -829,7 +829,7 @@ UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID,
if (buffer != NULL) {
error = allocator.AllocateData(request->buffer, buffer, *_size, 1,
false);
false, sizeof(DoIterativeFDIORequest));
if (error != B_OK)
return error;
}