CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
auto_umount.cc
Go to the documentation of this file.
1 
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/logging.h"
19 #include "util/platform.h"
20 #include "util/posix.h"
21 
22 using namespace std; // NOLINT
23 
24 namespace auto_umount {
25 
26 string *mountpoint_ = NULL;
27 
28 void SetMountpoint(const string &mountpoint) {
29  if (mountpoint == "") {
30  delete mountpoint_;
31  mountpoint_ = NULL;
32  } else {
33  mountpoint_ = new string(mountpoint);
34  }
35 }
36 
37 
38 void UmountOnCrash() {
39  if (!mountpoint_) {
40  LogCvmfs(kLogCvmfs, kLogSyslogErr, "crash cleanup handler: no mountpoint");
41  return;
42  }
43 
44  std::vector<std::string> all_mountpoints = platform_mountlist();
45  if (all_mountpoints.empty()) {
47  "crash cleanup handler: "
48  "failed to read mount point list");
49  return;
50  }
51 
52  // Mitigate auto-mount - crash - umount - auto-mount loops
53  SafeSleepMs(2000);
54 
55  // Check if *mountpoint_ is still mounted
56  // (we don't want to trigger a mount by immediately doing stat *mountpoint_)
57  bool still_mounted = false;
58  for (unsigned i = 0; i < all_mountpoints.size(); ++i) {
59  if (*mountpoint_ == all_mountpoints[i]) {
60  still_mounted = true;
61  break;
62  }
63  }
64  if (!still_mounted) {
65  LogCvmfs(kLogCvmfs, kLogSyslog, "crash cleanup handler: %s not mounted",
66  mountpoint_->c_str());
67  return;
68  }
69 
70  // stat() might be served from caches. Opendir ensures fuse module is called.
71  int expected_error;
72 #ifdef __APPLE__
73  expected_error = ENXIO;
74 #else
75  expected_error = ENOTCONN;
76 #endif
77  DIR *dirp = opendir(mountpoint_->c_str());
78  if (dirp || (errno != expected_error)) {
79  if (dirp)
80  closedir(dirp);
82  "crash cleanup handler: "
83  "%s seems not to be stalled (%d)",
84  mountpoint_->c_str(), errno);
85  return;
86  }
87 
88  // sudo umount -l *mountpoint_
89  if (!SwitchCredentials(0, getegid(), true)) {
91  "crash cleanup handler: "
92  "failed to re-gain root privileges");
93  return;
94  }
95  const bool lazy = true;
96  bool retval = platform_umount(mountpoint_->c_str(), lazy);
97  if (!retval) {
99  "crash cleanup handler: "
100  "failed to unmount %s",
101  mountpoint_->c_str());
102  return;
103  }
104 
105  LogCvmfs(kLogCvmfs, kLogSyslog, "crash cleanup handler unmounted stalled %s",
106  mountpoint_->c_str());
107 }
108 
109 } // namespace auto_umount
string * mountpoint_
Definition: auto_umount.cc:26
void SetMountpoint(const string &mountpoint)
Definition: auto_umount.cc:28
bool platform_umount(const char *mountpoint, const bool lazy)
void UmountOnCrash()
Definition: auto_umount.cc:38
std::vector< std::string > platform_mountlist()
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:773
void SafeSleepMs(const unsigned ms)
Definition: posix.cc:2024
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545