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:
Axel Dörfler
2009-07-29 12:16:15 +00:00
parent 75251adc37
commit 533cba7eff
9 changed files with 49 additions and 18 deletions
+3
View File
@@ -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);
}
-5
View File
@@ -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;
}