root/src/add-ons/kernel/file_systems/nfs4/FileSystem.h
/*
 * Copyright 2012 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Paweł Dziepak, pdziepak@quarnos.org
 */
#ifndef FILESYSTEM_H
#define FILESYSTEM_H


#include <fs_interface.h>

#include "Debug.h"
#include "Delegation.h"
#include "InodeIdMap.h"
#include "NFS4Defs.h"
#include "NFS4Server.h"


class Inode;
class RootInode;

struct MountConfiguration {
        bool            fReadOnly;

        bool            fHard;
        int                     fRetryLimit;
        bigtime_t       fRequestTimeout;

        bool            fEmulateNamedAttrs;
        bool            fCacheMetadata;

        bigtime_t       fDirectoryCacheTime;
};

class FileSystem : public DoublyLinkedListLinkImpl<FileSystem> {
public:
        static  status_t                        Mount(FileSystem** pfs, RPC::Server* serv,
                                                                        const char* serverName, const char* path,
                                                                        fs_volume* volume,
                                                                        const MountConfiguration& configuration);
                                                                ~FileSystem();

                        status_t                        GetInode(ino_t id, Inode** inode);
        inline  RootInode*                      Root();

                        status_t                        Migrate(const RPC::Server* serv);

                        DoublyLinkedList<OpenState>&    OpenFilesLock();
                        void                            OpenFilesUnlock();
        inline  uint32                          OpenFilesCount();
                        void                            AddOpenFile(OpenState* state);
                        void                            RemoveOpenFile(OpenState* state);

                        DoublyLinkedList<Delegation>&   DelegationsLock();
                        void                            DelegationsUnlock();
                        void                            AddDelegation(Delegation* delegation);
                        void                            RemoveDelegation(Delegation* delegation);
                        Delegation*                     GetDelegation(const FileHandle& handle);

        inline  bool                            IsAttrSupported(Attribute attr) const;
        inline  uint32                          ExpireType() const;

        inline  RPC::Server*            Server();
        inline  NFS4Server*                     NFSServer();

        inline  const char**            Path() const;
        inline  const FileSystemId&     FsId() const;

        inline  uint64                          AllocFileId();

        inline  dev_t                           DevId() const;
        inline  InodeIdMap*                     InoIdMap();

        inline  uint64                          OpenOwner() const;
        inline  uint32                          OpenOwnerSequenceLock();
        inline  void                            OpenOwnerSequenceUnlock(uint32 sequence);

        inline  bool                            NamedAttrs();
        inline  void                            SetNamedAttrs(bool attrs);

        inline  const MountConfiguration&       GetConfiguration();

        inline  mutex&                          CreateFileLock();

                        status_t                        TrashStaleNode(Inode* inode);
                        status_t                        TrashIfStale(Inode* inode);
                        void                            EnsureNoCollision(ino_t newId, const FileHandle& handle);
                        void                            ServerUnlinkCleanup(ino_t id, Inode* parent,
                                                                        const char* missingName);

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

private:
                                                                FileSystem(const MountConfiguration& config);

        static  status_t                        _ParsePath(RequestBuilder& req, uint32& count,
                                                                        const char* _path);

                        void                            _DumpLocked(void (*xprintf)(const char*, ...),
                                                                        bool dumpDelegations, bool dumpOpenFiles) const;

                        mutex                           fCreateFileLock;

                        mutex                           fDelegationLock;
                        DoublyLinkedList<Delegation>    fDelegationList;
                        AVLTreeMap<FileHandle, Delegation*> fHandleToDelegation;

                        DoublyLinkedList<OpenState>             fOpenFiles;
                        uint32                          fOpenCount;
                        mutex                           fOpenLock;

                        uint64                          fOpenOwner;
                        uint32                          fOpenOwnerSequence;
                        mutex                           fOpenOwnerLock;

                        uint32                          fExpireType;
                        uint32                          fSupAttrs[2];
                        bool                            fNamedAttrs;

                        FileSystemId            fFsId;
                        const char**            fPath;

                        RootInode*                      fRoot;

                        RPC::Server*            fServer;

                        int64                           fId;
                        dev_t                           fDevId;

                        InodeIdMap                      fInoIdMap;

                        MountConfiguration      fConfiguration;

                        fs_volume*                      fFsVolume;
};


inline RootInode*
FileSystem::Root()
{
        return fRoot;
}


inline uint32
FileSystem::OpenFilesCount()
{
        return fOpenCount;
}


inline bool
FileSystem::IsAttrSupported(Attribute attr) const
{
        return sIsAttrSet(attr, fSupAttrs, 2);
}


inline uint32
FileSystem::ExpireType() const
{
        return fExpireType;
}


inline RPC::Server*
FileSystem::Server()
{
        ASSERT(fServer != NULL);
        return fServer;
}


inline NFS4Server*
FileSystem::NFSServer()
{
        ASSERT(fServer->PrivateData() != NULL);
        return reinterpret_cast<NFS4Server*>(fServer->PrivateData());
}


inline const char**
FileSystem::Path() const
{
        ASSERT(fPath != NULL);
        return fPath;
}


inline const FileSystemId&
FileSystem::FsId() const
{
        return fFsId;
}


inline uint64
FileSystem::AllocFileId()
{
        return atomic_add64(&fId, 1);
}


inline dev_t
FileSystem::DevId() const
{
        return fDevId;
}


inline InodeIdMap*
FileSystem::InoIdMap()
{
        return &fInoIdMap;
}


inline uint64
FileSystem::OpenOwner() const
{
        return fOpenOwner;
}


inline uint32
FileSystem::OpenOwnerSequenceLock()
{
        mutex_lock(&fOpenOwnerLock);
        return fOpenOwnerSequence;
}


inline void
FileSystem::OpenOwnerSequenceUnlock(uint32 sequence)
{
        fOpenOwnerSequence = sequence;
        mutex_unlock(&fOpenOwnerLock);
}


inline bool
FileSystem::NamedAttrs()
{
        return fNamedAttrs;
}


inline void
FileSystem::SetNamedAttrs(bool attrs)
{
        fNamedAttrs = attrs;
}


inline const MountConfiguration&
FileSystem::GetConfiguration()
{
        return fConfiguration;
}


inline mutex&
FileSystem::CreateFileLock()
{
        return fCreateFileLock;
}


#endif  // FILESYSTEM_H