⛏️ index : haiku.git

/*
 * Copyright 2012 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Paweł Dziepak, pdziepak@quarnos.org
 */
#ifndef INODE_H
#define INODE_H


#include "DirectoryCache.h"
#include "MetadataCache.h"
#include "NFS4Inode.h"
#include "OpenState.h"


class Delegation;

class Inode : public NFS4Inode {
public:
	static			status_t	CreateInode(FileSystem* fs, const FileInfo& fi,
									Inode** inode);
	virtual						~Inode();

	inline			ino_t		ID() const;
	inline			mode_t		Type() const;
	virtual			const char*	Name() const;
	inline			FileSystem*	GetFileSystem() const;

	inline			void		SetOpenState(OpenState* state);

	inline			void*		FileCache();
					status_t	RevalidateFileCache();

	inline			uint64		MaxFileSize();

	inline			uint64		Change();
	inline			bool		Dirty();

	inline			OpenState*	GetOpenState();

	inline			Delegation*	GetDelegation() const;
					void		SetDelegation(Delegation* delegation);
					void		RecallDelegation(bool truncate = false);
					void		PrepareDelegationRecall(bool truncate = false);
					void		RecallDelegationAsync(bool truncate = false);
					void		RecallReadDelegation();
					void		UnlockAndRelockStateLocks();
					void		UnlockAndRelockWriteLock();

					status_t	LookUp(const char* name, ino_t* id);

					status_t	Access(int mode);

					status_t	Sync(bool force = false, bool wait = true);
					status_t	Commit(uid_t uid, gid_t gid);
					status_t	SyncAndCommit(bool force = false, OpenStateCookie* cookie = NULL);

					status_t	CreateObject(const char* name, const char* path,
									int mode, FileType type, ino_t* id);

					status_t	CreateLink(const char* name, const char* path,
									int mode, ino_t* id);

					status_t	Link(Inode* dir, const char* name);
					status_t	Remove(const char* name, FileType type,
									ino_t* id = NULL);
	static			status_t	Rename(Inode* from, Inode* to,
									const char* fromName, const char* toName,
									bool attribute = false, ino_t* id = NULL,
									ino_t* oldID = NULL);

					status_t	Stat(struct stat* st,
									OpenAttrCookie* attr = NULL, bool revalidate = false);
					status_t	WriteStat(const struct stat* st, uint32 mask,
									OpenAttrCookie* attr = NULL);

					status_t	Create(const char* name, int mode, int perms,
									OpenFileCookie* cookie,
									OpenDelegationData* data, ino_t* id);
					status_t	Open(int mode, OpenFileCookie* cookie);
					status_t	Close(OpenFileCookie* cookie);

					status_t	OpenAttr(const char* name,  int mode,
									OpenAttrCookie* cookie, bool create,
									int32 type = 0);
					status_t	CloseAttr(OpenAttrCookie* cookie);

					status_t	Read(OpenFileCookie* cookie, off_t pos,
									void* buffer, size_t* length);
					status_t	Write(OpenFileCookie* cookie, off_t pos,
									const void* buffer, size_t* _length);

					status_t	ReadDirect(OpenStateCookie* cookie, off_t pos,
									void* buffer, size_t* length, bool* eof);
					status_t	WriteDirect(OpenStateCookie* cookie, off_t pos,
									const void* buffer, size_t* _length);

					status_t	CreateDir(const char* name, int mode,
									ino_t* id);
					status_t	OpenDir(OpenDirCookie* cookie);
					status_t	ReadDir(void* buffer, uint32 size,
									uint32* count, OpenDirCookie* cookie);

					status_t	OpenAttrDir(OpenDirCookie* cookie);

					status_t	TestLock(OpenFileCookie* cookie,
									struct flock* lock);
					status_t	AcquireLock(OpenFileCookie* cookie,
									const struct flock* lock, bool wait);
					status_t	ReleaseLock(OpenFileCookie* cookie,
									const struct flock* lock);
					status_t	ReleaseAllLocks(OpenFileCookie* cookie);

					status_t	GetDirSnapshot(DirectoryCacheSnapshot**
									_snapshot, OpenDirCookie* cookie,
									uint64* _change, bool attribute);

					status_t	LoadAttrDirHandle();

	static inline	ino_t		FileIdToInoT(uint64 fileid);

					void		BeginAIOOp();
					void		EndAIOOp();
					bool		AIOIncomplete();
	inline			void		WaitAIOComplete();

	inline			void		SetStale(bool stale = true);
	inline			bool		IsStale() const;

					void		Dump(void (*xprintf)(const char*, ...) = dprintf);

protected:
								Inode();

					void		ReleaseOpenState();

					status_t	CreateState(const char* name, int mode,
									int perms, OpenState* state,
									OpenDelegationData* data);

					void		ReturnDelegation(bool truncate);

					status_t	ReadDirUp(struct dirent* de, uint32 pos,
									uint32 size);
					status_t	FillDirEntry(struct dirent* de, ino_t id,
									const char* name, uint32 pos, uint32 size);

					status_t	ChildAdded(const char* name, uint64 fileID,
									const FileHandle& fileHandle);

					status_t	GetStat(struct stat* st,
									OpenAttrCookie* attr = NULL);

					char*		AttrToFileName(const char* path);

	static inline	status_t	CheckLockType(short ltype, uint32 mode);

private:
					void		_DumpLocked(void (*xprintf)(const char*, ...), bool dumpDelegation,
									bool dumpAIO) const;
private:
					uint32		fType;

					MetadataCache	fMetaCache;
					DirectoryCache*	fCache;
					DirectoryCache*	fAttrCache;

					rw_lock		fDelegationLock;
					Delegation*	fDelegation;

					uint64		fChange;
					void*		fFileCache;
					mutex		fFileCacheLock;
					uint64		fMaxFileSize;

					OpenState*	fOpenState;
					mutex		fStateLock;

					rw_lock		fWriteLock;
					bool		fWriteDirty;

					sem_id		fAIOWait;
					uint32		fAIOCount;
					mutex		fAIOLock;
					uint32		fOpenStateReleasesPending;

					bool		fStale;
};


inline void
Inode::WaitAIOComplete()
{
	acquire_sem(fAIOWait);
	release_sem(fAIOWait);
}


inline ino_t
Inode::FileIdToInoT(uint64 fileid)
{
	if (sizeof(ino_t) >= sizeof(uint64))
		return fileid;
	else
		return (ino_t)fileid ^ (fileid >>
					(sizeof(uint64) - sizeof(ino_t)) * 8);
}


inline ino_t
Inode::ID() const
{
	return FileIdToInoT(fInfo.fFileId);
}


inline mode_t
Inode::Type() const
{
	return sNFSFileTypeToHaiku[fType];
}


inline FileSystem*
Inode::GetFileSystem() const
{
	ASSERT(fFileSystem != NULL);
	return fFileSystem;
}


inline void*
Inode::FileCache()
{
	return fFileCache;
}


inline void
Inode::SetOpenState(OpenState* state)
{
	ASSERT(state != NULL);
	fOpenState = state;
}


inline uint64
Inode::MaxFileSize()
{
	return fMaxFileSize;
}


inline uint64
Inode::Change()
{
	return fChange;
}


inline bool
Inode::Dirty()
{
	return fWriteDirty;
}


inline OpenState*
Inode::GetOpenState()
{
	return fOpenState;
}


inline Delegation*
Inode::GetDelegation() const
{
	return fDelegation;
}


inline void
Inode::SetStale(bool stale)
{
	fStale = stale;
}


inline bool
Inode::IsStale() const
{
	return fStale;
}


#endif	// INODE_H