From 20da0e4dd3c2536424a9191f8ced27340b452a43 Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Fri, 8 Sep 2017 15:23:10 -0400 Subject: [PATCH] Fix intermittent upload failures on macOS There were multiple problems with the FdManager::GetFreeDiskSpace() function on macOS: 1) When calling statvfs(), f_frsize should be used instead of f_bsize when converting available blocks to bytes. This was causing the free space calculation to be incorrect. 2) On macOS, fsblkcnt_t is a 32-bit integer. Thus, when calculating available disk space, there were frequently overflows. This caused s3fs to incorrectly determine that the cache location was out of space in the middle of a transfer which caused uploads to fail. Changing this to a uint64_t resolves the problem. --- src/fdcache.cpp | 6 +++--- src/fdcache.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fdcache.cpp b/src/fdcache.cpp index 1042fba..af82be6 100644 --- a/src/fdcache.cpp +++ b/src/fdcache.cpp @@ -1908,7 +1908,7 @@ size_t FdManager::SetEnsureFreeDiskSpace(size_t size) return old; } -fsblkcnt_t FdManager::GetFreeDiskSpace(const char* path) +uint64_t FdManager::GetFreeDiskSpace(const char* path) { struct statvfs vfsbuf; string ctoppath; @@ -1930,12 +1930,12 @@ fsblkcnt_t FdManager::GetFreeDiskSpace(const char* path) S3FS_PRN_ERR("could not get vfs stat by errno(%d)", errno); return 0; } - return (vfsbuf.f_bavail * vfsbuf.f_bsize); + return (vfsbuf.f_bavail * vfsbuf.f_frsize); } bool FdManager::IsSafeDiskSpace(const char* path, size_t size) { - fsblkcnt_t fsize = FdManager::GetFreeDiskSpace(path); + uint64_t fsize = FdManager::GetFreeDiskSpace(path); return ((size + FdManager::GetEnsureFreeDiskSpace()) <= fsize); } diff --git a/src/fdcache.h b/src/fdcache.h index 9931782..13f5bcf 100644 --- a/src/fdcache.h +++ b/src/fdcache.h @@ -194,7 +194,7 @@ class FdManager fdent_map_t fent; private: - static fsblkcnt_t GetFreeDiskSpace(const char* path); + static uint64_t GetFreeDiskSpace(const char* path); void CleanupCacheDirInternal(const std::string &path = ""); public: