bonefish + axeld:
* Reverted r31809 as it introduced a race condition; if the I/O request had been notified, it could already been deleted at that point. * Instead, we need to notify the request in each file system/driver that uses it. Added new notify_io_request() function that does that exactly. * Added a TODO comment to the userlandfs where the request notification needs a bit more thought. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31903 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#ifndef _IO_REQUESTS_H
|
||||
#define _IO_REQUESTS_H
|
||||
|
||||
|
||||
/*! I/O request interface */
|
||||
|
||||
|
||||
@@ -19,9 +20,11 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
bool io_request_is_write(const io_request* request);
|
||||
void notify_io_request(io_request* request, status_t status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _IO_REQUESTS_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2004-2009, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <io_requests.h>
|
||||
|
||||
|
||||
//#define TRACE_CD_DISK
|
||||
#ifdef TRACE_CD_DISK
|
||||
@@ -709,8 +711,10 @@ cd_io(void* cookie, io_request* request)
|
||||
{
|
||||
cd_handle* handle = (cd_handle*)cookie;
|
||||
|
||||
if (handle->info->capacity == 0)
|
||||
if (handle->info->capacity == 0) {
|
||||
notify_io_request(request, B_DEV_NO_MEDIA);
|
||||
return B_DEV_NO_MEDIA;
|
||||
}
|
||||
|
||||
return handle->info->io_scheduler->ScheduleRequest(request);
|
||||
}
|
||||
|
||||
@@ -485,12 +485,18 @@ bfs_io(fs_volume* _volume, fs_vnode* _node, void* _cookie, io_request* request)
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
|
||||
#ifndef BFS_SHELL
|
||||
if (io_request_is_write(request) && volume->IsReadOnly())
|
||||
if (io_request_is_write(request) && volume->IsReadOnly()) {
|
||||
notify_io_request(request, B_READ_ONLY_DEVICE);
|
||||
return B_READ_ONLY_DEVICE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inode->FileCache() == NULL)
|
||||
if (inode->FileCache() == NULL) {
|
||||
#ifndef BFS_SHELL
|
||||
notify_io_request(request, B_BAD_VALUE);
|
||||
#endif
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
}
|
||||
|
||||
// We lock the node here and will unlock it in the "finished" hook.
|
||||
rw_lock_read_lock(&inode->Lock());
|
||||
|
||||
@@ -456,11 +456,15 @@ fs_io(fs_volume* _volume, fs_vnode* _node, void* _cookie, io_request* request)
|
||||
iso9660_volume* volume = (iso9660_volume*)_volume->private_volume;
|
||||
iso9660_inode* node = (iso9660_inode*)_node->private_node;
|
||||
|
||||
if (io_request_is_write(request))
|
||||
if (io_request_is_write(request)) {
|
||||
notify_io_request(request, B_READ_ONLY_DEVICE);
|
||||
return B_READ_ONLY_DEVICE;
|
||||
}
|
||||
|
||||
if ((node->flags & ISO_IS_DIR) != 0)
|
||||
return EISDIR;
|
||||
if ((node->flags & ISO_IS_DIR) != 0) {
|
||||
notify_io_request(request, B_IS_A_DIRECTORY);
|
||||
return B_IS_A_DIRECTORY;
|
||||
}
|
||||
|
||||
return do_iterative_fd_io(volume->fd, request, iterative_io_get_vecs_hook,
|
||||
iterative_io_finished_hook, node);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include <fs/fd.h> // kernel private
|
||||
#include <io_requests.h>
|
||||
#include <thread.h>
|
||||
|
||||
#include "IORequest.h" // kernel internal
|
||||
@@ -1149,28 +1150,34 @@ Volume::DoIO(void* _node, void* cookie, io_request* ioRequest)
|
||||
|
||||
// check capability
|
||||
if (!HasVNodeCapability(vnode, FS_VNODE_CAPABILITY_IO))
|
||||
return B_BAD_VALUE;
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
// register the IO request
|
||||
int32 requestID;
|
||||
status_t error = _RegisterIORequest(ioRequest, &requestID);
|
||||
if (error != B_OK)
|
||||
if (error != B_OK) {
|
||||
notify_io_request(ioRequest, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
IORequestRemover requestRemover(this, requestID);
|
||||
|
||||
// get a free port
|
||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||
if (!port)
|
||||
if (!port) {
|
||||
notify_io_request(ioRequest, B_ERROR);
|
||||
return B_ERROR;
|
||||
}
|
||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
DoIORequest* request;
|
||||
error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
if (error != B_OK) {
|
||||
notify_io_request(ioRequest, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
request->volume = fUserlandVolume;
|
||||
request->node = vnode->clientNode;
|
||||
@@ -1182,6 +1189,8 @@ Volume::DoIO(void* _node, void* cookie, io_request* ioRequest)
|
||||
// send the request
|
||||
KernelRequestHandler handler(this, DO_IO_REPLY);
|
||||
DoIOReply* reply;
|
||||
|
||||
// TODO: when to notify the io_request?
|
||||
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -822,7 +822,6 @@ IORequest::NotifyFinished()
|
||||
if (fBuffer->IsMemoryLocked())
|
||||
fBuffer->UnlockMemory(fTeam, fIsWrite);
|
||||
|
||||
|
||||
// Cache the callbacks before we unblock waiters and unlock. Any of the
|
||||
// following could delete this request, so we don't want to touch it
|
||||
// once we have started telling others that it is done.
|
||||
|
||||
@@ -227,8 +227,10 @@ IOScheduler::ScheduleRequest(IORequest* request)
|
||||
if (buffer->IsVirtual()) {
|
||||
status_t status = buffer->LockMemory(request->Team(),
|
||||
request->IsWrite());
|
||||
if (status != B_OK)
|
||||
if (status != B_OK) {
|
||||
request->SetStatusAndNotify(status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
MutexLocker locker(fLock);
|
||||
@@ -240,6 +242,7 @@ IOScheduler::ScheduleRequest(IORequest* request)
|
||||
locker.Unlock();
|
||||
if (buffer->IsVirtual())
|
||||
buffer->UnlockMemory(request->Team(), request->IsWrite());
|
||||
request->SetStatusAndNotify(B_NO_MEMORY);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,3 +13,11 @@ io_request_is_write(const io_request* request)
|
||||
{
|
||||
return request->IsWrite();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
notify_io_request(io_request* request, status_t status)
|
||||
{
|
||||
request->SetStatusAndNotify(status);
|
||||
}
|
||||
|
||||
|
||||
@@ -410,11 +410,6 @@ vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request)
|
||||
return synchronous_io(request, io);
|
||||
}
|
||||
|
||||
if (result != B_OK && !request->IsFinished()) {
|
||||
// The request failed, but its owner has not been notified yet
|
||||
request->SetStatusAndNotify(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user