GCC Code Coverage Report


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