mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-11-16 09:17:11 +00:00
Break FdEntity locks into data and metadata
Previously long-running data operations like RowFlush would block metadata operations like GetStats and thus user readdir. Fixes #928.
This commit is contained in:
parent
21321a9d96
commit
ecf13a8cb9
@ -623,14 +623,16 @@ int FdEntity::FillFile(int fd, unsigned char byte, off_t size, off_t start)
|
|||||||
// FdEntity methods
|
// FdEntity methods
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
FdEntity::FdEntity(const char* tpath, const char* cpath)
|
FdEntity::FdEntity(const char* tpath, const char* cpath)
|
||||||
: is_lock_init(false), refcnt(0), path(SAFESTRPTR(tpath)), cachepath(SAFESTRPTR(cpath)), mirrorpath(""),
|
: is_lock_init(false), refcnt(0), path(SAFESTRPTR(tpath)),
|
||||||
fd(-1), pfile(NULL), is_modify(false), size_orgmeta(0), upload_id(""), mp_start(0), mp_size(0)
|
fd(-1), pfile(NULL), size_orgmeta(0), upload_id(""), mp_start(0), mp_size(0), is_modify(false),
|
||||||
|
cachepath(SAFESTRPTR(cpath)), mirrorpath("")
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
pthread_mutexattr_init(&attr);
|
pthread_mutexattr_init(&attr);
|
||||||
pthread_mutexattr_settype(&attr, S3FS_MUTEX_RECURSIVE); // recursive mutex
|
pthread_mutexattr_settype(&attr, S3FS_MUTEX_RECURSIVE); // recursive mutex
|
||||||
pthread_mutex_init(&fdent_lock, &attr);
|
pthread_mutex_init(&fdent_lock, &attr);
|
||||||
|
pthread_mutex_init(&fdent_data_lock, &attr);
|
||||||
is_lock_init = true;
|
is_lock_init = true;
|
||||||
}catch(exception& e){
|
}catch(exception& e){
|
||||||
S3FS_PRN_CRIT("failed to init mutex");
|
S3FS_PRN_CRIT("failed to init mutex");
|
||||||
@ -643,6 +645,7 @@ FdEntity::~FdEntity()
|
|||||||
|
|
||||||
if(is_lock_init){
|
if(is_lock_init){
|
||||||
try{
|
try{
|
||||||
|
pthread_mutex_destroy(&fdent_data_lock);
|
||||||
pthread_mutex_destroy(&fdent_lock);
|
pthread_mutex_destroy(&fdent_lock);
|
||||||
}catch(exception& e){
|
}catch(exception& e){
|
||||||
S3FS_PRN_CRIT("failed to destroy mutex");
|
S3FS_PRN_CRIT("failed to destroy mutex");
|
||||||
@ -654,6 +657,7 @@ FdEntity::~FdEntity()
|
|||||||
void FdEntity::Clear()
|
void FdEntity::Clear()
|
||||||
{
|
{
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_lock);
|
||||||
|
AutoLock auto_data_lock(&fdent_data_lock);
|
||||||
|
|
||||||
if(-1 != fd){
|
if(-1 != fd){
|
||||||
if(!cachepath.empty()){
|
if(!cachepath.empty()){
|
||||||
@ -696,6 +700,7 @@ void FdEntity::Close()
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if(0 == refcnt){
|
if(0 == refcnt){
|
||||||
|
AutoLock auto_data_lock(&fdent_data_lock);
|
||||||
if(!cachepath.empty()){
|
if(!cachepath.empty()){
|
||||||
CacheFileStat cfstat(path.c_str());
|
CacheFileStat cfstat(path.c_str());
|
||||||
if(!pagelist.Serialize(cfstat, true)){
|
if(!pagelist.Serialize(cfstat, true)){
|
||||||
@ -796,6 +801,7 @@ int FdEntity::Open(headers_t* pmeta, off_t size, time_t time, bool no_fd_lock_wa
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoLock auto_data_lock(&fdent_data_lock);
|
||||||
if(-1 != fd){
|
if(-1 != fd){
|
||||||
// already opened, needs to increment refcnt.
|
// already opened, needs to increment refcnt.
|
||||||
Dup();
|
Dup();
|
||||||
@ -994,7 +1000,7 @@ bool FdEntity::OpenAndLoadAll(headers_t* pmeta, off_t* size, bool force_load)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
if(force_load){
|
if(force_load){
|
||||||
SetAllStatusUnloaded();
|
SetAllStatusUnloaded();
|
||||||
@ -1173,7 +1179,7 @@ int FdEntity::Load(off_t start, off_t size)
|
|||||||
if(-1 == fd){
|
if(-1 == fd){
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
@ -1475,7 +1481,7 @@ int FdEntity::RowFlush(const char* tpath, bool force_sync)
|
|||||||
if(-1 == fd){
|
if(-1 == fd){
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
if(!force_sync && !is_modify){
|
if(!force_sync && !is_modify){
|
||||||
// nothing to update.
|
// nothing to update.
|
||||||
@ -1629,7 +1635,7 @@ ssize_t FdEntity::Read(char* bytes, off_t start, size_t size, bool force_load)
|
|||||||
if(-1 == fd){
|
if(-1 == fd){
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
if(force_load){
|
if(force_load){
|
||||||
pagelist.SetPageLoadedStatus(start, size, false);
|
pagelist.SetPageLoadedStatus(start, size, false);
|
||||||
@ -1692,7 +1698,7 @@ ssize_t FdEntity::Write(const char* bytes, off_t start, size_t size)
|
|||||||
if(FdManager::IsCacheDir() && !FdManager::IsSafeDiskSpace(NULL, size)){
|
if(FdManager::IsCacheDir() && !FdManager::IsSafeDiskSpace(NULL, size)){
|
||||||
FdManager::get()->CleanupCacheDir();
|
FdManager::get()->CleanupCacheDir();
|
||||||
}
|
}
|
||||||
AutoLock auto_lock(&fdent_lock);
|
AutoLock auto_lock(&fdent_data_lock);
|
||||||
|
|
||||||
// check file size
|
// check file size
|
||||||
if(pagelist.Size() < start){
|
if(pagelist.Size() < start){
|
||||||
|
@ -112,22 +112,23 @@ class FdEntity
|
|||||||
private:
|
private:
|
||||||
pthread_mutex_t fdent_lock;
|
pthread_mutex_t fdent_lock;
|
||||||
bool is_lock_init;
|
bool is_lock_init;
|
||||||
PageList pagelist;
|
|
||||||
int refcnt; // reference count
|
int refcnt; // reference count
|
||||||
std::string path; // object path
|
std::string path; // object path
|
||||||
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
|
|
||||||
int fd; // file descriptor(tmp file or cache file)
|
int fd; // file descriptor(tmp file or cache file)
|
||||||
FILE* pfile; // file pointer(tmp file or cache file)
|
FILE* pfile; // file pointer(tmp file or cache file)
|
||||||
bool is_modify; // if file is changed, this flag is true
|
|
||||||
headers_t orgmeta; // original headers at opening
|
headers_t orgmeta; // original headers at opening
|
||||||
off_t size_orgmeta; // original file size in original headers
|
off_t size_orgmeta; // original file size in original headers
|
||||||
|
|
||||||
|
pthread_mutex_t fdent_data_lock;// protects the following members
|
||||||
|
PageList pagelist;
|
||||||
std::string upload_id; // for no cached multipart uploading when no disk space
|
std::string upload_id; // for no cached multipart uploading when no disk space
|
||||||
etaglist_t etaglist; // for no cached multipart uploading when no disk space
|
etaglist_t etaglist; // for no cached multipart uploading when no disk space
|
||||||
off_t mp_start; // start position for no cached multipart(write method only)
|
off_t mp_start; // start position for no cached multipart(write method only)
|
||||||
off_t mp_size; // size for no cached multipart(write method only)
|
off_t mp_size; // size for no cached multipart(write method only)
|
||||||
|
bool is_modify; // if file is changed, this flag is true
|
||||||
|
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
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int FillFile(int fd, unsigned char byte, off_t size, off_t start);
|
static int FillFile(int fd, unsigned char byte, off_t size, off_t start);
|
||||||
|
Loading…
Reference in New Issue
Block a user