loolwsd/LOOLWSD.cpp | 6 ++++ loolwsd/Util.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++- loolwsd/Util.hpp | 7 ++++ 3 files changed, 85 insertions(+), 1 deletion(-)
New commits: commit 86bd8426d06590d2a10d7bb8e2e64aa468bb2309 Author: Tor Lillqvist <t...@collabora.com> Date: Thu Sep 29 17:47:28 2016 +0300 More work on disk space monitoring Monitor the disk space on important file systems: The ones where cached tiles are stored and where the chroot jails are created. Those might be the same file system of course, the code checks and doesn't do needless work. The check is done whenever a new loolkit process is taken into use and a new chroot jail it constructed, and whenever a new client session connects to a document. We don't check more often than once a minute, though. Still need to add code to guard against running out of diska space when saving documents back to where they were opened from. For that presumably need to enhance the Storage abstraction. diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp index aa45795..57ad7f9 100644 --- a/loolwsd/LOOLWSD.cpp +++ b/loolwsd/LOOLWSD.cpp @@ -186,6 +186,7 @@ static void forkChildren(const int number) if (number > 0) { + Util::checkDiskSpace(""); const std::string aMessage = "spawn " + std::to_string(number) + "\n"; Log::debug("MasterToForKit: " + aMessage.substr(0, aMessage.length() - 1)); IoUtil::writeFIFO(LOOLWSD::ForKitWritePipe, aMessage); @@ -716,6 +717,8 @@ private: Log::trace("Sending to Client [" + status + "]."); ws->sendFrame(status.data(), (int) status.size()); + Util::checkDiskSpace(""); + // Let messages flow IoUtil::SocketProcessor(ws, [&session](const std::vector<char>& payload) @@ -1766,6 +1769,9 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/) else if (ChildRoot[ChildRoot.size() - 1] != '/') ChildRoot += '/'; + Util::checkDiskSpace(ChildRoot); + Util::checkDiskSpace(Cache + "/."); + if (FileServerRoot.empty()) FileServerRoot = Poco::Path(Application::instance().commandPath()).parent().parent().toString(); FileServerRoot = Poco::Path(FileServerRoot).absolute().toString(); diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp index c3a5786..2ff8532 100644 --- a/loolwsd/Util.cpp +++ b/loolwsd/Util.cpp @@ -14,7 +14,9 @@ #include <csignal> #include <sys/poll.h> #include <sys/prctl.h> +#include <sys/stat.h> #include <sys/uio.h> +#include <sys/vfs.h> #include <unistd.h> #include <atomic> @@ -110,7 +112,7 @@ namespace { void alertAllUsersAndLog(const std::string& message, const std::string& cmd, const std::string& kind) { - Log::error(message + " Removing."); + Log::error(message); Util::alertAllUsers(cmd, kind); } } @@ -210,6 +212,75 @@ namespace Util } } + void checkDiskSpace(const std::string& path) + { + static std::mutex mutex; + std::lock_guard<std::mutex> lock(mutex); + + struct fs + { + fs(const std::string& p, dev_t d) + : path(p), dev(d) + { + } + + fs(dev_t d) + : fs("", d) + { + } + + std::string path; + dev_t dev; + }; + + struct fsComparator + { + bool operator() (const fs& lhs, const fs& rhs) const + { + return (lhs.dev < rhs.dev); + } + }; + + static std::set<fs, fsComparator> filesystems; + + if (path != "") + { + std::string dirPath = path; + std::string::size_type lastSlash = dirPath.rfind('/'); + assert(lastSlash != std::string::npos); + dirPath = dirPath.substr(0, lastSlash + 1) + "."; + + struct stat s; + if (stat(dirPath.c_str(), &s) == -1) + return; + filesystems.insert(fs(dirPath, s.st_dev)); + } + + static std::chrono::steady_clock::time_point lastCheck; + std::chrono::steady_clock::time_point now(std::chrono::steady_clock::now()); + + // Don't check disk space more often that once a minute + if (std::chrono::duration_cast<std::chrono::seconds>(now - lastCheck).count() < 60) + return; + + lastCheck = now; + + for (auto& i: filesystems) + { + struct stat s; + struct statfs sfs; + if (stat(i.path.c_str(), &s) == -1 || + statfs(i.path.c_str(), &sfs) == -1) + continue; + + if (static_cast<double>(sfs.f_bavail) / sfs.f_blocks <= 0.05) + { + alertAllUsersAndLog("File system of " + i.path + " dangerously low on disk space", "internal", "diskfull"); + break; + } + } + } + const char *signalName(const int signo) { switch (signo) diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp index 53c28a9..04673d0 100644 --- a/loolwsd/Util.hpp +++ b/loolwsd/Util.hpp @@ -73,6 +73,13 @@ namespace Util } #endif + // Check disk space on a list of file systems. The list is initially empty, and each call to the + // function with a non-empty 'path' adds the file system that path is located on to the list, if + // not already there. If the free space on any of the file systems in question is below 5%, call + // 'alertAllUsers("internal", "diskfull")'. The check will be made no more often than once a + // minute. + void checkDiskSpace(const std::string& path); + /// Assert that a lock is already taken. template <typename T> void assertIsLocked(T& lock) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits