GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/magic_xattr.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 32 33 97.0%
Branches: 4 8 50.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_MAGIC_XATTR_H_
6 #define CVMFS_MAGIC_XATTR_H_
7
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "backoff.h"
15 #include "catalog_counters.h"
16 #include "directory_entry.h"
17 #include "shortstring.h"
18 #include "util/exception.h"
19 #include "util/string.h"
20
21 class MountPoint;
22
23 enum MagicXattrFlavor {
24 kXattrBase = 0,
25 kXattrWithHash,
26 kXattrRegular,
27 kXattrExternal,
28 kXattrSymlink,
29 kXattrAuthz
30 };
31
32 enum MagicXattrMode {
33 kXattrMachineMode = 0,
34 kXattrHumanMode
35 };
36
37 class MagicXattrManager; // needed for BaseMagicXattr
38 /**
39 * This is a base class for magic extended attribute. Every extended
40 * attributes must inherit from this class. It should be generally used only
41 * in cooperation with MagicXattrManager.
42 * It contains an access mutex. Users should use Lock() and Release()
43 * before and after usage (Lock() is called implicitly in MagicXattrManager).
44 *
45 * To read out the attribute value, do:
46 * 0. Get an instance through MagicXattrManager::Get()
47 * 1. Call PrepareValueFenced() inside FuseRemounter::fence()
48 * 2. Call GetValue(int32_t requested_page, const MagicXattrMode mode);
49 * It returns a <bool, string> pair where the bool is set to true if the
50 * request was successful and the string contains the actual value.
51 * GetValue() can be called outside the fence.
52 * This will internally call FinalizeValue() to finalize the value
53 * preparation outside the fuse fence.
54 *
55 * Implementation notes:
56 * - Each MagicXattr must implement it's own FinalizeValue() function which
57 * has to write its value into result_pages_.
58 * - result_pages_ is a vector of strings. Each string is <= kMaxCharsPerPage
59 * - BaseMagicXattr::GetValue() takes care of clearing result_pages_ before each
60 * new call of FinalizeValue(), and takes care of adding a header for the
61 * human readable version
62 * - In case an invalid request happens, GetValue() <bool> is set to false.
63 * "ENOENT" will be returned, while in human-readable mode a more verbose
64 * error message will be returned
65 */
66 class BaseMagicXattr {
67 friend class MagicXattrManager;
68 FRIEND_TEST(T_MagicXattr, ProtectedXattr);
69 FRIEND_TEST(T_MagicXattr, TestFqrn);
70 FRIEND_TEST(T_MagicXattr, TestLogBuffer);
71
72 public:
73 1178 BaseMagicXattr() : is_protected_(false) {
74 1178 int retval = pthread_mutex_init(&access_mutex_, NULL);
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1178 times.
1178 assert(retval == 0);
76 1178 }
77
78 /**
79 * Mark a Xattr protected so that only certain users with the correct gid
80 * can access it.
81 */
82 1 void MarkProtected() {
83 1 is_protected_ = true;
84 1 }
85
86
87 // TODO(hereThereBeDragons) from C++11 should be marked final
88 /**
89 * Access right check before normal fence
90 */
91 bool PrepareValueFencedProtected(gid_t gid);
92
93 /**
94 * This function needs to be called after PrepareValueFenced(),
95 * which prepares the necessary data and header for kXattrHumanMode.
96 * It does the computationaly intensive part, which should not
97 * be done inside the FuseRemounter::fence(), and returns the
98 * value.
99 *
100 * Internally it calls FinalizeValue() which each MagicXAttr has to implement
101 * to set the value of result_pages_
102 *
103 * @params
104 * - requested_page:
105 * >= 0: requested paged of the attribute
106 * -1: get info about xattr: e.g. the number of pages available
107 * - mode: either machine-readable or human-readable
108 *
109 * @returns
110 * std::pair<bool, std::string>
111 * bool = false if in machine-readable mode an invalid request is performed
112 * (human-readable mode always succeeds and gives a verbose message)
113 * otherwise true
114 * std::string = the actual value of the attribute or info element
115 * ( or error message in human-readable mode)
116 *
117 */
118 std::pair<bool, std::string> GetValue(int32_t requested_page,
119 const MagicXattrMode mode);
120
121 31 virtual MagicXattrFlavor GetXattrFlavor() { return kXattrBase; }
122
123 4 void Lock(PathString path, catalog::DirectoryEntry *dirent) {
124 4 int retval = pthread_mutex_lock(&access_mutex_);
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(retval == 0);
126 4 path_ = path;
127 4 dirent_ = dirent;
128 4 }
129 4 void Release() {
130 4 int retval = pthread_mutex_unlock(&access_mutex_);
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(retval == 0);
132 4 }
133
134 4 virtual ~BaseMagicXattr() {}
135
136 // how many chars per page (with some leeway). system maximum would be 64k
137 static const uint32_t kMaxCharsPerPage = 40000;
138
139 protected:
140 /**
141 * This function is used to obtain the necessary information while
142 * inside FuseRemounter::fence(), which should prevent data races.
143 */
144 4 virtual bool PrepareValueFenced() { return true; }
145 virtual void FinalizeValue() {}
146
147 std::string HeaderMultipageHuman(uint32_t requested_page);
148
149 MagicXattrManager *xattr_mgr_;
150 PathString path_;
151 catalog::DirectoryEntry *dirent_;
152
153 pthread_mutex_t access_mutex_;
154 bool is_protected_;
155 std::vector<std::string> result_pages_;
156 };
157
158 /**
159 * This wrapper ensures that the attribute instance "ptr_" is
160 * released after the user finishes using it (on wrapper destruction).
161 */
162 class MagicXattrRAIIWrapper: public SingleCopy {
163 public:
164 inline MagicXattrRAIIWrapper() : ptr_(NULL) { }
165
166 inline explicit MagicXattrRAIIWrapper(
167 BaseMagicXattr *ptr,
168 PathString path,
169 catalog::DirectoryEntry *d)
170 : ptr_(ptr)
171 {
172 if (ptr_ != NULL) ptr_->Lock(path, d);
173 }
174 /// Wraps around a BaseMagicXattr* that is already locked (or NULL)
175 4 inline explicit MagicXattrRAIIWrapper(BaseMagicXattr *ptr) : ptr_(ptr) { }
176
177
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 inline ~MagicXattrRAIIWrapper() { if (ptr_ != NULL) ptr_->Release(); }
178
179 9 inline BaseMagicXattr* operator->() const { return ptr_; }
180 4 inline bool IsNull() const { return ptr_ == NULL; }
181 inline BaseMagicXattr* Move() {
182 BaseMagicXattr* ret = ptr_;
183 ptr_ = NULL;
184 return ret;
185 }
186
187 protected:
188 BaseMagicXattr *ptr_;
189 };
190
191 class WithHashMagicXattr : public BaseMagicXattr {
192 2 virtual MagicXattrFlavor GetXattrFlavor() { return kXattrWithHash; }
193 };
194
195 class RegularMagicXattr : public BaseMagicXattr {
196 5 virtual MagicXattrFlavor GetXattrFlavor() { return kXattrRegular; }
197 };
198
199 class ExternalMagicXattr : public BaseMagicXattr {
200 1 virtual MagicXattrFlavor GetXattrFlavor() { return kXattrExternal; }
201 };
202
203 class SymlinkMagicXattr : public BaseMagicXattr {
204 2 virtual MagicXattrFlavor GetXattrFlavor() { return kXattrSymlink; }
205 };
206
207 /**
208 * This class is acting as a user entry point for magic extended attributes.
209 * It instantiates all defined attributes in the constructor.
210 * Users can:
211 * 1. Register additional attributes
212 * 2. Get a string containing zero-byte delimited list of attribute names
213 * (used in "cvmfs.cc")
214 * 3. Get an attribute by name. Specifically, get a RAII wrapper around
215 * a singleton attribute instance. This means that the attribute instance
216 * registered with the manager does not get cloned or copied inside Get().
217 * Instead, member variables are set and the original instance is returned.
218 * A mutex prevents from race conditions in case of concurrent access.
219 */
220 class MagicXattrManager : public SingleCopy {
221 public:
222 enum EVisibility { kVisibilityAlways, kVisibilityNever, kVisibilityRootOnly };
223
224 MagicXattrManager(MountPoint *mountpoint, EVisibility visibility,
225 const std::set<std::string> &protected_xattrs,
226 const std::set<gid_t> &privileged_xattr_gids);
227 /// The returned BaseMagicXattr* is supposed to be wrapped by a
228 /// MagicXattrRAIIWrapper
229 BaseMagicXattr* GetLocked(const std::string &name, PathString path,
230 catalog::DirectoryEntry *d);
231 std::string GetListString(catalog::DirectoryEntry *dirent);
232 /**
233 * Registers a new extended attribute.
234 * Will fail if called after Freeze().
235 */
236 void Register(const std::string &name, BaseMagicXattr *magic_xattr);
237
238 /**
239 * Freezes the current setup of MagicXattrManager.
240 * No new extended attributes can be added.
241 * Only after freezing MagicXattrManager can registered attributes be
242 * accessed.
243 */
244 1 void Freeze() { is_frozen_ = true; SanityCheckProtectedXattrs(); }
245 bool IsPrivilegedGid(gid_t gid);
246
247
248 6 EVisibility visibility() { return visibility_; }
249 std::set<gid_t> privileged_xattr_gids()
250 { return privileged_xattr_gids_; }
251 2 MountPoint* mount_point() { return mount_point_; }
252 2 bool is_frozen() const { return is_frozen_; }
253
254 protected:
255 std::map<std::string, BaseMagicXattr *> xattr_list_;
256 MountPoint *mount_point_;
257 EVisibility visibility_;
258
259 // privileged_xattr_gids_ contains the (fuse) gids that
260 // can access xattrs that are part of protected_xattrs_
261 const std::set<std::string> protected_xattrs_;
262 const std::set<gid_t> privileged_xattr_gids_;
263
264 private:
265 bool is_frozen_;
266
267 void SanityCheckProtectedXattrs();
268 };
269
270 class AuthzMagicXattr : public BaseMagicXattr {
271 virtual bool PrepareValueFenced();
272 virtual void FinalizeValue();
273
274 virtual MagicXattrFlavor GetXattrFlavor();
275 };
276
277 class CatalogCountersMagicXattr : public BaseMagicXattr {
278 std::string subcatalog_path_;
279 shash::Any hash_;
280 catalog::Counters counters_;
281
282 virtual bool PrepareValueFenced();
283 virtual void FinalizeValue();
284 };
285
286 class ChunkListMagicXattr : public RegularMagicXattr {
287 virtual bool PrepareValueFenced();
288 virtual void FinalizeValue();
289
290 private:
291 std::vector<std::string> chunk_list_;
292 };
293
294 class ChunksMagicXattr : public RegularMagicXattr {
295 uint64_t n_chunks_;
296
297 virtual bool PrepareValueFenced();
298 virtual void FinalizeValue();
299 };
300
301 class CompressionMagicXattr : public RegularMagicXattr {
302 virtual bool PrepareValueFenced();
303 virtual void FinalizeValue();
304 };
305
306 class DirectIoMagicXattr : public RegularMagicXattr {
307 virtual bool PrepareValueFenced();
308 virtual void FinalizeValue();
309 };
310
311 class ExternalFileMagicXattr : public RegularMagicXattr {
312 virtual bool PrepareValueFenced();
313 virtual void FinalizeValue();
314 };
315
316 class ExternalHostMagicXattr : public BaseMagicXattr {
317 virtual void FinalizeValue();
318 };
319
320 class ExternalTimeoutMagicXattr : public BaseMagicXattr {
321 virtual void FinalizeValue();
322 };
323
324 class FqrnMagicXattr : public BaseMagicXattr {
325 virtual void FinalizeValue();
326 };
327
328 class HashMagicXattr : public WithHashMagicXattr {
329 virtual bool PrepareValueFenced();
330 virtual void FinalizeValue();
331 };
332
333 class HostMagicXattr : public BaseMagicXattr {
334 virtual void FinalizeValue();
335 };
336
337 class HostListMagicXattr : public BaseMagicXattr {
338 virtual void FinalizeValue();
339 };
340
341 class LHashMagicXattr : public WithHashMagicXattr {
342 virtual bool PrepareValueFenced();
343 virtual void FinalizeValue();
344 };
345
346 class LogBufferXattr : public BaseMagicXattr {
347 public:
348 LogBufferXattr();
349
350 private:
351 const unsigned int kMaxLogLine = 4096; // longer log lines are trimmed
352 // Generating the log buffer report involves 64 string copies. To mitigate
353 // memory fragmentation and performance loss, throttle the use of this
354 // attribute a little.
355 BackoffThrottle throttle_;
356
357 virtual void FinalizeValue();
358 };
359
360 class NCleanup24MagicXattr : public BaseMagicXattr {
361 virtual void FinalizeValue();
362 };
363
364 class NClgMagicXattr : public BaseMagicXattr {
365 int n_catalogs_;
366
367 virtual bool PrepareValueFenced();
368 virtual void FinalizeValue();
369 };
370
371 class NDirOpenMagicXattr : public BaseMagicXattr {
372 virtual void FinalizeValue();
373 };
374
375 class NDownloadMagicXattr : public BaseMagicXattr {
376 virtual void FinalizeValue();
377 };
378
379 class NIOErrMagicXattr : public BaseMagicXattr {
380 virtual void FinalizeValue();
381 };
382
383 class NOpenMagicXattr : public BaseMagicXattr {
384 virtual void FinalizeValue();
385 };
386
387 class HitrateMagicXattr : public BaseMagicXattr {
388 virtual void FinalizeValue();
389 };
390
391 class ProxyMagicXattr : public BaseMagicXattr {
392 virtual void FinalizeValue();
393 };
394
395 class ProxyListMagicXattr : public BaseMagicXattr {
396 virtual void FinalizeValue();
397 };
398
399 class ProxyListExternalMagicXattr : public BaseMagicXattr {
400 virtual void FinalizeValue();
401 };
402
403 class PubkeysMagicXattr : public BaseMagicXattr {
404 FRIEND_TEST(T_MagicXattr, MultiPageMachineModeXattr);
405 FRIEND_TEST(T_MagicXattr, MultiPageHumanModeXattr);
406
407 std::vector<std::string> pubkeys_;
408
409 virtual bool PrepareValueFenced();
410 virtual void FinalizeValue();
411 };
412
413 class RawlinkMagicXattr : public SymlinkMagicXattr {
414 virtual bool PrepareValueFenced();
415 virtual void FinalizeValue();
416 };
417
418 class RepoCountersMagicXattr : public BaseMagicXattr {
419 catalog::Counters counters_;
420
421 virtual bool PrepareValueFenced();
422 virtual void FinalizeValue();
423 };
424
425 class RepoMetainfoMagicXattr : public BaseMagicXattr {
426 static uint64_t kMaxMetainfoLength;
427
428 shash::Any metainfo_hash_;
429 std::string error_reason_;
430
431 virtual bool PrepareValueFenced();
432 virtual void FinalizeValue();
433 };
434
435 class RevisionMagicXattr : public BaseMagicXattr {
436 uint64_t revision_;
437
438 virtual bool PrepareValueFenced();
439 virtual void FinalizeValue();
440 };
441
442 class RootHashMagicXattr : public BaseMagicXattr {
443 shash::Any root_hash_;
444
445 virtual bool PrepareValueFenced();
446 virtual void FinalizeValue();
447 };
448
449 class RxMagicXattr : public BaseMagicXattr {
450 virtual void FinalizeValue();
451 };
452
453 class SpeedMagicXattr : public BaseMagicXattr {
454 virtual void FinalizeValue();
455 };
456
457 class TagMagicXattr : public BaseMagicXattr {
458 std::string tag_;
459
460 virtual bool PrepareValueFenced();
461 virtual void FinalizeValue();
462 };
463
464 class TimeoutMagicXattr : public BaseMagicXattr {
465 virtual void FinalizeValue();
466 };
467
468 class TimeoutDirectMagicXattr : public BaseMagicXattr {
469 virtual void FinalizeValue();
470 };
471
472 class TimestampLastIOErrMagicXattr : public BaseMagicXattr {
473 virtual void FinalizeValue();
474 };
475
476 class UsedFdMagicXattr : public BaseMagicXattr {
477 virtual void FinalizeValue();
478 };
479
480 class UsedDirPMagicXattr : public BaseMagicXattr {
481 virtual void FinalizeValue();
482 };
483
484 class VersionMagicXattr : public BaseMagicXattr {
485 virtual void FinalizeValue();
486 };
487
488 class ExternalURLMagicXattr : public ExternalMagicXattr {
489 virtual bool PrepareValueFenced();
490 virtual void FinalizeValue();
491 };
492
493 #endif // CVMFS_MAGIC_XATTR_H_
494