GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/fuse_remount.h
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 0 12 0.0%
Branches: 0 4 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_FUSE_REMOUNT_H_
6 #define CVMFS_FUSE_REMOUNT_H_
7
8 #include <pthread.h>
9
10 #include <ctime>
11
12 #include "crypto/hash.h"
13 #include "duplex_fuse.h"
14 #include "fence.h"
15 #include "fuse_evict.h"
16 #include "util/atomic.h"
17 #include "util/single_copy.h"
18
19 namespace cvmfs {
20 struct InodeGenerationInfo;
21 }
22 class MountPoint;
23
24 /**
25 * Orchestrates an orderly remount of a new snapshot revision in the Fuse
26 * module. Remounting always happens as a result of calling Check() followed
27 * by a call to TryFinish(). The Check() method is either called from the
28 * remount trigger or from the TalkManager. The TryFinish() method is either
29 * called from a fuse callback function or from CheckSynchronously(). If a new
30 * root file catalog is available online and the kernel caches got flushed, the
31 * actual heavy-lifting of applying the new catalog takes place in TryFinish();
32 *
33 * Remounting is inherently asynchronous because the kernel caches need to be
34 * flushed. We do this through the FuseInvalidator. Once the FuseInvalidor
35 * is ready (either by waiting or by active eviction), we flush all user-level
36 * caches and reload a new root catalog.
37 */
38 class FuseRemounter : SingleCopy {
39 public:
40 enum Status {
41 kStatusUp2Date = 0,
42 kStatusDraining,
43 kStatusMaintenance,
44 kStatusFailGeneral,
45 kStatusFailNoSpace,
46 };
47
48 FuseRemounter(MountPoint *mountpoint,
49 cvmfs::InodeGenerationInfo *inode_generation_info,
50 void **fuse_channel_or_session,
51 bool fuse_notify_invalidation);
52 ~FuseRemounter();
53 void Spawn();
54
55 Status Check();
56 Status CheckSynchronously();
57 Status ChangeRoot(const shash::Any &root_hash);
58 void TryFinish(const shash::Any &root_hash = shash::Any());
59 void EnterMaintenanceMode();
60 bool IsCaching() {
61 return (atomic_read32(&maintenance_mode_) == 0)
62 && (atomic_read32(&drainout_mode_) == 0);
63 }
64 bool IsInDrainoutMode() { return atomic_read32(&drainout_mode_) == 2; }
65 bool IsInMaintenanceMode() { return atomic_read32(&maintenance_mode_) == 1; }
66
67 Fence *fence() { return fence_; }
68 time_t catalogs_valid_until() { return catalogs_valid_until_; }
69
70 void InvalidateDentry(uint64_t parent_ino, const NameString &name) {
71 invalidator_->InvalidateDentry(parent_ino, name);
72 }
73
74 private:
75 static void *MainRemountTrigger(void *data);
76
77 bool HasRemountTrigger() { return pipe_remount_trigger_[0] >= 0; }
78 void SetAlarm(int timeout);
79
80 bool EnterCriticalSection() { return atomic_cas32(&critical_section_, 0, 1); }
81 void LeaveCriticalSection() { atomic_dec32(&critical_section_); /* 1 -> 0 */ }
82
83 void SetOfflineMode(bool value);
84
85 MountPoint *mountpoint_; ///< Not owned
86 cvmfs::InodeGenerationInfo *inode_generation_info_; ///< Not owned
87 FuseInvalidator *invalidator_;
88 /**
89 * Used to query whether the kernel cache invalidation is done.
90 */
91 FuseInvalidator::Handle invalidator_handle_;
92 /**
93 * Ensures that within a fuse callback all operations take place on the same
94 * catalog revision.
95 */
96 Fence *fence_;
97 /**
98 * This fence makes sure that Check() and TryFinish() have been left after
99 * the maintenance mode flag was set.
100 */
101 Fence fence_maintenance_;
102 pthread_t thread_remount_trigger_;
103 /**
104 * The thread that triggers the reload of the root catalog is controlled
105 * through this pipe.
106 */
107 int pipe_remount_trigger_[2];
108 /**
109 * Indicates whether the last reload attempt failed. If so, the short term
110 * TTL is active.
111 */
112 bool offline_mode_;
113 /**
114 * Stores the deadline after which the remount trigger will look again for
115 * an updated version. Can be MountPoint::kIndefiniteDeadline if a fixed root
116 * catalog is used. Only for information purposes ('expires' xattr).
117 * TODO(jblomer): access to this field should be locked
118 */
119 time_t catalogs_valid_until_;
120 /**
121 * In drainout mode, the fuse module sets the timeout of meta data replies to
122 * zero. If supported by Fuse, the FuseInvalidator will evict all active
123 * entries from the kernel cache. Drainout mode is left only once the new
124 * root catalog is active (after TryFinish()).
125 *
126 * Moving into drainout mode is a two-steps procedure. Going from zero to one
127 * the handle of the FuseInvalidator is prepared, from one to two is the
128 * actual move into drainout mode.
129 */
130 atomic_int32 drainout_mode_;
131 /**
132 * in maintenance mode, cache timeout is 0 and catalogs are not reloaded.
133 * Maintenance mode is entered when the fuse module gets reloaded.
134 */
135 atomic_int32 maintenance_mode_;
136 /**
137 * Only one thread must perform the actual remount (stopping user-level
138 * caches, loading new catalog, etc.). This is used to protect TyrFinish()
139 * from concurrent execution.
140 */
141 atomic_int32 critical_section_;
142 }; // class FuseRemounter
143
144 #endif // CVMFS_FUSE_REMOUNT_H_
145