From 55cb8920d540139523b30d3781b64dca9bf1e4cd Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Sun, 16 Aug 2020 12:37:11 +0000 Subject: [PATCH] Dynamically determine whether lseek extended options are supported --- src/fdcache.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++ src/fdcache.h | 3 +++ src/sighandlers.cpp | 5 ++++ 3 files changed, 65 insertions(+) diff --git a/src/fdcache.cpp b/src/fdcache.cpp index e08ac2b..3fa153e 100644 --- a/src/fdcache.cpp +++ b/src/fdcache.cpp @@ -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; diff --git a/src/fdcache.h b/src/fdcache.h index ffd4c73..f77bc3e 100644 --- a/src/fdcache.h +++ b/src/fdcache.h @@ -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); diff --git a/src/sighandlers.cpp b/src/sighandlers.cpp index a1edc82..3529757 100644 --- a/src/sighandlers.cpp +++ b/src/sighandlers.cpp @@ -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)");