GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/** |
||
2 |
* This file is part of the CernVM File System. |
||
3 |
*/ |
||
4 |
#include "cvmfs_config.h" |
||
5 |
#include "mountpoint.h" |
||
6 |
|||
7 |
#include <errno.h> |
||
8 |
#include <fcntl.h> |
||
9 |
#ifndef CVMFS_LIBCVMFS |
||
10 |
#include <fuse/fuse_lowlevel.h> |
||
11 |
#endif |
||
12 |
#include <inttypes.h> |
||
13 |
#include <stdint.h> |
||
14 |
#include <unistd.h> |
||
15 |
|||
16 |
#include <algorithm> |
||
17 |
#include <cassert> |
||
18 |
#include <climits> |
||
19 |
#include <cstring> |
||
20 |
#include <vector> |
||
21 |
|||
22 |
#ifndef CVMFS_LIBCVMFS |
||
23 |
#ifdef FUSE_CAP_EXPORT_SUPPORT |
||
24 |
#define CVMFS_NFS_SUPPORT |
||
25 |
#else |
||
26 |
#warning "No NFS support, Fuse too old" |
||
27 |
#endif |
||
28 |
#endif |
||
29 |
|||
30 |
#include "authz/authz_curl.h" |
||
31 |
#include "authz/authz_fetch.h" |
||
32 |
#include "authz/authz_session.h" |
||
33 |
#include "backoff.h" |
||
34 |
#include "cache.h" |
||
35 |
#include "cache_extern.h" |
||
36 |
#include "cache_posix.h" |
||
37 |
#include "cache_ram.h" |
||
38 |
#include "cache_tiered.h" |
||
39 |
#include "catalog.h" |
||
40 |
#include "catalog_mgr_client.h" |
||
41 |
#include "clientctx.h" |
||
42 |
#include "download.h" |
||
43 |
#include "duplex_sqlite3.h" |
||
44 |
#include "fetch.h" |
||
45 |
#include "file_chunk.h" |
||
46 |
#include "globals.h" |
||
47 |
#include "glue_buffer.h" |
||
48 |
#include "google/protobuf/stubs/common.h" |
||
49 |
#include "history.h" |
||
50 |
#include "history_sqlite.h" |
||
51 |
#include "logging.h" |
||
52 |
#include "lru_md.h" |
||
53 |
#include "manifest.h" |
||
54 |
#include "manifest_fetch.h" |
||
55 |
#include "nfs_maps.h" |
||
56 |
#ifdef CVMFS_NFS_SUPPORT |
||
57 |
#include "nfs_maps_leveldb.h" |
||
58 |
#include "nfs_maps_sqlite.h" |
||
59 |
#endif |
||
60 |
#include "options.h" |
||
61 |
#include "platform.h" |
||
62 |
#include "quota_posix.h" |
||
63 |
#include "resolv_conf_event_handler.h" |
||
64 |
#include "signature.h" |
||
65 |
#include "sqlitemem.h" |
||
66 |
#include "sqlitevfs.h" |
||
67 |
#include "statistics.h" |
||
68 |
#include "tracer.h" |
||
69 |
#include "util/pointer.h" |
||
70 |
#include "util/posix.h" |
||
71 |
#include "util/string.h" |
||
72 |
#include "util_concurrency.h" |
||
73 |
#include "uuid.h" |
||
74 |
#include "wpad.h" |
||
75 |
|||
76 |
using namespace std; // NOLINT |
||
77 |
|||
78 |
|||
79 |
bool FileSystem::g_alive = false; |
||
80 |
const char *FileSystem::kDefaultCacheBase = "/var/lib/cvmfs"; |
||
81 |
const char *FileSystem::kDefaultCacheMgrInstance = "default"; |
||
82 |
|||
83 |
|||
84 |
/** |
||
85 |
* A cache instance name is part of a bash parameter and can only contain |
||
86 |
* certain characters. |
||
87 |
*/ |
||
88 |
39 |
bool FileSystem::CheckInstanceName(const std::string &instance) { |
|
89 |
✓✓ | 39 |
if (instance.length() > 24) |
90 |
2 |
return false; |
|
91 |
37 |
sanitizer::CacheInstanceSanitizer instance_sanitizer; |
|
92 |
✓✓ | 37 |
if (!instance_sanitizer.IsValid(instance)) { |
93 |
boot_error_ = "invalid instance name (" + instance + "), " + |
||
94 |
4 |
"only characters a-z, A-Z, 0-9, _ are allowed"; |
|
95 |
4 |
boot_status_ = loader::kFailCacheDir; |
|
96 |
4 |
return false; |
|
97 |
} |
||
98 |
33 |
return true; |
|
99 |
} |
||
100 |
|||
101 |
|||
102 |
/** |
||
103 |
* Not all possible combinations of cache flags / modes are valid. |
||
104 |
*/ |
||
105 |
148 |
bool FileSystem::CheckPosixCacheSettings( |
|
106 |
const FileSystem::PosixCacheSettings &settings) |
||
107 |
{ |
||
108 |
✓✓✓✓ |
148 |
if (settings.is_alien && settings.is_shared) { |
109 |
boot_error_ = "Failure: shared local disk cache and alien cache mutually " |
||
110 |
10 |
"exclusive. Please turn off shared local disk cache."; |
|
111 |
10 |
boot_status_ = loader::kFailOptions; |
|
112 |
10 |
return false; |
|
113 |
} |
||
114 |
✓✓✓✓ |
138 |
if (settings.is_alien && settings.is_managed) { |
115 |
boot_error_ = "Failure: quota management and alien cache mutually " |
||
116 |
7 |
"exclusive. Please turn off quota limit."; |
|
117 |
7 |
boot_status_ = loader::kFailOptions; |
|
118 |
7 |
return false; |
|
119 |
} |
||
120 |
|||
121 |
✓✓ | 131 |
if (type_ == kFsLibrary) { |
122 |
✓✓✗✓ |
28 |
if (settings.is_shared || settings.is_managed) { |
123 |
boot_error_ = "Failure: libcvmfs supports only unmanaged exclusive cache " |
||
124 |
4 |
"or alien cache."; |
|
125 |
4 |
boot_status_ = loader::kFailOptions; |
|
126 |
4 |
return false; |
|
127 |
} |
||
128 |
} |
||
129 |
|||
130 |
✓✓✓✓ |
127 |
if (settings.cache_base_defined && settings.cache_dir_defined) { |
131 |
boot_error_ = |
||
132 |
4 |
"'CVMFS_CACHE_BASE' and 'CVMFS_CACHE_DIR' are mutually exclusive"; |
|
133 |
4 |
boot_status_ = loader::kFailOptions; |
|
134 |
4 |
return false; |
|
135 |
} |
||
136 |
|||
137 |
123 |
return true; |
|
138 |
} |
||
139 |
|||
140 |
|||
141 |
/** |
||
142 |
* Creation of state and manager classes. The destructor should mirror this |
||
143 |
* method. |
||
144 |
*/ |
||
145 |
137 |
FileSystem *FileSystem::Create(const FileSystem::FileSystemInfo &fs_info) { |
|
146 |
UniquePtr<FileSystem> |
||
147 |
137 |
file_system(new FileSystem(fs_info)); |
|
148 |
|||
149 |
137 |
file_system->SetupLogging(); |
|
150 |
LogCvmfs(kLogCvmfs, kLogDebug, "Options:\n%s", |
||
151 |
137 |
file_system->options_mgr()->Dump().c_str()); |
|
152 |
|||
153 |
137 |
file_system->CreateStatistics(); |
|
154 |
137 |
file_system->SetupSqlite(); |
|
155 |
✗✓ | 137 |
if (!file_system->DetermineNfsMode()) |
156 |
return file_system.Release(); |
||
157 |
✓✓ | 137 |
if (!file_system->SetupWorkspace()) |
158 |
6 |
return file_system.Release(); |
|
159 |
|||
160 |
// Redirect SQlite temp directory to workspace (global variable) |
||
161 |
131 |
unsigned length_tempdir = file_system->workspace_.length() + 1; |
|
162 |
131 |
sqlite3_temp_directory = static_cast<char *>(sqlite3_malloc(length_tempdir)); |
|
163 |
snprintf(sqlite3_temp_directory, |
||
164 |
length_tempdir, |
||
165 |
"%s", |
||
166 |
131 |
file_system->workspace_.c_str()); |
|
167 |
|||
168 |
✓✓ | 131 |
if (!file_system->TriageCacheMgr()) |
169 |
24 |
return file_system.Release(); |
|
170 |
107 |
file_system->SetupUuid(); |
|
171 |
✗✓ | 107 |
if (!file_system->SetupNfsMaps()) |
172 |
return file_system.Release(); |
||
173 |
bool retval = sqlite::RegisterVfsRdOnly( |
||
174 |
file_system->cache_mgr_, |
||
175 |
file_system->statistics_, |
||
176 |
107 |
sqlite::kVfsOptDefault); |
|
177 |
✗✓ | 107 |
assert(retval); |
178 |
107 |
file_system->has_custom_sqlitevfs_ = true; |
|
179 |
|||
180 |
107 |
ClientCtx::GetInstance(); |
|
181 |
|||
182 |
107 |
file_system->boot_status_ = loader::kFailOk; |
|
183 |
107 |
return file_system.Release(); |
|
184 |
} |
||
185 |
|||
186 |
|||
187 |
137 |
void FileSystem::CreateStatistics() { |
|
188 |
137 |
statistics_ = new perf::Statistics(); |
|
189 |
|||
190 |
// Register the ShortString's static counters |
||
191 |
137 |
statistics_->Register("pathstring.n_instances", "Number of instances"); |
|
192 |
137 |
statistics_->Register("pathstring.n_overflows", "Number of overflows"); |
|
193 |
137 |
statistics_->Register("namestring.n_instances", "Number of instances"); |
|
194 |
137 |
statistics_->Register("namestring.n_overflows", "Number of overflows"); |
|
195 |
137 |
statistics_->Register("linkstring.n_instances", "Number of instances"); |
|
196 |
137 |
statistics_->Register("linkstring.n_overflows", "Number of overflows"); |
|
197 |
|||
198 |
// Callback counters |
||
199 |
n_fs_open_ = statistics_->Register("cvmfs.n_fs_open", |
||
200 |
137 |
"Overall number of file open operations"); |
|
201 |
n_fs_dir_open_ = statistics_->Register("cvmfs.n_fs_dir_open", |
||
202 |
137 |
"Overall number of directory open operations"); |
|
203 |
n_fs_lookup_ = statistics_->Register("cvmfs.n_fs_lookup", |
||
204 |
137 |
"Number of lookups"); |
|
205 |
n_fs_lookup_negative_ = statistics_->Register("cvmfs.n_fs_lookup_negative", |
||
206 |
137 |
"Number of negative lookups"); |
|
207 |
137 |
n_fs_stat_ = statistics_->Register("cvmfs.n_fs_stat", "Number of stats"); |
|
208 |
137 |
n_fs_read_ = statistics_->Register("cvmfs.n_fs_read", "Number of files read"); |
|
209 |
n_fs_readlink_ = statistics_->Register("cvmfs.n_fs_readlink", |
||
210 |
137 |
"Number of links read"); |
|
211 |
n_fs_forget_ = statistics_->Register("cvmfs.n_fs_forget", |
||
212 |
137 |
"Number of inode forgets"); |
|
213 |
n_io_error_ = statistics_->Register("cvmfs.n_io_error", |
||
214 |
137 |
"Number of I/O errors"); |
|
215 |
no_open_files_ = statistics_->Register("cvmfs.no_open_files", |
||
216 |
137 |
"Number of currently opened files"); |
|
217 |
no_open_dirs_ = statistics_->Register("cvmfs.no_open_dirs", |
||
218 |
137 |
"Number of currently opened directories"); |
|
219 |
137 |
} |
|
220 |
|||
221 |
|||
222 |
/** |
||
223 |
* Figure out mode of operation and cache directory. Checking options for |
||
224 |
* sanity is in a separate method. |
||
225 |
*/ |
||
226 |
116 |
FileSystem::PosixCacheSettings FileSystem::DeterminePosixCacheSettings( |
|
227 |
const string &instance |
||
228 |
) { |
||
229 |
116 |
string optarg; |
|
230 |
116 |
PosixCacheSettings settings; |
|
231 |
|||
232 |
✓✓✓✓ ✓✗✗✗ ✗✗✓✗ ✗✗✓✗ ✓✓ |
116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_SHARED", instance), |
233 |
&optarg) |
||
234 |
&& options_mgr_->IsOn(optarg)) |
||
235 |
{ |
||
236 |
8 |
settings.is_shared = true; |
|
237 |
} |
||
238 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✓ |
116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_SERVER_MODE", instance), |
239 |
&optarg) |
||
240 |
&& options_mgr_->IsOn(optarg)) |
||
241 |
{ |
||
242 |
settings.avoid_rename = true; |
||
243 |
} |
||
244 |
|||
245 |
✓✓ | 116 |
if (type_ == kFsFuse) |
246 |
89 |
settings.quota_limit = kDefaultQuotaLimit; |
|
247 |
✓✓ | 116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_QUOTA_LIMIT", instance), |
248 |
&optarg)) |
||
249 |
{ |
||
250 |
38 |
settings.quota_limit = String2Int64(optarg) * 1024 * 1024; |
|
251 |
} |
||
252 |
✓✓ | 116 |
if (settings.quota_limit > 0) |
253 |
60 |
settings.is_managed = true; |
|
254 |
|||
255 |
116 |
settings.cache_path = kDefaultCacheBase; |
|
256 |
✓✓ | 116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_BASE", instance), |
257 |
&optarg)) |
||
258 |
{ |
||
259 |
92 |
settings.cache_path = MakeCanonicalPath(optarg); |
|
260 |
92 |
settings.cache_base_defined = true; |
|
261 |
} |
||
262 |
✓✓ | 116 |
if (settings.is_shared) { |
263 |
8 |
settings.cache_path += "/shared"; |
|
264 |
} else { |
||
265 |
108 |
settings.cache_path += "/" + name_; |
|
266 |
} |
||
267 |
|||
268 |
// CheckCacheMode makes sure that CVMFS_CACHE_DIR and CVMFS_CACHE_BASE are |
||
269 |
// not set at the same time. |
||
270 |
✓✓ | 116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_DIR", instance), |
271 |
&optarg)) |
||
272 |
{ |
||
273 |
24 |
settings.cache_dir_defined = true; |
|
274 |
24 |
settings.cache_path = optarg; |
|
275 |
} |
||
276 |
✓✓ | 116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_ALIEN", instance), |
277 |
&optarg)) |
||
278 |
{ |
||
279 |
22 |
settings.is_alien = true; |
|
280 |
22 |
settings.cache_path = optarg; |
|
281 |
} |
||
282 |
// We already changed the cwd to the workspace |
||
283 |
// Which is only done if using FUSE |
||
284 |
✓✓✓✓ ✓✓ |
116 |
if ((type_ == kFsFuse) && (settings.cache_path == workspace_fullpath_)) { |
285 |
65 |
settings.cache_path = "."; |
|
286 |
} |
||
287 |
|||
288 |
// The cache workspace usually is the cache directory, unless explicitly |
||
289 |
// set otherwise |
||
290 |
116 |
settings.workspace = settings.cache_path; |
|
291 |
✓✗✓✓ ✓✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✓✓ |
116 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_WORKSPACE", instance), |
292 |
&optarg) || |
||
293 |
options_mgr_->GetValue("CVMFS_WORKSPACE", &optarg)) |
||
294 |
{ |
||
295 |
// Used for the shared quota manager |
||
296 |
14 |
settings.workspace = optarg; |
|
297 |
} |
||
298 |
|||
299 |
return settings; |
||
300 |
} |
||
301 |
|||
302 |
|||
303 |
137 |
bool FileSystem::DetermineNfsMode() { |
|
304 |
137 |
string optarg; |
|
305 |
|||
306 |
✓✓✓✗ ✓✗✗✗ ✗✗✓✗ ✓✓ |
137 |
if (options_mgr_->GetValue("CVMFS_NFS_SOURCE", &optarg) && |
307 |
options_mgr_->IsOn(optarg)) |
||
308 |
{ |
||
309 |
12 |
nfs_mode_ |= kNfsMaps; |
|
310 |
✓✓ | 12 |
if (options_mgr_->GetValue("CVMFS_NFS_SHARED", &optarg)) { |
311 |
9 |
nfs_mode_ |= kNfsMapsHa; |
|
312 |
9 |
nfs_maps_dir_ = optarg; |
|
313 |
} |
||
314 |
} |
||
315 |
|||
316 |
✓✓✗✓ |
137 |
if ((type_ == kFsLibrary) && (nfs_mode_ != kNfsNone)) { |
317 |
boot_error_ = "Failure: libcvmfs does not support NFS export."; |
||
318 |
boot_status_ = loader::kFailOptions; |
||
319 |
return false; |
||
320 |
} |
||
321 |
137 |
return true; |
|
322 |
} |
||
323 |
|||
324 |
|||
325 |
137 |
FileSystem::FileSystem(const FileSystem::FileSystemInfo &fs_info) |
|
326 |
: name_(fs_info.name) |
||
327 |
, exe_path_(fs_info.exe_path) |
||
328 |
, type_(fs_info.type) |
||
329 |
, options_mgr_(fs_info.options_mgr) |
||
330 |
, wait_workspace_(fs_info.wait_workspace) |
||
331 |
, foreground_(fs_info.foreground) |
||
332 |
, n_fs_open_(NULL) |
||
333 |
, n_fs_dir_open_(NULL) |
||
334 |
, n_fs_lookup_(NULL) |
||
335 |
, n_fs_lookup_negative_(NULL) |
||
336 |
, n_fs_stat_(NULL) |
||
337 |
, n_fs_read_(NULL) |
||
338 |
, n_fs_readlink_(NULL) |
||
339 |
, n_fs_forget_(NULL) |
||
340 |
, n_io_error_(NULL) |
||
341 |
, no_open_files_(NULL) |
||
342 |
, no_open_dirs_(NULL) |
||
343 |
, statistics_(NULL) |
||
344 |
, fd_workspace_lock_(-1) |
||
345 |
, found_previous_crash_(false) |
||
346 |
, nfs_mode_(kNfsNone) |
||
347 |
, cache_mgr_(NULL) |
||
348 |
, uuid_cache_(NULL) |
||
349 |
, nfs_maps_(NULL) |
||
350 |
137 |
, has_custom_sqlitevfs_(false) |
|
351 |
{ |
||
352 |
✗✓ | 137 |
assert(!g_alive); |
353 |
137 |
g_alive = true; |
|
354 |
137 |
g_uid = geteuid(); |
|
355 |
137 |
g_gid = getegid(); |
|
356 |
|||
357 |
137 |
string optarg; |
|
358 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✓ |
137 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_SERVER_MODE", |
359 |
kDefaultCacheMgrInstance), |
||
360 |
&optarg) |
||
361 |
&& options_mgr_->IsOn(optarg)) |
||
362 |
{ |
||
363 |
g_raw_symlinks = true; |
||
364 |
} |
||
365 |
} |
||
366 |
|||
367 |
|||
368 |
134 |
FileSystem::~FileSystem() { |
|
369 |
134 |
ClientCtx::CleanupInstance(); |
|
370 |
|||
371 |
✓✓ | 134 |
if (has_custom_sqlitevfs_) |
372 |
104 |
sqlite::UnregisterVfsRdOnly(); |
|
373 |
|||
374 |
✓✓ | 134 |
delete uuid_cache_; |
375 |
✗✓ | 134 |
delete nfs_maps_; |
376 |
✓✓ | 134 |
delete cache_mgr_; |
377 |
|||
378 |
✓✓ | 134 |
if (sqlite3_temp_directory) { |
379 |
128 |
sqlite3_free(sqlite3_temp_directory); |
|
380 |
128 |
sqlite3_temp_directory = NULL; |
|
381 |
} |
||
382 |
|||
383 |
✓✓ | 134 |
if (!path_crash_guard_.empty()) |
384 |
128 |
unlink(path_crash_guard_.c_str()); |
|
385 |
✓✓ | 134 |
if (!path_workspace_lock_.empty()) |
386 |
130 |
unlink(path_workspace_lock_.c_str()); |
|
387 |
✓✓ | 134 |
if (fd_workspace_lock_ >= 0) |
388 |
128 |
UnlockFile(fd_workspace_lock_); |
|
389 |
|||
390 |
134 |
sqlite3_shutdown(); |
|
391 |
134 |
SqliteMemoryManager::CleanupInstance(); |
|
392 |
|||
393 |
✓✗ | 134 |
delete statistics_; |
394 |
|||
395 |
134 |
SetLogSyslogPrefix(""); |
|
396 |
134 |
SetLogMicroSyslog(""); |
|
397 |
134 |
SetLogDebugFile(""); |
|
398 |
134 |
google::protobuf::ShutdownProtobufLibrary(); |
|
399 |
134 |
g_alive = false; |
|
400 |
134 |
} |
|
401 |
|||
402 |
|||
403 |
133 |
bool FileSystem::LockWorkspace() { |
|
404 |
133 |
path_workspace_lock_ = workspace_ + "/lock." + name_; |
|
405 |
133 |
fd_workspace_lock_ = TryLockFile(path_workspace_lock_); |
|
406 |
✓✓ | 133 |
if (fd_workspace_lock_ >= 0) |
407 |
131 |
return true; |
|
408 |
|||
409 |
✗✓ | 2 |
if (fd_workspace_lock_ == -1) { |
410 |
boot_error_ = "could not acquire workspace lock (" + |
||
411 |
StringifyInt(errno) + ")"; |
||
412 |
boot_status_ = loader::kFailCacheDir; |
||
413 |
return false; |
||
414 |
} |
||
415 |
|||
416 |
✗✓ | 2 |
assert(fd_workspace_lock_ == -2); |
417 |
|||
418 |
✓✗ | 2 |
if (!wait_workspace_) { |
419 |
2 |
boot_status_ = loader::kFailLockWorkspace; |
|
420 |
2 |
return false; |
|
421 |
} |
||
422 |
|||
423 |
fd_workspace_lock_ = LockFile(path_workspace_lock_); |
||
424 |
if (fd_workspace_lock_ < 0) { |
||
425 |
boot_error_ = "could not acquire workspace lock (" + |
||
426 |
StringifyInt(errno) + ")"; |
||
427 |
boot_status_ = loader::kFailCacheDir; |
||
428 |
return false; |
||
429 |
} |
||
430 |
return true; |
||
431 |
} |
||
432 |
|||
433 |
|||
434 |
136 |
void FileSystem::LogSqliteError( |
|
435 |
void *user_data __attribute__((unused)), |
||
436 |
int sqlite_extended_error, |
||
437 |
const char *message) |
||
438 |
{ |
||
439 |
136 |
int log_dest = kLogDebug; |
|
440 |
136 |
int sqlite_error = sqlite_extended_error & 0xFF; |
|
441 |
✓✓ | 136 |
switch (sqlite_error) { |
442 |
case SQLITE_INTERNAL: |
||
443 |
case SQLITE_PERM: |
||
444 |
case SQLITE_NOMEM: |
||
445 |
case SQLITE_IOERR: |
||
446 |
case SQLITE_CORRUPT: |
||
447 |
case SQLITE_FULL: |
||
448 |
case SQLITE_CANTOPEN: |
||
449 |
case SQLITE_MISUSE: |
||
450 |
case SQLITE_FORMAT: |
||
451 |
case SQLITE_NOTADB: |
||
452 |
6 |
log_dest |= kLogSyslogErr; |
|
453 |
break; |
||
454 |
case SQLITE_WARNING: |
||
455 |
case SQLITE_NOTICE: |
||
456 |
default: |
||
457 |
break; |
||
458 |
} |
||
459 |
LogCvmfs(kLogCvmfs, log_dest, "SQlite3: %s (%d)", |
||
460 |
✗✗ | 136 |
message, sqlite_extended_error); |
461 |
136 |
} |
|
462 |
|||
463 |
|||
464 |
/** |
||
465 |
* Creates the cache parameter for a specific instance of the cache. Injects |
||
466 |
* the instance name such that CVMFS_CACHE_FOO_BAR becomes |
||
467 |
* CVMFS_CACHE_<INSTANCE>_FOO_BAR |
||
468 |
*/ |
||
469 |
1173 |
string FileSystem::MkCacheParm( |
|
470 |
const string &generic_parameter, |
||
471 |
const string &instance) |
||
472 |
{ |
||
473 |
✗✓ | 1173 |
assert(HasPrefix(generic_parameter, "CVMFS_CACHE_", false)); |
474 |
|||
475 |
✓✓ | 1173 |
if (instance == kDefaultCacheMgrInstance) { |
476 |
// Compatibility parameter names |
||
477 |
✓✓✓✗ ✓✓ |
853 |
if ((generic_parameter == "CVMFS_CACHE_SHARED") && |
478 |
!options_mgr_->IsDefined(generic_parameter)) |
||
479 |
{ |
||
480 |
102 |
return "CVMFS_SHARED_CACHE"; |
|
481 |
} |
||
482 |
✓✓✓✗ ✓✓ |
751 |
if ((generic_parameter == "CVMFS_CACHE_ALIEN") && |
483 |
!options_mgr_->IsDefined(generic_parameter)) |
||
484 |
{ |
||
485 |
102 |
return "CVMFS_ALIEN_CACHE"; |
|
486 |
} |
||
487 |
✓✓✓✗ ✓✓ |
649 |
if ((generic_parameter == "CVMFS_CACHE_SERVER_MODE") && |
488 |
!options_mgr_->IsDefined(generic_parameter)) |
||
489 |
{ |
||
490 |
239 |
return "CVMFS_SERVER_CACHE_MODE"; |
|
491 |
} |
||
492 |
✓✓✓✗ ✓✓ |
410 |
if ((generic_parameter == "CVMFS_CACHE_QUOTA_LIMIT") && |
493 |
!options_mgr_->IsDefined(generic_parameter)) |
||
494 |
{ |
||
495 |
102 |
return "CVMFS_QUOTA_LIMIT"; |
|
496 |
} |
||
497 |
308 |
return generic_parameter; |
|
498 |
} |
||
499 |
|||
500 |
320 |
return "CVMFS_CACHE_" + instance + "_" + generic_parameter.substr(12); |
|
501 |
} |
||
502 |
|||
503 |
|||
504 |
void FileSystem::ResetErrorCounters() { |
||
505 |
n_io_error_->Set(0); |
||
506 |
} |
||
507 |
|||
508 |
|||
509 |
/** |
||
510 |
* Can be recursive for the tiered cache manager. |
||
511 |
*/ |
||
512 |
179 |
CacheManager *FileSystem::SetupCacheMgr(const string &instance) { |
|
513 |
✓✓ | 179 |
if (constructed_instances_.find(instance) != constructed_instances_.end()) { |
514 |
2 |
boot_error_ = "circular cache definition: " + instance; |
|
515 |
2 |
boot_status_ = loader::kFailCacheDir; |
|
516 |
2 |
return NULL; |
|
517 |
} |
||
518 |
177 |
constructed_instances_.insert(instance); |
|
519 |
|||
520 |
LogCvmfs(kLogCvmfs, kLogDebug, "setting up cache manager instance %s", |
||
521 |
177 |
instance.c_str()); |
|
522 |
177 |
string instance_type; |
|
523 |
✓✓ | 177 |
if (instance == kDefaultCacheMgrInstance) { |
524 |
102 |
instance_type = "posix"; |
|
525 |
} else { |
||
526 |
options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_TYPE", instance), |
||
527 |
75 |
&instance_type); |
|
528 |
} |
||
529 |
✓✓ | 177 |
if (instance_type == "posix") { |
530 |
116 |
return SetupPosixCacheMgr(instance); |
|
531 |
✓✓ | 61 |
} else if (instance_type == "ram") { |
532 |
31 |
return SetupRamCacheMgr(instance); |
|
533 |
✓✓ | 30 |
} else if (instance_type == "tiered") { |
534 |
28 |
return SetupTieredCacheMgr(instance); |
|
535 |
✗✓ | 2 |
} else if (instance_type == "external") { |
536 |
return SetupExternalCacheMgr(instance); |
||
537 |
} else { |
||
538 |
boot_error_ = "invalid cache manager type for '" + instance + "':" + |
||
539 |
2 |
instance_type; |
|
540 |
2 |
boot_status_ = loader::kFailCacheDir; |
|
541 |
2 |
return NULL; |
|
542 |
} |
||
543 |
} |
||
544 |
|||
545 |
|||
546 |
CacheManager *FileSystem::SetupExternalCacheMgr(const string &instance) { |
||
547 |
string optarg; |
||
548 |
unsigned nfiles = kDefaultNfiles; |
||
549 |
if (options_mgr_->GetValue("CVMFS_NFILES", &optarg)) |
||
550 |
nfiles = String2Uint64(optarg); |
||
551 |
vector<string> cmd_line; |
||
552 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_CMDLINE", instance), |
||
553 |
&optarg)) |
||
554 |
{ |
||
555 |
cmd_line = SplitString(optarg, ','); |
||
556 |
} |
||
557 |
|||
558 |
if (!options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_LOCATOR", instance), |
||
559 |
&optarg)) |
||
560 |
{ |
||
561 |
boot_error_ = MkCacheParm("CVMFS_CACHE_LOCATOR", instance) + " missing"; |
||
562 |
boot_status_ = loader::kFailCacheDir; |
||
563 |
return NULL; |
||
564 |
} |
||
565 |
|||
566 |
UniquePtr<ExternalCacheManager::PluginHandle> plugin_handle( |
||
567 |
ExternalCacheManager::CreatePlugin(optarg, cmd_line)); |
||
568 |
if (!plugin_handle->IsValid()) { |
||
569 |
boot_error_ = plugin_handle->error_msg(); |
||
570 |
boot_status_ = loader::kFailCacheDir; |
||
571 |
return NULL; |
||
572 |
} |
||
573 |
ExternalCacheManager *cache_mgr = ExternalCacheManager::Create( |
||
574 |
plugin_handle->fd_connection(), nfiles, name_ + ":" + instance); |
||
575 |
if (cache_mgr == NULL) { |
||
576 |
boot_error_ = "failed to create external cache manager for " + instance; |
||
577 |
boot_status_ = loader::kFailCacheDir; |
||
578 |
return NULL; |
||
579 |
} |
||
580 |
cache_mgr->AcquireQuotaManager(ExternalQuotaManager::Create(cache_mgr)); |
||
581 |
return cache_mgr; |
||
582 |
} |
||
583 |
|||
584 |
|||
585 |
116 |
CacheManager *FileSystem::SetupPosixCacheMgr(const string &instance) { |
|
586 |
116 |
PosixCacheSettings settings = DeterminePosixCacheSettings(instance); |
|
587 |
✓✓ | 116 |
if (!CheckPosixCacheSettings(settings)) |
588 |
9 |
return NULL; |
|
589 |
|||
590 |
UniquePtr<PosixCacheManager> cache_mgr(PosixCacheManager::Create( |
||
591 |
settings.cache_path, |
||
592 |
settings.is_alien, |
||
593 |
settings.avoid_rename ? PosixCacheManager::kRenameLink |
||
594 |
✗✓ | 107 |
: PosixCacheManager::kRenameNormal)); |
595 |
✗✓ | 107 |
if (!cache_mgr.IsValid()) { |
596 |
boot_error_ = "Failed to setup posix cache '" + instance + "' in " + |
||
597 |
settings.cache_path + ": " + strerror(errno); |
||
598 |
boot_status_ = loader::kFailCacheDir; |
||
599 |
return NULL; |
||
600 |
} |
||
601 |
|||
602 |
// Sentinel file for future use |
||
603 |
// Might be a read-only cache |
||
604 |
107 |
const bool ignore_failure = settings.is_alien; |
|
605 |
107 |
CreateFile(settings.cache_path + "/.cvmfscache", 0600, ignore_failure); |
|
606 |
|||
607 |
✓✓ | 107 |
if (settings.is_managed) { |
608 |
✓✓ | 57 |
if (!SetupPosixQuotaMgr(settings, cache_mgr)) |
609 |
2 |
return NULL; |
|
610 |
} |
||
611 |
105 |
return cache_mgr.Release(); |
|
612 |
} |
||
613 |
|||
614 |
|||
615 |
31 |
CacheManager *FileSystem::SetupRamCacheMgr(const string &instance) { |
|
616 |
31 |
string optarg; |
|
617 |
31 |
unsigned nfiles = kDefaultNfiles; |
|
618 |
✓✗ | 31 |
if (options_mgr_->GetValue("CVMFS_NFILES", &optarg)) { |
619 |
nfiles = String2Uint64(optarg); |
||
620 |
} |
||
621 |
uint64_t sz_cache_bytes; |
||
622 |
✗✓ | 31 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_SIZE", instance), |
623 |
&optarg)) |
||
624 |
{ |
||
625 |
if (HasSuffix(optarg, "%", false)) { |
||
626 |
sz_cache_bytes = platform_memsize() * String2Uint64(optarg)/100; |
||
627 |
} else { |
||
628 |
sz_cache_bytes = String2Uint64(optarg) * 1024 * 1024; |
||
629 |
} |
||
630 |
} else { |
||
631 |
31 |
sz_cache_bytes = platform_memsize() >> 5; // ~3% |
|
632 |
} |
||
633 |
31 |
MemoryKvStore::MemoryAllocator alloc = MemoryKvStore::kMallocHeap; |
|
634 |
✓✓ | 31 |
if (options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_MALLOC", instance), |
635 |
&optarg)) |
||
636 |
{ |
||
637 |
✓✓ | 6 |
if (optarg == "libc") { |
638 |
3 |
alloc = MemoryKvStore::kMallocLibc; |
|
639 |
✗✓ | 3 |
} else if (optarg == "heap") { |
640 |
alloc = MemoryKvStore::kMallocHeap; |
||
641 |
} else { |
||
642 |
boot_error_ = "Failure: unknown malloc " + |
||
643 |
3 |
MkCacheParm("CVMFS_CACHE_MALLOC", instance) + "=" + optarg; |
|
644 |
3 |
boot_status_ = loader::kFailOptions; |
|
645 |
3 |
return NULL; |
|
646 |
} |
||
647 |
} |
||
648 |
sz_cache_bytes = RoundUp8(std::max(static_cast<uint64_t>(200 * 1024 * 1024), |
||
649 |
28 |
sz_cache_bytes)); |
|
650 |
RamCacheManager *cache_mgr = new RamCacheManager( |
||
651 |
sz_cache_bytes, |
||
652 |
nfiles, |
||
653 |
alloc, |
||
654 |
28 |
perf::StatisticsTemplate("cache." + instance, statistics_)); |
|
655 |
✗✓ | 28 |
if (cache_mgr == NULL) { |
656 |
boot_error_ = "failed to create ram cache manager for " + instance; |
||
657 |
boot_status_ = loader::kFailCacheDir; |
||
658 |
return NULL; |
||
659 |
} |
||
660 |
28 |
cache_mgr->AcquireQuotaManager(new NoopQuotaManager()); |
|
661 |
28 |
return cache_mgr; |
|
662 |
} |
||
663 |
|||
664 |
|||
665 |
28 |
CacheManager *FileSystem::SetupTieredCacheMgr(const string &instance) { |
|
666 |
28 |
string optarg; |
|
667 |
✓✓ | 28 |
if (!options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_UPPER", instance), |
668 |
&optarg)) |
||
669 |
{ |
||
670 |
2 |
boot_error_ = MkCacheParm("CVMFS_CACHE_UPPER", instance) + " missing"; |
|
671 |
2 |
boot_status_ = loader::kFailOptions; |
|
672 |
2 |
return NULL; |
|
673 |
} |
||
674 |
26 |
UniquePtr<CacheManager> upper(SetupCacheMgr(optarg)); |
|
675 |
✗✓ | 26 |
if (!upper.IsValid()) |
676 |
return NULL; |
||
677 |
|||
678 |
✓✓ | 26 |
if (!options_mgr_->GetValue(MkCacheParm("CVMFS_CACHE_LOWER", instance), |
679 |
&optarg)) |
||
680 |
{ |
||
681 |
2 |
boot_error_ = MkCacheParm("CVMFS_CACHE_LOWER", instance) + " missing"; |
|
682 |
2 |
boot_status_ = loader::kFailOptions; |
|
683 |
2 |
return NULL; |
|
684 |
} |
||
685 |
24 |
UniquePtr<CacheManager> lower(SetupCacheMgr(optarg)); |
|
686 |
✓✓ | 24 |
if (!lower.IsValid()) |
687 |
2 |
return NULL; |
|
688 |
|||
689 |
CacheManager *tiered = |
||
690 |
22 |
TieredCacheManager::Create(upper.Release(), lower.Release()); |
|
691 |
✗✓ | 22 |
if (tiered == NULL) { |
692 |
boot_error_ = "Failed to setup tiered cache manager " + instance; |
||
693 |
boot_status_ = loader::kFailCacheDir; |
||
694 |
return NULL; |
||
695 |
} |
||
696 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✓ |
22 |
if (options_mgr_->GetValue( |
697 |
MkCacheParm("CVMFS_CACHE_LOWER_READONLY", instance), &optarg) && |
||
698 |
options_mgr_->IsOn(optarg)) |
||
699 |
{ |
||
700 |
static_cast<TieredCacheManager*>(tiered)->SetLowerReadOnly(); |
||
701 |
} |
||
702 |
22 |
return tiered; |
|
703 |
} |
||
704 |
|||
705 |
|||
706 |
131 |
bool FileSystem::SetupCrashGuard() { |
|
707 |
131 |
path_crash_guard_ = workspace_ + "/running." + name_; |
|
708 |
platform_stat64 info; |
||
709 |
131 |
int retval = platform_stat(path_crash_guard_.c_str(), &info); |
|
710 |
✓✓ | 131 |
if (retval == 0) { |
711 |
2 |
found_previous_crash_ = true; |
|
712 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogWarn, |
||
713 |
2 |
"looks like cvmfs has been crashed previously"); |
|
714 |
} |
||
715 |
131 |
retval = open(path_crash_guard_.c_str(), O_RDONLY | O_CREAT, 0600); |
|
716 |
✗✓ | 131 |
if (retval < 0) { |
717 |
boot_error_ = "could not open running sentinel (" + |
||
718 |
StringifyInt(errno) + ")"; |
||
719 |
boot_status_ = loader::kFailCacheDir; |
||
720 |
return false; |
||
721 |
} |
||
722 |
131 |
close(retval); |
|
723 |
131 |
return true; |
|
724 |
} |
||
725 |
|||
726 |
|||
727 |
131 |
bool FileSystem::SetupCwd() { |
|
728 |
✓✓ | 131 |
if (type_ == kFsFuse) { |
729 |
// Try to jump to workspace / cache directory. This tests, if it is |
||
730 |
// accessible and it brings speed later on. |
||
731 |
104 |
int retval = chdir(workspace_.c_str()); |
|
732 |
✗✓ | 104 |
if (retval != 0) { |
733 |
boot_error_ = "workspace " + workspace_ + " is unavailable"; |
||
734 |
boot_status_ = loader::kFailCacheDir; |
||
735 |
return false; |
||
736 |
} |
||
737 |
104 |
workspace_ = "."; |
|
738 |
104 |
return true; |
|
739 |
} |
||
740 |
|||
741 |
// Note: as of version 2.4 support for CVMFS_CWD_CACHE is dropped due to |
||
742 |
// disproportionate large complexity to configure correctly. This affects |
||
743 |
// only libcvmfs, mostly the legacy part. |
||
744 |
// string optarg; |
||
745 |
// if (options_mgr_->GetValue("CVMFS_CWD_CACHE", &optarg) && |
||
746 |
// options_mgr_->IsOn(optarg)) |
||
747 |
// { |
||
748 |
// ... |
||
749 |
// } |
||
750 |
27 |
return true; |
|
751 |
} |
||
752 |
|||
753 |
|||
754 |
137 |
void FileSystem::SetupLogging() { |
|
755 |
137 |
string optarg; |
|
756 |
✓✓ | 137 |
if (options_mgr_->GetValue("CVMFS_SYSLOG_LEVEL", &optarg)) |
757 |
12 |
SetLogSyslogLevel(String2Uint64(optarg)); |
|
758 |
✓✗ | 137 |
if (options_mgr_->GetValue("CVMFS_SYSLOG_FACILITY", &optarg)) |
759 |
SetLogSyslogFacility(String2Int64(optarg)); |
||
760 |
✓✗ | 137 |
if (options_mgr_->GetValue("CVMFS_USYSLOG", &optarg)) |
761 |
SetLogMicroSyslog(optarg); |
||
762 |
✓✗ | 137 |
if (options_mgr_->GetValue("CVMFS_DEBUGLOG", &optarg)) |
763 |
SetLogDebugFile(optarg); |
||
764 |
✓✓ | 137 |
if (options_mgr_->GetValue("CVMFS_SYSLOG_PREFIX", &optarg)) { |
765 |
4 |
SetLogSyslogPrefix(optarg); |
|
766 |
} else { |
||
767 |
133 |
SetLogSyslogPrefix(name_); |
|
768 |
} |
||
769 |
137 |
} |
|
770 |
|||
771 |
|||
772 |
107 |
bool FileSystem::SetupNfsMaps() { |
|
773 |
#ifdef CVMFS_NFS_SUPPORT |
||
774 |
if (!IsHaNfsSource()) |
||
775 |
nfs_maps_dir_ = workspace_; |
||
776 |
|||
777 |
string no_nfs_sentinel; |
||
778 |
if (cache_mgr_->id() == kPosixCacheManager) { |
||
779 |
PosixCacheManager *posix_cache_mgr = |
||
780 |
reinterpret_cast<PosixCacheManager *>(cache_mgr_); |
||
781 |
no_nfs_sentinel = posix_cache_mgr->cache_path() + "/no_nfs_maps." + name_; |
||
782 |
if (!IsNfsSource()) { |
||
783 |
// Might be a read-only cache |
||
784 |
const bool ignore_failure = posix_cache_mgr->alien_cache(); |
||
785 |
CreateFile(no_nfs_sentinel, 0600, ignore_failure); |
||
786 |
return true; |
||
787 |
} |
||
788 |
} else { |
||
789 |
if (IsNfsSource()) { |
||
790 |
boot_error_ = "NFS source only works with POSIX cache manager."; |
||
791 |
boot_status_ = loader::kFailNfsMaps; |
||
792 |
return false; |
||
793 |
} |
||
794 |
return true; |
||
795 |
} |
||
796 |
|||
797 |
assert(cache_mgr_->id() == kPosixCacheManager); |
||
798 |
assert(IsNfsSource()); |
||
799 |
if (!no_nfs_sentinel.empty() && FileExists(no_nfs_sentinel)) { |
||
800 |
boot_error_ = "Cache was used without NFS maps before. " |
||
801 |
"It has to be wiped out."; |
||
802 |
boot_status_ = loader::kFailNfsMaps; |
||
803 |
return false; |
||
804 |
} |
||
805 |
|||
806 |
// nfs maps need to be protected by workspace lock |
||
807 |
PosixCacheManager *posix_cache_mgr = |
||
808 |
reinterpret_cast<PosixCacheManager *>(cache_mgr_); |
||
809 |
if (posix_cache_mgr->cache_path() != workspace_) { |
||
810 |
boot_error_ = "Cache directory and workspace must be identical for " |
||
811 |
"NFS export"; |
||
812 |
boot_status_ = loader::kFailNfsMaps; |
||
813 |
return false; |
||
814 |
} |
||
815 |
|||
816 |
string inode_cache_dir = nfs_maps_dir_ + "/nfs_maps." + name_; |
||
817 |
if (!MkdirDeep(inode_cache_dir, 0700)) { |
||
818 |
boot_error_ = "Failed to initialize NFS maps"; |
||
819 |
boot_status_ = loader::kFailNfsMaps; |
||
820 |
return false; |
||
821 |
} |
||
822 |
|||
823 |
// TODO(jblomer): make this a manager class |
||
824 |
if (IsHaNfsSource()) { |
||
825 |
nfs_maps_ = NfsMapsSqlite::Create( |
||
826 |
inode_cache_dir, |
||
827 |
catalog::ClientCatalogManager::kInodeOffset + 1, |
||
828 |
found_previous_crash_, |
||
829 |
statistics_); |
||
830 |
} else { |
||
831 |
nfs_maps_ = NfsMapsLeveldb::Create( |
||
832 |
inode_cache_dir, |
||
833 |
catalog::ClientCatalogManager::kInodeOffset + 1, |
||
834 |
found_previous_crash_, |
||
835 |
statistics_); |
||
836 |
} |
||
837 |
|||
838 |
if (nfs_maps_ == NULL) { |
||
839 |
boot_error_ = "Failed to initialize NFS maps"; |
||
840 |
boot_status_ = loader::kFailNfsMaps; |
||
841 |
return false; |
||
842 |
} |
||
843 |
|||
844 |
string optarg; |
||
845 |
if (options_mgr_->GetValue("CVMFS_NFS_INTERLEAVED_INODES", &optarg)) { |
||
846 |
vector<string> tokens = SplitString(optarg, '%'); |
||
847 |
if (tokens.size() != 2) { |
||
848 |
boot_error_ = |
||
849 |
"invalid format for CVMFS_NFS_INTERLEAVED_INODES: " + optarg; |
||
850 |
boot_status_ = loader::kFailNfsMaps; |
||
851 |
return false; |
||
852 |
} |
||
853 |
nfs_maps_->SetInodeResidue(String2Uint64(tokens[1]), |
||
854 |
String2Uint64(tokens[0])); |
||
855 |
} |
||
856 |
|||
857 |
return true; |
||
858 |
|||
859 |
#else |
||
860 |
107 |
return true; |
|
861 |
#endif |
||
862 |
} |
||
863 |
|||
864 |
|||
865 |
57 |
bool FileSystem::SetupPosixQuotaMgr( |
|
866 |
const FileSystem::PosixCacheSettings &settings, |
||
867 |
CacheManager *cache_mgr |
||
868 |
) { |
||
869 |
✗✓ | 57 |
assert(settings.quota_limit >= 0); |
870 |
57 |
int64_t quota_threshold = settings.quota_limit / 2; |
|
871 |
57 |
string cache_workspace = settings.cache_path; |
|
872 |
✗✓ | 57 |
if (settings.cache_path != settings.workspace) { |
873 |
LogCvmfs(kLogQuota, kLogDebug | kLogSyslog, |
||
874 |
"using workspace %s to protect cache database in %s", |
||
875 |
settings.workspace.c_str(), settings.cache_path.c_str()); |
||
876 |
cache_workspace += ":" + settings.workspace; |
||
877 |
} |
||
878 |
PosixQuotaManager *quota_mgr; |
||
879 |
|||
880 |
✓✓ | 57 |
if (settings.is_shared) { |
881 |
quota_mgr = PosixQuotaManager::CreateShared( |
||
882 |
exe_path_, |
||
883 |
cache_workspace, |
||
884 |
settings.quota_limit, |
||
885 |
quota_threshold, |
||
886 |
2 |
foreground_); |
|
887 |
✓✗ | 2 |
if (quota_mgr == NULL) { |
888 |
2 |
boot_error_ = "Failed to initialize shared lru cache"; |
|
889 |
2 |
boot_status_ = loader::kFailQuota; |
|
890 |
2 |
return false; |
|
891 |
} |
||
892 |
} else { |
||
893 |
quota_mgr = PosixQuotaManager::Create( |
||
894 |
cache_workspace, |
||
895 |
settings.quota_limit, |
||
896 |
quota_threshold, |
||
897 |
55 |
found_previous_crash_); |
|
898 |
✗✓ | 55 |
if (quota_mgr == NULL) { |
899 |
boot_error_ = "Failed to initialize lru cache"; |
||
900 |
boot_status_ = loader::kFailQuota; |
||
901 |
return false; |
||
902 |
} |
||
903 |
} |
||
904 |
|||
905 |
✗✓ | 55 |
if (quota_mgr->GetSize() > quota_mgr->GetCapacity()) { |
906 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslog, |
||
907 |
"cache is already beyond quota size " |
||
908 |
"(size: %" PRId64 ", capacity: %" PRId64 "), cleaning up", |
||
909 |
quota_mgr->GetSize(), quota_mgr->GetCapacity()); |
||
910 |
if (!quota_mgr->Cleanup(quota_threshold)) { |
||
911 |
delete quota_mgr; |
||
912 |
boot_error_ = "Failed to clean up cache"; |
||
913 |
boot_status_ = loader::kFailQuota; |
||
914 |
return false; |
||
915 |
} |
||
916 |
} |
||
917 |
|||
918 |
55 |
int retval = cache_mgr->AcquireQuotaManager(quota_mgr); |
|
919 |
✗✓ | 55 |
assert(retval); |
920 |
LogCvmfs(kLogCvmfs, kLogDebug, |
||
921 |
"CernVM-FS: quota initialized, current size %luMB", |
||
922 |
55 |
quota_mgr->GetSize() / (1024 * 1024)); |
|
923 |
55 |
return true; |
|
924 |
} |
||
925 |
|||
926 |
|||
927 |
137 |
void FileSystem::SetupSqlite() { |
|
928 |
// Make sure SQlite starts clean after initialization |
||
929 |
137 |
sqlite3_shutdown(); |
|
930 |
|||
931 |
int retval; |
||
932 |
137 |
retval = sqlite3_config(SQLITE_CONFIG_LOG, FileSystem::LogSqliteError, NULL); |
|
933 |
✗✓ | 137 |
assert(retval == SQLITE_OK); |
934 |
137 |
retval = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); |
|
935 |
✗✓ | 137 |
assert(retval == SQLITE_OK); |
936 |
137 |
SqliteMemoryManager::GetInstance()->AssignGlobalArenas(); |
|
937 |
|||
938 |
// Disable SQlite3 file locking |
||
939 |
137 |
retval = sqlite3_vfs_register(sqlite3_vfs_find("unix-none"), 1); |
|
940 |
✗✓ | 137 |
assert(retval == SQLITE_OK); |
941 |
137 |
} |
|
942 |
|||
943 |
|||
944 |
137 |
bool FileSystem::SetupWorkspace() { |
|
945 |
137 |
string optarg; |
|
946 |
// This is very similar to "determine cache dir". It's for backward |
||
947 |
// compatibility with classic cache configuration where there was no |
||
948 |
// distinction between workspace and cache. |
||
949 |
// Complicated cache configurations should explicitly set CVMFS_WORKSPACE. |
||
950 |
137 |
workspace_ = kDefaultCacheBase; |
|
951 |
✓✓ | 137 |
if (options_mgr_->GetValue("CVMFS_CACHE_BASE", &optarg)) |
952 |
112 |
workspace_ = MakeCanonicalPath(optarg); |
|
953 |
✓✓✓✓ ✓✗✗✗ ✗✗✓✗ ✓✓ |
137 |
if (options_mgr_->GetValue("CVMFS_SHARED_CACHE", &optarg) && |
954 |
options_mgr_->IsOn(optarg)) |
||
955 |
{ |
||
956 |
8 |
workspace_ += "/shared"; |
|
957 |
} else { |
||
958 |
129 |
workspace_ += "/" + name_; |
|
959 |
} |
||
960 |
✓✓ | 137 |
if (options_mgr_->GetValue("CVMFS_CACHE_DIR", &optarg)) { |
961 |
✓✓ | 28 |
if (options_mgr_->IsDefined("CVMFS_CACHE_BASE")) { |
962 |
boot_error_ = |
||
963 |
3 |
"'CVMFS_CACHE_BASE' and 'CVMFS_CACHE_DIR' are mutually exclusive"; |
|
964 |
3 |
boot_status_ = loader::kFailOptions; |
|
965 |
3 |
return false; |
|
966 |
} |
||
967 |
25 |
workspace_ = optarg; |
|
968 |
} |
||
969 |
✓✓ | 134 |
if (options_mgr_->GetValue("CVMFS_WORKSPACE", &optarg)) |
970 |
8 |
workspace_ = optarg; |
|
971 |
134 |
workspace_fullpath_ = workspace_; |
|
972 |
|||
973 |
// If workspace and alien cache are the same directory, we need to open |
||
974 |
// permission now to 0770 to avoid a race when fixing it later |
||
975 |
134 |
const int mode = 0770; |
|
976 |
✓✓ | 134 |
if (!MkdirDeep(workspace_, mode, false)) { |
977 |
1 |
boot_error_ = "cannot create workspace directory " + workspace_; |
|
978 |
1 |
boot_status_ = loader::kFailCacheDir; |
|
979 |
1 |
return false; |
|
980 |
} |
||
981 |
|||
982 |
✓✓ | 133 |
if (!LockWorkspace()) |
983 |
2 |
return false; |
|
984 |
✗✓ | 131 |
if (!SetupCwd()) |
985 |
return false; |
||
986 |
✗✓ | 131 |
if (!SetupCrashGuard()) |
987 |
return false; |
||
988 |
|||
989 |
131 |
return true; |
|
990 |
} |
||
991 |
|||
992 |
|||
993 |
107 |
void FileSystem::SetupUuid() { |
|
994 |
107 |
uuid_cache_ = cvmfs::Uuid::Create(workspace_ + "/uuid"); |
|
995 |
✗✓ | 107 |
if (uuid_cache_ == NULL) { |
996 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogWarn, |
||
997 |
"failed to load/store %s/uuid", workspace_.c_str()); |
||
998 |
uuid_cache_ = cvmfs::Uuid::Create(""); |
||
999 |
assert(uuid_cache_ != NULL); |
||
1000 |
} |
||
1001 |
107 |
} |
|
1002 |
|||
1003 |
|||
1004 |
/** |
||
1005 |
* Required by CernVM: the fuse module needs to free r/w file descriptor to the |
||
1006 |
* cache in order to properly unravel the file system stack on shutdown. |
||
1007 |
*/ |
||
1008 |
void FileSystem::TearDown2ReadOnly() { |
||
1009 |
if ((cache_mgr_ != NULL) && (cache_mgr_->id() == kPosixCacheManager)) { |
||
1010 |
PosixCacheManager *posix_cache_mgr = |
||
1011 |
reinterpret_cast<PosixCacheManager *>(cache_mgr_); |
||
1012 |
posix_cache_mgr->TearDown2ReadOnly(); |
||
1013 |
} |
||
1014 |
|||
1015 |
unlink(path_crash_guard_.c_str()); |
||
1016 |
LogCvmfs(kLogCache, kLogSyslog, "switch to read-only cache mode"); |
||
1017 |
SetLogMicroSyslog(""); |
||
1018 |
} |
||
1019 |
|||
1020 |
|||
1021 |
131 |
bool FileSystem::TriageCacheMgr() { |
|
1022 |
131 |
cache_mgr_instance_ = kDefaultCacheMgrInstance; |
|
1023 |
131 |
string instance; |
|
1024 |
✓✓✓✗ ✓✗✗✗ ✗✗✓✗ ✓✓ |
131 |
if (options_mgr_->GetValue("CVMFS_CACHE_PRIMARY", &instance) && |
1025 |
!instance.empty()) |
||
1026 |
{ |
||
1027 |
✓✓ | 31 |
if (!CheckInstanceName(instance)) |
1028 |
2 |
return false; |
|
1029 |
29 |
cache_mgr_instance_ = instance; |
|
1030 |
} |
||
1031 |
|||
1032 |
129 |
cache_mgr_ = SetupCacheMgr(cache_mgr_instance_); |
|
1033 |
129 |
return cache_mgr_ != NULL; |
|
1034 |
} |
||
1035 |
|||
1036 |
|||
1037 |
//------------------------------------------------------------------------------ |
||
1038 |
|||
1039 |
|||
1040 |
const char *MountPoint::kDefaultAuthzSearchPath = "/usr/libexec/cvmfs/authz"; |
||
1041 |
const char *MountPoint::kDefaultBlacklist = "/etc/cvmfs/blacklist"; |
||
1042 |
|||
1043 |
59 |
bool MountPoint::CheckBlacklists() { |
|
1044 |
59 |
blacklist_paths_.clear(); |
|
1045 |
59 |
string blacklist; |
|
1046 |
✓✓ | 59 |
if (!options_mgr_->GetValue("CVMFS_BLACKLIST", &blacklist)) |
1047 |
53 |
blacklist = kDefaultBlacklist; |
|
1048 |
59 |
blacklist_paths_.push_back(blacklist); |
|
1049 |
|||
1050 |
59 |
bool append = false; |
|
1051 |
✓✓ | 59 |
if (FileExists(blacklist)) { |
1052 |
✗✓ | 3 |
if (!signature_mgr_->LoadBlacklist(blacklist, append)) { |
1053 |
boot_error_ = "failed to load blacklist " + blacklist; |
||
1054 |
boot_status_ = loader::kFailSignature; |
||
1055 |
return false; |
||
1056 |
} |
||
1057 |
3 |
append = true; |
|
1058 |
} |
||
1059 |
|||
1060 |
59 |
string config_repository_path; |
|
1061 |
✓✓ | 59 |
if (options_mgr_->HasConfigRepository(fqrn_, &config_repository_path)) { |
1062 |
9 |
blacklist = config_repository_path + "blacklist"; |
|
1063 |
9 |
blacklist_paths_.push_back(blacklist); |
|
1064 |
✓✓ | 9 |
if (FileExists(blacklist)) { |
1065 |
✗✓ | 6 |
if (!signature_mgr_->LoadBlacklist(blacklist, append)) { |
1066 |
boot_error_ = "failed to load blacklist from config repository"; |
||
1067 |
boot_status_ = loader::kFailSignature; |
||
1068 |
return false; |
||
1069 |
} |
||
1070 |
} |
||
1071 |
} |
||
1072 |
|||
1073 |
59 |
return true; |
|
1074 |
} |
||
1075 |
|||
1076 |
|||
1077 |
/** |
||
1078 |
* Like CheckBlacklists but supposed to be used after bootstrap, possibly in |
||
1079 |
* multi-threaded context. |
||
1080 |
*/ |
||
1081 |
6 |
bool MountPoint::ReloadBlacklists() { |
|
1082 |
6 |
bool result = true; |
|
1083 |
6 |
bool append = false; |
|
1084 |
✓✗✓✓ |
6 |
for (unsigned i = 0; i < blacklist_paths_.size(); ++i) { |
1085 |
9 |
string blacklist = blacklist_paths_[i]; |
|
1086 |
✗✓ | 9 |
if (FileExists(blacklist)) { |
1087 |
bool retval = signature_mgr_->LoadBlacklist(blacklist, append); |
||
1088 |
// TODO(jblomer): this can leave us with a half-loaded blacklist |
||
1089 |
if (!retval) |
||
1090 |
return false; |
||
1091 |
append = true; |
||
1092 |
} |
||
1093 |
} |
||
1094 |
6 |
return result; |
|
1095 |
} |
||
1096 |
|||
1097 |
|||
1098 |
/** |
||
1099 |
* The option_mgr parameter can be NULL, in which case the global option manager |
||
1100 |
* from the file system is used. |
||
1101 |
*/ |
||
1102 |
61 |
MountPoint *MountPoint::Create( |
|
1103 |
const string &fqrn, |
||
1104 |
FileSystem *file_system, |
||
1105 |
OptionsManager *options_mgr) |
||
1106 |
{ |
||
1107 |
✓✓ | 61 |
if (options_mgr == NULL) |
1108 |
53 |
options_mgr = file_system->options_mgr(); |
|
1109 |
UniquePtr<MountPoint> mountpoint(new MountPoint( |
||
1110 |
61 |
fqrn, file_system, options_mgr)); |
|
1111 |
|||
1112 |
// At this point, we have a repository name, the type (fuse or library) and |
||
1113 |
// an options manager (which can be the same than the FileSystem's one). |
||
1114 |
|||
1115 |
61 |
mountpoint->CreateStatistics(); |
|
1116 |
61 |
mountpoint->CreateAuthz(); |
|
1117 |
61 |
mountpoint->backoff_throttle_ = new BackoffThrottle(); |
|
1118 |
|||
1119 |
✓✓✗✓ ✓✓ |
61 |
if (!mountpoint->CreateSignatureManager() || !mountpoint->CheckBlacklists()) |
1120 |
2 |
return mountpoint.Release(); |
|
1121 |
✓✓ | 59 |
if (!mountpoint->CreateDownloadManagers()) |
1122 |
2 |
return mountpoint.Release(); |
|
1123 |
✗✓ | 57 |
if (!mountpoint->CreateResolvConfWatcher()) { |
1124 |
return mountpoint.Release(); |
||
1125 |
} |
||
1126 |
57 |
mountpoint->CreateFetchers(); |
|
1127 |
✓✓ | 57 |
if (!mountpoint->CreateCatalogManager()) |
1128 |
20 |
return mountpoint.Release(); |
|
1129 |
✗✓ | 37 |
if (!mountpoint->CreateTracer()) |
1130 |
return mountpoint.Release(); |
||
1131 |
|||
1132 |
37 |
mountpoint->ReEvaluateAuthz(); |
|
1133 |
37 |
mountpoint->CreateTables(); |
|
1134 |
37 |
mountpoint->SetupBehavior(); |
|
1135 |
|||
1136 |
37 |
mountpoint->boot_status_ = loader::kFailOk; |
|
1137 |
37 |
return mountpoint.Release(); |
|
1138 |
} |
||
1139 |
|||
1140 |
|||
1141 |
61 |
void MountPoint::CreateAuthz() { |
|
1142 |
61 |
string optarg; |
|
1143 |
61 |
string authz_helper; |
|
1144 |
✓✗ | 61 |
if (options_mgr_->GetValue("CVMFS_AUTHZ_HELPER", &optarg)) |
1145 |
authz_helper = optarg; |
||
1146 |
61 |
string authz_search_path(kDefaultAuthzSearchPath); |
|
1147 |
✓✗ | 61 |
if (options_mgr_->GetValue("CVMFS_AUTHZ_SEARCH_PATH", &optarg)) |
1148 |
authz_search_path = optarg; |
||
1149 |
|||
1150 |
authz_fetcher_ = new AuthzExternalFetcher( |
||
1151 |
fqrn_, |
||
1152 |
authz_helper, |
||
1153 |
authz_search_path, |
||
1154 |
61 |
options_mgr_); |
|
1155 |
✗✓ | 61 |
assert(authz_fetcher_ != NULL); |
1156 |
|||
1157 |
authz_session_mgr_ = AuthzSessionManager::Create( |
||
1158 |
authz_fetcher_, |
||
1159 |
61 |
statistics_); |
|
1160 |
✗✓ | 61 |
assert(authz_session_mgr_ != NULL); |
1161 |
|||
1162 |
61 |
authz_attachment_ = new AuthzAttachment(authz_session_mgr_); |
|
1163 |
✗✓ | 61 |
assert(authz_attachment_ != NULL); |
1164 |
61 |
} |
|
1165 |
|||
1166 |
|||
1167 |
57 |
bool MountPoint::CreateCatalogManager() { |
|
1168 |
57 |
string optarg; |
|
1169 |
|||
1170 |
57 |
catalog_mgr_ = new catalog::ClientCatalogManager(this); |
|
1171 |
|||
1172 |
57 |
SetupInodeAnnotation(); |
|
1173 |
✓✓ | 57 |
if (!SetupOwnerMaps()) |
1174 |
2 |
return false; |
|
1175 |
55 |
shash::Any root_hash; |
|
1176 |
✓✓ | 55 |
if (!DetermineRootHash(&root_hash)) |
1177 |
4 |
return false; |
|
1178 |
|||
1179 |
bool retval; |
||
1180 |
✓✓ | 51 |
if (root_hash.IsNull()) { |
1181 |
24 |
retval = catalog_mgr_->Init(); |
|
1182 |
} else { |
||
1183 |
27 |
fixed_catalog_ = true; |
|
1184 |
bool alt_root_path = |
||
1185 |
options_mgr_->GetValue("CVMFS_ALT_ROOT_PATH", &optarg) && |
||
1186 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ |
27 |
options_mgr_->IsOn(optarg); |
1187 |
27 |
retval = catalog_mgr_->InitFixed(root_hash, alt_root_path); |
|
1188 |
} |
||
1189 |
✓✓ | 51 |
if (!retval) { |
1190 |
11 |
boot_error_ = "Failed to initialize root file catalog"; |
|
1191 |
11 |
boot_status_ = loader::kFailCatalog; |
|
1192 |
11 |
return false; |
|
1193 |
} |
||
1194 |
|||
1195 |
✓✓ | 40 |
if (catalog_mgr_->IsRevisionBlacklisted()) { |
1196 |
3 |
boot_error_ = "repository revision blacklisted"; |
|
1197 |
3 |
boot_status_ = loader::kFailRevisionBlacklisted; |
|
1198 |
3 |
return false; |
|
1199 |
} |
||
1200 |
|||
1201 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✓ |
37 |
if (options_mgr_->GetValue("CVMFS_AUTO_UPDATE", &optarg) && |
1202 |
!options_mgr_->IsOn(optarg)) |
||
1203 |
{ |
||
1204 |
fixed_catalog_ = true; |
||
1205 |
} |
||
1206 |
|||
1207 |
✓✗ | 37 |
if (options_mgr_->GetValue("CVMFS_CATALOG_WATERMARK", &optarg)) { |
1208 |
catalog_mgr_->SetCatalogWatermark(String2Uint64(optarg)); |
||
1209 |
} |
||
1210 |
|||
1211 |
✗✓ | 37 |
if (catalog_mgr_->volatile_flag()) { |
1212 |
LogCvmfs(kLogCvmfs, kLogDebug, "content of repository flagged as VOLATILE"); |
||
1213 |
} |
||
1214 |
|||
1215 |
37 |
return true; |
|
1216 |
} |
||
1217 |
|||
1218 |
|||
1219 |
59 |
bool MountPoint::CreateDownloadManagers() { |
|
1220 |
59 |
string optarg; |
|
1221 |
59 |
download_mgr_ = new download::DownloadManager(); |
|
1222 |
59 |
const bool use_system_proxy = false; |
|
1223 |
download_mgr_->Init(kDefaultNumConnections, use_system_proxy, |
||
1224 |
59 |
perf::StatisticsTemplate("download", statistics_)); |
|
1225 |
59 |
download_mgr_->SetCredentialsAttachment(authz_attachment_); |
|
1226 |
|||
1227 |
✗✓ | 59 |
if (options_mgr_->GetValue("CVMFS_SERVER_URL", &optarg)) { |
1228 |
59 |
download_mgr_->SetHostChain(optarg); |
|
1229 |
} |
||
1230 |
|||
1231 |
59 |
SetupDnsTuning(download_mgr_); |
|
1232 |
59 |
SetupHttpTuning(); |
|
1233 |
|||
1234 |
59 |
string forced_proxy_template; |
|
1235 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_PROXY_TEMPLATE", &optarg)) |
1236 |
forced_proxy_template = optarg; |
||
1237 |
download_mgr_->SetProxyTemplates(file_system_->uuid_cache()->uuid(), |
||
1238 |
59 |
forced_proxy_template); |
|
1239 |
|||
1240 |
59 |
string proxies; |
|
1241 |
✓✓ | 59 |
if (options_mgr_->GetValue("CVMFS_HTTP_PROXY", &optarg)) |
1242 |
57 |
proxies = optarg; |
|
1243 |
proxies = download::ResolveProxyDescription( |
||
1244 |
proxies, |
||
1245 |
file_system_->workspace() + "/proxies" + GetUniqFileSuffix(), |
||
1246 |
59 |
download_mgr_); |
|
1247 |
✓✓ | 59 |
if (proxies == "") { |
1248 |
2 |
boot_error_ = "failed to discover HTTP proxy servers"; |
|
1249 |
2 |
boot_status_ = loader::kFailWpad; |
|
1250 |
2 |
return false; |
|
1251 |
} |
||
1252 |
57 |
string fallback_proxies; |
|
1253 |
✓✗ | 57 |
if (options_mgr_->GetValue("CVMFS_FALLBACK_PROXY", &optarg)) |
1254 |
fallback_proxies = optarg; |
||
1255 |
download_mgr_->SetProxyChain(proxies, fallback_proxies, |
||
1256 |
57 |
download::DownloadManager::kSetProxyBoth); |
|
1257 |
|||
1258 |
bool do_geosort = options_mgr_->GetValue("CVMFS_USE_GEOAPI", &optarg) && |
||
1259 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ |
57 |
options_mgr_->IsOn(optarg); |
1260 |
✗✓ | 57 |
if (do_geosort) { |
1261 |
download_mgr_->ProbeGeo(); |
||
1262 |
} |
||
1263 |
✓✓ | 57 |
if (options_mgr_->GetValue("CVMFS_MAX_SERVERS", &optarg)) { |
1264 |
12 |
unsigned max_servers = String2Uint64(optarg); |
|
1265 |
12 |
std::vector<std::string> host_chain; |
|
1266 |
12 |
download_mgr_->GetHostInfo(&host_chain, NULL, NULL); |
|
1267 |
✓✓✓✓ ✓✓ |
12 |
if (max_servers > 0 && max_servers < host_chain.size()) { |
1268 |
3 |
host_chain.resize(max_servers); |
|
1269 |
3 |
download_mgr_->SetHostChain(host_chain); |
|
1270 |
} |
||
1271 |
} |
||
1272 |
57 |
return SetupExternalDownloadMgr(do_geosort); |
|
1273 |
} |
||
1274 |
|||
1275 |
57 |
bool MountPoint::CreateResolvConfWatcher() { |
|
1276 |
57 |
std::string roaming_value; |
|
1277 |
57 |
options_mgr_->GetValue("CVMFS_DNS_ROAMING", &roaming_value); |
|
1278 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✓ |
57 |
if (options_mgr_->IsDefined("CVMFS_DNS_ROAMING") && |
1279 |
options_mgr_->IsOn(roaming_value)) { |
||
1280 |
LogCvmfs(kLogCvmfs, kLogDebug, |
||
1281 |
"DNS roaming is enabled for this repository."); |
||
1282 |
// Create a file watcher to update the DNS settings of the download |
||
1283 |
// managers when there are changes to /etc/resolv.conf |
||
1284 |
resolv_conf_watcher_ = platform_file_watcher(); |
||
1285 |
|||
1286 |
if (resolv_conf_watcher_) { |
||
1287 |
ResolvConfEventHandler *handler = |
||
1288 |
new ResolvConfEventHandler(download_mgr_, external_download_mgr_); |
||
1289 |
resolv_conf_watcher_->RegisterHandler("/etc/resolv.conf", handler); |
||
1290 |
} |
||
1291 |
} else { |
||
1292 |
LogCvmfs(kLogCvmfs, kLogDebug, |
||
1293 |
57 |
"DNS roaming is disabled for this repository."); |
|
1294 |
} |
||
1295 |
57 |
return true; |
|
1296 |
} |
||
1297 |
|||
1298 |
57 |
void MountPoint::CreateFetchers() { |
|
1299 |
fetcher_ = new cvmfs::Fetcher( |
||
1300 |
file_system_->cache_mgr(), |
||
1301 |
download_mgr_, |
||
1302 |
backoff_throttle_, |
||
1303 |
57 |
perf::StatisticsTemplate("fetch", statistics_)); |
|
1304 |
|||
1305 |
57 |
const bool is_external_data = true; |
|
1306 |
external_fetcher_ = new cvmfs::Fetcher( |
||
1307 |
file_system_->cache_mgr(), |
||
1308 |
external_download_mgr_, |
||
1309 |
backoff_throttle_, |
||
1310 |
perf::StatisticsTemplate("fetch-external", statistics_), |
||
1311 |
57 |
is_external_data); |
|
1312 |
57 |
} |
|
1313 |
|||
1314 |
|||
1315 |
61 |
bool MountPoint::CreateSignatureManager() { |
|
1316 |
61 |
string optarg; |
|
1317 |
61 |
signature_mgr_ = new signature::SignatureManager(); |
|
1318 |
61 |
signature_mgr_->Init(); |
|
1319 |
|||
1320 |
61 |
string public_keys; |
|
1321 |
✓✓ | 61 |
if (options_mgr_->GetValue("CVMFS_PUBLIC_KEY", &optarg)) { |
1322 |
58 |
public_keys = optarg; |
|
1323 |
✓✗ | 3 |
} else if (options_mgr_->GetValue("CVMFS_KEYS_DIR", &optarg)) { |
1324 |
// Collect .pub files from CVMFS_KEYS_DIR |
||
1325 |
public_keys = JoinStrings(FindFilesBySuffix(optarg, ".pub"), ":"); |
||
1326 |
} else { |
||
1327 |
public_keys = |
||
1328 |
3 |
JoinStrings(FindFilesBySuffix("/etc/cvmfs/keys", ".pub"), ":"); |
|
1329 |
} |
||
1330 |
|||
1331 |
✓✓ | 61 |
if (!signature_mgr_->LoadPublicRsaKeys(public_keys)) { |
1332 |
2 |
boot_error_ = "failed to load public key(s)"; |
|
1333 |
2 |
boot_status_ = loader::kFailSignature; |
|
1334 |
2 |
return false; |
|
1335 |
} |
||
1336 |
LogCvmfs(kLogCvmfs, kLogDebug, "CernVM-FS: using public key(s) %s", |
||
1337 |
59 |
public_keys.c_str()); |
|
1338 |
|||
1339 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_TRUSTED_CERTS", &optarg)) { |
1340 |
if (!signature_mgr_->LoadTrustedCaCrl(optarg)) { |
||
1341 |
boot_error_ = "failed to load trusted certificates"; |
||
1342 |
boot_status_ = loader::kFailSignature; |
||
1343 |
return false; |
||
1344 |
} |
||
1345 |
} |
||
1346 |
|||
1347 |
59 |
return true; |
|
1348 |
} |
||
1349 |
|||
1350 |
|||
1351 |
61 |
void MountPoint::CreateStatistics() { |
|
1352 |
61 |
statistics_ = file_system_->statistics()->Fork(); |
|
1353 |
✓✓ | 61 |
if (file_system_->type() != FileSystem::kFsFuse) |
1354 |
8 |
return; |
|
1355 |
|||
1356 |
// TODO(jblomer): this should be registered by the tracker |
||
1357 |
statistics_->Register("inode_tracker.n_insert", |
||
1358 |
53 |
"overall number of accessed inodes"); |
|
1359 |
statistics_->Register("inode_tracker.n_remove", |
||
1360 |
53 |
"overall number of evicted inodes"); |
|
1361 |
statistics_->Register("inode_tracker.no_reference", |
||
1362 |
53 |
"currently active inodes"); |
|
1363 |
statistics_->Register("inode_tracker.n_hit_inode", |
||
1364 |
53 |
"overall number of inode lookups"); |
|
1365 |
statistics_->Register("inode_tracker.n_hit_path", |
||
1366 |
53 |
"overall number of successful path lookups"); |
|
1367 |
statistics_->Register("inode_tracker.n_miss_path", |
||
1368 |
53 |
"overall number of unsuccessful path lookups"); |
|
1369 |
} |
||
1370 |
|||
1371 |
|||
1372 |
37 |
void MountPoint::CreateTables() { |
|
1373 |
✓✓ | 37 |
if (file_system_->type() != FileSystem::kFsFuse) { |
1374 |
// Libcvmfs simplified tables |
||
1375 |
5 |
md5path_cache_ = new lru::Md5PathCache(kLibPathCacheSize, statistics_); |
|
1376 |
5 |
simple_chunk_tables_ = new SimpleChunkTables(); |
|
1377 |
5 |
return; |
|
1378 |
} |
||
1379 |
|||
1380 |
32 |
chunk_tables_ = new ChunkTables(); |
|
1381 |
|||
1382 |
32 |
string optarg; |
|
1383 |
32 |
uint64_t mem_cache_size = kDefaultMemcacheSize; |
|
1384 |
✓✗ | 32 |
if (options_mgr_->GetValue("CVMFS_MEMCACHE_SIZE", &optarg)) |
1385 |
mem_cache_size = String2Uint64(optarg) * 1024 * 1024; |
||
1386 |
|||
1387 |
const double memcache_unit_size = |
||
1388 |
(static_cast<double>(kInodeCacheFactor) * lru::Md5PathCache::GetEntrySize()) |
||
1389 |
32 |
+ lru::InodeCache::GetEntrySize() + lru::PathCache::GetEntrySize(); |
|
1390 |
const unsigned memcache_num_units = |
||
1391 |
32 |
mem_cache_size / static_cast<unsigned>(memcache_unit_size); |
|
1392 |
// Number of cache entries must be a multiple of 64 |
||
1393 |
32 |
const unsigned mask_64 = ~((1 << 6) - 1); |
|
1394 |
32 |
inode_cache_ = new lru::InodeCache(memcache_num_units & mask_64, statistics_); |
|
1395 |
32 |
path_cache_ = new lru::PathCache(memcache_num_units & mask_64, statistics_); |
|
1396 |
md5path_cache_ = new lru::Md5PathCache((memcache_num_units * 7) & mask_64, |
||
1397 |
32 |
statistics_); |
|
1398 |
|||
1399 |
32 |
inode_tracker_ = new glue::InodeTracker(); |
|
1400 |
} |
||
1401 |
|||
1402 |
/** |
||
1403 |
* Will create a tracer for the current mount point |
||
1404 |
* Tracefile path, Trace buffer size and trace buffer flush threshold |
||
1405 |
* can be configured by the options: CVMFS_TRACEFILE, |
||
1406 |
* CVMFS_TRACEBUFFER, CVMFS_TRACEBUFFER_THRESHOLD(respectively) |
||
1407 |
* VMFS_TRACEBUFFER and CVMFS_TRACEBUFFER_THRESHOLD will silently fallback |
||
1408 |
* to default values if configuration values don't exist or are invalid |
||
1409 |
*/ |
||
1410 |
37 |
bool MountPoint::CreateTracer() { |
|
1411 |
37 |
string optarg; |
|
1412 |
37 |
tracer_ = new Tracer(); |
|
1413 |
✓✗ | 37 |
if (options_mgr_->GetValue("CVMFS_TRACEFILE", &optarg)) { |
1414 |
if (file_system_->type() != FileSystem::kFsFuse) { |
||
1415 |
boot_error_ = "tracer is only supported in the fuse module"; |
||
1416 |
boot_status_ = loader::kFailOptions; |
||
1417 |
return false; |
||
1418 |
} |
||
1419 |
string tracebuffer_file = optarg; |
||
1420 |
uint64_t tracebuffer_size = kTracerBufferSize; |
||
1421 |
uint64_t tracebuffer_threshold = kTracerFlushThreshold; |
||
1422 |
|||
1423 |
if (options_mgr_->GetValue("CVMFS_TRACEBUFFER", &optarg)) { |
||
1424 |
tracebuffer_size = String2Uint64(optarg); |
||
1425 |
} |
||
1426 |
if (options_mgr_->GetValue("CVMFS_TRACEBUFFER_THRESHOLD", |
||
1427 |
&optarg)) { |
||
1428 |
tracebuffer_threshold = String2Uint64(optarg); |
||
1429 |
} |
||
1430 |
assert(tracebuffer_size <= INT_MAX |
||
1431 |
&& tracebuffer_threshold <= INT_MAX); |
||
1432 |
LogCvmfs(kLogCvmfs, kLogDebug, |
||
1433 |
"Initialising tracer with buffer size %" PRIu64 " and threshold %" PRIu64, |
||
1434 |
tracebuffer_size, tracebuffer_threshold); |
||
1435 |
tracer_->Activate(tracebuffer_size, tracebuffer_threshold, |
||
1436 |
tracebuffer_file); |
||
1437 |
} |
||
1438 |
37 |
return true; |
|
1439 |
} |
||
1440 |
|||
1441 |
|||
1442 |
55 |
bool MountPoint::DetermineRootHash(shash::Any *root_hash) { |
|
1443 |
55 |
string optarg; |
|
1444 |
✓✓ | 55 |
if (options_mgr_->GetValue("CVMFS_ROOT_HASH", &optarg)) { |
1445 |
✗✓ | 23 |
*root_hash = MkFromHexPtr(shash::HexPtr(optarg), shash::kSuffixCatalog); |
1446 |
23 |
return true; |
|
1447 |
} |
||
1448 |
|||
1449 |
✓✓✓✓ ✓✓✗✗ ✗✗✓✓ ✗✗✓✗ ✗✗✓✗ ✓✓ |
32 |
if (!options_mgr_->IsDefined("CVMFS_REPOSITORY_TAG") && |
1450 |
!options_mgr_->IsDefined("CVMFS_REPOSITORY_DATE")) |
||
1451 |
{ |
||
1452 |
24 |
root_hash->SetNull(); |
|
1453 |
24 |
return true; |
|
1454 |
} |
||
1455 |
|||
1456 |
8 |
string history_path; |
|
1457 |
✗✓ | 8 |
if (!FetchHistory(&history_path)) |
1458 |
return false; |
||
1459 |
8 |
UnlinkGuard history_file(history_path); |
|
1460 |
UniquePtr<history::History> tag_db( |
||
1461 |
8 |
history::SqliteHistory::Open(history_path)); |
|
1462 |
✗✓ | 8 |
if (!tag_db) { |
1463 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslog, |
||
1464 |
"failed to open history database (%s)", history_path.c_str()); |
||
1465 |
boot_error_ = "failed to open history database"; |
||
1466 |
boot_status_ = loader::kFailHistory; |
||
1467 |
return false; |
||
1468 |
} |
||
1469 |
|||
1470 |
8 |
history::History::Tag tag; |
|
1471 |
bool retval; |
||
1472 |
✓✓ | 8 |
if (!options_mgr_->GetValue("CVMFS_REPOSITORY_TAG", &repository_tag_)) { |
1473 |
4 |
string repository_date; |
|
1474 |
// options_mgr_->IsDefined("CVMFS_REPOSITORY_DATE") must be true |
||
1475 |
4 |
options_mgr_->GetValue("CVMFS_REPOSITORY_DATE", &repository_date); |
|
1476 |
4 |
time_t repository_utctime = IsoTimestamp2UtcTime(repository_date); |
|
1477 |
✗✓ | 4 |
if (repository_utctime == 0) { |
1478 |
boot_error_ = "invalid timestamp in CVMFS_REPOSITORY_DATE: " + |
||
1479 |
repository_date + ". Use YYYY-MM-DDTHH:MM:SSZ"; |
||
1480 |
boot_status_ = loader::kFailHistory; |
||
1481 |
return false; |
||
1482 |
} |
||
1483 |
4 |
retval = tag_db->GetByDate(repository_utctime, &tag); |
|
1484 |
✓✓ | 4 |
if (!retval) { |
1485 |
boot_error_ = "no repository state as early as utc timestamp " + |
||
1486 |
2 |
StringifyTime(repository_utctime, true); |
|
1487 |
2 |
boot_status_ = loader::kFailHistory; |
|
1488 |
2 |
return false; |
|
1489 |
} |
||
1490 |
LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslog, |
||
1491 |
"time stamp %s UTC resolved to tag '%s'", |
||
1492 |
StringifyTime(repository_utctime, true).c_str(), |
||
1493 |
2 |
tag.name.c_str()); |
|
1494 |
✓✓ | 2 |
repository_tag_ = tag.name; |
1495 |
} else { |
||
1496 |
4 |
retval = tag_db->GetByName(repository_tag_, &tag); |
|
1497 |
✓✓ | 4 |
if (!retval) { |
1498 |
2 |
boot_error_ = "no such tag: " + repository_tag_; |
|
1499 |
2 |
boot_status_ = loader::kFailHistory; |
|
1500 |
2 |
return false; |
|
1501 |
} |
||
1502 |
} |
||
1503 |
4 |
LogCvmfs(kLogCvmfs, kLogDebug, "mounting tag %s", tag.name.c_str()); |
|
1504 |
|||
1505 |
✗✓ | 4 |
*root_hash = tag.root_hash; |
1506 |
4 |
return true; |
|
1507 |
} |
||
1508 |
|||
1509 |
|||
1510 |
8 |
bool MountPoint::FetchHistory(std::string *history_path) { |
|
1511 |
manifest::Failures retval_mf; |
||
1512 |
8 |
manifest::ManifestEnsemble ensemble; |
|
1513 |
retval_mf = manifest::Fetch("", fqrn_, 0, NULL, signature_mgr_, download_mgr_, |
||
1514 |
8 |
&ensemble); |
|
1515 |
✗✓ | 8 |
if (retval_mf != manifest::kFailOk) { |
1516 |
boot_error_ = "Failed to fetch manifest"; |
||
1517 |
boot_status_ = loader::kFailHistory; |
||
1518 |
return false; |
||
1519 |
} |
||
1520 |
8 |
shash::Any history_hash = ensemble.manifest->history(); |
|
1521 |
✗✓ | 8 |
if (history_hash.IsNull()) { |
1522 |
boot_error_ = "No history"; |
||
1523 |
boot_status_ = loader::kFailHistory; |
||
1524 |
return false; |
||
1525 |
} |
||
1526 |
|||
1527 |
int fd = fetcher_->Fetch( |
||
1528 |
history_hash, |
||
1529 |
CacheManager::kSizeUnknown, |
||
1530 |
"tag database for " + fqrn_, |
||
1531 |
zlib::kZlibDefault, |
||
1532 |
8 |
CacheManager::kTypeRegular); |
|
1533 |
✗✓ | 8 |
if (fd < 0) { |
1534 |
boot_error_ = "failed to download history: " + StringifyInt(-fd); |
||
1535 |
boot_status_ = loader::kFailHistory; |
||
1536 |
return false; |
||
1537 |
} |
||
1538 |
// We have the custom sqlite vfs driver installed |
||
1539 |
8 |
*history_path = "@" + StringifyInt(fd); |
|
1540 |
8 |
return true; |
|
1541 |
} |
||
1542 |
|||
1543 |
|||
1544 |
unsigned MountPoint::GetEffectiveTtlSec() { |
||
1545 |
unsigned max_ttl; |
||
1546 |
{ |
||
1547 |
MutexLockGuard lock_guard(lock_max_ttl_); |
||
1548 |
max_ttl = max_ttl_sec_; |
||
1549 |
} |
||
1550 |
const unsigned catalog_ttl_sec = catalog_mgr_->GetTTL(); |
||
1551 |
|||
1552 |
return max_ttl ? std::min(max_ttl, catalog_ttl_sec) : catalog_ttl_sec; |
||
1553 |
} |
||
1554 |
|||
1555 |
|||
1556 |
unsigned MountPoint::GetMaxTtlMn() { |
||
1557 |
MutexLockGuard lock_guard(lock_max_ttl_); |
||
1558 |
return max_ttl_sec_ / 60; |
||
1559 |
} |
||
1560 |
|||
1561 |
|||
1562 |
/** |
||
1563 |
* Files in the workspace from different file systems / mountpoints need to |
||
1564 |
* have different names. Used, for example, for caching proxy settings. |
||
1565 |
*/ |
||
1566 |
59 |
string MountPoint::GetUniqFileSuffix() { |
|
1567 |
59 |
return "." + file_system_->name() + "-" + fqrn_; |
|
1568 |
} |
||
1569 |
|||
1570 |
|||
1571 |
61 |
MountPoint::MountPoint( |
|
1572 |
const string &fqrn, |
||
1573 |
FileSystem *file_system, |
||
1574 |
OptionsManager *options_mgr) |
||
1575 |
: fqrn_(fqrn) |
||
1576 |
, uuid_(cvmfs::Uuid::Create("")) |
||
1577 |
, file_system_(file_system) |
||
1578 |
, options_mgr_(options_mgr) |
||
1579 |
, statistics_(NULL) |
||
1580 |
, authz_fetcher_(NULL) |
||
1581 |
, authz_session_mgr_(NULL) |
||
1582 |
, authz_attachment_(NULL) |
||
1583 |
, backoff_throttle_(NULL) |
||
1584 |
, signature_mgr_(NULL) |
||
1585 |
, download_mgr_(NULL) |
||
1586 |
, external_download_mgr_(NULL) |
||
1587 |
, fetcher_(NULL) |
||
1588 |
, external_fetcher_(NULL) |
||
1589 |
, inode_annotation_(NULL) |
||
1590 |
, catalog_mgr_(NULL) |
||
1591 |
, chunk_tables_(NULL) |
||
1592 |
, simple_chunk_tables_(NULL) |
||
1593 |
, inode_cache_(NULL) |
||
1594 |
, path_cache_(NULL) |
||
1595 |
, md5path_cache_(NULL) |
||
1596 |
, tracer_(NULL) |
||
1597 |
, inode_tracker_(NULL) |
||
1598 |
, resolv_conf_watcher_(NULL) |
||
1599 |
, max_ttl_sec_(kDefaultMaxTtlSec) |
||
1600 |
, kcache_timeout_sec_(static_cast<double>(kDefaultKCacheTtlSec)) |
||
1601 |
, fixed_catalog_(false) |
||
1602 |
, hide_magic_xattrs_(false) |
||
1603 |
61 |
, has_membership_req_(false) |
|
1604 |
{ |
||
1605 |
61 |
int retval = pthread_mutex_init(&lock_max_ttl_, NULL); |
|
1606 |
✗✓ | 61 |
assert(retval == 0); |
1607 |
} |
||
1608 |
|||
1609 |
|||
1610 |
61 |
MountPoint::~MountPoint() { |
|
1611 |
61 |
pthread_mutex_destroy(&lock_max_ttl_); |
|
1612 |
|||
1613 |
✓✓ | 61 |
delete inode_tracker_; |
1614 |
✓✓ | 61 |
delete tracer_; |
1615 |
✓✓ | 61 |
delete md5path_cache_; |
1616 |
✓✓ | 61 |
delete path_cache_; |
1617 |
✓✓ | 61 |
delete inode_cache_; |
1618 |
✓✓ | 61 |
delete simple_chunk_tables_; |
1619 |
✓✓ | 61 |
delete chunk_tables_; |
1620 |
|||
1621 |
✓✓ | 61 |
delete catalog_mgr_; |
1622 |
✓✓ | 61 |
delete inode_annotation_; |
1623 |
✓✓ | 61 |
delete external_fetcher_; |
1624 |
✓✓ | 61 |
delete fetcher_; |
1625 |
✓✓ | 61 |
if (external_download_mgr_ != NULL) { |
1626 |
57 |
external_download_mgr_->Fini(); |
|
1627 |
✓✗ | 57 |
delete external_download_mgr_; |
1628 |
} |
||
1629 |
✓✓ | 61 |
if (download_mgr_ != NULL) { |
1630 |
59 |
download_mgr_->Fini(); |
|
1631 |
✓✗ | 59 |
delete download_mgr_; |
1632 |
} |
||
1633 |
✓✗ | 61 |
if (signature_mgr_ != NULL) { |
1634 |
61 |
signature_mgr_->Fini(); |
|
1635 |
✓✗ | 61 |
delete signature_mgr_; |
1636 |
} |
||
1637 |
|||
1638 |
✗✓ | 61 |
if (resolv_conf_watcher_ != NULL) { |
1639 |
resolv_conf_watcher_->Stop(); |
||
1640 |
delete resolv_conf_watcher_; |
||
1641 |
} |
||
1642 |
|||
1643 |
✓✗ | 61 |
delete backoff_throttle_; |
1644 |
✓✗ | 61 |
delete authz_attachment_; |
1645 |
✓✗ | 61 |
delete authz_session_mgr_; |
1646 |
✓✗ | 61 |
delete authz_fetcher_; |
1647 |
✓✗ | 61 |
delete statistics_; |
1648 |
✓✗ | 61 |
delete uuid_; |
1649 |
} |
||
1650 |
|||
1651 |
|||
1652 |
37 |
void MountPoint::ReEvaluateAuthz() { |
|
1653 |
37 |
string old_membership_req = membership_req_; |
|
1654 |
37 |
has_membership_req_ = catalog_mgr_->GetVOMSAuthz(&membership_req_); |
|
1655 |
✗✓ | 37 |
if (old_membership_req != membership_req_) { |
1656 |
authz_session_mgr_->ClearSessionCache(); |
||
1657 |
authz_attachment_->set_membership(membership_req_); |
||
1658 |
} |
||
1659 |
37 |
} |
|
1660 |
|||
1661 |
|||
1662 |
void MountPoint::SetMaxTtlMn(unsigned value_minutes) { |
||
1663 |
MutexLockGuard lock_guard(lock_max_ttl_); |
||
1664 |
max_ttl_sec_ = value_minutes * 60; |
||
1665 |
} |
||
1666 |
|||
1667 |
|||
1668 |
37 |
void MountPoint::SetupBehavior() { |
|
1669 |
37 |
string optarg; |
|
1670 |
|||
1671 |
✓✗ | 37 |
if (options_mgr_->GetValue("CVMFS_MAX_TTL", &optarg)) |
1672 |
SetMaxTtlMn(String2Uint64(optarg)); |
||
1673 |
|||
1674 |
✓✗ | 37 |
if (options_mgr_->GetValue("CVMFS_KCACHE_TIMEOUT", &optarg)) { |
1675 |
// Can be negative and should then be interpreted as 0.0 |
||
1676 |
kcache_timeout_sec_ = |
||
1677 |
std::max(0.0, static_cast<double>(String2Int64(optarg))); |
||
1678 |
} |
||
1679 |
LogCvmfs(kLogCvmfs, kLogDebug, "kernel caches expire after %d seconds", |
||
1680 |
37 |
static_cast<int>(kcache_timeout_sec_)); |
|
1681 |
|||
1682 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✓ |
37 |
if (options_mgr_->GetValue("CVMFS_HIDE_MAGIC_XATTRS", &optarg) |
1683 |
&& options_mgr_->IsOn(optarg)) |
||
1684 |
{ |
||
1685 |
hide_magic_xattrs_ = true; |
||
1686 |
} |
||
1687 |
37 |
} |
|
1688 |
|||
1689 |
|||
1690 |
/** |
||
1691 |
* Called twice once for the regular download manager and once for the external |
||
1692 |
* download manager. |
||
1693 |
*/ |
||
1694 |
59 |
void MountPoint::SetupDnsTuning(download::DownloadManager *manager) { |
|
1695 |
59 |
string optarg; |
|
1696 |
59 |
unsigned dns_timeout_ms = download::DownloadManager::kDnsDefaultTimeoutMs; |
|
1697 |
59 |
unsigned dns_retries = download::DownloadManager::kDnsDefaultRetries; |
|
1698 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_DNS_TIMEOUT", &optarg)) |
1699 |
dns_timeout_ms = String2Uint64(optarg) * 1000; |
||
1700 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_DNS_RETRIES", &optarg)) |
1701 |
dns_retries = String2Uint64(optarg); |
||
1702 |
59 |
manager->SetDnsParameters(dns_retries, dns_timeout_ms); |
|
1703 |
|||
1704 |
// Rest has to be after SetDnsParameters because SetDnsParameters might |
||
1705 |
// construct a new resolver object |
||
1706 |
|||
1707 |
59 |
unsigned dns_min_ttl = dns::Resolver::kDefaultMinTtl; |
|
1708 |
59 |
unsigned dns_max_ttl = dns::Resolver::kDefaultMaxTtl; |
|
1709 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_DNS_MIN_TTL", &optarg)) |
1710 |
dns_min_ttl = String2Uint64(optarg); |
||
1711 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_DNS_MAX_TTL", &optarg)) |
1712 |
dns_max_ttl = String2Uint64(optarg); |
||
1713 |
59 |
manager->SetDnsTtlLimits(dns_min_ttl, dns_max_ttl); |
|
1714 |
|||
1715 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_DNS_SERVER", &optarg)) { |
1716 |
download_mgr_->SetDnsServer(optarg); |
||
1717 |
} |
||
1718 |
|||
1719 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_IPFAMILY_PREFER", &optarg)) { |
1720 |
switch (String2Int64(optarg)) { |
||
1721 |
case 4: |
||
1722 |
manager->SetIpPreference(dns::kIpPreferV4); |
||
1723 |
break; |
||
1724 |
case 6: |
||
1725 |
manager->SetIpPreference(dns::kIpPreferV6); |
||
1726 |
break; |
||
1727 |
} |
||
1728 |
} |
||
1729 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_MAX_IPADDR_PER_PROXY", &optarg)) |
1730 |
manager->SetMaxIpaddrPerProxy(String2Uint64(optarg)); |
||
1731 |
59 |
} |
|
1732 |
|||
1733 |
|||
1734 |
57 |
bool MountPoint::SetupExternalDownloadMgr(bool dogeosort) { |
|
1735 |
57 |
string optarg; |
|
1736 |
external_download_mgr_ = |
||
1737 |
download_mgr_->Clone(perf::StatisticsTemplate("download-external", |
||
1738 |
57 |
statistics_)); |
|
1739 |
|||
1740 |
unsigned timeout; |
||
1741 |
unsigned timeout_direct; |
||
1742 |
57 |
download_mgr_->GetTimeout(&timeout, &timeout_direct); |
|
1743 |
✓✗ | 57 |
if (options_mgr_->GetValue("CVMFS_EXTERNAL_TIMEOUT", &optarg)) { |
1744 |
timeout = String2Uint64(optarg); |
||
1745 |
} |
||
1746 |
✓✗ | 57 |
if (options_mgr_->GetValue("CVMFS_EXTERNAL_TIMEOUT_DIRECT", &optarg)) { |
1747 |
timeout_direct = String2Uint64(optarg); |
||
1748 |
} |
||
1749 |
57 |
external_download_mgr_->SetTimeout(timeout, timeout_direct); |
|
1750 |
|||
1751 |
✓✓ | 57 |
if (options_mgr_->GetValue("CVMFS_EXTERNAL_URL", &optarg)) { |
1752 |
6 |
external_download_mgr_->SetHostChain(optarg); |
|
1753 |
✗✓ | 6 |
if (dogeosort) { |
1754 |
std::vector<std::string> host_chain; |
||
1755 |
external_download_mgr_->GetHostInfo(&host_chain, NULL, NULL); |
||
1756 |
download_mgr_->GeoSortServers(&host_chain); |
||
1757 |
external_download_mgr_->SetHostChain(host_chain); |
||
1758 |
} |
||
1759 |
} else { |
||
1760 |
51 |
external_download_mgr_->SetHostChain(""); |
|
1761 |
} |
||
1762 |
|||
1763 |
✓✓ | 57 |
if (options_mgr_->GetValue("CVMFS_EXTERNAL_MAX_SERVERS", &optarg)) { |
1764 |
9 |
unsigned max_servers = String2Uint64(optarg); |
|
1765 |
9 |
std::vector<std::string> host_chain; |
|
1766 |
9 |
external_download_mgr_->GetHostInfo(&host_chain, NULL, NULL); |
|
1767 |
✓✓✓✓ ✓✓ |
9 |
if (max_servers > 0 && max_servers < host_chain.size()) { |
1768 |
3 |
host_chain.resize(max_servers); |
|
1769 |
3 |
external_download_mgr_->SetHostChain(host_chain); |
|
1770 |
} |
||
1771 |
} |
||
1772 |
|||
1773 |
57 |
string proxies = "DIRECT"; |
|
1774 |
✓✗ | 57 |
if (options_mgr_->GetValue("CVMFS_EXTERNAL_HTTP_PROXY", &optarg)) { |
1775 |
proxies = download::ResolveProxyDescription( |
||
1776 |
optarg, |
||
1777 |
file_system_->workspace() + "/proxies-external" + GetUniqFileSuffix(), |
||
1778 |
external_download_mgr_); |
||
1779 |
if (proxies == "") { |
||
1780 |
boot_error_ = "failed to discover external HTTP proxy servers"; |
||
1781 |
boot_status_ = loader::kFailWpad; |
||
1782 |
return false; |
||
1783 |
} |
||
1784 |
} |
||
1785 |
57 |
string fallback_proxies; |
|
1786 |
✓✗ | 57 |
if (options_mgr_->GetValue("CVMFS_EXTERNAL_FALLBACK_PROXY", &optarg)) |
1787 |
fallback_proxies = optarg; |
||
1788 |
external_download_mgr_->SetProxyChain( |
||
1789 |
57 |
proxies, fallback_proxies, download::DownloadManager::kSetProxyBoth); |
|
1790 |
|||
1791 |
57 |
return true; |
|
1792 |
} |
||
1793 |
|||
1794 |
|||
1795 |
59 |
void MountPoint::SetupHttpTuning() { |
|
1796 |
59 |
string optarg; |
|
1797 |
|||
1798 |
// TODO(jblomer): avoid double default settings |
||
1799 |
|||
1800 |
59 |
unsigned timeout = kDefaultTimeoutSec; |
|
1801 |
59 |
unsigned timeout_direct = kDefaultTimeoutSec; |
|
1802 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_TIMEOUT", &optarg)) |
1803 |
timeout = String2Uint64(optarg); |
||
1804 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_TIMEOUT_DIRECT", &optarg)) |
1805 |
timeout_direct = String2Uint64(optarg); |
||
1806 |
59 |
download_mgr_->SetTimeout(timeout, timeout_direct); |
|
1807 |
|||
1808 |
59 |
unsigned max_retries = kDefaultRetries; |
|
1809 |
59 |
unsigned backoff_init = kDefaultBackoffInitMs; |
|
1810 |
59 |
unsigned backoff_max = kDefaultBackoffMaxMs; |
|
1811 |
✓✓ | 59 |
if (options_mgr_->GetValue("CVMFS_MAX_RETRIES", &optarg)) |
1812 |
54 |
max_retries = String2Uint64(optarg); |
|
1813 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_BACKOFF_INIT", &optarg)) |
1814 |
backoff_init = String2Uint64(optarg) * 1000; |
||
1815 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_BACKOFF_MAX", &optarg)) |
1816 |
backoff_max = String2Uint64(optarg) * 1000; |
||
1817 |
59 |
download_mgr_->SetRetryParameters(max_retries, backoff_init, backoff_max); |
|
1818 |
|||
1819 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_LOW_SPEED_LIMIT", &optarg)) |
1820 |
download_mgr_->SetLowSpeedLimit(String2Uint64(optarg)); |
||
1821 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_PROXY_RESET_AFTER", &optarg)) |
1822 |
download_mgr_->SetProxyGroupResetDelay(String2Uint64(optarg)); |
||
1823 |
✓✗ | 59 |
if (options_mgr_->GetValue("CVMFS_HOST_RESET_AFTER", &optarg)) |
1824 |
download_mgr_->SetHostResetDelay(String2Uint64(optarg)); |
||
1825 |
|||
1826 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✓ |
59 |
if (options_mgr_->GetValue("CVMFS_FOLLOW_REDIRECTS", &optarg) && |
1827 |
options_mgr_->IsOn(optarg)) |
||
1828 |
{ |
||
1829 |
download_mgr_->EnableRedirects(); |
||
1830 |
} |
||
1831 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✓ |
59 |
if (options_mgr_->GetValue("CVMFS_SEND_INFO_HEADER", &optarg) && |
1832 |
options_mgr_->IsOn(optarg)) |
||
1833 |
{ |
||
1834 |
download_mgr_->EnableInfoHeader(); |
||
1835 |
} |
||
1836 |
59 |
} |
|
1837 |
|||
1838 |
|||
1839 |
57 |
void MountPoint::SetupInodeAnnotation() { |
|
1840 |
57 |
string optarg; |
|
1841 |
|||
1842 |
57 |
inode_annotation_ = new catalog::InodeGenerationAnnotation(); |
|
1843 |
✓✗ | 57 |
if (options_mgr_->GetValue("CVMFS_INITIAL_GENERATION", &optarg)) { |
1844 |
inode_annotation_->IncGeneration(String2Uint64(optarg)); |
||
1845 |
} |
||
1846 |
|||
1847 |
✓✓✓✗ ✓✓ |
57 |
if ((file_system_->type() == FileSystem::kFsFuse) && |
1848 |
!file_system_->IsNfsSource()) |
||
1849 |
{ |
||
1850 |
49 |
catalog_mgr_->SetInodeAnnotation(inode_annotation_); |
|
1851 |
} |
||
1852 |
57 |
} |
|
1853 |
|||
1854 |
|||
1855 |
57 |
bool MountPoint::SetupOwnerMaps() { |
|
1856 |
57 |
string optarg; |
|
1857 |
57 |
catalog::OwnerMap uid_map; |
|
1858 |
57 |
catalog::OwnerMap gid_map; |
|
1859 |
|||
1860 |
✓✓ | 57 |
if (options_mgr_->GetValue("CVMFS_UID_MAP", &optarg)) { |
1861 |
✓✗ | 2 |
if (!uid_map.Read(optarg)) { |
1862 |
2 |
boot_error_ = "failed to parse uid map " + optarg; |
|
1863 |
2 |
boot_status_ = loader::kFailOptions; |
|
1864 |
2 |
return false; |
|
1865 |
} |
||
1866 |
} |
||
1867 |
✓✗ | 55 |
if (options_mgr_->GetValue("CVMFS_GID_MAP", &optarg)) { |
1868 |
if (!gid_map.Read(optarg)) { |
||
1869 |
boot_error_ = "failed to parse gid map " + optarg; |
||
1870 |
boot_status_ = loader::kFailOptions; |
||
1871 |
return false; |
||
1872 |
} |
||
1873 |
} |
||
1874 |
55 |
catalog_mgr_->SetOwnerMaps(uid_map, gid_map); |
|
1875 |
|||
1876 |
// TODO(jblomer): make local to catalog manager |
||
1877 |
✗✓✗✗ ✓✗✗✗ ✗✗✓✗ ✗✓ |
55 |
if (options_mgr_->GetValue("CVMFS_CLAIM_OWNERSHIP", &optarg) && |
1878 |
options_mgr_->IsOn(optarg)) |
||
1879 |
{ |
||
1880 |
g_claim_ownership = true; |
||
1881 |
} |
||
1882 |
|||
1883 |
55 |
return true; |
|
1884 |
✓✗✓✗ |
45 |
} |
Generated by: GCOVR (Version 4.1) |