From bab48e0ddc42c1e37f730916f54399804f5e7933 Mon Sep 17 00:00:00 2001 From: wanghai01 Date: Tue, 6 Sep 2022 19:02:01 +0800 Subject: [PATCH] curvefs/client: fix update nlink error Signed-off-by: wanghai01 --- curvefs/src/client/common/common.h | 5 ++ curvefs/src/client/fuse_client.cpp | 25 +++--- curvefs/src/client/fuse_client.h | 4 +- curvefs/src/client/inode_wrapper.cpp | 49 ++++++++++- curvefs/src/client/inode_wrapper.h | 73 +++------------- curvefs/src/metaserver/inode_manager.cpp | 7 -- curvefs/test/client/test_fuse_client.cpp | 107 +++++++++++++++++++---- 7 files changed, 169 insertions(+), 101 deletions(-) diff --git a/curvefs/src/client/common/common.h b/curvefs/src/client/common/common.h index 389c5710fe..536fb881dc 100644 --- a/curvefs/src/client/common/common.h +++ b/curvefs/src/client/common/common.h @@ -87,6 +87,11 @@ enum class FileHandle : uint64_t { kKeepCache = 1, }; +enum class NlinkChange : int32_t { + kAddOne = 1, + kSubOne = -1, +}; + } // namespace common } // namespace client } // namespace curvefs diff --git a/curvefs/src/client/fuse_client.cpp b/curvefs/src/client/fuse_client.cpp index 1ac116433e..b166ae8993 100644 --- a/curvefs/src/client/fuse_client.cpp +++ b/curvefs/src/client/fuse_client.cpp @@ -565,8 +565,8 @@ CURVEFS_ERROR FuseClient::FuseOpOpen(fuse_req_t req, fuse_ino_t ino, return ret; } -CURVEFS_ERROR FuseClient::UpdateParentInodeMCTimeAndInvalidNlink( - fuse_ino_t parent, FsFileType type) { +CURVEFS_ERROR FuseClient::UpdateParentMCTimeAndNlink( + fuse_ino_t parent, FsFileType type, NlinkChange nlink) { std::shared_ptr parentInodeWrapper; auto ret = inodeManager_->GetInode(parent, parentInodeWrapper); if (ret != CURVEFS_ERROR::OK) { @@ -580,9 +580,10 @@ CURVEFS_ERROR FuseClient::UpdateParentInodeMCTimeAndInvalidNlink( parentInodeWrapper->UpdateTimestampLocked(kModifyTime | kChangeTime); if (FsFileType::TYPE_DIRECTORY == type) { - parentInodeWrapper->InvalidateNlink(); + parentInodeWrapper->UpdateNlinkLocked(nlink); } } + inodeManager_->ShipToFlush(parentInodeWrapper); return CURVEFS_ERROR::OK; } @@ -647,9 +648,9 @@ CURVEFS_ERROR FuseClient::MakeNode(fuse_req_t req, fuse_ino_t parent, return ret; } - ret = UpdateParentInodeMCTimeAndInvalidNlink(parent, type); + ret = UpdateParentMCTimeAndNlink(parent, type, NlinkChange::kAddOne); if (ret != CURVEFS_ERROR::OK) { - LOG(ERROR) << "UpdateParentInodeMCTimeAndInvalidNlink failed" + LOG(ERROR) << "UpdateParentMCTimeAndNlink failed" << ", parent: " << parent << ", name: " << name << ", type: " << type; @@ -738,9 +739,9 @@ CURVEFS_ERROR FuseClient::RemoveNode(fuse_req_t req, fuse_ino_t parent, return ret; } - ret = UpdateParentInodeMCTimeAndInvalidNlink(parent, type); + ret = UpdateParentMCTimeAndNlink(parent, type, NlinkChange::kSubOne); if (ret != CURVEFS_ERROR::OK) { - LOG(ERROR) << "UpdateParentInodeMCTimeAndInvalidNlink failed" + LOG(ERROR) << "UpdateParentMCTimeAndNlink failed" << ", parent: " << parent << ", name: " << name << ", type: " << type; @@ -1249,10 +1250,10 @@ CURVEFS_ERROR FuseClient::FuseOpSymlink(fuse_req_t req, const char *link, return ret; } - ret = UpdateParentInodeMCTimeAndInvalidNlink( - parent, FsFileType::TYPE_SYM_LINK); + ret = UpdateParentMCTimeAndNlink(parent, FsFileType::TYPE_SYM_LINK, + NlinkChange::kAddOne); if (ret != CURVEFS_ERROR::OK) { - LOG(ERROR) << "UpdateParentInodeMCTimeAndInvalidNlink failed" + LOG(ERROR) << "UpdateParentMCTimeAndNlink failed" << ", link:" << link << ", parent: " << parent << ", name: " << name @@ -1321,9 +1322,9 @@ CURVEFS_ERROR FuseClient::FuseOpLink(fuse_req_t req, fuse_ino_t ino, return ret; } - ret = UpdateParentInodeMCTimeAndInvalidNlink(newparent, type); + ret = UpdateParentMCTimeAndNlink(newparent, type, NlinkChange::kAddOne); if (ret != CURVEFS_ERROR::OK) { - LOG(ERROR) << "UpdateParentInodeMCTimeAndInvalidNlink failed" + LOG(ERROR) << "UpdateParentMCTimeAndNlink failed" << ", parent: " << newparent << ", name: " << newname << ", type: " << type; diff --git a/curvefs/src/client/fuse_client.h b/curvefs/src/client/fuse_client.h index 6cb5f7e95a..28bb31295c 100644 --- a/curvefs/src/client/fuse_client.h +++ b/curvefs/src/client/fuse_client.h @@ -348,8 +348,8 @@ class FuseClient { virtual void FlushData() = 0; - CURVEFS_ERROR UpdateParentInodeMCTimeAndInvalidNlink( - fuse_ino_t parent, FsFileType type); + CURVEFS_ERROR UpdateParentMCTimeAndNlink( + fuse_ino_t parent, FsFileType type, NlinkChange nlink); void WarmUpTask(); diff --git a/curvefs/src/client/inode_wrapper.cpp b/curvefs/src/client/inode_wrapper.cpp index 7058289052..19041dbdf8 100644 --- a/curvefs/src/client/inode_wrapper.cpp +++ b/curvefs/src/client/inode_wrapper.cpp @@ -50,6 +50,14 @@ using rpcclient::DataIndices; bvar::Adder g_alive_inode_count{"alive_inode_count"}; +#define REFRESH_NLINK \ +do { \ + CURVEFS_ERROR ret = RefreshNlink(); \ + if (ret != CURVEFS_ERROR::OK) { \ + return ret; \ + } \ +} while (0) + std::ostream &operator<<(std::ostream &os, const struct stat &attr) { os << "{ st_ino = " << attr.st_ino << ", st_mode = " << attr.st_mode << ", st_nlink = " << attr.st_nlink << ", st_uid = " << attr.st_uid @@ -136,6 +144,42 @@ class GetOrModifyS3ChunkInfoAsyncDone : public MetaServerClientDone { std::shared_ptr inodeWrapper_; }; +CURVEFS_ERROR InodeWrapper::GetInodeAttrLocked(InodeAttr *attr) { + attr->set_inodeid(inode_.inodeid()); + attr->set_fsid(inode_.fsid()); + attr->set_length(inode_.length()); + attr->set_ctime(inode_.ctime()); + attr->set_ctime_ns(inode_.ctime_ns()); + attr->set_mtime(inode_.mtime()); + attr->set_mtime_ns(inode_.mtime_ns()); + attr->set_atime(inode_.atime()); + attr->set_atime_ns(inode_.atime_ns()); + attr->set_uid(inode_.uid()); + attr->set_gid(inode_.gid()); + attr->set_mode(inode_.mode()); + attr->set_nlink(inode_.nlink()); + attr->set_type(inode_.type()); + *(attr->mutable_parent()) = inode_.parent(); + if (inode_.has_symlink()) { + attr->set_symlink(inode_.symlink()); + } + if (inode_.has_rdev()) { + attr->set_rdev(inode_.rdev()); + } + if (inode_.has_dtime()) { + attr->set_dtime(inode_.dtime()); + } + if (inode_.xattr_size() > 0) { + *(attr->mutable_xattr()) = inode_.xattr(); + } + return CURVEFS_ERROR::OK; +} + +void InodeWrapper::GetInodeAttr(InodeAttr *attr) { + curve::common::UniqueLock lg(mtx_); + GetInodeAttrLocked(attr); +} + CURVEFS_ERROR InodeWrapper::SyncAttr(bool internal) { curve::common::UniqueLock lock = GetSyncingInodeUniqueLock(); if (dirty_) { @@ -263,7 +307,7 @@ CURVEFS_ERROR InodeWrapper::RefreshS3ChunkInfo() { CURVEFS_ERROR InodeWrapper::Link(uint64_t parent) { curve::common::UniqueLock lg(mtx_); - REFRESH_NLINK_IF_NEED; + REFRESH_NLINK; uint32_t old = inode_.nlink(); inode_.set_nlink(old + 1); dirtyAttr_.set_nlink(inode_.nlink()); @@ -294,7 +338,7 @@ CURVEFS_ERROR InodeWrapper::Link(uint64_t parent) { CURVEFS_ERROR InodeWrapper::UnLink(uint64_t parent) { curve::common::UniqueLock lg(mtx_); - REFRESH_NLINK_IF_NEED; + REFRESH_NLINK; uint32_t old = inode_.nlink(); VLOG(1) << "Unlink inode = " << inode_.DebugString(); if (old > 0) { @@ -567,7 +611,6 @@ CURVEFS_ERROR InodeWrapper::RefreshNlink() { } inode_.set_nlink(attr.nlink()); VLOG(3) << "RefreshNlink from metaserver, newnlink: " << attr.nlink(); - ResetNlinkValid(); return CURVEFS_ERROR::OK; } diff --git a/curvefs/src/client/inode_wrapper.h b/curvefs/src/client/inode_wrapper.h index 73eed92070..e832bdc101 100644 --- a/curvefs/src/client/inode_wrapper.h +++ b/curvefs/src/client/inode_wrapper.h @@ -52,16 +52,6 @@ constexpr int kAccessTime = 1 << 0; constexpr int kChangeTime = 1 << 1; constexpr int kModifyTime = 1 << 2; -#define REFRESH_NLINK_IF_NEED \ -do { \ - if (!isNlinkValid_) { \ - CURVEFS_ERROR ret = RefreshNlink(); \ - if (ret != CURVEFS_ERROR::OK) { \ - return ret; \ - } \ - } \ -} while (0) - using ::curvefs::metaserver::VolumeExtentList; enum class InodeStatus { @@ -76,6 +66,7 @@ using rpcclient::MetaServerClient; using rpcclient::MetaServerClientImpl; using rpcclient::MetaServerClientDone; using metric::S3ChunkInfoMetric; +using common::NlinkChange; std::ostream &operator<<(std::ostream &os, const struct stat &attr); void AppendS3ChunkInfoToMap(uint64_t chunkIndex, const S3ChunkInfo &info, @@ -96,7 +87,6 @@ class InodeWrapper : public std::enable_shared_from_this { maxDataSize_(maxDataSize), refreshDataInterval_(refreshDataInterval), lastRefreshTime_(::curve::common::TimeUtility::GetTimeofDaySec()), - isNlinkValid_(true), s3ChunkInfoAddSize_(0), metaClient_(std::move(metaClient)), s3ChunkInfoMetric_(std::move(s3ChunkInfoMetric)), @@ -196,43 +186,9 @@ class InodeWrapper : public std::enable_shared_from_this { void MergeXAttrLocked( const google::protobuf::Map& xattrs); - CURVEFS_ERROR GetInodeAttrLocked(InodeAttr *attr) { - REFRESH_NLINK_IF_NEED; - - attr->set_inodeid(inode_.inodeid()); - attr->set_fsid(inode_.fsid()); - attr->set_length(inode_.length()); - attr->set_ctime(inode_.ctime()); - attr->set_ctime_ns(inode_.ctime_ns()); - attr->set_mtime(inode_.mtime()); - attr->set_mtime_ns(inode_.mtime_ns()); - attr->set_atime(inode_.atime()); - attr->set_atime_ns(inode_.atime_ns()); - attr->set_uid(inode_.uid()); - attr->set_gid(inode_.gid()); - attr->set_mode(inode_.mode()); - attr->set_nlink(inode_.nlink()); - attr->set_type(inode_.type()); - *(attr->mutable_parent()) = inode_.parent(); - if (inode_.has_symlink()) { - attr->set_symlink(inode_.symlink()); - } - if (inode_.has_rdev()) { - attr->set_rdev(inode_.rdev()); - } - if (inode_.has_dtime()) { - attr->set_dtime(inode_.dtime()); - } - if (inode_.xattr_size() > 0) { - *(attr->mutable_xattr()) = inode_.xattr(); - } - return CURVEFS_ERROR::OK; - } + CURVEFS_ERROR GetInodeAttrLocked(InodeAttr *attr); - void GetInodeAttr(InodeAttr *attr) { - curve::common::UniqueLock lg(mtx_); - GetInodeAttrLocked(attr); - } + void GetInodeAttr(InodeAttr *attr); XAttr GetXattr() const { XAttr ret; @@ -254,19 +210,6 @@ class InodeWrapper : public std::enable_shared_from_this { CURVEFS_ERROR UnLink(uint64_t parent = 0); - // mark nlink invalid, need to refresh from metaserver - void InvalidateNlink() { - isNlinkValid_ = false; - } - - void ResetNlinkValid() { - isNlinkValid_ = true; - } - - bool IsNlinkValid() { - return isNlinkValid_; - } - CURVEFS_ERROR RefreshNlink(); CURVEFS_ERROR Sync(bool internal = false); @@ -312,6 +255,14 @@ class InodeWrapper : public std::enable_shared_from_this { return s3ChunkInfoAdd_.empty(); } + uint32_t GetNlinkLocked() { + return inode_.nlink(); + } + + void UpdateNlinkLocked(NlinkChange nlink) { + inode_.set_nlink(inode_.nlink() + static_cast(nlink)); + } + void AppendS3ChunkInfo(uint64_t chunkIndex, const S3ChunkInfo &info) { curve::common::UniqueLock lg(mtx_); AppendS3ChunkInfoToMap(chunkIndex, info, &s3ChunkInfoAdd_); @@ -438,8 +389,6 @@ class InodeWrapper : public std::enable_shared_from_this { uint32_t refreshDataInterval_; uint64_t lastRefreshTime_; - bool isNlinkValid_; - google::protobuf::Map s3ChunkInfoAdd_; int64_t s3ChunkInfoAddSize_; int64_t s3ChunkInfoSize_; diff --git a/curvefs/src/metaserver/inode_manager.cpp b/curvefs/src/metaserver/inode_manager.cpp index 3e4ea88a63..c13cadffb9 100644 --- a/curvefs/src/metaserver/inode_manager.cpp +++ b/curvefs/src/metaserver/inode_manager.cpp @@ -460,13 +460,6 @@ MetaStatusCode InodeManager::UpdateInodeWhenCreateOrRemoveSubNode( } } - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); - inode.set_ctime(now.tv_sec); - inode.set_ctime_ns(now.tv_nsec); - inode.set_mtime(now.tv_sec); - inode.set_mtime_ns(now.tv_nsec); - ret = inodeStorage_->Update(inode); if (ret != MetaStatusCode::OK) { LOG(ERROR) << "UpdateInode fail, " << inode.ShortDebugString() diff --git a/curvefs/test/client/test_fuse_client.cpp b/curvefs/test/client/test_fuse_client.cpp index 8ec4e9dd0f..3823dcccb4 100644 --- a/curvefs/test/client/test_fuse_client.cpp +++ b/curvefs/test/client/test_fuse_client.cpp @@ -461,8 +461,6 @@ TEST_F(TestFuseVolumeClient, FuseOpMkDir) { fuse_entry_param e; CURVEFS_ERROR ret = client_->FuseOpMkDir(req, parent, name, mode, &e); ASSERT_EQ(CURVEFS_ERROR::OK, ret); - - ASSERT_EQ(false, parentInodeWrapper->IsNlinkValid()); } TEST_F(TestFuseVolumeClient, FuseOpCreateFailed) { @@ -543,6 +541,12 @@ TEST_F(TestFuseVolumeClient, FuseOpUnlink) { inode.set_nlink(nlink); auto inodeWrapper = std::make_shared(inode, metaClient_); + InodeAttr attr; + attr.set_fsid(fsId); + attr.set_inodeid(inodeid); + attr.set_length(4096); + attr.set_nlink(nlink); + Inode parentInode; parentInode.set_fsid(fsId); parentInode.set_inodeid(parent); @@ -556,7 +560,8 @@ TEST_F(TestFuseVolumeClient, FuseOpUnlink) { Return(CURVEFS_ERROR::OK))) .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); - + EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(attr), Return(MetaStatusCode::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillOnce(Return(MetaStatusCode::OK)); @@ -595,8 +600,16 @@ TEST_F(TestFuseVolumeClient, FuseOpRmDir) { inode.set_inodeid(inodeid); inode.set_length(4096); inode.set_nlink(nlink); + inode.set_type(FsFileType::TYPE_DIRECTORY); auto inodeWrapper = std::make_shared(inode, metaClient_); + InodeAttr attr; + attr.set_fsid(fsId); + attr.set_inodeid(inodeid); + attr.set_length(4096); + attr.set_nlink(nlink); + attr.set_type(FsFileType::TYPE_DIRECTORY); + Inode parentInode; parentInode.set_fsid(fsId); parentInode.set_inodeid(parent); @@ -610,7 +623,8 @@ TEST_F(TestFuseVolumeClient, FuseOpRmDir) { Return(CURVEFS_ERROR::OK))) .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); - + EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(attr), Return(MetaStatusCode::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillOnce(Return(MetaStatusCode::OK)); @@ -620,8 +634,7 @@ TEST_F(TestFuseVolumeClient, FuseOpRmDir) { ASSERT_EQ(CURVEFS_ERROR::OK, ret); Inode inode2 = inodeWrapper->GetInode(); ASSERT_EQ(nlink - 1, inode2.nlink()); - - ASSERT_EQ(false, parentInodeWrapper->IsNlinkValid()); + ASSERT_EQ(2, parentInodeWrapper->GetNlinkLocked()); } TEST_F(TestFuseVolumeClient, FuseOpUnlinkFailed) { @@ -658,6 +671,12 @@ TEST_F(TestFuseVolumeClient, FuseOpUnlinkFailed) { inode.set_nlink(nlink); auto inodeWrapper = std::make_shared(inode, metaClient_); + InodeAttr attr; + attr.set_fsid(fsId); + attr.set_inodeid(inodeid); + attr.set_length(4096); + attr.set_nlink(nlink); + Inode parentInode; parentInode.set_fsid(fsId); parentInode.set_inodeid(parent); @@ -674,7 +693,8 @@ TEST_F(TestFuseVolumeClient, FuseOpUnlinkFailed) { Return(CURVEFS_ERROR::OK))) .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); - + EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(attr), Return(MetaStatusCode::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillOnce(Return(MetaStatusCode::UNKNOWN_ERROR)); @@ -855,11 +875,16 @@ TEST_F(TestFuseVolumeClient, FuseOpRenameBasic) { Inode destParentInode; destParentInode.set_inodeid(newparent); destParentInode.set_nlink(2); + InodeAttr dattr; + dattr.set_inodeid(newparent); + dattr.set_nlink(2); auto inodeWrapper = std::make_shared(destParentInode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(newparent, _)) .WillOnce(DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, newparent, _)) + .WillOnce(DoAll(SetArgPointee<2>(dattr), Return(MetaStatusCode::OK))); // include below unlink operate and update inode parent EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .Times(2) @@ -914,6 +939,11 @@ TEST_F(TestFuseVolumeClient, FuseOpRenameBasic) { Inode srcParentInode; srcParentInode.set_inodeid(parent); srcParentInode.set_nlink(3); + InodeAttr sattr; + sattr.set_inodeid(parent); + sattr.set_nlink(3); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, parent, _)) + .WillOnce(DoAll(SetArgPointee<2>(sattr), Return(MetaStatusCode::OK))); inodeWrapper = std::make_shared(srcParentInode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(parent, _)) .WillOnce(DoAll(SetArgReferee<1>(inodeWrapper), @@ -1050,11 +1080,16 @@ TEST_F(TestFuseVolumeClient, FuseOpRenameOverwrite) { Inode inode; inode.set_inodeid(oldInodeId); inode.set_nlink(1); + InodeAttr oldAttr; + oldAttr.set_inodeid(oldInodeId); + oldAttr.set_nlink(1); inodeWrapper = std::make_shared(inode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(oldInodeId, _)) .Times(1) .WillRepeatedly(DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, oldInodeId, _)) + .WillOnce(DoAll(SetArgPointee<2>(oldAttr), Return(MetaStatusCode::OK))); // step7: update inode parent Inode InodeInfo; @@ -1192,12 +1227,19 @@ TEST_F(TestFuseVolumeClient, FuseOpRenameParallel) { Inode srcParentInode; srcParentInode.set_inodeid(1); srcParentInode.set_nlink(times + 2); + InodeAttr srcAttr; + srcAttr.set_inodeid(1); + srcAttr.set_nlink(times + 2); auto srcParentInodeWrapper = std::make_shared(srcParentInode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(srcParentInode.inodeid(), _)) .Times(times * 2) .WillRepeatedly(DoAll(SetArgReferee<1>(srcParentInodeWrapper), Return(CURVEFS_ERROR::OK))); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, 1, _)) + .Times(times) + .WillRepeatedly(DoAll(SetArgPointee<2>(srcAttr), + Return(MetaStatusCode::OK))); // include below operator which unlink old inode and update inode parent EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .Times(times * 2) @@ -1212,11 +1254,19 @@ TEST_F(TestFuseVolumeClient, FuseOpRenameParallel) { inode.set_inodeid(10); inode.set_nlink(times); inode.set_type(FsFileType::TYPE_FILE); + InodeAttr oldAttr; + oldAttr.set_inodeid(10); + oldAttr.set_nlink(times); + oldAttr.set_type(FsFileType::TYPE_FILE); auto inodeWrapper = std::make_shared(inode, metaClient_); EXPECT_CALL(*inodeManager_, GetInode(inode.inodeid(), _)) .Times(2 * times) .WillRepeatedly(DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, 10, _)) + .Times(times) + .WillRepeatedly(DoAll(SetArgPointee<2>(oldAttr), + Return(MetaStatusCode::OK))); // step7: update cache EXPECT_CALL(*dentryManager_, DeleteCache(_, _)).Times(times); @@ -1536,8 +1586,15 @@ TEST_F(TestFuseVolumeClient, FuseOpLink) { inode.set_inodeid(ino); inode.set_length(0); inode.set_nlink(nlink); + inode.set_type(FsFileType::TYPE_FILE); auto inodeWrapper = std::make_shared(inode, metaClient_); + InodeAttr attr; + attr.set_inodeid(ino); + attr.set_length(0); + attr.set_nlink(nlink); + attr.set_type(FsFileType::TYPE_FILE); + Inode parentInode; parentInode.set_fsid(fsId); parentInode.set_inodeid(newparent); @@ -1555,14 +1612,17 @@ TEST_F(TestFuseVolumeClient, FuseOpLink) { EXPECT_CALL(*dentryManager_, CreateDentry(_)) .WillOnce(Return(CURVEFS_ERROR::OK)); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(attr), Return(MetaStatusCode::OK))); + EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillOnce(Return(MetaStatusCode::OK)); fuse_entry_param e; CURVEFS_ERROR ret = client_->FuseOpLink(req, ino, newparent, newname, &e); ASSERT_EQ(CURVEFS_ERROR::OK, ret); - Inode inode2 = inodeWrapper->GetInode(); - ASSERT_EQ(nlink + 1, inode2.nlink()); + ASSERT_EQ(nlink + 1, inodeWrapper->GetNlinkLocked()); + ASSERT_EQ(2, parentInodeWrapper->GetNlinkLocked()); } TEST_F(TestFuseVolumeClient, FuseOpLinkFailed) { @@ -1579,6 +1639,11 @@ TEST_F(TestFuseVolumeClient, FuseOpLinkFailed) { inode.set_nlink(nlink); auto inodeWrapper = std::make_shared(inode, metaClient_); + InodeAttr attr; + attr.set_inodeid(ino); + attr.set_length(0); + attr.set_nlink(nlink); + EXPECT_CALL(*inodeManager_, GetInode(ino, _)) .WillOnce(Return(CURVEFS_ERROR::INTERNAL)) .WillOnce( @@ -1588,6 +1653,10 @@ TEST_F(TestFuseVolumeClient, FuseOpLinkFailed) { .WillOnce( DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK))); + EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<2>(attr), + Return(MetaStatusCode::OK))); + EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillOnce(Return(MetaStatusCode::UNKNOWN_ERROR)) // link .WillOnce(Return(MetaStatusCode::OK)) // link @@ -1616,13 +1685,13 @@ TEST_F(TestFuseVolumeClient, FuseOpLinkFailed) { ret = client_->FuseOpLink(req, ino, newparent, newname, &e); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); Inode inode4 = inodeWrapper->GetInode(); - ASSERT_EQ(nlink, inode4.nlink()); + ASSERT_EQ(nlink - 1, inode4.nlink()); // also unlink failed ret = client_->FuseOpLink(req, ino, newparent, newname, &e); ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret); Inode inode5 = inodeWrapper->GetInode(); - ASSERT_EQ(nlink, inode5.nlink()); + ASSERT_EQ(nlink - 1, inode5.nlink()); } TEST_F(TestFuseVolumeClient, FuseOpReadLink) { @@ -3098,7 +3167,7 @@ TEST_F(TestFuseS3Client, FuseOpCreate_EnableSummary) { .WillRepeatedly(Return(MetaStatusCode::OK)); EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(1); + .Times(2); fuse_entry_param e; CURVEFS_ERROR ret = client_->FuseOpCreate(req, parent, name, mode, &fi, &e); @@ -3201,7 +3270,7 @@ TEST_F(TestFuseS3Client, FuseOpLink_EnableSummary) { EXPECT_CALL(*dentryManager_, CreateDentry(_)) .WillOnce(Return(CURVEFS_ERROR::OK)); EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(1); + .Times(2); fuse_entry_param e; CURVEFS_ERROR ret = client_->FuseOpLink(req, ino, newparent, newname, &e); ASSERT_EQ(CURVEFS_ERROR::OK, ret); @@ -3241,6 +3310,7 @@ TEST_F(TestFuseS3Client, FuseOpUnlink_EnableSummary) { inode.set_inodeid(inodeid); inode.set_length(4096); inode.set_nlink(nlink); + inode.set_type(FsFileType::TYPE_FILE); auto inodeWrapper = std::make_shared(inode, metaClient_); Inode parentInode; @@ -3253,6 +3323,11 @@ TEST_F(TestFuseS3Client, FuseOpUnlink_EnableSummary) { parentInode.mutable_xattr()->insert({XATTRENTRIES, "2"}); parentInode.mutable_xattr()->insert({XATTRFBYTES, "4196"}); + InodeAttr attr; + attr.set_fsid(fsId); + attr.set_inodeid(inodeid); + attr.set_nlink(nlink); + auto parentInodeWrapper = std::make_shared( parentInode, metaClient_); @@ -3265,12 +3340,13 @@ TEST_F(TestFuseS3Client, FuseOpUnlink_EnableSummary) { .WillOnce( DoAll(SetArgReferee<1>(parentInodeWrapper), Return(CURVEFS_ERROR::OK))); - + EXPECT_CALL(*metaClient_, GetInodeAttr(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(attr), Return(MetaStatusCode::OK))); EXPECT_CALL(*metaClient_, UpdateInodeAttr(_, _, _)) .WillRepeatedly(Return(MetaStatusCode::OK)); EXPECT_CALL(*inodeManager_, ShipToFlush(_)) - .Times(1); + .Times(2); EXPECT_CALL(*inodeManager_, ClearInodeCache(inodeid)) .Times(1); @@ -3281,6 +3357,7 @@ TEST_F(TestFuseS3Client, FuseOpUnlink_EnableSummary) { ASSERT_EQ(nlink - 1, inode2.nlink()); auto p = parentInodeWrapper->GetInode(); + ASSERT_EQ(3, p.nlink()); ASSERT_EQ(p.xattr().find(XATTRFILES)->second, "0"); ASSERT_EQ(p.xattr().find(XATTRSUBDIRS)->second, "1"); ASSERT_EQ(p.xattr().find(XATTRENTRIES)->second, "1");