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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user