in src/fuse/FuseOps.cc [808:907]
void hf3fs_setattr(fuse_req_t req, fuse_ino_t fino, struct stat *attr, int to_set, struct fuse_file_info *fi) {
(void)fi;
auto userInfo = UserInfo(flat::Uid(fuse_req_ctx(req)->uid), flat::Gid(fuse_req_ctx(req)->gid), d.fuseToken);
if (d.userConfig.getConfig(userInfo).readonly()) {
fuse_reply_err(req, EROFS);
return;
}
auto ino = real_ino(fino);
struct fuse_file_info fi2 {};
if (!fi) {
fi = &fi2;
}
auto pi = inodeOf(*fi, ino);
XLOGF(OP_LOG_LEVEL, "hf3fs_setattr(ino={}, to_set={}, pid={})", ino, to_set, fuse_req_ctx(req)->pid);
record("setattr", fuse_req_ctx(req)->uid);
if (checkVirtDir(ino)) {
fuse_reply_err(req, EPERM);
return;
}
std::optional<Result<Inode>> res;
if (to_set & (FUSE_SET_ATTR_MODE | FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)) {
std::optional<Permission> perm = std::nullopt;
std::optional<Uid> uid = std::nullopt;
std::optional<Gid> gid = std::nullopt;
if (to_set & FUSE_SET_ATTR_UID) {
uid = Uid(attr->st_uid);
}
if (to_set & FUSE_SET_ATTR_GID) {
gid = Gid(attr->st_gid);
}
if (to_set & FUSE_SET_ATTR_MODE) {
perm = Permission(attr->st_mode & ALLPERMS);
}
res = withRequestInfo(req, d.metaClient->setPermission(userInfo, ino, std::nullopt, false, uid, gid, perm));
if (res->hasError()) {
handle_error(req, res.value());
return;
}
}
if (to_set & FUSE_SET_ATTR_SIZE) {
{
std::lock_guard lock(pi->wbMtx);
auto wb = pi->writeBuf;
if (wb) {
if (wb->len) {
XLOGF(DBG, "flushing for truncate");
if (flushBuf(req, pi, wb->off, *wb->memh, wb->len, true) < 0) {
wb->len = 0;
return;
}
wb->len = 0;
}
}
}
res = withRequestInfo(req, truncate(userInfo, *pi, attr->st_size));
if (res->hasError()) {
handle_error(req, res.value());
return;
}
}
if (to_set & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
std::optional<UtcTime> atime, mtime;
if (to_set & FUSE_SET_ATTR_ATIME) {
pi->dynamicAttr.wlock()->atime.reset();
if (to_set & FUSE_SET_ATTR_ATIME_NOW) {
atime = SETATTR_TIME_NOW;
} else {
atime = UtcTime::from(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::seconds{attr->st_atim.tv_sec} + std::chrono::nanoseconds{attr->st_atim.tv_nsec}));
}
}
if (to_set & FUSE_SET_ATTR_MTIME) {
pi->dynamicAttr.wlock()->mtime.reset();
if (to_set & FUSE_SET_ATTR_MTIME_NOW) {
mtime = SETATTR_TIME_NOW;
} else {
mtime = UtcTime::from(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::seconds{attr->st_mtim.tv_sec} + std::chrono::nanoseconds{attr->st_mtim.tv_nsec}));
}
}
res = withRequestInfo(req, d.metaClient->utimes(userInfo, ino, std::nullopt, false, atime, mtime));
if (res->hasError()) {
handle_error(req, res.value());
return;
}
}
if (res) {
struct ::stat buf;
fillLinuxStat(buf, res->value());
fuse_reply_attr(req, &buf, d.userConfig.getConfig(userInfo).attr_timeout());
} else {
hf3fs_getattr(req, linux_ino(ino), fi);
}
}