* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <disk_device_manager.h>
#include <fs_cache.h>
#include <fs_interface.h>
#include <io_requests.h>
#include <KernelExport.h>
#include <NodeMonitor.h>
#include <fs/node_monitor.h>
#include "Debug.h"
#include "../FileSystem.h"
#include "../IORequestInfo.h"
#include "../kernel_emu.h"
#include "../RequestThread.h"
#include "HaikuKernelIORequest.h"
#include "HaikuKernelNode.h"
#include "HaikuKernelVolume.h"
#include "vfs.h"
#if __GNUC__ == 2
#include <cpu.h>
#include <smp.h>
cpu_ent gCPU[1];
int32
smp_get_current_cpu(void)
{
return 0;
}
#endif
status_t
notify_entry_created(dev_t device, ino_t directory, const char *name,
ino_t node)
{
if (!name)
return B_BAD_VALUE;
return UserlandFS::KernelEmu::notify_listener(B_ENTRY_CREATED, 0, device, 0,
directory, node, NULL, name);
}
status_t
notify_entry_removed(dev_t device, ino_t directory, const char *name,
ino_t node)
{
if (!name)
return B_BAD_VALUE;
return UserlandFS::KernelEmu::notify_listener(B_ENTRY_REMOVED, 0, device, 0,
directory, node, NULL, name);
}
status_t
notify_entry_moved(dev_t device, ino_t fromDirectory,
const char *fromName, ino_t toDirectory, const char *toName,
ino_t node)
{
if (!fromName || !toName)
return B_BAD_VALUE;
return UserlandFS::KernelEmu::notify_listener(B_ENTRY_MOVED, 0, device,
fromDirectory, toDirectory, node, fromName, toName);
}
status_t
notify_stat_changed(dev_t device, ino_t directory, ino_t node,
uint32 statFields)
{
return UserlandFS::KernelEmu::notify_listener(B_STAT_CHANGED, statFields,
device, 0, directory, node, NULL, NULL);
}
status_t
notify_attribute_changed(dev_t device, ino_t directory, ino_t node,
const char *attribute, int32 cause)
{
if (!attribute)
return B_BAD_VALUE;
return UserlandFS::KernelEmu::notify_listener(B_ATTR_CHANGED, cause,
device, 0, directory, node, NULL, attribute);
}
status_t
notify_select_event(selectsync *sync, uint8 event)
{
return UserlandFS::KernelEmu::notify_select_event(sync, event, false);
}
status_t
notify_query_entry_created(port_id port, int32 token, dev_t device,
ino_t directory, const char *name, ino_t node)
{
if (!name)
return B_BAD_VALUE;
return UserlandFS::KernelEmu::notify_query(port, token, B_ENTRY_CREATED,
device, directory, name, node);
}
status_t
notify_query_entry_removed(port_id port, int32 token, dev_t device,
ino_t directory, const char *name, ino_t node)
{
if (!name)
return B_BAD_VALUE;
return UserlandFS::KernelEmu::notify_query(port, token, B_ENTRY_REMOVED,
device, directory, name, node);
}
status_t
new_vnode(fs_volume *_volume, ino_t vnodeID, void *privateNode,
fs_vnode_ops *ops)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
HaikuKernelNode* node;
status_t error = volume->NewVNode(vnodeID, privateNode, ops, &node);
if (error != B_OK)
return error;
error = UserlandFS::KernelEmu::new_vnode(volume->GetID(), vnodeID, node,
node->capabilities->capabilities);
if (error != B_OK)
volume->UndoNewVNode(node);
return error;
}
status_t
publish_vnode(fs_volume *_volume, ino_t vnodeID, void *privateNode,
fs_vnode_ops *ops, int type, uint32 flags)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
HaikuKernelNode* node;
status_t error = volume->PublishVNode(vnodeID, privateNode, ops, type,
flags, &node);
if (error != B_OK)
return error;
error = UserlandFS::KernelEmu::publish_vnode(volume->GetID(), vnodeID, node,
type, flags, node->capabilities->capabilities);
if (error != B_OK)
volume->UndoPublishVNode(node);
return error;
}
status_t
get_vnode(fs_volume *_volume, ino_t vnodeID, void **privateNode)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
void* foundNode;
status_t error = UserlandFS::KernelEmu::get_vnode(volume->GetID(), vnodeID,
&foundNode);
if (error != B_OK)
return error;
if (privateNode != NULL)
*privateNode = ((HaikuKernelNode*)foundNode)->private_node;
return B_OK;
}
status_t
put_vnode(fs_volume *_volume, ino_t vnodeID)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
return UserlandFS::KernelEmu::put_vnode(volume->GetID(), vnodeID);
}
status_t
acquire_vnode(fs_volume *_volume, ino_t vnodeID)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
return UserlandFS::KernelEmu::acquire_vnode(volume->GetID(), vnodeID);
}
status_t
remove_vnode(fs_volume *_volume, ino_t vnodeID)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
return UserlandFS::KernelEmu::remove_vnode(volume->GetID(), vnodeID);
}
status_t
unremove_vnode(fs_volume *_volume, ino_t vnodeID)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
return UserlandFS::KernelEmu::unremove_vnode(volume->GetID(), vnodeID);
}
status_t
get_vnode_removed(fs_volume *_volume, ino_t vnodeID, bool* removed)
{
HaikuKernelVolume* volume = HaikuKernelVolume::GetVolume(_volume);
return UserlandFS::KernelEmu::get_vnode_removed(volume->GetID(), vnodeID,
removed);
}
fs_volume*
volume_for_vnode(fs_vnode *vnode)
{
return HaikuKernelNode::GetNode(vnode)->GetVolume()->GetFSVolume();
}
status_t
read_file_io_vec_pages(int fd, const struct file_io_vec *fileVecs,
size_t fileVecCount, const struct iovec *vecs, size_t vecCount,
uint32 *_vecIndex, size_t *_vecOffset, size_t *_bytes)
{
return B_UNSUPPORTED;
}
status_t
write_file_io_vec_pages(int fd, const struct file_io_vec *fileVecs,
size_t fileVecCount, const struct iovec *vecs, size_t vecCount,
uint32 *_vecIndex, size_t *_vecOffset, size_t *_bytes)
{
return B_UNSUPPORTED;
}
status_t
do_fd_io(int fd, io_request *request)
{
return B_UNSUPPORTED;
}
status_t
do_iterative_fd_io(int fd, io_request *_request, iterative_io_get_vecs getVecs,
iterative_io_finished finished, void *_cookie)
{
HaikuKernelIORequest* request = (HaikuKernelIORequest*)_request;
file_io_vec fileVecs[DoIterativeFDIORequest::MAX_VECS];
size_t fileVecCount = DoIterativeFDIORequest::MAX_VECS;
status_t error = getVecs(_cookie, _request, request->offset,
request->length, fileVecs, &fileVecCount);
if (error != B_OK && error != B_BUFFER_OVERFLOW)
return error;
HaikuKernelIterativeFDIOCookie* cookie
= new(std::nothrow) HaikuKernelIterativeFDIOCookie(fd, request, getVecs,
finished, _cookie);
if (cookie == NULL) {
finished(_cookie, _request, B_NO_MEMORY, false, 0);
return B_NO_MEMORY;
}
error = UserlandFS::KernelEmu::do_iterative_fd_io(
request->volume->GetID(), fd, request->id, cookie, fileVecs,
fileVecCount);
if (error != B_OK) {
delete cookie;
return error;
}
return B_OK;
}
bool
io_request_is_write(const io_request* request)
{
return ((HaikuKernelIORequest*)request)->isWrite;
}
bool
io_request_is_vip(const io_request* request)
{
return ((HaikuKernelIORequest*)request)->isVIP;
}
off_t
io_request_offset(const io_request* request)
{
return ((HaikuKernelIORequest*)request)->offset;
}
off_t
io_request_length(const io_request* request)
{
return ((HaikuKernelIORequest*)request)->length;
}
status_t
read_from_io_request(io_request* _request, void* buffer, size_t size)
{
if (size == 0)
return B_OK;
HaikuKernelIORequest* request = (HaikuKernelIORequest*)_request;
return UserlandFS::KernelEmu::read_from_io_request(request->volume->GetID(),
request->id, buffer, size);
}
status_t
write_to_io_request(io_request* _request, const void* buffer, size_t size)
{
HaikuKernelIORequest* request = (HaikuKernelIORequest*)_request;
return UserlandFS::KernelEmu::write_to_io_request(request->volume->GetID(),
request->id, buffer, size);
}
void
notify_io_request(io_request* _request, status_t status)
{
HaikuKernelIORequest* request = (HaikuKernelIORequest*)_request;
UserlandFS::KernelEmu::notify_io_request(request->volume->GetID(),
request->id, status);
}
status_t
add_node_listener(dev_t device, ino_t node, uint32 flags,
NotificationListener& listener)
{
return UserlandFS::KernelEmu::add_node_listener(device, node, flags,
&listener);
}
status_t
remove_node_listener(dev_t device, ino_t node, NotificationListener& listener)
{
return UserlandFS::KernelEmu::remove_node_listener(device, node, &listener);
}
status_t
get_default_partition_content_name(partition_id partitionID,
const char* fileSystemName, char* buffer, size_t bufferSize)
{
snprintf(buffer, bufferSize, "%s Volume", fileSystemName);
return B_OK;
}
status_t
scan_partition(partition_id partitionID)
{
return B_OK;
}
bool
update_disk_device_job_progress(disk_job_id jobID, float progress)
{
return true;
}
status_t
vfs_get_file_map(struct vnode *vnode, off_t offset, size_t size,
struct file_io_vec *vecs, size_t *_count)
{
HaikuKernelNode* node = (HaikuKernelNode*)vnode;
return node->volume->GetFileMap(node, offset, size, vecs, _count);
}
status_t
vfs_lookup_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode)
{
HaikuKernelVolume* volume = dynamic_cast<HaikuKernelVolume*>(
FileSystem::GetInstance()->VolumeWithID(mountID));
if (volume == NULL)
return B_BAD_VALUE;
HaikuKernelNode* node = volume->NodeWithID(vnodeID);
if (node == NULL)
return B_BAD_VALUE;
*_vnode = (struct vnode*)node;
return B_OK;
}