GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/auto_umount.cc Lines: 0 32 0.0 %
Date: 2019-02-03 02:48:13 Branches: 0 24 0.0 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 */
4
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 "logging.h"
19
#include "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