cmogstored 1.8.1 - use default system stack size
[cmogstored.git] / mnt_usable.c
blob7f79ca275efa674ff52aa670a8ff2aeb346fbc2e
1 /*
2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
4 */
5 #include "cmogstored.h"
7 /*
8 * statvfs() on GNU/Linux may call stat() internally, and stat() is bad
9 * for network mounts which may be stalled/slow, so favor the non-portable
10 * statfs() on GNU/Linux
12 #ifdef __linux__
13 #include <sys/vfs.h>
14 #define MY_STATFS statfs
15 #else /* statvfs() is POSIX */
16 #define MY_STATFS statvfs
17 #endif
19 static bool resolve_symlink(char **orig)
21 char *p = canonicalize_filename_mode(*orig, CAN_EXISTING);
23 if (p) {
24 free(*orig);
25 *orig = p;
26 return true;
28 return false;
31 static bool stat_harder(struct mount_entry *me)
33 struct stat sb;
35 /* the device number may not have been populated, do it */
36 if (me->me_dev == (dev_t)-1) {
37 if (stat(me->me_mountdir, &sb) != 0)
38 return false;
39 me->me_dev = sb.st_dev;
43 * resolve symlinks for things that look like paths
44 * and skip dead symlinks
46 if (me->me_devname[0] == '/') {
47 if (lstat(me->me_devname, &sb) == 0
48 && S_ISLNK(sb.st_mode)
49 && ! resolve_symlink(&me->me_devname))
50 return false;
52 return true;
56 * prevents us from using filesystems of unknown size, since those could
57 * be stalled/dead network mounts
59 bool mog_mnt_usable(struct mount_entry *me)
61 struct MY_STATFS buf;
62 const char *path = me->me_mountdir;
64 if (me->me_dummy)
65 return false;
67 retry:
68 errno = 0;
69 if (MY_STATFS(path, &buf) == 0)
70 return (buf.f_blocks > 0) ? stat_harder(me) : false;
72 /* unknown */
73 assert(errno != EFAULT && "BUG: EFAULT from statfs/statvfs");
74 switch (errno) {
75 case EINTR: goto retry;
76 case EIO: /* this is important enough to log: */
77 case EOVERFLOW: /* this is important enough to log: */
78 syslog(LOG_ERR, MOG_STR(MY_STATFS) "(%s) failed: %m", path);
79 case ENOTDIR: /* race between read_file_system_list and statvfs */
80 case ELOOP: /* race between read_file_system_list and statvfs? */
81 case ENOSYS: /* if statvfs() doesn't work, fstatvfs() won't, either */
82 case EACCES: /* this is common */
83 return false;
86 * assume other errors are recoverable (or fail elsewhere)
87 * ENAMETOOLONG - would fail anyways if we need to stat(2)
88 * ENOMEM - maybe the kernel will get more memory back, soon
90 return true;