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
|
#ifndef _IO_REQUESTS_H
|
||||||
#define _IO_REQUESTS_H
|
#define _IO_REQUESTS_H
|
||||||
|
|
||||||
|
|
||||||
/*! I/O request interface */
|
/*! I/O request interface */
|
||||||
|
|
||||||
|
|
||||||
@@ -19,9 +20,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool io_request_is_write(const io_request* request);
|
bool io_request_is_write(const io_request* request);
|
||||||
|
void notify_io_request(io_request* request, status_t status);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* _IO_REQUESTS_H */
|
#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.
|
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <io_requests.h>
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_CD_DISK
|
//#define TRACE_CD_DISK
|
||||||
#ifdef TRACE_CD_DISK
|
#ifdef TRACE_CD_DISK
|
||||||
@@ -709,8 +711,10 @@ cd_io(void* cookie, io_request* request)
|
|||||||
{
|
{
|
||||||
cd_handle* handle = (cd_handle*)cookie;
|
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 B_DEV_NO_MEDIA;
|
||||||
|
}
|
||||||
|
|
||||||
return handle->info->io_scheduler->ScheduleRequest(request);
|
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;
|
Inode* inode = (Inode*)_node->private_node;
|
||||||
|
|
||||||
#ifndef BFS_SHELL
|
#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;
|
return B_READ_ONLY_DEVICE;
|
||||||
|
}
|
||||||
#endif
|
#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);
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
// We lock the node here and will unlock it in the "finished" hook.
|
// We lock the node here and will unlock it in the "finished" hook.
|
||||||
rw_lock_read_lock(&inode->Lock());
|
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_volume* volume = (iso9660_volume*)_volume->private_volume;
|
||||||
iso9660_inode* node = (iso9660_inode*)_node->private_node;
|
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;
|
return B_READ_ONLY_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((node->flags & ISO_IS_DIR) != 0)
|
if ((node->flags & ISO_IS_DIR) != 0) {
|
||||||
return EISDIR;
|
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,
|
return do_iterative_fd_io(volume->fd, request, iterative_io_get_vecs_hook,
|
||||||
iterative_io_finished_hook, node);
|
iterative_io_finished_hook, node);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include <fs/fd.h> // kernel private
|
#include <fs/fd.h> // kernel private
|
||||||
|
#include <io_requests.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
|
|
||||||
#include "IORequest.h" // kernel internal
|
#include "IORequest.h" // kernel internal
|
||||||
@@ -1149,28 +1150,34 @@ Volume::DoIO(void* _node, void* cookie, io_request* ioRequest)
|
|||||||
|
|
||||||
// check capability
|
// check capability
|
||||||
if (!HasVNodeCapability(vnode, FS_VNODE_CAPABILITY_IO))
|
if (!HasVNodeCapability(vnode, FS_VNODE_CAPABILITY_IO))
|
||||||
return B_BAD_VALUE;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
// register the IO request
|
// register the IO request
|
||||||
int32 requestID;
|
int32 requestID;
|
||||||
status_t error = _RegisterIORequest(ioRequest, &requestID);
|
status_t error = _RegisterIORequest(ioRequest, &requestID);
|
||||||
if (error != B_OK)
|
if (error != B_OK) {
|
||||||
|
notify_io_request(ioRequest, error);
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
IORequestRemover requestRemover(this, requestID);
|
IORequestRemover requestRemover(this, requestID);
|
||||||
|
|
||||||
// get a free port
|
// get a free port
|
||||||
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||||
if (!port)
|
if (!port) {
|
||||||
|
notify_io_request(ioRequest, B_ERROR);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
}
|
||||||
PortReleaser _(fFileSystem->GetPortPool(), port);
|
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||||
|
|
||||||
// prepare the request
|
// prepare the request
|
||||||
RequestAllocator allocator(port->GetPort());
|
RequestAllocator allocator(port->GetPort());
|
||||||
DoIORequest* request;
|
DoIORequest* request;
|
||||||
error = AllocateRequest(allocator, &request);
|
error = AllocateRequest(allocator, &request);
|
||||||
if (error != B_OK)
|
if (error != B_OK) {
|
||||||
|
notify_io_request(ioRequest, error);
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
request->volume = fUserlandVolume;
|
request->volume = fUserlandVolume;
|
||||||
request->node = vnode->clientNode;
|
request->node = vnode->clientNode;
|
||||||
@@ -1182,6 +1189,8 @@ Volume::DoIO(void* _node, void* cookie, io_request* ioRequest)
|
|||||||
// send the request
|
// send the request
|
||||||
KernelRequestHandler handler(this, DO_IO_REPLY);
|
KernelRequestHandler handler(this, DO_IO_REPLY);
|
||||||
DoIOReply* reply;
|
DoIOReply* reply;
|
||||||
|
|
||||||
|
// TODO: when to notify the io_request?
|
||||||
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -822,7 +822,6 @@ IORequest::NotifyFinished()
|
|||||||
if (fBuffer->IsMemoryLocked())
|
if (fBuffer->IsMemoryLocked())
|
||||||
fBuffer->UnlockMemory(fTeam, fIsWrite);
|
fBuffer->UnlockMemory(fTeam, fIsWrite);
|
||||||
|
|
||||||
|
|
||||||
// Cache the callbacks before we unblock waiters and unlock. Any of the
|
// 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
|
// following could delete this request, so we don't want to touch it
|
||||||
// once we have started telling others that it is done.
|
// once we have started telling others that it is done.
|
||||||
|
|||||||
@@ -227,9 +227,11 @@ IOScheduler::ScheduleRequest(IORequest* request)
|
|||||||
if (buffer->IsVirtual()) {
|
if (buffer->IsVirtual()) {
|
||||||
status_t status = buffer->LockMemory(request->Team(),
|
status_t status = buffer->LockMemory(request->Team(),
|
||||||
request->IsWrite());
|
request->IsWrite());
|
||||||
if (status != B_OK)
|
if (status != B_OK) {
|
||||||
|
request->SetStatusAndNotify(status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MutexLocker locker(fLock);
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
@@ -240,6 +242,7 @@ IOScheduler::ScheduleRequest(IORequest* request)
|
|||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
if (buffer->IsVirtual())
|
if (buffer->IsVirtual())
|
||||||
buffer->UnlockMemory(request->Team(), request->IsWrite());
|
buffer->UnlockMemory(request->Team(), request->IsWrite());
|
||||||
|
request->SetStatusAndNotify(B_NO_MEMORY);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,3 +13,11 @@ io_request_is_write(const io_request* request)
|
|||||||
{
|
{
|
||||||
return request->IsWrite();
|
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);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user