* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef USERLAND_FS_FUSE_VOLUME_H
#define USERLAND_FS_FUSE_VOLUME_H
#include <AutoLocker.h>
#include <RWLockManager.h>
#include "Locker.h"
#include "fuse_fs.h"
#include "FUSEEntry.h"
#include "FUSEFileSystem.h"
#include "../Volume.h"
namespace UserlandFS {
class FUSEFileSystem;
class FUSEVolume : public Volume {
public:
FUSEVolume(FUSEFileSystem* fileSystem,
dev_t id);
virtual ~FUSEVolume();
status_t Init();
void SetFS(fuse_fs* fs) { fFS = fs; }
virtual status_t Mount(const char* device, uint32 flags,
const char* parameters, ino_t* rootID);
virtual status_t Unmount();
virtual status_t Sync();
virtual status_t ReadFSInfo(fs_info* info);
virtual status_t Lookup(void* dir, const char* entryName,
ino_t* vnid);
virtual status_t GetVNodeName(void* node, char* buffer,
size_t bufferSize);
virtual status_t ReadVNode(ino_t vnid, bool reenter,
void** node, int* type, uint32* flags,
FSVNodeCapabilities* _capabilities);
virtual status_t WriteVNode(void* node, bool reenter);
virtual status_t RemoveVNode(void* node, bool reenter);
virtual status_t DoIO(void* node, void* cookie,
const IORequestInfo& requestInfo);
virtual status_t SetFlags(void* node, void* cookie,
int flags);
virtual status_t FSync(void* node);
virtual status_t ReadSymlink(void* node, char* buffer,
size_t bufferSize, size_t* bytesRead);
virtual status_t CreateSymlink(void* dir, const char* name,
const char* target, int mode);
virtual status_t Link(void* dir, const char* name,
void* node);
virtual status_t Unlink(void* dir, const char* name);
virtual status_t Rename(void* oldDir, const char* oldName,
void* newDir, const char* newName);
virtual status_t Access(void* node, int mode);
virtual status_t ReadStat(void* node, struct stat* st);
virtual status_t WriteStat(void* node, const struct stat* st,
uint32 mask);
virtual status_t Create(void* dir, const char* name,
int openMode, int mode, void** cookie,
ino_t* vnid);
virtual status_t Open(void* node, int openMode,
void** cookie);
virtual status_t Close(void* node, void* cookie);
virtual status_t FreeCookie(void* node, void* cookie);
virtual status_t Read(void* node, void* cookie, off_t pos,
void* buffer, size_t bufferSize,
size_t* bytesRead);
virtual status_t Write(void* node, void* cookie,
off_t pos, const void* buffer,
size_t bufferSize, size_t* bytesWritten);
virtual status_t CreateDir(void* dir, const char* name,
int mode);
virtual status_t RemoveDir(void* dir, const char* name);
virtual status_t OpenDir(void* node, void** cookie);
virtual status_t CloseDir(void* node, void* cookie);
virtual status_t FreeDirCookie(void* node, void* cookie);
virtual status_t ReadDir(void* node, void* cookie,
void* buffer, size_t bufferSize,
uint32 count, uint32* countRead);
virtual status_t RewindDir(void* node, void* cookie);
virtual status_t OpenAttrDir(void* node, void** cookie);
virtual status_t CloseAttrDir(void* node, void* cookie);
virtual status_t FreeAttrDirCookie(void* node,
void* cookie);
virtual status_t ReadAttrDir(void* node, void* cookie,
void* buffer, size_t bufferSize,
uint32 count, uint32* countRead);
virtual status_t RewindAttrDir(void* node, void* cookie);
virtual status_t OpenAttr(void* node, const char* name,
int openMode, void** cookie);
virtual status_t CloseAttr(void* node, void* cookie);
virtual status_t FreeAttrCookie(void* node, void* cookie);
virtual status_t ReadAttr(void* node, void* cookie,
off_t pos, void* buffer, size_t bufferSize,
size_t* bytesRead);
virtual status_t ReadAttrStat(void* node, void* cookie,
struct stat* st);
private:
struct DirEntryCache;
struct DirCookie;
struct FileCookie;
struct AttrDirCookie;
struct AttrCookie;
struct ReadDirBuffer;
struct LockIterator;
struct RWLockableReadLocking;
struct RWLockableWriteLocking;
struct RWLockableReadLocker;
struct RWLockableWriteLocker;
struct NodeLocker;
struct NodeReadLocker;
struct NodeWriteLocker;
struct MultiNodeLocker;
friend struct LockIterator;
friend struct RWLockableReadLocking;
friend struct RWLockableWriteLocking;
friend struct NodeLocker;
friend struct MultiNodeLocker;
private:
inline FUSEFileSystem* _FileSystem() const
{ return static_cast<FUSEFileSystem*>(fFileSystem); }
ino_t _GenerateNodeID();
bool _GetNodeID(FUSENode* dir, const char* entryName,
ino_t* _nodeID);
status_t _GetNode(FUSENode* dir, const char* entryName,
FUSENode** _node);
status_t _InternalGetNode(FUSENode* dir,
const char* entryName, FUSENode** _node,
AutoLocker<Locker>& locker);
void _PutNode(FUSENode* node);
void _PutNodes(FUSENode* const* nodes, int32 count);
void _RemoveEntry(FUSEEntry* entry);
status_t _RemoveEntry(FUSENode* dir, const char* name);
status_t _RenameEntry(FUSENode* oldDir,
const char* oldName, FUSENode* newDir,
const char* newName);
status_t _LockNodeChain(FUSENode* node, bool lockParent,
bool writeLock);
void _UnlockNodeChain(FUSENode* node, bool parent,
bool writeLock);
void _UnlockNodeChainInternal(FUSENode* node,
bool writeLock, FUSENode* stopNode,
FUSENode* stopBeforeNode);
status_t _LockNodeChains(FUSENode* node1,
bool lockParent1, bool writeLock1,
FUSENode* node2, bool lockParent2,
bool writeLock2);
status_t _LockNodeChainsInternal(FUSENode* node1,
bool lockParent1, bool writeLock1,
FUSENode* node2, bool lockParent2,
bool writeLock2, bool* _retry);
void _UnlockNodeChains(FUSENode* node1, bool parent1,
bool writeLock1, FUSENode* node2,
bool parent2, bool writeLock2);
bool _FindCommonAncestor(FUSENode* node1,
FUSENode* node2, FUSENode** _commonAncestor,
bool* _inverseLockingOrder);
bool _GetNodeAncestors(FUSENode* node,
FUSENode** ancestors, uint32* _count);
status_t _BuildPath(FUSENode* dir, const char* entryName,
char* path, size_t& pathLen);
status_t _BuildPath(FUSENode* node, char* path,
size_t& pathLen);
static int _AddReadDirEntryLowLevel(void* buffer, char* buf, size_t bufsize,
const char* name, const struct stat* st, off_t offset);
static int _AddReadDirEntry(void* buffer, const char* name,
const struct stat* st, off_t offset);
static int _AddReadDirEntryGetDir(fuse_dirh_t handle,
const char* name, int type, ino_t nodeID);
int _AddReadDirEntryLowLevel(ReadDirBuffer* buffer,
char* buf, size_t bufSize, const char* name, int type,
ino_t nodeID, off_t offset);
int _AddReadDirEntry(ReadDirBuffer* buffer,
const char* name, int type, ino_t nodeID,
off_t offset);
status_t _InternalIO(FUSENode* node, FileCookie* cookie, const char* path,
off_t pos, char* buffer, size_t& bytes, bool isWrite);
private:
RWLockManager fLockManager;
Locker fLock;
const fuse_lowlevel_ops* fOps;
fuse_fs* fFS;
FUSEEntryTable fEntries;
FUSENodeTable fNodes;
FUSENode* fRootNode;
ino_t fNextNodeID;
bool fUseNodeIDs;
char fName[B_OS_NAME_LENGTH];
};
}
using UserlandFS::FUSEVolume;
#endif