CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
auto_umount.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
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()) {
46  LogCvmfs(kLogCvmfs, kLogSyslogErr, "crash cleanup handler: "
47  "failed to read mount point list");
48  return;
49  }
50 
51  // Mitigate auto-mount - crash - umount - auto-mount loops
52  SafeSleepMs(2000);
53 
54  // Check if *mountpoint_ is still mounted
55  // (we don't want to trigger a mount by immediately doing stat *mountpoint_)
56  bool still_mounted = false;
57  for (unsigned i = 0; i < all_mountpoints.size(); ++i) {
58  if (*mountpoint_ == all_mountpoints[i]) {
59  still_mounted = true;
60  break;
61  }
62  }
63  if (!still_mounted) {
64  LogCvmfs(kLogCvmfs, kLogSyslog, "crash cleanup handler: %s not mounted",
65  mountpoint_->c_str());
66  return;
67  }
68 
69  // stat() might be served from caches. Opendir ensures fuse module is called.
70  int expected_error;
71 #ifdef __APPLE__
72  expected_error = ENXIO;
73 #else
74  expected_error = ENOTCONN;
75 #endif
76  DIR *dirp = opendir(mountpoint_->c_str());
77  if (dirp || (errno != expected_error)) {
78  if (dirp) closedir(dirp);
79  LogCvmfs(kLogCvmfs, kLogSyslog, "crash cleanup handler: "
80  "%s seems not to be stalled (%d)", mountpoint_->c_str(), errno);
81  return;
82  }
83 
84  // sudo umount -l *mountpoint_
85  if (!SwitchCredentials(0, getegid(), true)) {
86  LogCvmfs(kLogCvmfs, kLogSyslogErr, "crash cleanup handler: "
87  "failed to re-gain root privileges");
88  return;
89  }
90  const bool lazy = true;
91  bool retval = platform_umount(mountpoint_->c_str(), lazy);
92  if (!retval) {
93  LogCvmfs(kLogCvmfs, kLogSyslogErr, "crash cleanup handler: "
94  "failed to unmount %s", mountpoint_->c_str());
95  return;
96  }
97 
98  LogCvmfs(kLogCvmfs, kLogSyslog, "crash cleanup handler unmounted stalled %s",
99  mountpoint_->c_str());
100 }
101 
102 } // 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:761
void SafeSleepMs(const unsigned ms)
Definition: posix.cc:1975
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528