25 #define ENOATTR ENODATA
27 #ifndef __STDC_FORMAT_MACROS
28 #define __STDC_FORMAT_MACROS
33 #include <sys/xattr.h>
46 #include <sys/errno.h>
48 #include <sys/mount.h>
49 #include <sys/resource.h>
52 #include <sys/types.h>
63 #include <google/dense_hash_map>
189 virtual bool IsCanceled() {
return fuse_req_interrupted(*req_ptr_); }
202 FuseState() : version(0), cache_symlinks(false), has_dentry_expire(false) { }
245 return "init-catalog-revision: "
247 +
"current-catalog-revision: "
250 +
" " +
"inode generation: "
260 "Got VOMS authz %s from filesystem "
277 const struct stat &info) {
336 *dirent = dirent_negative;
355 "GetDirentForInode: Race condition? Not found dirent %s",
371 "GetDirentForInode inode lookup failure %" PRId64, ino);
372 *dirent = dirent_negative;
381 "Warning: inode %" PRId64
" (%s) changed file type", ino,
408 uint64_t live_inode = 0;
413 "GetDirentForPath: live inode for %s: %" PRIu64, path.
c_str(),
435 }
else if (live_inode != 0) {
439 "content of %s change, replacing inode %" PRIu64
482 "GetPathForInode: Race condition? "
483 "Inode not found in inode tracker at path %s",
495 const std::string &msg) {
500 "Tracing: Could not find path for inode %" PRIu64, uint64_t(ino));
509 const std::string &msg) {
519 static void cvmfs_lookup(fuse_req_t req, fuse_ino_t parent,
const char *name) {
523 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
525 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
532 const fuse_ino_t parent_fuse = parent;
535 "cvmfs_lookup in parent inode: %" PRIu64
" for name: %s",
536 uint64_t(parent), name);
540 uint64_t live_inode = 0;
542 struct fuse_entry_param result;
544 memset(&result, 0,
sizeof(result));
546 result.attr_timeout = timeout;
547 result.entry_timeout = timeout;
550 if ((strcmp(name,
".") == 0) || (strcmp(name,
"..") == 0)) {
552 if (strcmp(name,
".") == 0) {
553 goto lookup_reply_positive;
558 goto lookup_reply_positive;
561 goto lookup_reply_negative;
563 goto lookup_reply_positive;
568 goto lookup_reply_negative;
570 goto lookup_reply_error;
576 goto lookup_reply_negative;
581 path.
Append(name, strlen(name));
583 if (live_inode == 0) {
585 goto lookup_reply_negative;
587 goto lookup_reply_error;
590 lookup_reply_positive:
593 if (live_inode > 1) {
617 static_cast<uint64_t>(timeout));
621 result.ino = dirent.
inode();
623 fuse_reply_entry(req, &result);
626 lookup_reply_negative:
628 "lookup()-NOTFOUND");
634 fuse_reply_entry(req, &result);
639 "lookup()-NOTFOUND");
643 "EIO (01): lookup failed for %s", name);
647 fuse_reply_err(req, EIO);
656 #
if CVMFS_USE_LIBFUSE == 2
657 unsigned long nlookup
667 if (ino == FUSE_ROOT_ID) {
668 fuse_reply_none(req);
676 uint64_t(ino), nlookup);
685 fuse_reply_none(req);
689 #if (FUSE_VERSION >= 29)
690 static void cvmfs_forget_multi(fuse_req_t req,
692 struct fuse_forget_data *forgets) {
697 fuse_reply_none(req);
706 for (
size_t i = 0; i < count; ++i) {
707 if (forgets[i].ino == FUSE_ROOT_ID) {
714 forgets[i].ino, forgets[i].nlookup);
717 vfs_put_raii.
VfsPut(forgets[i].ino, forgets[i].nlookup);
719 evict_raii.
Evict(forgets[i].ino);
723 fuse_reply_none(req);
725 #endif // FUSE_VERSION >= 29
737 fuse_reply_err(req, ENOENT);
739 const char *name = dirent.
name().
c_str();
744 "EIO (02): CVMFS-specific metadata not found for name=%s symlink=%s",
745 name ? name :
"<unset>", link ? link :
"<unset>");
749 fuse_reply_err(req, EIO);
758 struct fuse_file_info *fi) {
762 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
764 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
775 fuse_reply_err(req, EACCES);
786 "cvmfs_getattr %" PRIu64
" "
787 "served from page cache tracker",
802 &parent_ino, &name)) {
831 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
833 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
852 fuse_reply_err(req, EINVAL);
861 const struct stat *stat_info,
864 uint64_t(stat_info->st_ino));
865 size_t remaining_size = listing->
capacity() - listing->
size();
866 const size_t entry_size = fuse_add_direntry(req, NULL, 0, name, stat_info, 0);
868 while (entry_size > remaining_size) {
876 fuse_add_direntry(req, buffer + listing->
size(), remaining_size, name,
877 stat_info, listing->
size() + entry_size);
886 struct fuse_file_info *fi) {
889 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
891 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
902 fuse_reply_err(req, EACCES);
912 fuse_reply_err(req, ENOENT);
924 fuse_reply_err(req, ENOTDIR);
929 uint64_t(ino), path.
c_str());
949 const bool retval = catalog_mgr->
ListingStat(path, &listing_from_catalog);
953 fuse_listing.Clear();
956 "EIO (03): failed to open directory at %s", path.
c_str());
959 fuse_reply_err(req, EIO);
962 for (
unsigned i = 0; i < listing_from_catalog.
size(); ++i) {
966 entry_path.
Append(
"/", 1);
967 entry_path.
Append(listing_from_catalog.
AtPtr(i)->name.GetChars(),
968 listing_from_catalog.
AtPtr(i)->name.GetLength());
977 struct stat fixed_info = listing_from_catalog.
AtPtr(i)->info;
978 fixed_info.st_ino = entry_dirent.
inode();
980 &fixed_info, &fuse_listing);
985 stream_listing.
size = fuse_listing.size();
986 stream_listing.
capacity = fuse_listing.capacity();
988 fuse_listing.ShareBuffer(&stream_listing.
buffer, &large_alloc);
996 "linking directory handle %lu to dir inode: %" PRIu64,
1005 #if (FUSE_VERSION >= 30)
1006 #ifdef CVMFS_ENABLE_FUSE3_CACHE_READDIR
1010 fi->cache_readdir = 1;
1013 fuse_reply_open(req, fi);
1021 struct fuse_file_info *fi) {
1026 "cvmfs_releasedir on inode %" PRIu64
", handle %lu", uint64_t(ino),
1033 const DirectoryHandles::iterator iter_handle =
1036 if (iter_handle->second.capacity == 0)
1037 smunmap(iter_handle->second.buffer);
1039 free(iter_handle->second.buffer);
1047 fuse_reply_err(req, reply);
1055 const size_t buffer_size,
const off_t offset,
1056 const size_t max_size) {
1057 if (offset < static_cast<int>(buffer_size)) {
1059 req, buffer + offset,
1060 std::min(static_cast<size_t>(buffer_size - offset), max_size));
1062 fuse_reply_buf(req, NULL, 0);
1071 off_t off,
struct fuse_file_info *fi) {
1075 "cvmfs_readdir on inode %" PRIu64
1076 " reading %lu bytes from offset %ld",
1083 const DirectoryHandles::const_iterator iter_handle =
1086 listing = iter_handle->second;
1092 fuse_reply_err(req, EINVAL);
1096 struct fuse_file_info *fi) {
1109 static const uint64_t kFileHandleIgnore =
static_cast<uint64_t
>(2) << 60;
1119 struct fuse_file_info *fi) {
1122 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
1124 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
1139 fuse_reply_err(req, ENOENT);
1151 fuse_reply_err(req, EACCES);
1163 if ((fi->flags & O_SHLOCK) || (fi->flags & O_EXLOCK)) {
1165 fuse_reply_err(req, EOPNOTSUPP);
1168 if (fi->flags & O_SYMLINK) {
1170 fi->fh = kFileHandleIgnore;
1171 fuse_reply_open(req, fi);
1175 if (fi->flags & O_EXCL) {
1177 fuse_reply_err(req, EEXIST);
1194 "chunked file %s opened (download delayed to read() call)",
1201 fuse_reply_err(req, EMFILE);
1214 "chunked file %s vanished unexpectedly", path.
c_str());
1215 fuse_reply_err(req, ENOENT);
1218 const uint64_t unique_inode = dirent_origin.
inode();
1221 chunk_tables->
Lock();
1232 "EIO (04): failed to open file %s. "
1233 "It is marked as 'chunked', but no chunks found.",
1237 fuse_reply_err(req, EIO);
1242 chunk_tables->
Lock();
1268 "linking chunk handle %lu to unique inode: %" PRIu64,
1269 chunk_tables->
next_handle, uint64_t(unique_inode));
1289 fi->fh =
static_cast<uint64_t
>(-
static_cast<int64_t
>(fi->fh));
1293 fuse_reply_open(req, fi);
1308 fd = this_fetcher->
Fetch(
1317 fuse_reply_open(req, fi);
1329 fuse_reply_err(req, EMFILE);
1345 "failed to open inode: %" PRIu64
", CAS key %s, error code %d",
1347 if (errno == EMFILE) {
1349 fuse_reply_err(req, EMFILE);
1357 if (EIO == errno || EIO == -fd) {
1359 "EIO (06): Failed to open file %s", path.
c_str());
1364 fuse_reply_err(req, -fd);
1372 struct fuse_file_info *fi) {
1376 "cvmfs_read inode: %" PRIu64
" reading %lu bytes from offset %ld "
1383 if (fi->fh == kFileHandleIgnore) {
1384 fuse_reply_err(req, EBADF);
1390 char *data =
static_cast<char *
>(alloca(size));
1391 unsigned int overall_bytes_fetched = 0;
1393 const int64_t fd =
static_cast<int64_t
>(fi->fh);
1394 uint64_t abs_fd = (fd < 0) ? -fd : fd;
1397 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
1399 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
1404 const uint64_t chunk_handle = abs_fd;
1405 uint64_t unique_inode;
1412 chunk_tables->
Lock();
1425 pthread_mutex_t *handle_lock = chunk_tables->
Handle2Lock(chunk_handle);
1427 chunk_tables->
Lock();
1433 off_t offset_in_chunk = off - chunks.
list->
AtPtr(chunk_idx)->
offset();
1436 if ((chunk_fd.
fd == -1) || (chunk_fd.
chunk_idx != chunk_idx)) {
1437 if (chunk_fd.
fd != -1)
1455 if (chunk_fd.
fd < 0) {
1457 chunk_tables->
Lock();
1462 "EIO (05): Failed to fetch chunk %d from file %s", chunk_idx,
1466 fuse_reply_err(req, EIO);
1474 const size_t bytes_to_read = size - overall_bytes_fetched;
1475 const size_t remaining_bytes_in_chunk = chunks.
list->
AtPtr(chunk_idx)
1478 const size_t bytes_to_read_in_chunk =
1479 std::min(bytes_to_read, remaining_bytes_in_chunk);
1482 data + overall_bytes_fetched,
1483 bytes_to_read_in_chunk,
1486 if (bytes_fetched < 0) {
1489 chunk_tables->
Lock();
1492 if (EIO == errno || EIO == -bytes_fetched) {
1494 "EIO (07): Failed to read chunk %d from file %s", chunk_idx,
1499 fuse_reply_err(req, -bytes_fetched);
1502 overall_bytes_fetched += bytes_fetched;
1506 offset_in_chunk = 0;
1507 }
while ((overall_bytes_fetched < size)
1508 && (chunk_idx < chunks.list->
size()));
1511 chunk_tables->
Lock();
1517 const int64_t nbytes =
1520 if (EIO == errno || EIO == -nbytes) {
1525 "EIO (08): Failed to read file %s", path.
ToString().c_str());
1528 "EIO (08): Failed to read from %s - <unknown inode>",
1534 fuse_reply_err(req, -nbytes);
1537 overall_bytes_fetched = nbytes;
1541 fuse_reply_buf(req, data, overall_bytes_fetched);
1543 overall_bytes_fetched);
1551 struct fuse_file_info *fi) {
1559 if (fi->fh == kFileHandleIgnore) {
1560 fuse_reply_err(req, 0);
1565 const int64_t fd =
static_cast<int64_t
>(fi->fh);
1566 uint64_t abs_fd = (fd < 0) ? -fd : fd;
1574 const uint64_t chunk_handle = abs_fd;
1577 uint64_t unique_inode;
1584 chunk_tables->
Lock();
1601 uint64_t(unique_inode));
1607 delete to_delete.
list;
1613 if (chunk_fd.
fd != -1)
1621 fuse_reply_err(req, 0);
1656 fuse_reply_statfs(req, info);
1660 uint64_t available = 0;
1662 const uint64_t capacity =
1665 info->f_bsize = info->f_frsize = 512;
1667 if (capacity == (uint64_t)(-1)) {
1669 info->f_blocks = size / info->f_bsize;
1672 info->f_blocks = capacity / info->f_bsize;
1673 available = capacity -
size;
1676 info->f_bfree = info->f_bavail = available / info->f_bsize;
1682 info->f_files = all_inodes;
1683 info->f_ffree = info->f_favail = all_inodes - loaded_inode;
1690 fuse_reply_statfs(req, info);
1694 static void cvmfs_getxattr(fuse_req_t req, fuse_ino_t ino,
const char *name,
1695 size_t size, uint32_t position)
1701 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
1703 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
1710 "cvmfs_getxattr on inode: %" PRIu64
" for xattr: %s", uint64_t(ino),
1714 fuse_reply_err(req, EACCES);
1719 vector<string> tokens_mode_machine =
SplitString(name,
'~');
1720 vector<string> tokens_mode_human =
SplitString(name,
'@');
1722 int32_t attr_req_page = 0;
1726 bool attr_req_is_valid =
false;
1729 if (tokens_mode_human.size() > 1) {
1730 const std::string token = tokens_mode_human[tokens_mode_human.size() - 1];
1732 attr_req_is_valid =
true;
1735 if (page_num_sanitizer.
IsValid(token)) {
1736 attr_req_is_valid =
true;
1741 attr = tokens_mode_human[0];
1742 }
else if (tokens_mode_machine.size() > 1) {
1744 token = tokens_mode_machine[tokens_mode_machine.size() - 1];
1746 attr_req_is_valid =
true;
1749 if (page_num_sanitizer.
IsValid(token)) {
1750 attr_req_is_valid =
true;
1755 attr = tokens_mode_machine[0];
1758 attr_req_is_valid =
true;
1759 attr = tokens_mode_machine[0];
1762 if (!attr_req_is_valid) {
1764 fuse_reply_err(req, ENODATA);
1783 "cvmfs_statfs: Race condition? "
1784 "GetPathForInode did not succeed for path %s "
1785 "(path might have not been set)",
1788 fuse_reply_err(req, ESTALE);
1797 retval = catalog_mgr->
LookupPath(path, lookup_options, &raw_symlink);
1800 "cvmfs_statfs: Race condition? "
1801 "LookupPath did not succeed for path %s",
1804 fuse_reply_err(req, ESTALE);
1814 "cvmfs_statfs: Race condition? "
1815 "LookupXattrs did not succeed for path %s",
1818 fuse_reply_err(req, ESTALE);
1823 bool magic_xattr_success =
true;
1826 if (!magic_xattr.IsNull()) {
1833 if (!magic_xattr_success) {
1838 std::pair<bool, std::string> attribute_result;
1840 if (!magic_xattr.IsNull()) {
1841 attribute_result = magic_xattr->GetValue(attr_req_page, xattr_mode);
1843 if (!xattrs.
Get(attr, &attribute_result.second)) {
1847 attribute_result.first =
true;
1850 if (!attribute_result.first) {
1851 fuse_reply_err(req, ENODATA);
1852 }
else if (size == 0) {
1853 fuse_reply_xattr(req, attribute_result.second.length());
1854 }
else if (size >= attribute_result.second.length()) {
1855 fuse_reply_buf(req, &attribute_result.second[0],
1856 attribute_result.second.length());
1858 fuse_reply_err(req, ERANGE);
1864 const struct fuse_ctx *fuse_ctx = fuse_req_ctx(req);
1866 const ClientCtxGuard ctx_guard(fuse_ctx->uid, fuse_ctx->gid, fuse_ctx->pid,
1874 "cvmfs_listxattr on inode: %" PRIu64
", size %zu [visibility %d]",
1880 if (d.HasXattrs()) {
1885 "cvmfs_listxattr: Race condition? "
1886 "GetPathForInode did not succeed for ino %lu",
1889 fuse_reply_err(req, ESTALE);
1895 "cvmfs_listxattr: Race condition? "
1896 "LookupXattrs did not succeed for ino %lu",
1899 fuse_reply_err(req, ESTALE);
1910 string attribute_list;
1915 fuse_reply_xattr(req, attribute_list.length());
1916 }
else if (size >= attribute_list.length()) {
1917 if (attribute_list.empty())
1918 fuse_reply_buf(req, NULL, 0);
1920 fuse_reply_buf(req, &attribute_list[0], attribute_list.length());
1922 fuse_reply_err(req, ERANGE);
1943 for (
unsigned i = 0; i < chunks.
size(); ++i) {
1953 bool Pin(
const string &path) {
1973 for (
unsigned i = 0; i < chunks.
size(); ++i) {
1976 "Part of " + path,
false);
1990 fd = this_fetcher->
Fetch(
2009 const int fd = this_fetcher->
Fetch(
2022 static void cvmfs_init(
void *userdata,
struct fuse_conn_info *conn) {
2026 #ifdef CVMFS_NFS_SUPPORT
2027 conn->want |= FUSE_CAP_EXPORT_SUPPORT;
2031 #ifdef FUSE_CAP_POSIX_ACL
2032 if ((conn->capable & FUSE_CAP_POSIX_ACL) == 0) {
2034 "FUSE: ACL support requested but missing fuse kernel support, "
2037 conn->want |= FUSE_CAP_POSIX_ACL;
2041 "FUSE: ACL support requested but not available in this version of "
2042 "libfuse %d, aborting",
2048 #ifdef FUSE_CAP_CACHE_SYMLINKS
2049 if ((conn->capable & FUSE_CAP_CACHE_SYMLINKS) == FUSE_CAP_CACHE_SYMLINKS) {
2050 conn->want |= FUSE_CAP_CACHE_SYMLINKS;
2052 #ifndef FUSE_CAP_EXPIRE_ONLY
2055 "FUSE: Symlink caching enabled but no support for fuse_expire_entry. "
2056 "Symlinks will be cached but mountpoints on top of symlinks will "
2058 "Current libfuse %d is too old; required: libfuse >= 3.16, "
2059 "kernel >= 6.2-rc1",
2066 "FUSE: Symlink caching requested but missing fuse kernel support, "
2067 "falling back to no caching");
2072 "FUSE: Symlink caching requested but missing libfuse support, "
2073 "falling back to no caching. Current libfuse %d",
2078 #ifdef FUSE_CAP_EXPIRE_ONLY
2079 if ((conn->capable & FUSE_CAP_EXPIRE_ONLY) == FUSE_CAP_EXPIRE_ONLY
2080 && FUSE_VERSION >= FUSE_MAKE_VERSION(3, 16)) {
2086 "FUSE: Symlink caching enabled but no support for fuse_expire_entry. "
2087 "Symlinks will be cached but mountpoints on top of symlinks will "
2089 "Current libfuse %d; required: libfuse >= 3.16, kernel >= 6.2-rc1",
2104 memset(cvmfs_operations, 0,
sizeof(*cvmfs_operations));
2123 #if (FUSE_VERSION >= 29)
2124 cvmfs_operations->forget_multi = cvmfs_forget_multi;
2142 #if (FUSE_VERSION >= 30)
2143 fuse_fd = fuse_session_fd(*reinterpret_cast<struct fuse_session **>(
2146 fuse_fd = fuse_chan_fd(*reinterpret_cast<struct fuse_chan **>(
2153 socket_path.c_str(), errno);
2167 visibility(
"default"))) loader::CvmfsExports *g_cvmfs_exports = NULL;
2183 result_pages_.push_back(
"never (fixed root catalog)");
2186 const time_t now = time(NULL);
2187 result_pages_.push_back(
StringifyInt((catalogs_valid_until_ - now) / 60));
2196 + xattr_mgr_->mount_point()->catalog_mgr()->inode_gauge()));
2202 result_pages_.push_back(
2215 const time_t now = time(NULL);
2247 string fqrn_from_xattr;
2257 if (fqrn_from_xattr == fqrn) {
2259 "repository already mounted on %s", mount_path.c_str());
2263 "CernVM-FS repository %s already mounted on %s", fqrn.c_str(),
2264 mount_path.c_str());
2285 for (
unsigned i = 0, s = tokens.size(); i < s; ++i) {
2295 static unsigned max_open_files;
2296 static bool already_done =
false;
2299 if (!already_done) {
2300 unsigned soft_limit = 0;
2301 unsigned hard_limit = 0;
2306 "Warning: current limits for number of open files are "
2308 "CernVM-FS is likely to run out of file descriptors, "
2309 "set ulimit -n to at least %u",
2312 max_open_files = soft_limit;
2313 already_done =
true;
2316 return max_open_files;
2375 sizeof(fuse_ino_t) * 8);
2385 void **channel_or_session = NULL;
2386 if (loader_exports->
version >= 4) {
2390 bool fuse_notify_invalidation =
true;
2394 fuse_notify_invalidation =
false;
2400 fuse_notify_invalidation);
2414 *
g_boot_error = std::string(
"failed to set talk socket ownership - ")
2430 if (options->
IsDefined(
"CVMFS_NOTIFICATION_SERVER")) {
2432 options->
GetValue(
"CVMFS_NOTIFICATION_SERVER", &config);
2559 if (strcmp(argv[1],
"__cachemgr__") == 0) {
2562 if (strcmp(argv[1],
"__wpad__") == 0) {
2571 string msg_progress =
"Draining out kernel caches (";
2573 msg_progress +=
"up to ";
2584 string msg_progress;
2587 if (num_open_dirs != 0) {
2589 for (cvmfs::DirectoryHandles::iterator
2598 msg_progress =
"Saving open directory handles ("
2607 save_open_dirs->
state = saved_handles;
2608 saved_states->push_back(save_open_dirs);
2612 msg_progress =
"Saving inode tracker\n";
2618 state_glue_buffer->
state = saved_inode_tracker;
2619 saved_states->push_back(state_glue_buffer);
2622 msg_progress =
"Saving negative entry cache\n";
2628 state_dentry_tracker->
state = saved_dentry_tracker;
2629 saved_states->push_back(state_dentry_tracker);
2631 msg_progress =
"Saving page cache entry tracker\n";
2637 state_page_cache_tracker->
state = saved_page_cache_tracker;
2638 saved_states->push_back(state_page_cache_tracker);
2640 msg_progress =
"Saving chunk tables\n";
2646 state_chunk_tables->
state = saved_chunk_tables;
2647 saved_states->push_back(state_chunk_tables);
2649 msg_progress =
"Saving inode generation\n";
2658 state_inode_generation->
state = saved_inode_generation;
2659 saved_states->push_back(state_inode_generation);
2661 msg_progress =
"Saving fuse state\n";
2669 state_fuse->
state = saved_fuse_state;
2670 saved_states->push_back(state_fuse);
2679 saved_states->push_back(state_cache_mgr);
2681 msg_progress =
"Saving open files counter\n";
2682 uint32_t *saved_num_fd =
new uint32_t(
2686 state_num_fd->
state = saved_num_fd;
2687 saved_states->push_back(state_num_fd);
2700 for (
unsigned i = 0, l = saved_states.size(); i < l; ++i) {
2702 SendMsg2Socket(fd_progress,
"Restoring open directory handles... ");
2722 SendMsg2Socket(fd_progress,
"Migrating inode tracker (v1 to v4)... ");
2733 SendMsg2Socket(fd_progress,
"Migrating inode tracker (v2 to v4)... ");
2744 SendMsg2Socket(fd_progress,
"Migrating inode tracker (v3 to v4)... ");
2769 saved_states[i]->state);
2776 SendMsg2Socket(fd_progress,
"Restoring page cache entry tracker... ");
2789 SendMsg2Socket(fd_progress,
"Migrating chunk tables (v1 to v4)... ");
2801 SendMsg2Socket(fd_progress,
"Migrating chunk tables (v2 to v4)... ");
2813 SendMsg2Socket(fd_progress,
"Migrating chunk tables (v3 to v4)... ");
2828 saved_states[i]->state);
2829 new (chunk_tables)
ChunkTables(*saved_chunk_tables);
2854 *(reinterpret_cast<uint32_t *>(saved_states[i]->state)));
2865 int fixup_root_fd = -1;
2878 fixup_root_fd = new_cache_mgr->
PlantFd(old_root_fd);
2890 ->MoveOutBackingCacheMgr(
2900 fd_progress, saved_states[i]->state);
2903 if (new_root_fd >= 0) {
2905 }
else if (fixup_root_fd >= 0) {
2907 "new root file catalog descriptor (fixup) @%d", fixup_root_fd);
2915 saved_states[i]->state);
2924 const uint64_t saved_generation =
2935 for (
unsigned i = 0, l = saved_states.size(); i < l; ++i) {
2936 switch (saved_states[i]->state_id) {
2938 SendMsg2Socket(fd_progress,
"Releasing saved open directory handles\n");
2943 "Releasing saved glue buffer (version 1)\n");
2945 saved_states[i]->state);
2949 "Releasing saved glue buffer (version 2)\n");
2951 saved_states[i]->state);
2955 "Releasing saved glue buffer (version 3)\n");
2957 saved_states[i]->state);
2968 SendMsg2Socket(fd_progress,
"Releasing saved page cache entry cache\n");
2972 SendMsg2Socket(fd_progress,
"Releasing chunk tables (version 1)\n");
2974 saved_states[i]->state);
2977 SendMsg2Socket(fd_progress,
"Releasing chunk tables (version 2)\n");
2979 saved_states[i]->state);
2982 SendMsg2Socket(fd_progress,
"Releasing chunk tables (version 3)\n");
2984 saved_states[i]->state);
2988 delete static_cast<ChunkTables *
>(saved_states[i]->state);
2991 SendMsg2Socket(fd_progress,
"Releasing saved inode generation info\n");
2993 saved_states[i]->state);
2997 saved_states[i]->state);
3001 delete static_cast<uint32_t *
>(saved_states[i]->state);
3016 g_cvmfs_exports->so_version = CVMFS_VERSION;
3018 g_cvmfs_exports->fnInit =
Init;
3019 g_cvmfs_exports->fnSpawn =
Spawn;
3020 g_cvmfs_exports->fnFini =
Fini;
3023 g_cvmfs_exports->fnSaveState =
SaveState;
3031 delete g_cvmfs_exports;
3032 g_cvmfs_exports = NULL;
bool GetInfoIfOpen(uint64_t inode, shash::Any *hash, struct stat *info)
perf::Counter * n_eio_total()
VfsPutRaii GetVfsPutRaii()
std::string repository_name
OptionsManager * options_mgr()
void Dec(class Counter *counter)
bool IsExternalFile() const
perf::Counter * n_eio_05()
void UnregisterQuotaListener()
static const time_t kIndefiniteDeadline
perf::Counter * n_fs_inode_replace()
int64_t Xadd(class Counter *counter, const int64_t delta)
static void cvmfs_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
std::string ListKeysPosix(const std::string &merge_with) const
perf::Counter * n_eio_01()
FileSystem * file_system()
void TryFinish(const shash::Any &root_hash=shash::Any())
bool InsertNegative(const shash::Md5 &hash)
Log2Histogram * hist_fs_opendir()
time_t catalogs_valid_until_
static bool HasDifferentContent(const catalog::DirectoryEntry &dirent, const shash::Any &hash, const struct stat &info)
virtual void ParsePath(const std::string &config_file, const bool external)=0
bool ReplaceInode(uint64_t old_inode, const InodeEx &new_inode)
static void cvmfs_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
static double GetKcacheTimeout()
void EnterMaintenanceMode()
void set_inode(const inode_t inode)
InodeGenerationInfo inode_generation_info_
loader::Failures boot_status()
static void FreeSavedState(const int fd_progress, const loader::StateList &saved_states)
int PlantFd(int fd_in_cache_mgr)
static void cvmfs_statfs(fuse_req_t req, fuse_ino_t ino)
bool PrepareValueFencedProtected(gid_t gid)
void set_boot_status(loader::Failures code)
static void DoTraceInode(const int event, fuse_ino_t ino, const std::string &msg)
cvmfs::Fetcher * fetcher()
void Migrate(ChunkTables *old_tables,::ChunkTables *new_tables)
void ShareBuffer(Item **duplicate, bool *large_alloc)
static void cvmfs_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
bool IsChunkedFile() const
FuseRemounter * fuse_remounter_
int RestoreState(const int fd_progress, void *state)
void Register(const std::string &name, BaseMagicXattr *magic_xattr)
bool volatile_flag() const
SmallHashDynamic< uint64_t, uint64_t > handle2uniqino
bool Insert(const fuse_ino_t &inode, const catalog::DirectoryEntry &dirent)
google::dense_hash_map< uint64_t, DirectoryListing, hash_murmur< uint64_t > > DirectoryHandles
SpecialDirents GetSpecial() const
static int AltProcessFlavor(int argc, char **argv)
std::string ToString(const bool with_suffix=false) const
double kcache_timeout_sec()
void Assign(const char *chars, const unsigned length)
static void cvmfs_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
std::string PrintInodeGeneration()
zlib::Algorithms compression_alg
static void SetupLoggingStandalone(const OptionsManager &options_mgr, const std::string &prefix)
int MainResolveProxyDescription(int argc, char **argv)
bool FindDentry(uint64_t ino, uint64_t *parent_ino, NameString *name)
perf::Counter * n_fs_readlink()
void SetMountpoint(const string &mountpoint)
#define CVMFS_TEST_INJECT_BARRIER(...)
void InvalidateDentry(uint64_t parent_ino, const NameString &name)
void set_symlink(const LinkString &symlink)
static void cvmfs_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
BaseMagicXattr * GetLocked(const std::string &name, PathString path, catalog::DirectoryEntry *d)
static const size_t kDefaultBufferSize
bool Lookup(const shash::Md5 &hash, catalog::DirectoryEntry *dirent, bool update_lru=true)
lru::InodeCache * inode_cache()
NotificationClient * notification_client_
void * SaveState(const int fd_progress)
DirectoryHandles * directory_handles_
CVMFS_EXPORT void CleanupLibcryptoMt()
const shash::Any & content_hash() const
time_t catalogs_valid_until()
static bool SaveState(const int fd_progress, loader::StateList *saved_states)
void SendMsg2Socket(const int fd, const std::string &msg)
bool ListingStat(const PathString &path, StatEntryList *listing)
assert((mem||(size==0))&&"Out Of Memory")
void ** fuse_channel_or_session
MountPoint * mount_point_
MagicXattrManager * magic_xattr_mgr()
Log2Histogram * hist_fs_read()
bool SendFd2Socket(int socket_fd, int passing_fd)
bool LookupPath(const PathString &path, const LookupOptions options, DirectoryEntry *entry)
void EnableFuseExpireEntry()
static bool RestoreState(const int fd_progress, const loader::StateList &saved_states)
virtual uint64_t GetSize()=0
perf::Counter * n_fs_read()
bool Lookup(const fuse_ino_t &inode, catalog::DirectoryEntry *dirent, bool update_lru=true)
std::string StringifyUint(const uint64_t value)
lru::Md5PathCache * md5path_cache()
shash::Any checksum() const
void ParseDefault(const std::string &fqrn)
SmallHashDynamic< uint64_t, ChunkFd > handle2fd
bool VfsPut(const uint64_t inode, const uint32_t by)
void Migrate(InodeTracker *old_tracker, glue::InodeTracker *new_tracker)
bool has_membership_req()
virtual bool PrepareValueFenced()
unsigned int mode() const
struct cvmcache_object_info __attribute__
const unsigned kLookupDefault
void RemapCatalogFd(int from, int to)
bool Pin(const string &path)
static void cvmfs_destroy(void *unused __attribute__((unused)))
perf::Counter * n_eio_08()
static TalkManager * Create(const std::string &socket_path, MountPoint *mount_point, FuseRemounter *remounter)
static bool HasFuseNotifyInval()
perf::Counter * n_fs_open()
bool IsStale(const catalog::DirectoryEntry &dirent)
static void cvmfs_init(void *userdata, struct fuse_conn_info *conn)
const unsigned int kMinOpenFiles
virtual uint64_t GetCapacity()=0
std::string membership_req()
std::string GetListString(catalog::DirectoryEntry *dirent)
bool Lookup(const fuse_ino_t &inode, PathString *path, bool update_lru=true)
uint64_t next_directory_handle_
static void InitOptionsMgr(const loader::LoaderExports *loader_exports)
const uint64_t cache_timeout()
void ReplaceCacheManager(CacheManager *new_cache_mgr)
void DisableCacheSymlinks()
static bool GetDirentForInode(const fuse_ino_t ino, catalog::DirectoryEntry *dirent)
glue::PageCacheTracker * page_cache_tracker()
static Watchdog * Create(FnOnCrash on_crash)
void SetBit(unsigned int bit, T *field)
perf::Counter * n_eio_07()
BigVector< FileChunk > FileChunkList
static bool FixupOpenInode(const PathString &path, catalog::DirectoryEntry *dirent)
static void TraceInode(const int event, fuse_ino_t ino, const std::string &msg)
void GetLimitNoFile(unsigned *soft_limit, unsigned *hard_limit)
bool Get(const std::string &key, std::string *value) const
catalog::ClientCatalogManager * catalog_mgr()
void Set(const int64_t val)
Log2Histogram * hist_fs_forget_multi()
static void cvmfs_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
vector< string > SplitString(const string &str, char delim)
void ClearBit(unsigned int bit, T *field)
uint64_t size
unzipped size, if known
static bool MayBeInPageCacheTracker(const catalog::DirectoryEntry &dirent)
Log2Histogram * hist_fs_release()
pthread_mutex_t * Handle2Lock(const uint64_t handle) const
uint64_t FindInode(const PathString &path)
ListenerHandle * RegisterWatchdogListener(QuotaManager *quota_manager, const string &repository_name)
perf::Counter * n_emfile()
const loader::LoaderExports * loader_exports_
int Fetch(const CacheManager::LabeledObject &object, const std::string &alt_url="")
virtual inode_t GetGeneration()=0
perf::Counter * no_open_dirs()
catalog::InodeAnnotation * inode_annotation()
Log2Histogram * hist_fs_releasedir()
quota::ListenerHandle * watchdog_listener_
void Add(const uint64_t inode_parent, const char *name, uint64_t timeout_s)
virtual bool IsCanceled()
void SetSize(const size_t new_size)
lru::PathCache * path_cache()
static void cvmfs_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
zlib::Algorithms compression_algorithm() const
CacheManager * cache_mgr()
const signature::SignatureManager * signature_mgr() const
file_watcher::FileWatcher * resolv_conf_watcher()
virtual bool Pin(const shash::Any &hash, const uint64_t size, const std::string &description, const bool is_catalog)=0
bool IsMemberOf(const pid_t pid, const std::string &membership)
void Migrate(InodeTracker *old_tracker, glue::InodeTracker *new_tracker)
void SpawnCleaner(unsigned interval_s)
static void ShutdownMountpoint()
static bool AssertOrLog(int t, const LogSource, const int, const char *,...)
static bool IncAndCheckNoOpenFiles()
unsigned FindChunkIdx(const uint64_t offset)
virtual void FinalizeValue()
perf::TelemetryAggregator * telemetry_aggr()
bool SendFuseFd(const std::string &socket_path)
perf::Counter * no_open_files()
AuthzSessionManager * authz_session_mgr()
LinkString symlink() const
void Insert(const Key &key, const Value &value)
IoErrorInfo * io_error_info()
download::DownloadManager * download_mgr()
perf::Counter * n_fs_stat_stale()
void ReplaceCacheManager(CacheManager *new_cache_mgr)
static void SetCvmfsOperations(struct fuse_lowlevel_ops *cvmfs_operations)
bool simple_options_parsing
static const int kLabelPinned
perf::Counter * n_fs_forget()
Log2Histogram * hist_fs_readlink()
static int Init(const loader::LoaderExports *loader_exports)
void Append(const char *chars, const unsigned length)
ListenerHandle * RegisterUnpinListener(QuotaManager *quota_manager, CatalogManager *catalog_manager, const string &repository_name)
string StringifyInt(const int64_t value)
SmallHashDynamic< uint64_t, uint32_t > inode2references
static void cvmfs_readlink(fuse_req_t req, fuse_ino_t ino)
static void ReplyNegative(const catalog::DirectoryEntry &dirent, fuse_req_t req)
void Inc(class Counter *counter)
virtual int Close(int fd)=0
CacheManagerIds PeekState(void *state)
bool GetValue(const std::string &key, std::string *value) const
static void cvmfs_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
uint64_t initial_revision
ChunkTables * chunk_tables()
const unsigned kLookupRawSymlink
pthread_mutex_t lock_directory_handles_
static void cvmfs_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
OptionsManager * options_mgr_
virtual bool GetPath(const uint64_t inode, PathString *path)=0
shash::Algorithms hash_algorithm() const
glue::DentryTracker * dentry_tracker()
static int MainCacheManager(int argc, char **argv)
perf::Counter * n_fs_dir_open()
Log2Histogram * hist_fs_readdir()
cvmfs::Fetcher * external_fetcher()
static const int kLabelVolatile
bool IsInMaintenanceMode()
static bool CheckVoms(const fuse_ctx &fctx)
static void FillOpenFlags(const glue::PageCacheTracker::OpenDirectives od, struct fuse_file_info *fi)
void FreeState(const int fd_progress, void *state)
static FileSystem * Create(const FileSystemInfo &fs_info)
zlib::Algorithms zip_algorithm
bool Contains(const Key &key) const
Log2Histogram * hist_fs_open()
OpenDirectives Open(uint64_t inode, const shash::Any &hash, const struct stat &info)
std::string ToString() const
QuotaManager * quota_mgr()
static string GetErrorMsg()
uint64_t GetRevision() const
static uint64_t GetDirentForPath(const PathString &path, catalog::DirectoryEntry *dirent)
int ConnectSocket(const std::string &path)
void Migrate(ChunkTables *old_tables,::ChunkTables *new_tables)
void Evict(uint64_t inode)
Log2Histogram * hist_fs_lookup()
bool IsCompatibleFileType(unsigned mode) const
uint64_t String2Uint64(const string &value)
bool TestBit(unsigned int bit, const T field)
CVMFS_EXPORT void SetupLibcryptoMt()
void Close(uint64_t inode)
virtual void FinalizeValue()
bool ListFileChunks(const PathString &path, const shash::Algorithms interpret_hashes_as, FileChunkList *chunks)
perf::Counter * n_fs_lookup()
static bool UseWatchdog()
void Migrate(InodeTracker *old_tracker, glue::InodeTracker *new_tracker)
OpenDirectives OpenDirect()
ShortString< kDefaultMaxPath, 0 > PathString
shash::Any HashChunkList()
FuseInterruptCue(fuse_req_t *r)
void UnregisterListener(ListenerHandle *handle)
bool Evict(const string &path)
std::vector< SavedState * > StateList
perf::Counter * n_eio_02()
PathString GetParentPath(const PathString &path)
static unsigned CheckMaxOpenFiles()
FileSystem * file_system_
perf::Counter * n_eio_03()
perf::Counter * n_eio_04()
void GetReloadStatus(bool *drainout_mode, bool *maintenance_mode)
bool Erase(const Key &key)
bool LookupXattrs(const PathString &path, XattrList *xattrs)
perf::Counter * n_fs_lookup_negative()
StatfsCache * statfs_cache()
uint64_t all_inodes() const
virtual uint64_t GetInode(const PathString &path)=0
void Spawn(const std::string &crash_dump_path)
virtual void FinalizeValue()
Log2Histogram * hist_fs_forget()
static void ReplyBufferSlice(const fuse_req_t req, const char *buffer, const size_t buffer_size, const off_t offset, const size_t max_size)
inode_t GetRootInode() const
unsigned GetLength() const
static const int kLabelExternal
virtual void IncGeneration(const uint64_t by)=0
bool Lookup(const Key &key, Value *value) const
inode_t MangleInode(const inode_t inode) const
static const int kLabelChunked
uint64_t inode_generation
virtual void FinalizeValue()
bool Insert(const fuse_ino_t &inode, const PathString &path)
BackoffThrottle * backoff_throttle()
Log2Histogram * hist_fs_getattr()
const char * c_str() const
static bool GetPathForInode(const fuse_ino_t ino, PathString *path)
static const unsigned int kBitDirectIo
virtual void FinalizeValue()
const char * GetChars() const
static void RegisterMagicXattrs()
bool IsDefined(const std::string &key)
std::string GetCurrentWorkingDirectory()
virtual void Remove(const shash::Any &file)=0
glue::InodeTracker * inode_tracker()
bool Insert(const shash::Md5 &hash, const catalog::DirectoryEntry &dirent)
perf::Counter * n_fs_stat()
virtual ~FuseInterruptCue()
static void cvmfs_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
virtual int64_t Pread(int fd, void *buf, uint64_t size, uint64_t offset)=0
SmallHashDynamic< uint64_t, FileChunkReflist > inode2chunks
static bool MaintenanceMode(const int fd_progress)
uint64_t * expiry_deadline()
uint64_t loaded_inodes() const
void Migrate(ChunkTables *old_tables,::ChunkTables *new_tables)
static FileSystem * InitSystemFs(const string &mount_path, const string &fqrn, FileSystem::FileSystemInfo fs_info)
static const inode_t kInodeOffset
void VfsGet(const InodeEx inode_ex, const PathString &path)
const Item * AtPtr(const size_t index) const
static void cvmfs_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
perf::Counter * n_fs_statfs_cached()
bool FindPath(InodeEx *inode_ex, PathString *path)
struct stat GetStatStructure() const
virtual bool HasCapability(Capabilities capability)=0
static void AddToDirListing(const fuse_req_t req, const char *name, const struct stat *stat_info, BigVector< char > *listing)
download::DownloadManager * external_download_mgr()
perf::Counter * n_fs_statfs()
quota::ListenerHandle * unpin_listener_
static MountPoint * Create(const std::string &fqrn, FileSystem *file_system, OptionsManager *options_mgr=NULL)
perf::Counter * n_eio_06()
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
OptionsManager * options_mgr