summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2021-03-11 11:58:29 +0000
committerGabriel Masei <gabriel.masei@1and1.ro>2021-03-12 14:03:57 +0200
commitde89da293a40385e0ef0194f8a0a0197eb39efe6 (patch)
tree3558cef7651cd754600589856673045f864b15e1
parentDon't steal focus from inputs in calc (diff)
downloadonline-feature/michael/overlayfs.tar.gz
online-feature/michael/overlayfs.zip
Optimize for overlayfs by forcing an initial copy to linkable/ feature/michael/overlayfs
built-in hard-link support performs extremely badly otherwise. Change-Id: I26d5080590538cb6342d64e2e0a4023bbc84c427 Signed-off-by: Michael Meeks <michael.meeks@collabora.com>
-rw-r--r--kit/Kit.cpp42
1 files changed, 36 insertions, 6 deletions
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 7c68c21eca..9d427bd941 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -16,6 +16,8 @@
#include <dlfcn.h>
#ifdef __linux__
#include <ftw.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
#include <sys/capability.h>
#include <sys/sysmacros.h>
#endif
@@ -150,12 +152,34 @@ namespace
LinkOrCopyType linkOrCopyType;
std::string sourceForLinkOrCopy;
Path destinationForLinkOrCopy;
+ bool forceInitialCopy; // some stackable file-systems have very slow first hard link creation
std::string linkableForLinkOrCopy; // Place to stash copies that we can hard-link from
std::chrono::time_point<std::chrono::steady_clock> linkOrCopyStartTime;
bool linkOrCopyVerboseLogging = false;
unsigned linkOrCopyFileCount = 0; // Track to help quantify the link-or-copy performance.
constexpr unsigned SlowLinkOrCopyLimitInSecs = 2; // After this many seconds, start spamming the logs.
+ bool detectSlowStackingFileSystem(const std::string &directory)
+ {
+#ifdef __linux__
+ struct statfs fs = {};
+ if (::statfs(directory.c_str(), &fs) != 0)
+ {
+ LOG_SYS("statfs failed on '" << directory << "'");
+ return false;
+ }
+ switch (fs.f_type) {
+// case FUSE_SUPER_MAGIC: ?
+ case OVERLAYFS_SUPER_MAGIC:
+ return true;
+ default:
+ return false;
+ }
+#else
+ return false;
+#endif
+ }
+
/// Returns the LinkOrCopyType as a human-readable string (for logging).
std::string linkOrCopyTypeString(LinkOrCopyType type)
{
@@ -253,17 +277,22 @@ namespace
if (linkOrCopyVerboseLogging)
LOG_INF("Linking file \"" << fpath << "\" to \"" << newPath << '"');
- // first try a simple hard-link
- if (link(fpath, newPath.c_str()) == 0)
- return;
+ if (!forceInitialCopy)
+ {
+ // first try a simple hard-link
+ if (link(fpath, newPath.c_str()) == 0)
+ return;
+ }
+ // else always copy before linking to linkable/
// incrementally build our 'linkable/' copy nearby
static bool canChown = true; // only if we can get permissions right
- if (errno == EXDEV && canChown)
+ if ((forceInitialCopy || errno == EXDEV) && canChown)
{
// then copy somewhere closer and hard link from there
- LOG_TRC("link(\"" << fpath << "\", \"" << newPath << "\") failed: " << strerror(errno)
- << ". Will try to link template.");
+ if (!forceInitialCopy)
+ LOG_TRC("link(\"" << fpath << "\", \"" << newPath << "\") failed: " << strerror(errno)
+ << ". Will try to link template.");
std::string linkableCopy = linkableForLinkOrCopy + fpath;
if (::link(linkableCopy.c_str(), newPath.c_str()) == 0)
@@ -432,6 +461,7 @@ namespace
linkableForLinkOrCopy = linkable;
linkOrCopyFileCount = 0;
linkOrCopyStartTime = std::chrono::steady_clock::now();
+ forceInitialCopy = detectSlowStackingFileSystem(destination.toString());
if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_ACTIONRETVAL|FTW_PHYS) == -1)
{