Do not create zero-byte object when creating file (#1640)

Previously s3fs created this object to store metadata and overwrote it
when flushing.  This prevented use with object stores which do not
allow overwrites like HDS.  Instead only create an in-memory
representation which reduces the time to create small files.
Fixes #1013.
This commit is contained in:
Andrew Gaul 2021-04-30 19:56:33 +09:00 committed by GitHub
parent 3694786112
commit 771bbfeac5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 6 deletions

View File

@ -118,6 +118,12 @@ class FdEntity
bool ReserveDiskSpace(off_t size);
bool PunchHole(off_t start = 0, size_t size = 0);
// Indicate that a new file's is dirty. This ensures that both metadata and data are synced during flush.
void MarkDirtyNewFile() {
pagelist.SetPageLoadedStatus(0, 1, PageList::PAGE_LOAD_MODIFIED);
is_meta_pending = true;
}
};
typedef std::map<std::string, class FdEntity*> fdent_map_t; // key=path, value=FdEntity*

View File

@ -970,20 +970,27 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
}else if(0 != result){
return result;
}
result = create_file_object(path, mode, pcxt->uid, pcxt->gid);
StatCache::getStatCacheData()->DelStat(path);
if(result != 0){
return result;
time_t now = time(NULL);
headers_t meta;
meta["Content-Length"] = "0";
meta["x-amz-meta-uid"] = str(pcxt->uid);
meta["x-amz-meta-gid"] = str(pcxt->gid);
meta["x-amz-meta-mode"] = str(mode);
meta["x-amz-meta-atime"] = str(now);
meta["x-amz-meta-mtime"] = str(now);
meta["x-amz-meta-ctime"] = str(now);
if(!StatCache::getStatCacheData()->AddStat(path, meta)){
return -EIO;
}
AutoFdEntity autoent;
FdEntity* ent;
headers_t meta;
get_object_attribute(path, NULL, &meta, true, NULL, true); // no truncate cache
if(NULL == (ent = autoent.Open(path, &meta, 0, -1, false, true))){
StatCache::getStatCacheData()->DelStat(path);
return -EIO;
}
ent->MarkDirtyNewFile();
autoent.Detach(); // KEEP fdentity open
fi->fh = ent->GetFd();
@ -2016,6 +2023,7 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
// then the meta is pending and accumulated to be put after the upload is complete.
S3FS_PRN_INFO("meta pending until upload is complete");
need_put_header = false;
ent->SetHoldingMtime(ts[1]); // ts[1] is mtime
}else{
S3FS_PRN_INFO("meta is not pending, but need to keep current mtime.");

View File

@ -24,6 +24,20 @@ set -o pipefail
source test-utils.sh
function test_create_empty_file {
describe "Testing creating an empty file ..."
OBJECT_NAME="$(basename $PWD)/${TEST_TEXT_FILE}"
touch ${TEST_TEXT_FILE}
check_file_size "${TEST_TEXT_FILE}" 0
aws_cli s3api head-object --bucket "${TEST_BUCKET_1}" --key "${OBJECT_NAME}"
rm_test_file
}
function test_append_file {
describe "Testing append to file ..."
TEST_INPUT="echo ${TEST_TEXT} to ${TEST_TEXT_FILE}"
@ -1425,6 +1439,7 @@ function add_all_tests {
if ! ps u $S3FS_PID | grep -q ensure_diskfree && ! uname | grep -q Darwin; then
add_tests test_clean_up_cache
fi
add_tests test_create_empty_file
add_tests test_append_file
add_tests test_truncate_file
add_tests test_truncate_upload