Flush after opened file size is shrinked

This commit is contained in:
Takeshi Nakatani 2023-03-16 12:49:20 +00:00
parent 18495c44aa
commit 67f98b7925
5 changed files with 134 additions and 10 deletions

2
.gitignore vendored
View File

@ -42,6 +42,7 @@ config.status
config.sub
configure
configure.scan
configure.ac~
depcomp
install-sh
libtool
@ -86,6 +87,7 @@ test/junk_data
test/s3proxy-*
test/write_multiblock
test/mknod_test
test/truncate_read_file
#
# Windows ports

View File

@ -2563,6 +2563,7 @@ static int s3fs_truncate(const char* _path, off_t size)
// Get file information
if(0 == (result = get_object_attribute(path, NULL, &meta))){
// File exists
off_t cur_size = get_size(meta);
// [NOTE]
// If the file exists, the file has already been opened by FUSE before
@ -2596,20 +2597,34 @@ static int s3fs_truncate(const char* _path, off_t size)
}
ent->UpdateCtime();
#if defined(__APPLE__)
// [NOTE]
// Only for macos, this truncate calls to "size=0" do not reflect size.
// The cause is unknown now, but it can be avoided by flushing the file.
// In the case of reducing the file size, the stats information on the server
// side must be updated.
// This is because truncate is called, but flush (sync) is not performed, and
// when reading is performed by another process etc. until that flush, the file
// size resets to original size and the correct(reduced) file size cannot be
// reflected.
//
if(0 == size){
if(size < cur_size){
if(0 != (result = ent->Flush(autoent.GetPseudoFd(), AutoLock::NONE, true))){
S3FS_PRN_ERR("could not upload file(%s): result=%d", path, result);
return result;
}
StatCache::getStatCacheData()->DelStat(path);
}
#endif
#if defined(__APPLE__)
}else if(0 == size){
// [NOTE]
// Only for macos, this truncate calls to "size=0" do not reflect size.
// The cause is unknown now, but it can be avoided by flushing the file.
//
if(0 != (result = ent->Flush(autoent.GetPseudoFd(), AutoLock::NONE, true))){
S3FS_PRN_ERR("could not upload file(%s): result=%d", path, result);
return result;
}
StatCache::getStatCacheData()->DelStat(path);
#endif
}
}else{
// Not found -> Make tmpfile(with size)
struct fuse_context* pcxt;

View File

@ -32,11 +32,13 @@ testdir = test
noinst_PROGRAMS = \
junk_data \
write_multiblock \
mknod_test
mknod_test \
truncate_read_file
junk_data_SOURCES = junk_data.c
write_multiblock_SOURCES = write_multiblock.cc
mknod_test_SOURCES = mknod_test.c
junk_data_SOURCES = junk_data.c
write_multiblock_SOURCES = write_multiblock.cc
mknod_test_SOURCES = mknod_test.c
truncate_read_file_SOURCES = truncate_read_file.c
#
# Local variables:

View File

@ -112,6 +112,29 @@ function test_truncate_shrink_file {
rm_test_file "${BIG_TRUNCATE_TEST_FILE}"
}
function test_truncate_shrink_read_file {
describe "Testing truncate(shrink) and read file ..."
# Initiate file size is 1024, and shrink file size is 512
local init_size=1024
local shrink_size=512
# create file
dd if=/dev/urandom of="${TEST_TEXT_FILE}" bs="${init_size}" count=1
# truncate(shrink) file and read it before flusing
../../truncate_read_file "${TEST_TEXT_FILE}" "${shrink_size}"
# check file size
check_file_size "${TEST_TEXT_FILE}" "${shrink_size}"
# Truncate the file to 1024 length
local t_size=1024
rm_test_file
}
function test_mv_file {
describe "Testing mv file function ..."
# if the rename file exists, delete it
@ -2610,6 +2633,7 @@ function add_all_tests {
add_tests test_truncate_upload
add_tests test_truncate_empty_file
add_tests test_truncate_shrink_file
add_tests test_truncate_shrink_read_file
add_tests test_mv_file
add_tests test_mv_to_exist_file
add_tests test_mv_empty_directory

81
test/truncate_read_file.c Normal file
View File

@ -0,0 +1,81 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2021 Andrew Gaul <andrew@gaul.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
// [NOTE]
// This is a program used for file size inspection.
// File size checking should be done by the caller of this program.
// This program truncates the file and reads the file in another process
// between truncate and flush(close file).
//
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr, "[ERROR] Wrong paraemters\n");
fprintf(stdout, "[Usage] truncate_read_file <file path> <truncate size(bytes)>\n");
exit(EXIT_FAILURE);
}
const char* filepath = argv[1];
off_t size = (off_t)strtoull(argv[2], NULL, 10);
int fd;
// open file
if(-1 == (fd = open(filepath, O_RDWR))){
fprintf(stderr, "[ERROR] Could not open file(%s)\n", filepath);
exit(EXIT_FAILURE);
}
// truncate
if(0 != ftruncate(fd, size)){
fprintf(stderr, "[ERROR] Could not truncate file(%s) to %lld byte.\n", filepath, (long long)size);
close(fd);
exit(EXIT_FAILURE);
}
// run sub-process for reading file(cat)
char szCommand[1024];
sprintf(szCommand, "cat %s >/dev/null 2>&1", filepath);
if(0 != system(szCommand)){
fprintf(stderr, "[ERROR] Failed to run sub-process(cat).\n");
close(fd);
exit(EXIT_FAILURE);
}
// close file(flash)
close(fd);
exit(EXIT_SUCCESS);
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/