root/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h
/*
 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */
#ifndef USERLAND_FS_VOLUME_H
#define USERLAND_FS_VOLUME_H

#include <fs_interface.h>

#include <Referenceable.h>

#include <kernel/lock.h>

#include "FSCapabilities.h"

namespace UserlandFSUtil {

class Request;
class RequestAllocator;
class RequestHandler;
class RequestPort;
struct userlandfs_ioctl;

}

using UserlandFSUtil::FSVolumeCapabilities;
using UserlandFSUtil::Request;
using UserlandFSUtil::RequestAllocator;
using UserlandFSUtil::RequestHandler;
using UserlandFSUtil::RequestPort;
using UserlandFSUtil::userlandfs_ioctl;

class FileSystem;

class Volume : public BReferenceable {
public:
                                                                Volume(FileSystem* fileSystem,
                                                                        fs_volume* fsVolume);
                                                                ~Volume();

        inline  FileSystem*                     GetFileSystem() const;
        inline  dev_t                           GetID() const;

        inline  fs_volume_ops*          GetVolumeOps()          { return &fVolumeOps; }
        inline  bool                            HasCapability(int capability) const;

        inline  void*                           GetUserlandVolume() const;
        inline  ino_t                           GetRootID() const;

                        // client methods
                        status_t                        GetVNode(ino_t vnid, void** node);
                        status_t                        PutVNode(ino_t vnid);
                        status_t                        AcquireVNode(ino_t vnid);
                        status_t                        NewVNode(ino_t vnid, void* node,
                                                                        const FSVNodeCapabilities& capabilities);
                        status_t                        PublishVNode(ino_t vnid, void* node,
                                                                        int type, uint32 flags,
                                                                        const FSVNodeCapabilities& capabilities);
                        status_t                        RemoveVNode(ino_t vnid);
                        status_t                        UnremoveVNode(ino_t vnid);
                        status_t                        GetVNodeRemoved(ino_t vnid, bool* removed);

                        status_t                        CreateFileCache(ino_t vnodeID, off_t size);
                        status_t                        DeleteFileCache(ino_t vnodeID);
                        status_t                        SetFileCacheEnabled(ino_t vnodeID,
                                                                        bool enabled);
                        status_t                        SetFileCacheSize(ino_t vnodeID, off_t size);
                        status_t                        SyncFileCache(ino_t vnodeID);
                        status_t                        ReadFileCache(ino_t vnodeID, void* cookie,
                                                                        off_t offset, void* buffer, size_t* _size);
                        status_t                        WriteFileCache(ino_t vnodeID, void* cookie,
                                                                        off_t offset, const void* buffer,
                                                                        size_t* _size);

                        status_t                        DoIterativeFDIO(int fd, int32 requestID,
                                                                        void* cookie, const file_io_vec* vecs,
                                                                        uint32 vecCount);
                        status_t                        ReadFromIORequest(int32 requestID, void* buffer,
                                                                        size_t size);
                        status_t                        WriteToIORequest(int32 requestID,
                                                                        const void* buffer, size_t size);
                        status_t                        NotifyIORequest(int32 requestID,
                                                                        status_t status);

                        // FS
                        status_t                        Mount(const char* device, uint32 flags,
                                                                        const char* parameters);
                        status_t                        Unmount();
                        status_t                        Sync();
                        status_t                        ReadFSInfo(fs_info* info);
                        status_t                        WriteFSInfo(const struct fs_info* info,
                                                                        uint32 mask);

                        // vnodes
                        status_t                        Lookup(void* dir, const char* entryName,
                                                                        ino_t* vnid);
                        status_t                        GetVNodeName(void* node, char* buffer,
                                                                        size_t bufferSize);
                        status_t                        ReadVNode(ino_t vnid, bool reenter,
                                                                        void** node, fs_vnode_ops** _ops, int* type,
                                                                        uint32* flags);
                        status_t                        WriteVNode(void* node, bool reenter);
                        status_t                        RemoveVNode(void* node, bool reenter);

                        // asynchronous I/O
                        status_t                        DoIO(void* node, void* cookie,
                                                                        io_request* ioRequest);
                        status_t                        CancelIO(void* node, void* cookie,
                                                                        io_request* ioRequest);

                        // nodes
                        status_t                        IOCtl(void* node, void* cookie,
                                                                        uint32 command, void *buffer, size_t size);
                        status_t                        SetFlags(void* node, void* cookie,
                                                                        int flags);
                        status_t                        Select(void* node, void* cookie, uint8 event,
                                                                        selectsync* sync);
                        status_t                        Deselect(void* node, void* cookie, uint8 event,
                                                                        selectsync* sync);

                        status_t                        FSync(void* node);

                        status_t                        ReadSymlink(void* node, char* buffer,
                                                                        size_t bufferSize, size_t* bytesRead);
                        status_t                        CreateSymlink(void* dir, const char* name,
                                                                        const char* target, int mode);

                        status_t                        Link(void* dir, const char* name,
                                                                        void* node);
                        status_t                        Unlink(void* dir, const char* name);
                        status_t                        Rename(void* oldDir, const char* oldName,
                                                                        void* newDir, const char* newName);

                        status_t                        Access(void* node, int mode);
                        status_t                        ReadStat(void* node, struct stat* st);
                        status_t                        WriteStat(void* node, const struct stat *st,
                                                                        uint32 mask);

                        // files
                        status_t                        Create(void* dir, const char* name,
                                                                        int openMode, int mode, void** cookie,
                                                                        ino_t* vnid);
                        status_t                        Open(void* node, int openMode,
                                                                        void** cookie);
                        status_t                        Close(void* node, void* cookie);
                        status_t                        FreeCookie(void* node, void* cookie);
                        status_t                        Read(void* node, void* cookie, off_t pos,
                                                                        void* buffer, size_t bufferSize,
                                                                        size_t* bytesRead);
                        status_t                        Write(void* node, void* cookie,
                                                                        off_t pos, const void* buffer,
                                                                        size_t bufferSize, size_t* bytesWritten);

                        // directories
                        status_t                        CreateDir(void* dir, const char* name,
                                                                        int mode);
                        status_t                        RemoveDir(void* dir, const char* name);
                        status_t                        OpenDir(void* node, void** cookie);
                        status_t                        CloseDir(void* node, void* cookie);
                        status_t                        FreeDirCookie(void* node, void* cookie);
                        status_t                        ReadDir(void* node, void* cookie,
                                                                        void* buffer, size_t bufferSize,
                                                                        uint32 count, uint32* countRead);
                        status_t                        RewindDir(void* node, void* cookie);

                        // attribute directories
                        status_t                        OpenAttrDir(void* node, void** cookie);
                        status_t                        CloseAttrDir(void* node, void* cookie);
                        status_t                        FreeAttrDirCookie(void* node,
                                                                        void* cookie);
                        status_t                        ReadAttrDir(void* node, void* cookie,
                                                                        void* buffer, size_t bufferSize,
                                                                        uint32 count, uint32* countRead);
                        status_t                        RewindAttrDir(void* node, void* cookie);

                        // attributes
                        status_t                        CreateAttr(void* node, const char* name,
                                                                        uint32 type, int openMode,
                                                                        void** cookie);
                        status_t                        OpenAttr(void* node, const char* name,
                                                                        int openMode, void** cookie);
                        status_t                        CloseAttr(void* node, void* cookie);
                        status_t                        FreeAttrCookie(void* node, void* cookie);
                        status_t                        ReadAttr(void* node, void* cookie,
                                                                        off_t pos, void* buffer, size_t bufferSize,
                                                                        size_t* bytesRead);
                        status_t                        WriteAttr(void* node, void* cookie,
                                                                        off_t pos, const void* buffer,
                                                                        size_t bufferSize, size_t* bytesWritten);
                        status_t                        ReadAttrStat(void* node, void* cookie,
                                                                        struct stat *st);
                        status_t                        WriteAttrStat(void* node, void* cookie,
                                                                        const struct stat *st, int statMask);
                        status_t                        RenameAttr(void* oldNode,
                                                                        const char* oldName, void* newNode,
                                                                        const char* newName);
                        status_t                        RemoveAttr(void* node, const char* name);

                        // indices
                        status_t                        OpenIndexDir(void** cookie);
                        status_t                        CloseIndexDir(void* cookie);
                        status_t                        FreeIndexDirCookie(void* cookie);
                        status_t                        ReadIndexDir(void* cookie, void* buffer,
                                                                        size_t bufferSize, uint32 count,
                                                                        uint32* countRead);
                        status_t                        RewindIndexDir(void* cookie);
                        status_t                        CreateIndex(const char* name, uint32 type,
                                                                        uint32 flags);
                        status_t                        RemoveIndex(const char* name);
                        status_t                        ReadIndexStat(const char *name,
                                                                        struct stat *st);

                        // queries
                        status_t                        OpenQuery(const char* queryString,
                                                                        uint32 flags, port_id port, uint32 token,
                                                                        void** cookie);
                        status_t                        CloseQuery(void* cookie);
                        status_t                        FreeQueryCookie(void* cookie);
                        status_t                        ReadQuery(void* cookie, void* buffer,
                                                                        size_t bufferSize, uint32 count,
                                                                        uint32* countRead);
                        status_t                        RewindQuery(void* cookie);

private:
                        struct VNode;
                        struct VNodeHashDefinition;
                        struct VNodeMap;
                        struct IORequestInfo;
                        struct IORequestIDHashDefinition;
                        struct IORequestStructHashDefinition;
                        struct IORequestIDMap;
                        struct IORequestStructMap;
                        struct IterativeFDIOCookie;

                        class AutoIncrementer;
                        class IORequestRemover;
                        friend class IORequestRemover;
                        class VNodeRemover;
                        friend class VNodeRemover;

private:
                        void                            _InitVolumeOps();

                        status_t                        _Mount(const char* device, uint32 flags,
                                                                        const char* parameters);
                        status_t                        _Unmount();
                        status_t                        _ReadFSInfo(fs_info* info);
                        status_t                        _Lookup(void* dir, const char* entryName,
                                                                        ino_t* vnid);
                        status_t                        _WriteVNode(void* node, bool reenter);
                        status_t                        _ReadStat(void* node, struct stat* st);
                        status_t                        _Close(void* node, void* cookie);
                        status_t                        _FreeCookie(void* node, void* cookie);
                        status_t                        _CloseDir(void* node, void* cookie);
                        status_t                        _FreeDirCookie(void* node, void* cookie);
                        status_t                        _CloseAttrDir(void* node, void* cookie);
                        status_t                        _FreeAttrDirCookie(void* node,
                                                                        void* cookie);
                        status_t                        _CloseAttr(void* node, void* cookie);
                        status_t                        _FreeAttrCookie(void* node,
                                                                        void* cookie);
                        status_t                        _CloseIndexDir(void* cookie);
                        status_t                        _FreeIndexDirCookie(void* cookie);
                        status_t                        _CloseQuery(void* cookie);
                        status_t                        _FreeQueryCookie(void* cookie);

                        status_t                        _SendRequest(RequestPort* port,
                                                                        RequestAllocator* allocator,
                                                                        RequestHandler* handler, Request** reply);
                        status_t                        _SendReceiptAck(RequestPort* port);

                        void                            _IncrementVNodeCount(ino_t vnid);
                        void                            _DecrementVNodeCount(ino_t vnid);
                        void                            _RemoveInvalidVNode(ino_t vnid);

                        status_t                        _InternalIOCtl(userlandfs_ioctl* buffer,
                                                                        int32 bufferSize);

                        status_t                        _PutAllPendingVNodes();

                        status_t                        _RegisterIORequest(io_request* request,
                                                                        int32* requestID);
                        status_t                        _UnregisterIORequest(int32 requestID);
                        status_t                        _FindIORequest(io_request* request,
                                                                        int32* requestID);
                        status_t                        _FindIORequest(int32 requestID,
                                                                        io_request** request);

        static  status_t                        _IterativeFDIOGetVecs(void* cookie,
                                                                        io_request* request, off_t offset,
                                                                        size_t size, struct file_io_vec* vecs,
                                                                        size_t* _count);
        static  status_t                        _IterativeFDIOFinished(void* cookie,
                                                                        io_request* request, status_t status,
                                                                        bool partialTransfer,
                                                                        size_t bytesTransferred);

        inline  bool                            HasVNodeCapability(VNode* vnode,
                                                                        int capability) const;

private:
                        mutex                           fLock;
                        FileSystem*                     fFileSystem;
                        fs_volume*                      fFSVolume;
                        FSVolumeCapabilities fCapabilities;
                        fs_volume_ops           fVolumeOps;
                        void*                           fUserlandVolume;
                        ino_t                           fRootID;
                        VNode*                          fRootNode;
                        int32                           fOpenFiles;
                        int32                           fOpenDirectories;
                        int32                           fOpenAttributeDirectories;
                        int32                           fOpenAttributes;
                        int32                           fOpenIndexDirectories;
                        int32                           fOpenQueries;
                        VNodeMap*                       fVNodes;
                        IORequestIDMap*         fIORequestInfosByID;
                        IORequestStructMap*     fIORequestInfosByStruct;
                        int32                           fLastIORequestID;
        volatile bool                           fVNodeCountingEnabled;
};


// GetID
inline dev_t
Volume::GetID() const
{
        return fFSVolume->id;
}


// GetFileSystem
inline FileSystem*
Volume::GetFileSystem() const
{
        return fFileSystem;
}


// HasCapability
inline bool
Volume::HasCapability(int capability) const
{
        return fCapabilities.Get(capability);
}


// GetUserlandVolume
inline void*
Volume::GetUserlandVolume() const
{
        return fUserlandVolume;
}


// GetRootID
inline ino_t
Volume::GetRootID() const
{
        return fRootID;
}


#endif  // USERLAND_FS_VOLUME_H