Skip to content

Commit

Permalink
curvefs: implement setxattr interface.
Browse files Browse the repository at this point in the history
Signed-off-by: wanghai01 <seanhaizi@163.com>
  • Loading branch information
SeanHai committed Oct 12, 2022
1 parent 98a3987 commit 41bab2a
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 38 deletions.
12 changes: 8 additions & 4 deletions curvefs/src/client/curve_fuse_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,17 +322,21 @@ int Warmup(const std::string& name, const std::string& value) {

void FuseOpSetXattr(fuse_req_t req, fuse_ino_t ino, const char* name,
const char* value, size_t size, int flags) {
// only support "curvefs.warmup.op" xattr
std::string xattrValue(value, size);
VLOG(9) << "FuseOpSetXattr"
<< " ino " << ino << " name " << name << " value " << xattrValue
<< " flags " << flags;
int code = ENOTSUP;
if (strcmp(name, curvefs::client::common::kCurveFsWarmupXAttr) == 0) {
// warmup
code = Warmup(name, xattrValue);
int code = Warmup(name, xattrValue);
fuse_reply_err(req, code);
} else {
// set xattr
CURVEFS_ERROR ret = g_ClientInstance->FuseOpSetXattr(req, ino, name,
value, size, flags);
FuseReplyErrByErrCode(req, ret);
}
fuse_reply_err(req, code);

VLOG(9) << "FuseOpSetXattr done";
}

Expand Down
105 changes: 71 additions & 34 deletions curvefs/src/client/fuse_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,49 +1104,49 @@ CURVEFS_ERROR FuseClient::FuseOpGetXattr(fuse_req_t req, fuse_ino_t ino,
}

std::string xValue;
// get summary info
if (IsSummaryInfo(name)) {
InodeAttr inodeAttr;
CURVEFS_ERROR ret = inodeManager_->GetInodeAttr(ino, &inodeAttr);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "inodeManager get inodeAttr fail, ret = " << ret
<< ", inodeid = " << ino;
return ret;
}
InodeAttr inodeAttr;
CURVEFS_ERROR ret = inodeManager_->GetInodeAttr(ino, &inodeAttr);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "inodeManager get inodeAttr fail, ret = " << ret
<< ", inodeid = " << ino;
return ret;
}

if (inodeAttr.type() == FsFileType::TYPE_DIRECTORY) {
// not enable record summary info in dir xattr,
// need recursive computation all files
if (!enableSumInDir_) {
if (IsOneLayer(name)) {
ret = xattrManager_->CalOneLayerSumInfo(&inodeAttr);
} else {
ret = xattrManager_->CalAllLayerSumInfo(&inodeAttr);
}
// get summary info if the xattr name is summary type
if (IsSummaryInfo(name) && inodeAttr.type() == FsFileType::TYPE_DIRECTORY) {
// if not enable record summary info in dir xattr,
// need recursive computation all files;
// otherwise only recursive computation all dirs.
if (!enableSumInDir_) {
if (IsOneLayer(name)) {
ret = xattrManager_->CalOneLayerSumInfo(&inodeAttr);
} else {
if (IsOneLayer(name)) {
ret = xattrManager_->FastCalOneLayerSumInfo(&inodeAttr);
} else {
ret = xattrManager_->FastCalAllLayerSumInfo(&inodeAttr);
}
}

if (CURVEFS_ERROR::OK != ret) {
return ret;
ret = xattrManager_->CalAllLayerSumInfo(&inodeAttr);
}
LOG(INFO) << "After calculate summary info:\n"
<< inodeAttr.DebugString();
auto it = inodeAttr.xattr().find(name);
if (it != inodeAttr.xattr().end()) {
xValue = it->second;
} else {
if (IsOneLayer(name)) {
ret = xattrManager_->FastCalOneLayerSumInfo(&inodeAttr);
} else {
ret = xattrManager_->FastCalAllLayerSumInfo(&inodeAttr);
}
}

if (CURVEFS_ERROR::OK != ret) {
return ret;
}
LOG(INFO) << "After calculate summary info:\n"
<< inodeAttr.DebugString();
}

CURVEFS_ERROR ret = CURVEFS_ERROR::NODATA;
auto it = inodeAttr.xattr().find(name);
if (it != inodeAttr.xattr().end()) {
xValue = it->second;
}

ret = CURVEFS_ERROR::NODATA;
if (xValue.length() > 0) {
if ((size == 0 && xValue.length() <= MAXXATTRLENGTH) ||
(size >= xValue.length() && size <= MAXXATTRLENGTH)) {
(size >= xValue.length() && xValue.length() <= MAXXATTRLENGTH)) {
memcpy(value, xValue.c_str(), xValue.length());
ret = CURVEFS_ERROR::OK;
} else {
Expand All @@ -1156,6 +1156,43 @@ CURVEFS_ERROR FuseClient::FuseOpGetXattr(fuse_req_t req, fuse_ino_t ino,
return ret;
}

CURVEFS_ERROR FuseClient::FuseOpSetXattr(fuse_req_t req, fuse_ino_t ino,
const char* name, const char* value,
size_t size, int flags) {
VLOG(1) << "FuseOpSetXattr ino: " << ino << ", name: " << name
<< ", value: " << value;
if (option_.disableXattr) {
return CURVEFS_ERROR::NOTSUPPORT;
}

std::string strname(name);
std::string strvalue(value, size);
if (strname.length() > MAXXATTRLENGTH || size > MAXXATTRLENGTH) {
LOG(ERROR) << "xattr length is too long, name = " << name
<< ", name length = " << strname.length()
<< ", value length = " << size;
return CURVEFS_ERROR::OUT_OF_RANGE;
}

std::shared_ptr<InodeWrapper> inodeWrapper;
CURVEFS_ERROR ret = inodeManager_->GetInode(ino, inodeWrapper);
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "inodeManager get inode fail, ret = " << ret
<< ", inodeid = " << ino;
return ret;
}

::curve::common::UniqueLock lgGuard = inodeWrapper->GetUniqueLock();
inodeWrapper->SetXattrLocked(strname, strvalue);
ret = inodeWrapper->SyncAttr();
if (ret != CURVEFS_ERROR::OK) {
LOG(ERROR) << "set xattr fail, ret = " << ret << ", inodeid = " << ino
<< ", name = " << strname << ", value = " << strvalue;
return ret;
}
return CURVEFS_ERROR::OK;
}

CURVEFS_ERROR FuseClient::FuseOpListXattr(fuse_req_t req, fuse_ino_t ino,
char *value, size_t size, size_t *realSize) {
VLOG(1) << "FuseOpListXattr, ino: " << ino << ", size = " << size;
Expand Down
4 changes: 4 additions & 0 deletions curvefs/src/client/fuse_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ class FuseClient {
const char* name, void* value,
size_t size);

virtual CURVEFS_ERROR FuseOpSetXattr(fuse_req_t req, fuse_ino_t ino,
const char* name, const char* value,
size_t size, int flags);

virtual CURVEFS_ERROR FuseOpListXattr(fuse_req_t req, fuse_ino_t ino,
char *value, size_t size, size_t *realSize);

Expand Down
6 changes: 6 additions & 0 deletions curvefs/src/client/inode_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ class InodeWrapper : public std::enable_shared_from_this<InodeWrapper> {
return ret;
}

void SetXattrLocked(const std::string &key, const std::string &value) {
(*inode_.mutable_xattr())[key] = value;
(*dirtyAttr_.mutable_xattr()) = inode_.xattr();
dirty_ = true;
}

curve::common::UniqueLock GetUniqueLock() {
return curve::common::UniqueLock(mtx_);
}
Expand Down
53 changes: 53 additions & 0 deletions curvefs/test/client/test_fuse_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3484,5 +3484,58 @@ TEST_F(TestFuseS3Client, FuseOpListXattr) {
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
}

TEST_F(TestFuseS3Client, FuseOpSetXattr_TooLong) {
// in
fuse_req_t req;
fuse_ino_t ino = 1;
const char name[] = "security.selinux";
size_t size = 300;
char value[300];
std::memset(value, 0, 300);

CURVEFS_ERROR ret = client_->FuseOpSetXattr(
req, ino, name, value, size, 0);
ASSERT_EQ(CURVEFS_ERROR::OUT_OF_RANGE, ret);
}

TEST_F(TestFuseS3Client, FuseOpSetXattr) {
// in
fuse_req_t req;
fuse_ino_t ino = 1;
const char name[] = "security.selinux";
size_t size = 100;
char value[100];
std::memset(value, 0, 100);

// get inode failed
EXPECT_CALL(*inodeManager_, GetInode(ino, _))
.WillOnce(Return(CURVEFS_ERROR::INTERNAL));
CURVEFS_ERROR ret = client_->FuseOpSetXattr(
req, ino, name, value, size, 0);
ASSERT_EQ(CURVEFS_ERROR::INTERNAL, ret);

// updateInode failed
auto inodeWrapper = std::make_shared<InodeWrapper>(Inode(), metaClient_);
EXPECT_CALL(*inodeManager_, GetInode(ino, _))
.WillOnce(
DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK)));
EXPECT_CALL(*metaClient_, UpdateInodeAttrWithOutNlink(_, _, _, _, _))
.WillOnce(Return(MetaStatusCode::NOT_FOUND));
ret = client_->FuseOpSetXattr(
req, ino, name, value, size, 0);
ASSERT_EQ(CURVEFS_ERROR::NOTEXIST, ret);

// success
EXPECT_CALL(*inodeManager_, GetInode(ino, _))
.WillOnce(
DoAll(SetArgReferee<1>(inodeWrapper), Return(CURVEFS_ERROR::OK)));
EXPECT_CALL(*metaClient_, UpdateInodeAttrWithOutNlink(_, _, _, _, _))
.WillOnce(Return(MetaStatusCode::OK));
ret = client_->FuseOpSetXattr(
req, ino, name, value, size, 0);
ASSERT_EQ(CURVEFS_ERROR::OK, ret);
}


} // namespace client
} // namespace curvefs
8 changes: 8 additions & 0 deletions curvefs/test/client/test_inodeWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,5 +333,13 @@ TEST_F(TestInodeWrapper, TestUpdateInodeAttrIncrementally) {
ASSERT_FALSE(wrapper.dirtyAttr_.has_atime_ns());
}

TEST_F(TestInodeWrapper, TestSetXattr) {
inodeWrapper_->SetXattrLocked("name", "value");
XAttr xattr = inodeWrapper_->GetXattr();
ASSERT_TRUE(xattr.xattrinfos().find("name") != xattr.xattrinfos().end());
ASSERT_EQ((*xattr.mutable_xattrinfos())["name"], "value");
ASSERT_TRUE(inodeWrapper_->IsDirty());
}

} // namespace client
} // namespace curvefs

0 comments on commit 41bab2a

Please sign in to comment.