Merge pull request #1365 from ggtakec/check_lseek

Dynamically determine whether lseek extended options are supported
This commit is contained in:
Takeshi Nakatani 2020-08-20 22:36:56 +09:00 committed by GitHub
commit a5186c73c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 0 deletions

View File

@ -55,6 +55,19 @@ using namespace std;
static const int MAX_MULTIPART_CNT = 10 * 1000; // S3 multipart max count
static const int CHECK_CACHEFILE_PART_SIZE = 1024 * 16; // Buffer size in PageList::CheckZeroAreaInFile()
//
// [NOTE]
// If the following symbols in lseek whence are undefined, define them.
// If it is not supported by lseek, s3fs judges by the processing result of lseek.
//
#ifndef SEEK_DATA
#define SEEK_DATA 3
#endif
#ifndef SEEK_HOLE
#define SEEK_HOLE 4
#endif
#define TMPFILE_FOR_CHECK_HOLE "/tmp/.s3fs_hole_check.tmp"
//
// For cache directory top path
//
@ -2719,6 +2732,8 @@ string FdManager::cache_dir;
bool FdManager::check_cache_dir_exist(false);
off_t FdManager::free_disk_space = 0;
std::string FdManager::check_cache_output;
bool FdManager::checked_lseek(false);
bool FdManager::have_lseek_hole(false);
//------------------------------------------------
// FdManager class methods
@ -2928,6 +2943,43 @@ bool FdManager::IsSafeDiskSpace(const char* path, off_t size)
return size + FdManager::GetEnsureFreeDiskSpace() <= fsize;
}
bool FdManager::HaveLseekHole(void)
{
if(FdManager::checked_lseek){
return FdManager::have_lseek_hole;
}
// create tempolary file
int fd;
if(-1 == (fd = open(TMPFILE_FOR_CHECK_HOLE, O_CREAT|O_RDWR, 0600))){
S3FS_PRN_ERR("failed to open tempolary file(%s) - errno(%d)", TMPFILE_FOR_CHECK_HOLE, errno);
FdManager::checked_lseek = true;
FdManager::have_lseek_hole = false;
return FdManager::have_lseek_hole;
}
// check SEEK_DATA/SEEK_HOLE options
bool result = true;
if(-1 == lseek(fd, 0, SEEK_DATA)){
if(EINVAL == errno){
S3FS_PRN_ERR("lseek does not support SEEK_DATA");
result = false;
}
}
if(result && -1 == lseek(fd, 0, SEEK_HOLE)){
if(EINVAL == errno){
S3FS_PRN_ERR("lseek does not support SEEK_HOLE");
result = false;
}
}
close(fd);
unlink(TMPFILE_FOR_CHECK_HOLE);
FdManager::checked_lseek = true;
FdManager::have_lseek_hole = result;
return FdManager::have_lseek_hole;
}
//------------------------------------------------
// FdManager methods
//------------------------------------------------
@ -3470,6 +3522,11 @@ bool FdManager::RawCheckAllCache(FILE* fp, const char* cache_stat_top_dir, const
bool FdManager::CheckAllCache()
{
if(!FdManager::HaveLseekHole()){
S3FS_PRN_ERR("lseek does not support SEEK_DATA/SEEK_HOLE, then could not check cache.");
return false;
}
FILE* fp;
if(FdManager::check_cache_output.empty()){
fp = stdout;

View File

@ -232,6 +232,8 @@ class FdManager
static bool check_cache_dir_exist;
static off_t free_disk_space; // limit free disk space
static std::string check_cache_output;
static bool checked_lseek;
static bool have_lseek_hole;
fdent_map_t fent;
@ -265,6 +267,7 @@ class FdManager
static bool IsSafeDiskSpace(const char* path, off_t size);
static void FreeReservedDiskSpace(off_t size);
static bool ReserveDiskSpace(off_t size);
static bool HaveLseekHole(void);
// Return FdEntity associated with path, returning NULL on error. This operation increments the reference count; callers must decrement via Close after use.
FdEntity* GetFdEntity(const char* path, int existfd = -1);

View File

@ -93,6 +93,11 @@ void S3fsSignals::HandlerUSR1(int sig)
bool S3fsSignals::SetUsr1Handler(const char* path)
{
if(!FdManager::HaveLseekHole()){
S3FS_PRN_ERR("Could not set SIGUSR1 for checking cache, because this system does not support SEEK_DATA/SEEK_HOLE in lseek function.");
return false;
}
// set output file
if(!FdManager::SetCacheCheckOutput(path)){
S3FS_PRN_ERR("Could not set output file(%s) for checking cache.", path ? path : "null(stdout)");