fix dead lock in disk insufficient and optimize code

This commit is contained in:
yongqingliu 2020-09-16 22:45:28 +08:00
parent c58c91fc4f
commit 211cc0f5f2
4 changed files with 29 additions and 59 deletions

View File

@ -1032,7 +1032,6 @@ int FdEntity::NoCachePreMultipartPost()
// initialize multipart upload values
upload_id.erase();
etaglist.clear();
pending_headers.clear();
S3fsCurl s3fscurl(true);
int result;
@ -1457,70 +1456,43 @@ bool FdEntity::MergeOrgMeta(headers_t& updatemeta)
{
AutoLock auto_lock(&fdent_lock);
bool is_pending;
if(upload_id.empty()){
// merge update meta
headers_t mergedmeta = orgmeta;
merge_headers(orgmeta, updatemeta, false); // overwrite existing keys only
merge_headers(mergedmeta, updatemeta, true); // overwrite all keys
updatemeta = mergedmeta; // swap
is_pending = false;
}else{
// could not update meta because uploading now, then put pending.
pending_headers.push_back(updatemeta);
is_pending = true;
merge_headers(orgmeta, updatemeta, true); // overwrite all keys
// [NOTE]
// this is special cases, we remove the key which has empty values.
for(headers_t::iterator hiter = orgmeta.begin(); hiter != orgmeta.end(); ){
if(hiter->second.empty()){
orgmeta.erase(hiter++);
}else{
++hiter;
}
}
updatemeta = orgmeta;
// update ctime/mtime
time_t updatetime = get_mtime(updatemeta, false); // not overcheck
if(0 != updatetime){
SetMtime(updatetime, true);
}
updatetime = get_ctime(updatemeta, false); // not overcheck
if(0 != updatetime){
SetCtime(updatetime, true);
}
bool is_pending = !upload_id.empty();
return is_pending;
}
// global function in s3fs.cpp
int put_headers(const char* path, headers_t& meta, bool is_copy);
int put_headers(const char* path, headers_t& meta, bool is_copy, bool update_mtime);
int FdEntity::UploadPendingMeta()
{
AutoLock auto_lock(&fdent_lock);
int result = 0;
for(headers_list_t::const_iterator iter = pending_headers.begin(); iter != pending_headers.end(); ++iter){
// [NOTE]
// orgmeta will be updated sequentially.
headers_t putmeta = orgmeta;
merge_headers(putmeta, *iter, true); // overwrite all keys
merge_headers(orgmeta, *iter, false); // overwrite existing keys only
// [NOTE]
// this is special cases, we remove the key which has empty values.
for(headers_t::iterator hiter = putmeta.begin(); hiter != putmeta.end(); ){
if(hiter->second.empty()){
if(orgmeta.end() != orgmeta.find(hiter->first)){
orgmeta.erase(hiter->first);
}
putmeta.erase(hiter++);
}else{
++hiter;
}
}
// update ctime/mtime
time_t updatetime = get_mtime((*iter), false); // not overcheck
if(0 != updatetime){
SetMtime(updatetime, true);
}
updatetime = get_ctime((*iter), false); // not overcheck
if(0 != updatetime){
SetCtime(updatetime, true);
}
// put headers
int one_result = put_headers(path.c_str(), putmeta, true);
if(0 != one_result){
S3FS_PRN_ERR("failed to put header after flushing file(%s) by(%d).", path.c_str(), one_result);
result = one_result; // keep lastest result code
}
// put headers, no need to update mtime to avoid dead lock
int result = put_headers(path.c_str(), orgmeta, true, false);
if(0 != result){
S3FS_PRN_ERR("failed to put header after flushing file(%s) by(%d).", path.c_str(), result);
}
pending_headers.clear();
return result;
}

View File

@ -51,7 +51,6 @@ class FdEntity
std::string cachepath; // local cache file path
// (if this is empty, does not load/save pagelist.)
std::string mirrorpath; // mirror file path to local cache file path
headers_list_t pending_headers;// pending update headers
private:
static int FillFile(int fd, unsigned char byte, off_t size, off_t start);

View File

@ -36,7 +36,6 @@ struct header_nocase_cmp : public std::binary_function<std::string, std::string,
}
};
typedef std::map<std::string, std::string, header_nocase_cmp> headers_t;
typedef std::list<headers_t> headers_list_t;
//-------------------------------------------------------------------
// Functions

View File

@ -105,7 +105,7 @@ static const std::string aws_secretkey = "AWSSecretKey";
//-------------------------------------------------------------------
// Global functions : prototype
//-------------------------------------------------------------------
int put_headers(const char* path, headers_t& meta, bool is_copy); // [NOTE] global function because this is called from FdEntity class
int put_headers(const char* path, headers_t& meta, bool is_copy, bool update_mtime = true); // [NOTE] global function because this is called from FdEntity class
//-------------------------------------------------------------------
// Static functions : prototype
@ -709,7 +709,7 @@ static FdEntity* get_local_fent(AutoFdEntity& autoent, const char* path, bool is
// ow_sse_flg is for over writing sse header by use_sse option.
// @return fuse return code
//
int put_headers(const char* path, headers_t& meta, bool is_copy)
int put_headers(const char* path, headers_t& meta, bool is_copy, bool update_mtime)
{
int result;
S3fsCurl s3fscurl(true);
@ -739,7 +739,7 @@ int put_headers(const char* path, headers_t& meta, bool is_copy)
// [NOTE]
// if path is 'dir/', it does not have cache(could not open file for directory stat)
//
if('/' != path[strlen(path) - 1]){
if(update_mtime && '/' != path[strlen(path) - 1] ){
AutoFdEntity autoent;
FdEntity* ent;
if(NULL == (ent = autoent.ExistOpen(path, -1, !FdManager::IsCacheDir()))){