mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-22 08:48:55 +00:00
Fixed a bug when reading a reduced file without flushing (#2133)
This commit is contained in:
parent
2cd7c94653
commit
a25cb9e07a
2
.gitignore
vendored
2
.gitignore
vendored
@ -42,6 +42,7 @@ config.status
|
|||||||
config.sub
|
config.sub
|
||||||
configure
|
configure
|
||||||
configure.scan
|
configure.scan
|
||||||
|
configure.ac~
|
||||||
depcomp
|
depcomp
|
||||||
install-sh
|
install-sh
|
||||||
libtool
|
libtool
|
||||||
@ -86,6 +87,7 @@ test/junk_data
|
|||||||
test/s3proxy-*
|
test/s3proxy-*
|
||||||
test/write_multiblock
|
test/write_multiblock
|
||||||
test/mknod_test
|
test/mknod_test
|
||||||
|
test/truncate_read_file
|
||||||
|
|
||||||
#
|
#
|
||||||
# Windows ports
|
# Windows ports
|
||||||
|
@ -456,7 +456,13 @@ bool PageList::Resize(off_t size, bool is_loaded, bool is_modified)
|
|||||||
off_t total = Size();
|
off_t total = Size();
|
||||||
|
|
||||||
if(0 == total){
|
if(0 == total){
|
||||||
|
// [NOTE]
|
||||||
|
// The is_shrink flag remains unchanged in this function.
|
||||||
|
//
|
||||||
|
bool backup_is_shrink = is_shrink;
|
||||||
|
|
||||||
Init(size, is_loaded, is_modified);
|
Init(size, is_loaded, is_modified);
|
||||||
|
is_shrink = backup_is_shrink;
|
||||||
|
|
||||||
}else if(total < size){
|
}else if(total < size){
|
||||||
// add new area
|
// add new area
|
||||||
|
@ -245,7 +245,7 @@ gid_t get_gid(const headers_t& meta)
|
|||||||
|
|
||||||
blkcnt_t get_blocks(off_t size)
|
blkcnt_t get_blocks(off_t size)
|
||||||
{
|
{
|
||||||
return size / 512 + 1;
|
return (size / 512) + (0 == (size % 512) ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t cvtIAMExpireStringToTime(const char* s)
|
time_t cvtIAMExpireStringToTime(const char* s)
|
||||||
|
19
src/s3fs.cpp
19
src/s3fs.cpp
@ -2682,19 +2682,32 @@ static int s3fs_open(const char* _path, struct fuse_file_info* fi)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoFdEntity autoent;
|
||||||
|
FdEntity* ent;
|
||||||
|
headers_t meta;
|
||||||
|
|
||||||
if((unsigned int)fi->flags & O_TRUNC){
|
if((unsigned int)fi->flags & O_TRUNC){
|
||||||
if(0 != st.st_size){
|
if(0 != st.st_size){
|
||||||
st.st_size = 0;
|
st.st_size = 0;
|
||||||
needs_flush = true;
|
needs_flush = true;
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
// [NOTE]
|
||||||
|
// If the file has already been opened and edited, the file size in
|
||||||
|
// the edited state is given priority.
|
||||||
|
// This prevents the file size from being reset to its original size
|
||||||
|
// if you keep the file open, shrink its size, and then read the file
|
||||||
|
// from another process while it has not yet been flushed.
|
||||||
|
//
|
||||||
|
if(NULL != (ent = autoent.OpenExistFdEntity(path)) && ent->IsModified()){
|
||||||
|
// sets the file size being edited.
|
||||||
|
ent->GetSize(st.st_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(!S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)){
|
if(!S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)){
|
||||||
st.st_mtime = -1;
|
st.st_mtime = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoFdEntity autoent;
|
|
||||||
FdEntity* ent;
|
|
||||||
headers_t meta;
|
|
||||||
if(0 != (result = get_object_attribute(path, NULL, &meta, true, NULL, true))){ // no truncate cache
|
if(0 != (result = get_object_attribute(path, NULL, &meta, true, NULL, true))){ // no truncate cache
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,13 @@ testdir = test
|
|||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
junk_data \
|
junk_data \
|
||||||
write_multiblock \
|
write_multiblock \
|
||||||
mknod_test
|
mknod_test \
|
||||||
|
truncate_read_file
|
||||||
|
|
||||||
junk_data_SOURCES = junk_data.c
|
junk_data_SOURCES = junk_data.c
|
||||||
write_multiblock_SOURCES = write_multiblock.cc
|
write_multiblock_SOURCES = write_multiblock.cc
|
||||||
mknod_test_SOURCES = mknod_test.c
|
mknod_test_SOURCES = mknod_test.c
|
||||||
|
truncate_read_file_SOURCES = truncate_read_file.c
|
||||||
|
|
||||||
#
|
#
|
||||||
# Local variables:
|
# Local variables:
|
||||||
|
@ -112,6 +112,28 @@ function test_truncate_shrink_file {
|
|||||||
rm_test_file "${BIG_TRUNCATE_TEST_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 {
|
function test_mv_file {
|
||||||
describe "Testing mv file function ..."
|
describe "Testing mv file function ..."
|
||||||
# if the rename file exists, delete it
|
# if the rename file exists, delete it
|
||||||
@ -2610,6 +2632,7 @@ function add_all_tests {
|
|||||||
add_tests test_truncate_upload
|
add_tests test_truncate_upload
|
||||||
add_tests test_truncate_empty_file
|
add_tests test_truncate_empty_file
|
||||||
add_tests test_truncate_shrink_file
|
add_tests test_truncate_shrink_file
|
||||||
|
add_tests test_truncate_shrink_read_file
|
||||||
add_tests test_mv_file
|
add_tests test_mv_file
|
||||||
add_tests test_mv_to_exist_file
|
add_tests test_mv_to_exist_file
|
||||||
add_tests test_mv_empty_directory
|
add_tests test_mv_empty_directory
|
||||||
|
81
test/truncate_read_file.c
Normal file
81
test/truncate_read_file.c
Normal 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(flush)
|
||||||
|
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
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user