From 78fc85a6ba25da91d4a0a591d53e0fad073f50d9 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Tue, 10 Jul 2012 20:57:52 +0200 Subject: [PATCH] nfs4: Cache file attributes and filesystem info --- .../kernel/file_systems/nfs4/FileSystem.h | 6 +- .../kernel/file_systems/nfs4/Inode.cpp | 113 +++++++++++++----- src/add-ons/kernel/file_systems/nfs4/Inode.h | 6 + .../kernel/file_systems/nfs4/InodeDir.cpp | 2 + .../kernel/file_systems/nfs4/InodeRegular.cpp | 4 + .../kernel/file_systems/nfs4/RootInode.cpp | 53 ++++++-- .../kernel/file_systems/nfs4/RootInode.h | 24 +++- 7 files changed, 164 insertions(+), 44 deletions(-) diff --git a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h index 1099f2788e..3a30659329 100644 --- a/src/add-ons/kernel/file_systems/nfs4/FileSystem.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileSystem.h @@ -24,7 +24,7 @@ public: ~FileSystem(); status_t GetInode(ino_t id, Inode** inode); - inline Inode* Root(); + inline RootInode* Root(); status_t Migrate(const RPC::Server* serv); @@ -74,10 +74,10 @@ private: }; -inline Inode* +inline RootInode* FileSystem::Root() { - return reinterpret_cast(fRoot); + return fRoot; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 5650947543..181ef37ca6 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -20,7 +20,10 @@ Inode::Inode() + : + fAttrCacheExpire(0) { + mutex_init(&fAttrCacheLock, NULL); } @@ -96,6 +99,7 @@ Inode::CreateInode(FileSystem* fs, const FileInfo &fi, Inode** _inode) Inode::~Inode() { + mutex_destroy(&fAttrCacheLock); } @@ -288,7 +292,11 @@ Inode::Remove(const char* name, FileType type) return result; reply.PutFH(); - return reply.Remove(); + result = reply.Remove(); + + fFileSystem->Root()->MakeInfoInvalid(); + + return result; } while (true); } @@ -391,7 +399,11 @@ Inode::CreateLink(const char* name, const char* path, int mode) reply.PutFH(); - return reply.Create(); + result = reply.Create(); + + fFileSystem->Root()->MakeInfoInvalid(); + + return result; } while (true); } @@ -481,6 +493,36 @@ Inode::Access(int mode) status_t Inode::Stat(struct stat* st) { + status_t result = _UpdateAttrCache(); + if (result != B_OK) + return result; + + // Do not touch other members of struct stat + st->st_size = fAttrCache.st_size; + st->st_mode = fAttrCache.st_mode; + st->st_nlink = fAttrCache.st_nlink; + st->st_uid = fAttrCache.st_uid; + st->st_gid = fAttrCache.st_gid; + st->st_atim = fAttrCache.st_atim; + st->st_ctim = fAttrCache.st_ctim; + st->st_crtim = fAttrCache.st_crtim; + st->st_mtim = fAttrCache.st_mtim; + + return B_OK; +} + + +status_t +Inode::_UpdateAttrCache(bool force) +{ + if (!force && fAttrCacheExpire > time(NULL)) + return B_OK; + + MutexLocker _(fAttrCacheLock); + + if (fAttrCacheExpire > time(NULL)) + return B_OK; + do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); @@ -516,12 +558,12 @@ Inode::Stat(struct stat* st) delete[] values; return B_BAD_VALUE; } - st->st_size = values[0].fData.fValue64; + fAttrCache.st_size = values[0].fData.fValue64; uint32 next = 1; - st->st_mode = Type(); + fAttrCache.st_mode = Type(); if (count >= next && values[next].fAttribute == FATTR4_MODE) { - st->st_mode |= values[next].fData.fValue32; + fAttrCache.st_mode |= values[next].fData.fValue32; next++; } else { // Try to guess using ACCESS request @@ -538,70 +580,76 @@ Inode::Stat(struct stat* st) return result; if ((prvl & ACCESS4_READ) != 0) - st->st_mode |= S_IRUSR | S_IRGRP | S_IROTH; + fAttrCache.st_mode |= S_IRUSR | S_IRGRP | S_IROTH; if ((prvl & ACCESS4_MODIFY) != 0) - st->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + fAttrCache.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; if (fType == NF4DIR && (prvl & ACCESS4_LOOKUP) != 0) - st->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + fAttrCache.st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; if (fType != NF4DIR && (prvl & ACCESS4_EXECUTE) != 0) - st->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + fAttrCache.st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; } if (count >= next && values[next].fAttribute == FATTR4_NUMLINKS) { - st->st_nlink = values[next].fData.fValue32; + fAttrCache.st_nlink = values[next].fData.fValue32; next++; } else - st->st_nlink = 1; + fAttrCache.st_nlink = 1; if (count >= next && values[next].fAttribute == FATTR4_OWNER) { char* owner = reinterpret_cast(values[next].fData.fPointer); if (owner != NULL && isdigit(owner[0])) - st->st_uid = atoi(owner); + fAttrCache.st_uid = atoi(owner); else - st->st_uid = gIdMapper->GetUserId(owner); + fAttrCache.st_uid = gIdMapper->GetUserId(owner); next++; } else - st->st_uid = 0; + fAttrCache.st_uid = 0; if (count >= next && values[next].fAttribute == FATTR4_OWNER_GROUP) { char* group = reinterpret_cast(values[next].fData.fPointer); if (group != NULL && isdigit(group[0])) - st->st_gid = atoi(group); + fAttrCache.st_gid = atoi(group); else - st->st_gid = gIdMapper->GetGroupId(group); + fAttrCache.st_gid = gIdMapper->GetGroupId(group); next++; } else - st->st_gid = 0; + fAttrCache.st_gid = 0; if (count >= next && values[next].fAttribute == FATTR4_TIME_ACCESS) { - memcpy(&st->st_atim, values[next].fData.fPointer, sizeof(timespec)); - next++; - } else - memset(&st->st_atim, 0, sizeof(timespec)); - - if (count >= next && values[next].fAttribute == FATTR4_TIME_CREATE) { - memcpy(&st->st_crtim, values[next].fData.fPointer, + memcpy(&fAttrCache.st_atim, values[next].fData.fPointer, sizeof(timespec)); next++; } else - memset(&st->st_crtim, 0, sizeof(timespec)); + memset(&fAttrCache.st_atim, 0, sizeof(timespec)); + + if (count >= next && values[next].fAttribute == FATTR4_TIME_CREATE) { + memcpy(&fAttrCache.st_crtim, values[next].fData.fPointer, + sizeof(timespec)); + next++; + } else + memset(&fAttrCache.st_crtim, 0, sizeof(timespec)); if (count >= next && values[next].fAttribute == FATTR4_TIME_METADATA) { - memcpy(&st->st_ctim, values[next].fData.fPointer, sizeof(timespec)); + memcpy(&fAttrCache.st_ctim, values[next].fData.fPointer, + sizeof(timespec)); next++; } else - memset(&st->st_ctim, 0, sizeof(timespec)); + memset(&fAttrCache.st_ctim, 0, sizeof(timespec)); if (count >= next && values[next].fAttribute == FATTR4_TIME_MODIFY) { - memcpy(&st->st_mtim, values[next].fData.fPointer, sizeof(timespec)); + memcpy(&fAttrCache.st_mtim, values[next].fData.fPointer, + sizeof(timespec)); next++; } else - memset(&st->st_mtim, 0, sizeof(timespec)); + memset(&fAttrCache.st_mtim, 0, sizeof(timespec)); delete[] values; + + fAttrCacheExpire = time(NULL) + kAttrCacheExpirationTime; + return B_OK; } while (true); } @@ -701,9 +749,14 @@ Inode::WriteStat(const struct stat* st, uint32 mask) delete cookie; } - return result; + if (result != B_OK) + return result; + + break; } while (true); + _UpdateAttrCache(true); + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 91751bb91e..9ca2466879 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -89,6 +89,12 @@ protected: static inline ino_t _FileIdToInoT(uint64 fileid); + struct stat fAttrCache; + mutex fAttrCacheLock; + time_t fAttrCacheExpire; + static const time_t kAttrCacheExpirationTime = 60; + status_t _UpdateAttrCache(bool force = false); + uint32 fType; FileInfo fInfo; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index 5f3c25c77b..47d6f8766b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -109,6 +109,8 @@ Inode::OpenDir(OpenDirCookie* cookie) cookie->fCookie = 0; cookie->fCookieVerf = 2; + fFileSystem->Root()->MakeInfoInvalid(); + return B_OK; } while (true); } diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 9ecb03a239..9c7c83d491 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -15,6 +15,7 @@ #include "IdMap.h" #include "Request.h" +#include "RootInode.h" status_t @@ -172,6 +173,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, } while (true); fFileSystem->AddOpenFile(cookie); + fFileSystem->Root()->MakeInfoInvalid(); if (confirm) return _ConfirmOpen(fh, cookie); @@ -430,6 +432,8 @@ Inode::Write(OpenFileCookie* cookie, off_t pos, const void* _buffer, *_length = size; + fFileSystem->Root()->MakeInfoInvalid(); + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp index d5830cea7d..82a0340400 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RootInode.cpp @@ -14,9 +14,44 @@ #include "Request.h" +RootInode::RootInode() + : + fInfoCacheExpire(0) +{ + mutex_init(&fInfoCacheLock, NULL); +} + + +RootInode::~RootInode() +{ + mutex_destroy(&fInfoCacheLock); +} + + status_t RootInode::ReadInfo(struct fs_info* info) { + status_t result = _UpdateInfo(); + if (result != B_OK) + return result; + + memcpy(info, &fInfoCache, sizeof(struct fs_info)); + + return B_OK; +} + + +status_t +RootInode::_UpdateInfo(bool force) +{ + if (!force && fInfoCacheExpire > time(NULL)) + return B_OK; + + MutexLocker _(fInfoCacheLock); + + if (fInfoCacheExpire > time(NULL)) + return B_OK; + do { RPC::Server* serv = fFileSystem->Server(); Request request(serv); @@ -46,12 +81,12 @@ RootInode::ReadInfo(struct fs_info* info) return result; if (count >= next && values[next].fAttribute == FATTR4_FILES_FREE) { - info->free_nodes = values[next].fData.fValue64; + fInfoCache.free_nodes = values[next].fData.fValue64; next++; } if (count >= next && values[next].fAttribute == FATTR4_FILES_TOTAL) { - info->total_nodes = values[next].fData.fValue64; + fInfoCache.total_nodes = values[next].fData.fValue64; next++; } @@ -68,16 +103,16 @@ RootInode::ReadInfo(struct fs_info* info) if (io_size == LONGLONG_MAX) io_size = 32768; - info->io_size = io_size; - info->block_size = io_size; + fInfoCache.io_size = io_size; + fInfoCache.block_size = io_size; if (count >= next && values[next].fAttribute == FATTR4_SPACE_FREE) { - info->free_blocks = values[next].fData.fValue64 / io_size; + fInfoCache.free_blocks = values[next].fData.fValue64 / io_size; next++; } if (count >= next && values[next].fAttribute == FATTR4_SPACE_TOTAL) { - info->total_blocks = values[next].fData.fValue64 / io_size; + fInfoCache.total_blocks = values[next].fData.fValue64 / io_size; next++; } @@ -86,8 +121,10 @@ RootInode::ReadInfo(struct fs_info* info) break; } while (true); - info->flags = 0; - strncpy(info->volume_name, fInfo.fName, B_FILE_NAME_LENGTH); + fInfoCache.flags = 0; + strncpy(fInfoCache.volume_name, fInfo.fName, B_FILE_NAME_LENGTH); + + fInfoCacheExpire = time(NULL) + kAttrCacheExpirationTime; return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/RootInode.h b/src/add-ons/kernel/file_systems/nfs4/RootInode.h index c2101875e8..5b01b89ff5 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RootInode.h +++ b/src/add-ons/kernel/file_systems/nfs4/RootInode.h @@ -16,13 +16,31 @@ class RootInode : public Inode { public: - status_t ReadInfo(struct fs_info* info); + RootInode(); + ~RootInode(); - bool ProbeMigration(); - status_t GetLocations(AttrValue** attr); + status_t ReadInfo(struct fs_info* info); + inline void MakeInfoInvalid(); + + bool ProbeMigration(); + status_t GetLocations(AttrValue** attr); + +private: + struct fs_info fInfoCache; + mutex fInfoCacheLock; + time_t fInfoCacheExpire; + + status_t _UpdateInfo(bool force = false); }; +inline void +RootInode::MakeInfoInvalid() +{ + fInfoCacheExpire = 0; +} + + #endif // ROOTINODE_H