Fixed the same bug in chmod/chown/utimens and added tests

This commit is contained in:
Takeshi Nakatani 2021-02-20 13:20:46 +00:00 committed by Andrew Gaul
parent 4fc92d59f3
commit 81e267d421
3 changed files with 135 additions and 39 deletions

View File

@ -1680,24 +1680,21 @@ static int s3fs_chmod(const char* _path, mode_t mode)
//
AutoFdEntity autoent;
FdEntity* ent;
bool need_put_header = true;
if(NULL != (ent = autoent.ExistOpen(path, -1, true))){
// the file is opened now.
if(ent->MergeOrgMeta(updatemeta)){
// now uploading
// the meta is pending and accumulated to be put after the upload is complete.
// meta is changed, but now uploading.
// then the meta is pending and accumulated to be put after the upload is complete.
S3FS_PRN_INFO("meta pending until upload is complete");
}else{
// allow to put header
// updatemeta already merged the orgmeta of the opened files.
if(0 != (result = put_headers(strpath.c_str(), updatemeta, true))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
need_put_header = false;
}
}else{
// not opened file, then put headers
}
if(need_put_header){
// not found opened file.
merge_headers(meta, updatemeta, true);
if(0 != (result = put_headers(strpath.c_str(), meta, true))){
// upload meta directly.
if(0 != (result = put_headers(strpath.c_str(), meta, true, false))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
@ -1856,24 +1853,21 @@ static int s3fs_chown(const char* _path, uid_t uid, gid_t gid)
//
AutoFdEntity autoent;
FdEntity* ent;
bool need_put_header = true;
if(NULL != (ent = autoent.ExistOpen(path, -1, true))){
// the file is opened now.
if(ent->MergeOrgMeta(updatemeta)){
// now uploading
// the meta is pending and accumulated to be put after the upload is complete.
// meta is changed, but now uploading.
// then the meta is pending and accumulated to be put after the upload is complete.
S3FS_PRN_INFO("meta pending until upload is complete");
}else{
// allow to put header
// updatemeta already merged the orgmeta of the opened files.
if(0 != (result = put_headers(strpath.c_str(), updatemeta, true))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
need_put_header = false;
}
}else{
// not opened file, then put headers
}
if(need_put_header){
// not found opened file.
merge_headers(meta, updatemeta, true);
if(0 != (result = put_headers(strpath.c_str(), meta, true))){
// upload meta directly.
if(0 != (result = put_headers(strpath.c_str(), meta, true, false))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
@ -2036,34 +2030,39 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
//
AutoFdEntity autoent;
FdEntity* ent;
bool need_put_header = true;
bool keep_mtime = false;
if(NULL != (ent = autoent.ExistOpen(path, -1, true))){
// the file is opened now.
if(ent->MergeOrgMeta(updatemeta)){
// now uploading
// the meta is pending and accumulated to be put after the upload is complete.
// meta is changed, but now uploading.
// 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;
}else{
// allow to put header
// updatemeta already merged the orgmeta of the opened files.
if(0 != (result = put_headers(strpath.c_str(), updatemeta, true))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
S3FS_PRN_INFO("meta is not pending, but need to keep current mtime.");
// [NOTE]
// Depending on the order in which write/flush and utimens are called,
// the mtime updated here may be overwritten at the time of flush.
// To avoid that, set a special flag.
//
ent->SetHoldingMtime(ts[1].tv_sec); // ts[1].tv_sec is mtime
keep_mtime = true;
}
}else{
// not opened file, then put headers
}
if(need_put_header){
// not found opened file.
merge_headers(meta, updatemeta, true);
if(0 != (result = put_headers(strpath.c_str(), meta, true))){
// upload meta directly.
if(0 != (result = put_headers(strpath.c_str(), meta, true, false))){
return result;
}
StatCache::getStatCacheData()->DelStat(nowcache);
if(keep_mtime){
ent->SetHoldingMtime(ts[1].tv_sec); // ts[1].tv_sec is mtime
}
}
}
S3FS_MALLOCTRIM(0);

View File

@ -344,6 +344,91 @@ function test_read_external_object() {
rm -f ${TEST_TEXT_FILE}
}
function test_update_metadata_external_small_object() {
describe "update meta to small file after created file by aws cli"
# [NOTE]
# Use the only filename in the test to avoid being affected by noobjcache.
#
TEST_FILE_EXT=`make_random_string`
TEST_CHMOD_FILE="${TEST_TEXT_FILE}_chmod.${TEST_FILE_EXT}"
TEST_CHOWN_FILE="${TEST_TEXT_FILE}_chown.${TEST_FILE_EXT}"
TEST_UTIMENS_FILE="${TEST_TEXT_FILE}_utimens.${TEST_FILE_EXT}"
TEST_INPUT="TEST_STRING_IN_SMALL_FILE"
#
# chmod
#
OBJECT_NAME="$(basename $PWD)/${TEST_CHMOD_FILE}"
echo "${TEST_INPUT}" | aws_cli s3 cp - "s3://${TEST_BUCKET_1}/${OBJECT_NAME}"
chmod +x ${TEST_CHMOD_FILE}
cmp ${TEST_CHMOD_FILE} <(echo "${TEST_INPUT}")
#
# chown
#
OBJECT_NAME="$(basename $PWD)/${TEST_CHOWN_FILE}"
echo "${TEST_INPUT}" | aws_cli s3 cp - "s3://${TEST_BUCKET_1}/${OBJECT_NAME}"
chown $UID ${TEST_CHOWN_FILE}
cmp ${TEST_CHOWN_FILE} <(echo "${TEST_INPUT}")
#
# utimens
#
OBJECT_NAME="$(basename $PWD)/${TEST_UTIMENS_FILE}"
echo "${TEST_INPUT}" | aws_cli s3 cp - "s3://${TEST_BUCKET_1}/${OBJECT_NAME}"
touch ${TEST_UTIMENS_FILE}
cmp ${TEST_UTIMENS_FILE} <(echo "${TEST_INPUT}")
rm -f ${TEST_CHMOD_FILE}
rm -f ${TEST_CHOWN_FILE}
rm -f ${TEST_UTIMENS_FILE}
}
function test_update_metadata_external_large_object() {
describe "update meta to large file after created file by aws cli"
# [NOTE]
# Use the only filename in the test to avoid being affected by noobjcache.
#
TEST_FILE_EXT=`make_random_string`
TEST_CHMOD_FILE="${TEST_TEXT_FILE}_chmod.${TEST_FILE_EXT}"
TEST_CHOWN_FILE="${TEST_TEXT_FILE}_chown.${TEST_FILE_EXT}"
TEST_UTIMENS_FILE="${TEST_TEXT_FILE}_utimens.${TEST_FILE_EXT}"
dd if=/dev/urandom of="${TEMP_DIR}/${BIG_FILE}" bs=$BIG_FILE_BLOCK_SIZE count=$BIG_FILE_COUNT
#
# chmod
#
OBJECT_NAME="$(basename $PWD)/${TEST_CHMOD_FILE}"
aws_cli s3 cp ${TEMP_DIR}/${BIG_FILE} "s3://${TEST_BUCKET_1}/${OBJECT_NAME}" --no-progress
chmod +x ${TEST_CHMOD_FILE}
cmp ${TEST_CHMOD_FILE} ${TEMP_DIR}/${BIG_FILE}
#
# chown
#
OBJECT_NAME="$(basename $PWD)/${TEST_CHOWN_FILE}"
aws_cli s3 cp ${TEMP_DIR}/${BIG_FILE} "s3://${TEST_BUCKET_1}/${OBJECT_NAME}" --no-progress
chown $UID ${TEST_CHOWN_FILE}
cmp ${TEST_CHOWN_FILE} ${TEMP_DIR}/${BIG_FILE}
#
# utimens
#
OBJECT_NAME="$(basename $PWD)/${TEST_UTIMENS_FILE}"
aws_cli s3 cp ${TEMP_DIR}/${BIG_FILE} "s3://${TEST_BUCKET_1}/${OBJECT_NAME}" --no-progress
touch ${TEST_UTIMENS_FILE}
cmp ${TEST_UTIMENS_FILE} ${TEMP_DIR}/${BIG_FILE}
rm -f ${TEMP_DIR}/${BIG_FILE}
rm -f ${TEST_CHMOD_FILE}
rm -f ${TEST_CHOWN_FILE}
rm -f ${TEST_UTIMENS_FILE}
}
function test_rename_before_close {
describe "Testing rename before close ..."
(
@ -1315,6 +1400,8 @@ function add_all_tests {
fi
add_tests test_external_modification
add_tests test_read_external_object
add_tests test_update_metadata_external_small_object
add_tests test_update_metadata_external_large_object
add_tests test_rename_before_close
add_tests test_multipart_upload
add_tests test_multipart_copy

View File

@ -337,6 +337,16 @@ function wait_for_port() {
done
}
function make_random_string() {
if [ -n "$1" ]; then
END_POS=$1
else
END_POS=8
fi
RANDOM_STR=`cat /dev/urandom | base64 | sed 's#[/|+]##g' | head -1 | cut -c 1-${END_POS}`
echo "${RANDOM_STR}"
}
#
# Local variables:
# tab-width: 4