2 #define _FILE_OFFSET_BITS 64 10 #include <sys/param.h> 12 #include <sys/statvfs.h> 13 #include <sys/ucred.h> 14 #include <sys/mount.h> 24 #pragma GCC diagnostic ignored "-Wformat" // shut warning on '%z' 63 static const char procfs[] =
"/proc/filesystems";
64 FILE *fs = fopen(procfs,
"r");
68 <<
"Cannot read '" << procfs <<
"': " << strerror(nerr) <<
" (error " << nerr <<
")";
80 if ((nread = getdelim(&type, &len,
'\t', fs)) == -1 && !feof(fs)) {
81 fprintf(
stderr,
"%s:%d: %s (%zd; 1)\n", procfs, line, strerror(errno), nread);
87 if ((nread = getdelim(&fstype, &len,
'\n', fs)) == -1 && !feof(fs)) {
88 fprintf(
stderr,
"%s:%d: %s (%zd; 2)\n", procfs, line, strerror(errno), nread);
101 if (!strcmp(type,
"nodev\t") || !strcmp(fstype,
"lustre\n") || !strncmp(fstype,
"fuse", 4)) {
108 fstype[nread - 1] = 0;
130 struct statfs *
m =
static_cast<struct statfs *
>(
arg);
131 size_t infolen =
sizeof(
struct FSInfo);
132 size_t fslen = strlen(m->f_mntfromname) + 1;
133 size_t dirlen = strlen(m->f_mntonname) + 1;
134 size_t typelen = strlen(m->f_fstypename) + 1;
135 size_t totlen = infolen + fslen + dirlen + typelen;
138 i->
fsname = strncpy(p += infolen, m->f_mntfromname, fslen);
139 i->
type = strncpy(p += fslen, m->f_fstypename, typelen);
140 i->
dir = strncpy(p += typelen, m->f_mntonname, dirlen);
141 i->
dev = m->f_fsid.val[0];
146 if (m->f_bsize > 0) {
149 i->
freespc /= 1024. * 1024. * 1024.;
157 i->
local = ((m->f_flags & MNT_LOCAL) ? 1 : 0);
162 mntent *m =
static_cast<mntent *
>(
arg);
163 size_t infolen =
sizeof(
struct FSInfo);
164 size_t fslen = strlen(m->mnt_fsname) + 1;
165 size_t dirlen = strlen(m->mnt_dir) + 1;
166 size_t typelen = strlen(m->mnt_type) + 1;
167 size_t originlen = strlen(m->mnt_fsname) + 1;
168 size_t totlen = infolen + fslen + dirlen + typelen + originlen;
171 i->
fsname =
static_cast<char *
>(memcpy(p += infolen, m->mnt_fsname, fslen));
172 i->
type =
static_cast<char *
>(memcpy(p += fslen, m->mnt_type, typelen));
173 i->
dir =
static_cast<char *
>(memcpy(p += typelen, m->mnt_dir, dirlen));
174 i->
origin =
static_cast<char *
>(memcpy(p += dirlen, m->mnt_fsname, originlen));
180 i->
bind = strstr(m->mnt_opts,
"bind") !=
nullptr;
199 struct statfs *mtab = 0;
200 if ((rc = getmntinfo(&mtab, MNT_NOWAIT)) < 0) {
203 <<
"getmntinfo() failed: " << strerror(nerr) <<
" (error " << nerr <<
")";
208 for (
int ix = 0; ix < rc; ++ix)
213 const char *
const _PATH_MOUNTED_LINUX =
"/proc/self/mounts";
215 FILE *mtab = setmntent(_PATH_MOUNTED_LINUX,
"r");
219 <<
"Cannot read '" << _PATH_MOUNTED_LINUX <<
"': " << strerror(nerr) <<
" (error " << nerr <<
")";
224 while ((m = getmntent(mtab)))
247 if (lstat(i->
dir, &s) < 0) {
251 if (nerr != ENOENT && nerr != EACCES)
253 <<
"Cannot lstat('" << i->
dir <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
257 if (statfs(i->
dir, &sfs) < 0) {
261 <<
"Cannot statfs('" << i->
dir <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
267 if (sfs.f_bsize > 0) {
270 i->
freespc /= 1024. * 1024. * 1024.;
273 }
else if (i->
fstype == -1) {
297 std::vector<std::string> &prev_paths)
const {
298 for (
const auto &old_path : prev_paths) {
299 if (!strcmp(old_path.c_str(),
path)) {
300 edm::LogWarning(
"LocalFileSystem::findMount()") <<
"Found a loop in bind mounts; stopping evaluation.";
307 size_t len = strlen(path);
308 for (
size_t i = 0;
i <
fs_.size(); ++
i) {
317 size_t fslen = strlen(
fs_[
i]->
dir);
318 if (!strncmp(
fs_[
i]->
dir, path, fslen) &&
319 ((fslen == 1 &&
fs_[
i]->
dir[0] ==
'/') || len == fslen || path[fslen] ==
'/') &&
320 (!best || fslen > bestlen || (fslen == bestlen && !best->
local))) {
330 if (
fs_[i]->
dev != s->st_dev ||
fs_[i]->fstype != sfs->f_type) {
347 fullpath = strdup(best->
origin);
349 if (lstat(fullpath, &s2) < 0) {
351 edm::LogWarning(
"LocalFileSystem::findMount()") <<
"Cannot lstat('" << fullpath <<
"' alias '" << path
352 <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
357 if (statfs(fullpath, &sfs2) < 0) {
359 edm::LogWarning(
"LocalFileSystem::findMount()") <<
"Cannot statfs('" << fullpath <<
"' alias '" << path
360 <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
365 prev_paths.push_back(path);
367 return new_best ? new_best : best;
385 char *
fullpath = realpath(path.c_str(),
nullptr);
388 fullpath = strdup(path.c_str());
390 if (lstat(fullpath, &s) < 0) {
393 <<
"Cannot lstat('" << fullpath <<
"' alias '" << path <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
398 if (statfs(fullpath, &sfs) < 0) {
400 edm::LogWarning(
"LocalFileSystem::isLocalPath()") <<
"Cannot statfs('" << fullpath <<
"' alias '" << path
401 <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
406 std::vector<std::string> prev_paths;
410 return m ? m->
local :
false;
432 double minFreeSpace)
const {
435 std::ostringstream warningst;
436 warningst <<
"Cannot use lazy-download because:\n";
438 for (
size_t i = 0,
e = paths.size();
i <
e; ++
i) {
440 const char *inpath = paths[
i].c_str();
441 const char *
path = inpath;
444 char *
p = std::getenv(path + 1);
447 else if (!strcmp(path,
"$TMPDIR"))
451 if (!(fullpath = realpath(path,
nullptr)))
452 fullpath = strdup(path);
456 <<
"Checking if '" << fullpath <<
"', from '" 457 << inpath <<
"' is valid cache path with " 458 << minFreeSpace <<
" free space" << std::endl;
461 if (lstat(fullpath, &s) < 0) {
463 if (nerr != ENOENT && nerr != EACCES)
464 edm::LogWarning(
"LocalFileSystem::findCachePath()") <<
"Cannot lstat('" << fullpath <<
"', from '" << inpath
465 <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
470 if (statfs(fullpath, &sfs) < 0) {
472 edm::LogWarning(
"LocalFileSystem::findCachePath()") <<
"Cannot statfs('" << fullpath <<
"', from '" << inpath
473 <<
"'): " << strerror(nerr) <<
" (error " << nerr <<
")";
478 std::vector<std::string> prev_paths;
482 <<
"Candidate '" << fullpath <<
"': " 483 <<
"found=" << (m ? 1 : 0)
484 <<
" local=" << (m && m->
local)
485 <<
" free=" << (m ? m->
freespc : 0)
486 <<
" access=" << access(fullpath, W_OK)
490 if (m && m->
local && m->
freespc >= minFreeSpace && access(fullpath, W_OK) == 0) {
496 warningst <<
"- The mount " << fullpath <<
" is not local.\n";
497 }
else if (m->
freespc < minFreeSpace) {
498 warningst <<
" - The mount at " << fullpath <<
" has only " << m->
freespc <<
" GB free; a minumum of " 499 << minFreeSpace <<
" GB is required.\n";
500 }
else if (access(fullpath, W_OK)) {
501 warningst <<
" - The process has no permission to write into " << fullpath <<
"\n";
509 if (!warning_str.empty()) {
510 warning_str = warning_str.substr(0, warning_str.size() - 2);
527 for (
size_t i = 0,
e =
fs_.size();
i <
e; ++
i)
int statFSInfo(FSInfo *i) const
ret
prodAgent to be discontinued
Information about file systems on this node.
std::vector< std::string > fstypes_
FSInfo * initFSInfo(void *p)
bool isLocalPath(const std::string &path) const
std::atomic< bool > checked
std::pair< std::string, std::string > findCachePath(const std::vector< std::string > &paths, double minFreeSpace) const
std::vector< FSInfo * > fs_
FSInfo * findMount(const char *path, struct statfs *sfs, struct stat *s, std::vector< std::string > &) const