mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-04-11 02:51:52 +00:00
Additional bug fixing for not creating zero-byte object
This commit is contained in:
parent
42f5965d8a
commit
b5fef788da
@ -100,7 +100,9 @@ inline bool IsExpireStatCacheTime(const struct timespec& ts, const time_t& expir
|
|||||||
{
|
{
|
||||||
struct timespec nowts;
|
struct timespec nowts;
|
||||||
SetStatCacheTime(nowts);
|
SetStatCacheTime(nowts);
|
||||||
return ((ts.tv_sec + expire) < nowts.tv_sec);
|
nowts.tv_sec -= expire;
|
||||||
|
|
||||||
|
return (0 < CompareStatCacheTime(nowts, ts));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -258,7 +260,7 @@ bool StatCache::GetStat(const std::string& key, struct stat* pst, headers_t* met
|
|||||||
|
|
||||||
if(iter != stat_cache.end() && (*iter).second){
|
if(iter != stat_cache.end() && (*iter).second){
|
||||||
stat_cache_entry* ent = (*iter).second;
|
stat_cache_entry* ent = (*iter).second;
|
||||||
if(!IsExpireTime || !IsExpireStatCacheTime(ent->cache_date, ExpireTime)){
|
if(0 < ent->notruncate || !IsExpireTime || !IsExpireStatCacheTime(ent->cache_date, ExpireTime)){
|
||||||
if(ent->noobjcache){
|
if(ent->noobjcache){
|
||||||
if(!IsCacheNoObject){
|
if(!IsCacheNoObject){
|
||||||
// need to delete this cache.
|
// need to delete this cache.
|
||||||
@ -343,7 +345,8 @@ bool StatCache::IsNoObjectCache(const std::string& key, bool overcheck)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(iter != stat_cache.end() && (*iter).second) {
|
if(iter != stat_cache.end() && (*iter).second) {
|
||||||
if(!IsExpireTime || !IsExpireStatCacheTime((*iter).second->cache_date, ExpireTime)){
|
stat_cache_entry* ent = (*iter).second;
|
||||||
|
if(0 < ent->notruncate || !IsExpireTime || !IsExpireStatCacheTime((*iter).second->cache_date, ExpireTime)){
|
||||||
if((*iter).second->noobjcache){
|
if((*iter).second->noobjcache){
|
||||||
// noobjcache = true means no object.
|
// noobjcache = true means no object.
|
||||||
SetStatCacheTime((*iter).second->cache_date);
|
SetStatCacheTime((*iter).second->cache_date);
|
||||||
@ -434,6 +437,47 @@ bool StatCache::AddStat(const std::string& key, headers_t& meta, bool forcedir,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [NOTE]
|
||||||
|
// Updates only meta data if cached data exists.
|
||||||
|
// And when these are updated, it also updates the cache time.
|
||||||
|
//
|
||||||
|
bool StatCache::UpdateMetaStats(const std::string& key, headers_t& meta)
|
||||||
|
{
|
||||||
|
if(CacheSize < 1){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
S3FS_PRN_INFO3("update stat cache entry[path=%s]", key.c_str());
|
||||||
|
|
||||||
|
AutoLock lock(&StatCache::stat_cache_lock);
|
||||||
|
stat_cache_t::iterator iter = stat_cache.find(key);
|
||||||
|
if(stat_cache.end() == iter || !(iter->second)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stat_cache_entry* ent = iter->second;
|
||||||
|
|
||||||
|
// update only meta keys
|
||||||
|
for(headers_t::iterator metaiter = meta.begin(); metaiter != meta.end(); ++metaiter){
|
||||||
|
std::string tag = lower(metaiter->first);
|
||||||
|
std::string value = metaiter->second;
|
||||||
|
if(tag == "content-type"){
|
||||||
|
ent->meta[metaiter->first] = value;
|
||||||
|
}else if(tag == "content-length"){
|
||||||
|
ent->meta[metaiter->first] = value;
|
||||||
|
}else if(tag == "etag"){
|
||||||
|
ent->meta[metaiter->first] = value;
|
||||||
|
}else if(tag == "last-modified"){
|
||||||
|
ent->meta[metaiter->first] = value;
|
||||||
|
}else if(is_prefix(tag.c_str(), "x-amz")){
|
||||||
|
ent->meta[tag] = value; // key is lower case for "x-amz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update time.
|
||||||
|
SetStatCacheTime(ent->cache_date);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool StatCache::AddNoObjectCache(const std::string& key)
|
bool StatCache::AddNoObjectCache(const std::string& key)
|
||||||
{
|
{
|
||||||
if(!IsCacheNoObject){
|
if(!IsCacheNoObject){
|
||||||
|
@ -158,6 +158,9 @@ class StatCache
|
|||||||
// Add stat cache
|
// Add stat cache
|
||||||
bool AddStat(const std::string& key, headers_t& meta, bool forcedir = false, bool no_truncate = false);
|
bool AddStat(const std::string& key, headers_t& meta, bool forcedir = false, bool no_truncate = false);
|
||||||
|
|
||||||
|
// Update meta stats
|
||||||
|
bool UpdateMetaStats(const std::string& key, headers_t& meta);
|
||||||
|
|
||||||
// Change no truncate flag
|
// Change no truncate flag
|
||||||
void ChangeNoTruncateFlag(const std::string& key, bool no_truncate);
|
void ChangeNoTruncateFlag(const std::string& key, bool no_truncate);
|
||||||
|
|
||||||
|
43
src/s3fs.cpp
43
src/s3fs.cpp
@ -385,7 +385,6 @@ static int get_object_attribute(const char* path, struct stat* pstbuf, headers_t
|
|||||||
strpath += "/";
|
strpath += "/";
|
||||||
}
|
}
|
||||||
if(StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce)){
|
if(StatCache::getStatCacheData()->GetStat(strpath, pstat, pheader, overcheck, pisforce)){
|
||||||
StatCache::getStatCacheData()->ChangeNoTruncateFlag(strpath, add_no_truncate_cache);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(StatCache::getStatCacheData()->IsNoObjectCache(strpath)){
|
if(StatCache::getStatCacheData()->IsNoObjectCache(strpath)){
|
||||||
@ -980,7 +979,16 @@ static int s3fs_create(const char* _path, mode_t mode, struct fuse_file_info* fi
|
|||||||
meta["x-amz-meta-atime"] = str(now);
|
meta["x-amz-meta-atime"] = str(now);
|
||||||
meta["x-amz-meta-mtime"] = str(now);
|
meta["x-amz-meta-mtime"] = str(now);
|
||||||
meta["x-amz-meta-ctime"] = str(now);
|
meta["x-amz-meta-ctime"] = str(now);
|
||||||
if(!StatCache::getStatCacheData()->AddStat(path, meta)){
|
|
||||||
|
// [NOTE] set no_truncate flag
|
||||||
|
// At this point, the file has not been created(uploaded) and
|
||||||
|
// the data is only present in the Stats cache.
|
||||||
|
// The Stats cache should not be deleted automatically by
|
||||||
|
// timeout. If this stats is deleted, s3fs will try to get it
|
||||||
|
// from the server with a Head request and will get an
|
||||||
|
// unexpected error because the result object does not exist.
|
||||||
|
//
|
||||||
|
if(!StatCache::getStatCacheData()->AddStat(path, meta, false, true)){
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1066,9 +1074,9 @@ static int s3fs_unlink(const char* _path)
|
|||||||
}
|
}
|
||||||
S3fsCurl s3fscurl;
|
S3fsCurl s3fscurl;
|
||||||
result = s3fscurl.DeleteRequest(path);
|
result = s3fscurl.DeleteRequest(path);
|
||||||
FdManager::DeleteCacheFile(path);
|
|
||||||
StatCache::getStatCacheData()->DelStat(path);
|
StatCache::getStatCacheData()->DelStat(path);
|
||||||
StatCache::getStatCacheData()->DelSymlink(path);
|
StatCache::getStatCacheData()->DelSymlink(path);
|
||||||
|
FdManager::DeleteCacheFile(path);
|
||||||
S3FS_MALLOCTRIM(0);
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1671,6 +1679,9 @@ static int s3fs_chmod(const char* _path, mode_t mode)
|
|||||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||||
need_put_header = false;
|
need_put_header = false;
|
||||||
|
|
||||||
|
// If there is data in the Stats cache, update the Stats cache.
|
||||||
|
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(need_put_header){
|
if(need_put_header){
|
||||||
@ -1845,6 +1856,9 @@ static int s3fs_chown(const char* _path, uid_t uid, gid_t gid)
|
|||||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||||
need_put_header = false;
|
need_put_header = false;
|
||||||
|
|
||||||
|
// If there is data in the Stats cache, update the Stats cache.
|
||||||
|
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(need_put_header){
|
if(need_put_header){
|
||||||
@ -2026,6 +2040,9 @@ static int s3fs_utimens(const char* _path, const struct timespec ts[2])
|
|||||||
need_put_header = false;
|
need_put_header = false;
|
||||||
ent->SetHoldingMtime(ts[1]); // ts[1] is mtime
|
ent->SetHoldingMtime(ts[1]); // ts[1] is mtime
|
||||||
|
|
||||||
|
// If there is data in the Stats cache, update the Stats cache.
|
||||||
|
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
S3FS_PRN_INFO("meta is not pending, but need to keep current mtime.");
|
S3FS_PRN_INFO("meta is not pending, but need to keep current mtime.");
|
||||||
|
|
||||||
@ -2223,16 +2240,21 @@ static int s3fs_open(const char* _path, struct fuse_file_info* fi)
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear stat for reading fresh stat.
|
// [NOTE]
|
||||||
// (if object stat is changed, we refresh it. then s3fs gets always
|
// Delete the Stats cache only if the file is not open.
|
||||||
// stat when s3fs open the object).
|
// If the file is open, the stats cache will not be deleted as
|
||||||
|
// there are cases where the object does not exist on the server
|
||||||
|
// and only the Stats cache exists.
|
||||||
|
//
|
||||||
if(StatCache::getStatCacheData()->HasStat(path)){
|
if(StatCache::getStatCacheData()->HasStat(path)){
|
||||||
// flush any dirty data so that subsequent stat gets correct size
|
AutoFdEntity autoent_local;
|
||||||
|
if(NULL == autoent_local.ExistOpen(path, -1, true)){
|
||||||
if((result = s3fs_flush(_path, fi)) != 0){
|
if((result = s3fs_flush(_path, fi)) != 0){
|
||||||
S3FS_PRN_ERR("could not flush(%s): result=%d", path, result);
|
S3FS_PRN_ERR("could not flush(%s): result=%d", path, result);
|
||||||
}
|
}
|
||||||
StatCache::getStatCacheData()->DelStat(path);
|
StatCache::getStatCacheData()->DelStat(path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mask = (O_RDONLY != (fi->flags & O_ACCMODE) ? W_OK : R_OK);
|
int mask = (O_RDONLY != (fi->flags & O_ACCMODE) ? W_OK : R_OK);
|
||||||
if(0 != (result = check_parent_object_access(path, X_OK))){
|
if(0 != (result = check_parent_object_access(path, X_OK))){
|
||||||
@ -2390,6 +2412,7 @@ static int s3fs_flush(const char* _path, struct fuse_file_info* fi)
|
|||||||
ent->UpdateMtime(true); // clear the flag not to update mtime.
|
ent->UpdateMtime(true); // clear the flag not to update mtime.
|
||||||
ent->UpdateCtime();
|
ent->UpdateCtime();
|
||||||
result = ent->Flush(false);
|
result = ent->Flush(false);
|
||||||
|
StatCache::getStatCacheData()->DelStat(path);
|
||||||
}
|
}
|
||||||
S3FS_MALLOCTRIM(0);
|
S3FS_MALLOCTRIM(0);
|
||||||
|
|
||||||
@ -3048,6 +3071,9 @@ static int s3fs_setxattr(const char* path, const char* name, const char* value,
|
|||||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||||
need_put_header = false;
|
need_put_header = false;
|
||||||
|
|
||||||
|
// If there is data in the Stats cache, update the Stats cache.
|
||||||
|
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(need_put_header){
|
if(need_put_header){
|
||||||
@ -3318,6 +3344,9 @@ static int s3fs_removexattr(const char* path, const char* name)
|
|||||||
// then the meta is pending and accumulated to be put after the upload is complete.
|
// then the meta is pending and accumulated to be put after the upload is complete.
|
||||||
S3FS_PRN_INFO("meta pending until upload is complete");
|
S3FS_PRN_INFO("meta pending until upload is complete");
|
||||||
need_put_header = false;
|
need_put_header = false;
|
||||||
|
|
||||||
|
// If there is data in the Stats cache, update the Stats cache.
|
||||||
|
StatCache::getStatCacheData()->UpdateMetaStats(strpath, updatemeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(need_put_header){
|
if(need_put_header){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user