GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/auto_umount.cc
Date: 2026-04-26 02:35:59
Exec Total Coverage
Lines: 0 49 0.0%
Branches: 0 71 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5
6 #include "auto_umount.h"
7
8 #include <dirent.h>
9 #include <errno.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include <string>
14 #include <vector>
15
16 #include "util/capabilities.h"
17 #include "util/logging.h"
18 #include "util/platform.h"
19 #include "util/posix.h"
20
21 using namespace std; // NOLINT
22
23 namespace auto_umount {
24
25 string *mountpoint_ = NULL;
26
27 void SetMountpoint(const string &mountpoint) {
28 if (mountpoint == "") {
29 delete mountpoint_;
30 mountpoint_ = NULL;
31 } else {
32 mountpoint_ = new string(mountpoint);
33 }
34 }
35
36
37 void UmountOnExit(const bool crashed) {
38 const char *cleanuptype = "exit";
39 if (crashed)
40 cleanuptype = "crash";
41
42 if (!mountpoint_) {
43 LogCvmfs(kLogCvmfs, kLogSyslogErr,
44 "%s cleanup handler: no mountpoint",
45 cleanuptype);
46 return;
47 }
48
49 std::vector<std::string> all_mountpoints = platform_mountlist();
50 if (all_mountpoints.empty()) {
51 LogCvmfs(kLogCvmfs, kLogSyslogErr,
52 "%s cleanup handler: "
53 "failed to read mount point list",
54 cleanuptype);
55 return;
56 }
57
58 if (crashed) {
59 // Mitigate auto-mount - crash - umount - auto-mount loops
60 SafeSleepMs(2000);
61 }
62
63 // Check if *mountpoint_ is still mounted
64 // (we don't want to trigger a mount by immediately doing stat *mountpoint_)
65 bool still_mounted = false;
66 for (unsigned i = 0; i < all_mountpoints.size(); ++i) {
67 if (*mountpoint_ == all_mountpoints[i]) {
68 still_mounted = true;
69 break;
70 }
71 }
72 if (!still_mounted) {
73 int logtype = kLogDebug;
74 if (crashed)
75 logtype = kLogSyslog;
76 LogCvmfs(kLogCvmfs, logtype,
77 "%s cleanup handler: %s not mounted",
78 cleanuptype, mountpoint_->c_str());
79 return;
80 }
81
82 if (crashed) {
83 // stat() might be served from caches. Opendir ensures fuse module is called.
84 int expected_error;
85 #ifdef __APPLE__
86 expected_error = ENXIO;
87 #else
88 expected_error = ENOTCONN;
89 #endif
90 DIR *dirp = opendir(mountpoint_->c_str());
91 if (dirp || (errno != expected_error)) {
92 if (dirp)
93 closedir(dirp);
94 LogCvmfs(kLogCvmfs, kLogSyslog, "crash cleanup handler: "
95 "%s seems not to be stalled (%d)",
96 mountpoint_->c_str(), errno);
97 return;
98 }
99 }
100
101 // sudo umount -l *mountpoint_
102 if (!ObtainSysAdminCapability()) {
103 LogCvmfs(kLogCvmfs, kLogSyslogErr,
104 "%s cleanup handler: "
105 "failed to re-gain sys_admin capability",
106 cleanuptype);
107 return;
108 }
109 const bool lazy = true;
110 bool retval = platform_umount(mountpoint_->c_str(), lazy);
111 if (!retval) {
112 LogCvmfs(kLogCvmfs, kLogSyslogErr,
113 "%s cleanup handler: "
114 "failed to unmount %s",
115 cleanuptype, mountpoint_->c_str());
116 return;
117 }
118
119 if (crashed) {
120 LogCvmfs(kLogCvmfs, kLogSyslog,
121 "crash cleanup handler unmounted stalled %s",
122 mountpoint_->c_str());
123 } else {
124 LogCvmfs(kLogCvmfs, kLogSyslog,
125 "exit cleanup handler unmounted %s",
126 mountpoint_->c_str());
127 }
128 }
129
130 } // namespace auto_umount
131