Introduced pseudo fd and separated fd for each file opening

This commit is contained in:
Takeshi Nakatani
2021-05-23 16:28:50 +00:00
committed by Andrew Gaul
parent 53dfd48f59
commit ac578d188e
14 changed files with 1068 additions and 573 deletions

View File

@ -28,6 +28,7 @@
#include "common.h"
#include "s3fs.h"
#include "fdcache.h"
#include "fdcache_pseudofd.h"
#include "s3fs_util.h"
#include "s3fs_logger.h"
#include "string_util.h"
@ -344,6 +345,16 @@ bool FdManager::HaveLseekHole()
return FdManager::have_lseek_hole;
}
bool FdManager::HasOpenEntityFd(const char* path)
{
FdEntity* ent;
int fd = -1;
if(NULL == (ent = FdManager::singleton.GetFdEntity(path, fd, false))){
return false;
}
return (0 < ent->GetOpenCount());
}
//------------------------------------------------
// FdManager methods
//------------------------------------------------
@ -379,7 +390,7 @@ FdManager::~FdManager()
if(this == FdManager::get()){
for(fdent_map_t::iterator iter = fent.begin(); fent.end() != iter; ++iter){
FdEntity* ent = (*iter).second;
S3FS_PRN_WARN("To exit with the cache file opened: path=%s, refcnt=%d", ent->GetPath(), ent->GetRefCnt());
S3FS_PRN_WARN("To exit with the cache file opened: path=%s, refcnt=%d", ent->GetPath(), ent->GetOpenCount());
delete ent;
}
fent.clear();
@ -405,7 +416,7 @@ FdManager::~FdManager()
}
}
FdEntity* FdManager::GetFdEntity(const char* path, int existfd, bool increase_ref)
FdEntity* FdManager::GetFdEntity(const char* path, int& existfd, bool newfd)
{
S3FS_PRN_INFO3("[path=%s][fd=%d]", SAFESTRPTR(path), existfd);
@ -415,22 +426,29 @@ FdEntity* FdManager::GetFdEntity(const char* path, int existfd, bool increase_re
AutoLock auto_lock(&FdManager::fd_manager_lock);
fdent_map_t::iterator iter = fent.find(std::string(path));
if(fent.end() != iter && (-1 == existfd || (*iter).second->GetFd() == existfd)){
if(increase_ref){
iter->second->Dup();
if(fent.end() != iter && iter->second){
if(-1 == existfd){
if(newfd){
existfd = iter->second->OpenPseudoFd(O_RDWR); // [NOTE] O_RDWR flags
}
return iter->second;
}else if(iter->second->FindPseudoFd(existfd)){
if(newfd){
existfd = iter->second->Dup(existfd);
}
return iter->second;
}
return (*iter).second;
}
if(-1 != existfd){
for(iter = fent.begin(); iter != fent.end(); ++iter){
if((*iter).second && (*iter).second->GetFd() == existfd){
if(iter->second && iter->second->FindPseudoFd(existfd)){
// found opened fd in map
if(0 == strcmp((*iter).second->GetPath(), path)){
if(increase_ref){
iter->second->Dup();
if(0 == strcmp(iter->second->GetPath(), path)){
if(newfd){
existfd = iter->second->Dup(existfd);
}
return (*iter).second;
return iter->second;
}
// found fd, but it is used another file(file descriptor is recycled)
// so returns NULL.
@ -438,24 +456,30 @@ FdEntity* FdManager::GetFdEntity(const char* path, int existfd, bool increase_re
}
}
}
// If the cache directory is not specified, s3fs opens a temporary file
// when the file is opened.
if(!FdManager::IsCacheDir()){
for(iter = fent.begin(); iter != fent.end(); ++iter){
if(iter->second && iter->second->IsOpen() && 0 == strcmp(iter->second->GetPath(), path)){
return iter->second;
}
}
}
return NULL;
}
FdEntity* FdManager::Open(const char* path, headers_t* pmeta, off_t size, time_t time, bool force_tmpfile, bool is_create, bool no_fd_lock_wait)
FdEntity* FdManager::Open(int& fd, const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, bool no_fd_lock_wait)
{
S3FS_PRN_DBG("[path=%s][size=%lld][time=%lld]", SAFESTRPTR(path), static_cast<long long>(size), static_cast<long long>(time));
S3FS_PRN_DBG("[path=%s][size=%lld][time=%lld][flags=0x%x]", SAFESTRPTR(path), static_cast<long long>(size), static_cast<long long>(time), flags);
if(!path || '\0' == path[0]){
return NULL;
}
bool close = false;
FdEntity* ent;
AutoLock auto_lock(&FdManager::fd_manager_lock);
// search in mapping by key(path)
fdent_map_t::iterator iter = fent.find(std::string(path));
if(fent.end() == iter && !force_tmpfile && !FdManager::IsCacheDir()){
// If the cache directory is not specified, s3fs opens a temporary file
// when the file is opened.
@ -463,16 +487,17 @@ FdEntity* FdManager::Open(const char* path, headers_t* pmeta, off_t size, time_t
// search a entity in all which opened the temporary file.
//
for(iter = fent.begin(); iter != fent.end(); ++iter){
if((*iter).second && (*iter).second->IsOpen() && 0 == strcmp((*iter).second->GetPath(), path)){
if(iter->second && iter->second->IsOpen() && 0 == strcmp(iter->second->GetPath(), path)){
break; // found opened fd in mapping
}
}
}
FdEntity* ent;
if(fent.end() != iter){
// found
ent = (*iter).second;
ent->Dup();
ent = iter->second;
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;
@ -480,7 +505,12 @@ FdEntity* FdManager::Open(const char* path, headers_t* pmeta, off_t size, time_t
size = -1;
}
}
close = true;
// (re)open
if(-1 == (fd = ent->Open(pmeta, size, time, flags, no_fd_lock_wait ? AutoLock::NO_WAIT : AutoLock::NON))){
S3FS_PRN_ERR("failed to (re)open and create new pseudo fd for path(%s).", path);
return NULL;
}
}else if(is_create){
// not found
@ -492,6 +522,12 @@ FdEntity* FdManager::Open(const char* path, headers_t* pmeta, off_t size, time_t
// make new obj
ent = new FdEntity(path, cache_path.c_str());
// open
if(-1 == (fd = ent->Open(pmeta, size, time, flags, no_fd_lock_wait ? AutoLock::NO_WAIT : AutoLock::NON))){
delete ent;
return NULL;
}
if(!cache_path.empty()){
// using cache
fent[std::string(path)] = ent;
@ -507,48 +543,44 @@ FdEntity* FdManager::Open(const char* path, headers_t* pmeta, off_t size, time_t
FdManager::MakeRandomTempPath(path, tmppath);
fent[tmppath] = ent;
}
}else{
return NULL;
}
// open
if(0 != ent->Open(pmeta, size, time, no_fd_lock_wait ? AutoLock::NO_WAIT : AutoLock::NONE)){
if(close){
ent->Close();
}
return NULL;
}
if(close){
ent->Close();
}
return ent;
}
FdEntity* FdManager::ExistOpen(const char* path, int existfd, bool ignore_existfd)
// [NOTE]
// This method does not create a new pseudo fd.
// It just finds existfd and returns the corresponding entity.
//
FdEntity* FdManager::GetExistFdEntiy(const char* path, int existfd)
{
S3FS_PRN_DBG("[path=%s][fd=%d][ignore_existfd=%s]", SAFESTRPTR(path), existfd, ignore_existfd ? "true" : "false");
S3FS_PRN_DBG("[path=%s][existfd=%d]", SAFESTRPTR(path), existfd);
// search by real path
FdEntity* ent = Open(path, NULL, -1, -1, false, false);
AutoLock auto_lock(&FdManager::fd_manager_lock);
if(!ent && (ignore_existfd || (-1 != existfd))){
// search from all fdentity because of not using cache.
AutoLock auto_lock(&FdManager::fd_manager_lock);
for(fdent_map_t::iterator iter = fent.begin(); iter != fent.end(); ++iter){
if((*iter).second && (*iter).second->IsOpen() && (ignore_existfd || ((*iter).second->GetFd() == existfd))){
// found opened fd in map
if(0 == strcmp((*iter).second->GetPath(), path)){
ent = (*iter).second;
ent->Dup();
}else{
// found fd, but it is used another file(file descriptor is recycled)
// so returns NULL.
}
break;
}
// search from all entity.
for(fdent_map_t::iterator iter = fent.begin(); iter != fent.end(); ++iter){
if(iter->second && iter->second->FindPseudoFd(existfd)){
// found existfd in entity
return iter->second;
}
}
// not found entity
return NULL;
}
FdEntity* FdManager::OpenExistFdEntiy(const char* path, int& fd, int flags)
{
S3FS_PRN_DBG("[path=%s][flags=0x%x]", SAFESTRPTR(path), flags);
// search entity by path, and create pseudo fd
FdEntity* ent = Open(fd, path, NULL, -1, -1, flags, false, false);
if(!ent){
// Not found entity
return NULL;
}
return ent;
}
@ -564,7 +596,7 @@ void FdManager::Rename(const std::string &from, const std::string &to)
// search a entity in all which opened the temporary file.
//
for(iter = fent.begin(); iter != fent.end(); ++iter){
if((*iter).second && (*iter).second->IsOpen() && 0 == strcmp((*iter).second->GetPath(), from.c_str())){
if(iter->second && iter->second->IsOpen() && 0 == strcmp(iter->second->GetPath(), from.c_str())){
break; // found opened fd in mapping
}
}
@ -574,7 +606,7 @@ void FdManager::Rename(const std::string &from, const std::string &to)
// found
S3FS_PRN_DBG("[from=%s][to=%s]", from.c_str(), to.c_str());
FdEntity* ent = (*iter).second;
FdEntity* ent = iter->second;
// retrieve old fd entity from map
fent.erase(iter);
@ -591,34 +623,33 @@ void FdManager::Rename(const std::string &from, const std::string &to)
}
}
bool FdManager::Close(FdEntity* ent)
bool FdManager::Close(FdEntity* ent, int fd)
{
S3FS_PRN_DBG("[ent->file=%s][ent->fd=%d]", ent ? ent->GetPath() : "", ent ? ent->GetFd() : -1);
S3FS_PRN_DBG("[ent->file=%s][pseudo_fd=%d]", ent ? ent->GetPath() : "", fd);
if(!ent){
if(!ent || -1 == fd){
return true; // returns success
}
AutoLock auto_lock(&FdManager::fd_manager_lock);
for(fdent_map_t::iterator iter = fent.begin(); iter != fent.end(); ++iter){
if((*iter).second == ent){
ent->Close();
if(iter->second == ent){
ent->Close(fd);
if(!ent->IsOpen()){
// remove found entity from map.
fent.erase(iter++);
// check another key name for entity value to be on the safe side
for(; iter != fent.end(); ){
if((*iter).second == ent){
if(iter->second == ent){
fent.erase(iter++);
}else{
++iter;
}
}
delete ent;
}
return true;
}
return true;
}
}
return false;
@ -629,7 +660,7 @@ bool FdManager::ChangeEntityToTempPath(FdEntity* ent, const char* path)
AutoLock auto_lock(&FdManager::fd_manager_lock);
for(fdent_map_t::iterator iter = fent.begin(); iter != fent.end(); ){
if((*iter).second == ent){
if(iter->second == ent){
fent.erase(iter++);
std::string tmppath;