Fixed not to call Flush even if the file size is increased (#1887)

Changed s3fs_truncate function.
This change reduces the number of file uploads if the file size is changed.

On macOS, I have found that the truncate call when "size=0" cannot reflect the file size.(This reason is not understood...)
To avoid this, only when "size=0", the flush method is called as before.

Other than that, I found a bug in FdEntity::Open() and fixed it.

Fixes #1875.
This commit is contained in:
Takeshi Nakatani 2022-02-15 21:29:07 +09:00 committed by GitHub
parent 4dfe2bfdd7
commit 839a33de49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 17 deletions

View File

@ -553,6 +553,11 @@ FdEntity* FdManager::Open(int& fd, const char* path, headers_t* pmeta, off_t siz
// found
ent = iter->second;
// [NOTE]
// Even if getting the request to change the size of modifying
// file to small, we do not change it. Because if it will change,
// test_open_second_fd test will be failed.
//
if(ent->IsModified()){
// If the file is being modified and it's size is larger than size parameter, it will not be resized.
off_t cur_size = 0;

View File

@ -426,7 +426,7 @@ int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, A
// check only file size(do not need to save cfs and time.
if(0 <= size && pagelist.Size() != size){
// truncate temporary file size
if(-1 == ftruncate(physical_fd, size)){
if(-1 == ftruncate(physical_fd, size) || -1 == fsync(physical_fd)){
S3FS_PRN_ERR("failed to truncate temporary file(physical_fd=%d) by errno(%d).", physical_fd, errno);
return -errno;
}
@ -440,7 +440,7 @@ int FdEntity::Open(const headers_t* pmeta, off_t size, time_t time, int flags, A
off_t new_size = (0 <= size ? size : size_orgmeta);
if(pmeta){
orgmeta = *pmeta;
new_size = get_size(orgmeta);
size_orgmeta = get_size(orgmeta);
}
if(new_size < size_orgmeta){
size_orgmeta = new_size;

View File

@ -2168,20 +2168,38 @@ static int s3fs_truncate(const char* _path, off_t size)
// Get file information
if(0 == (result = get_object_attribute(path, NULL, &meta))){
// Exists -> Get file(with size)
// File exists
// [NOTE]
// If the file exists, the file has already been opened by FUSE before
// truncate is called. Then the call below will change the file size.
// (When an already open file is changed the file size, FUSE will not
// reopen it.)
// The Flush is called before this file is closed, so there is no need
// to do it here.
//
if(NULL == (ent = autoent.Open(path, &meta, size, -1, O_RDWR, false, true, AutoLock::NONE))){
S3FS_PRN_ERR("could not open file(%s): errno=%d", path, errno);
return -EIO;
}
if(0 != (result = ent->Load(0, size, AutoLock::NONE))){
S3FS_PRN_ERR("could not download file(%s): result=%d", path, result);
return result;
}
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.
//
if(0 == size){
if(0 != (result = ent->Flush(autoent.GetPseudoFd(), 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;
if(NULL == (pcxt = fuse_get_context())){
return -EIO;
@ -2198,15 +2216,12 @@ static int s3fs_truncate(const char* _path, off_t size)
S3FS_PRN_ERR("could not open file(%s): errno=%d", path, errno);
return -EIO;
}
if(0 != (result = ent->Flush(autoent.GetPseudoFd(), true))){
S3FS_PRN_ERR("could not upload file(%s): result=%d", path, result);
return result;
}
StatCache::getStatCacheData()->DelStat(path);
}
// upload
if(0 != (result = ent->Flush(autoent.GetPseudoFd(), true))){
S3FS_PRN_ERR("could not upload file(%s): result=%d", path, result);
return result;
}
StatCache::getStatCacheData()->DelStat(path);
S3FS_MALLOCTRIM(0);
return result;