diff --git a/ifs/include/daemon/adafs_ops/metadentry.hpp b/ifs/include/daemon/adafs_ops/metadentry.hpp index 59f95f660533f0c4e8c7632ad5bc20f9b0e97ff3..859b79ac963c8a4206dfe40a9fc69aa98d40224b 100644 --- a/ifs/include/daemon/adafs_ops/metadentry.hpp +++ b/ifs/include/daemon/adafs_ops/metadentry.hpp @@ -3,15 +3,13 @@ #define IFS_METADENTRY_HPP #include -#include +#include #include int create_node(const std::string& path, const uid_t uid, const gid_t gid, mode_t mode); void create_metadentry(const std::string& path, mode_t mode); -int db_val_to_stat(const std::string& path, std::string db_val, struct stat& attr); - std::string get_metadentry_str(const std::string& path); Metadata get_metadentry(const std::string& path); diff --git a/ifs/include/daemon/backend/metadata/merge.hpp b/ifs/include/daemon/backend/metadata/merge.hpp index 331ff9774ba4807229b5a7fa48d85f0bd3d3fd06..f72d818ecba8d5d6c877fcacd9a59e0a60ebea18 100644 --- a/ifs/include/daemon/backend/metadata/merge.hpp +++ b/ifs/include/daemon/backend/metadata/merge.hpp @@ -3,7 +3,7 @@ #include "rocksdb/merge_operator.h" -#include +#include "global/metadata.hpp" namespace rdb = rocksdb; diff --git a/ifs/include/daemon/classes/metadata.hpp b/ifs/include/daemon/classes/metadata.hpp deleted file mode 100644 index b43671701d12f93de6d64262c7268e1b1cdefd24..0000000000000000000000000000000000000000 --- a/ifs/include/daemon/classes/metadata.hpp +++ /dev/null @@ -1,84 +0,0 @@ - -#ifndef FS_METADATA_H -#define FS_METADATA_H - -#include - -class Metadata { - -private: - time_t atime_; // access time. gets updated on file access unless mounted with noatime - time_t mtime_; // modify time. gets updated when file content is modified. - time_t ctime_; // change time. gets updated when the file attributes are changed AND when file content is modified. - uid_t uid_; - gid_t gid_; - mode_t mode_; - uint64_t inode_no_; - nlink_t link_count_; // number of names for this inode (hardlinks) - size_t size_; // size_ in bytes, might be computed instead of stored - blkcnt_t blocks_; // allocated file system blocks_ - - std::string path_; - -public: - Metadata(); - - Metadata(const std::string& path, mode_t mode); - - Metadata(const std::string& path, std::string db_val); - - void init_ACM_time(); - - void update_ACM_time(bool a, bool c, bool m); - - std::string serialize() const; - - //Getter and Setter - time_t atime() const; - - void atime(time_t atime_); - - time_t mtime() const; - - void mtime(time_t mtime_); - - time_t ctime() const; - - void ctime(time_t ctime_); - - uid_t uid() const; - - void uid(uid_t uid_); - - gid_t gid() const; - - void gid(gid_t gid_); - - mode_t mode() const; - - void mode(mode_t mode_); - - uint64_t inode_no() const; - - void inode_no(uint64_t inode_no_); - - nlink_t link_count() const; - - void link_count(nlink_t link_count_); - - size_t size() const; - - void size(size_t size_); - - blkcnt_t blocks() const; - - void blocks(blkcnt_t blocks_); - - const std::string& path() const; - - void path(const std::string& path); - -}; - - -#endif //FS_METADATA_H diff --git a/ifs/include/global/metadata.hpp b/ifs/include/global/metadata.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eb5fa8d649729ca79a291c358bfa2699de33a452 --- /dev/null +++ b/ifs/include/global/metadata.hpp @@ -0,0 +1,59 @@ +#ifndef FS_METADATA_H +#define FS_METADATA_H +#pragma once + + +#include "global/configure.hpp" +#include +#include + + +class Metadata { +private: + time_t atime_; // access time. gets updated on file access unless mounted with noatime + time_t mtime_; // modify time. gets updated when file content is modified. + time_t ctime_; // change time. gets updated when the file attributes are changed AND when file content is modified. + uid_t uid_; + gid_t gid_; + mode_t mode_; + unsigned long inode_no_; + nlink_t link_count_; // number of names for this inode (hardlinks) + size_t size_; // size_ in bytes, might be computed instead of stored + blkcnt_t blocks_; // allocated file system blocks_ + +public: + Metadata(); + Metadata(mode_t mode); + // Construct from a binary representation of the object + Metadata(const std::string& binary_str); + + std::string serialize() const; + + void init_ACM_time(); + void update_ACM_time(bool a, bool c, bool m); + + //Getter and Setter + time_t atime() const; + void atime(time_t atime_); + time_t mtime() const; + void mtime(time_t mtime_); + time_t ctime() const; + void ctime(time_t ctime_); + uid_t uid() const; + void uid(uid_t uid_); + gid_t gid() const; + void gid(gid_t gid_); + mode_t mode() const; + void mode(mode_t mode_); + unsigned long inode_no() const; + void inode_no(unsigned long inode_no_); + nlink_t link_count() const; + void link_count(nlink_t link_count_); + size_t size() const; + void size(size_t size_); + blkcnt_t blocks() const; + void blocks(blkcnt_t blocks_); +}; + + +#endif //FS_METADATA_H diff --git a/ifs/include/preload/preload_util.hpp b/ifs/include/preload/preload_util.hpp index 21ffad597babe9c7967b9aa5c3e11f7ffecb64cc..c5943ddb90beb5acfce7b20d61fd700b5602f537 100644 --- a/ifs/include/preload/preload_util.hpp +++ b/ifs/include/preload/preload_util.hpp @@ -3,6 +3,7 @@ #define IFS_PRELOAD_UTIL_HPP #include +#include // third party libs #include #include @@ -11,21 +12,6 @@ extern "C" { #include } -// Used to bundle metadata into one place -struct Metadentry { - time_t atime; - time_t mtime; - time_t ctime; - uid_t uid; - gid_t gid; - mode_t mode; - uint64_t inode_no; - nlink_t link_count; - off_t size; - blkcnt_t blocks; - - std::string path; -}; struct MetadentryUpdateFlags { bool atime = false; bool mtime = false; @@ -83,7 +69,7 @@ extern std::map rpc_addresses; bool is_fs_path(const char* path); -int db_val_to_stat(const std::string& path, std::string db_val, struct stat& attr); +int metadata_to_stat(const std::string& path, const Metadata& md, struct stat& attr); int get_daemon_pid(); diff --git a/ifs/include/preload/rpc/ld_rpc_metadentry.hpp b/ifs/include/preload/rpc/ld_rpc_metadentry.hpp index e4a05af76607706888b574b7d290f893692bede8..0ad0e062a2ecb6d3b2e42c98752a6870f1f53a40 100644 --- a/ifs/include/preload/rpc/ld_rpc_metadentry.hpp +++ b/ifs/include/preload/rpc/ld_rpc_metadentry.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include inline hg_return_t margo_forward_timed_wrap_timer(hg_handle_t& handle, void* in_struct, const char* func); @@ -24,7 +25,7 @@ int rpc_send_rm_node(const std::string& path, const bool remove_metadentry_only) int rpc_send_decr_size(const std::string& path, size_t length); -int rpc_send_update_metadentry(const std::string& path, const Metadentry& md, const MetadentryUpdateFlags& md_flags); +int rpc_send_update_metadentry(const std::string& path, const Metadata& md, const MetadentryUpdateFlags& md_flags); int rpc_send_update_metadentry_size(const std::string& path, size_t size, off64_t offset, bool append_flag, off64_t& ret_size); diff --git a/ifs/scripts/dl_dep.sh b/ifs/scripts/dl_dep.sh index 4f947af318768c002a775ccf2258810f7647e15f..8e9a3220232458290f0d550a8eb85d62b106c80c 100755 --- a/ifs/scripts/dl_dep.sh +++ b/ifs/scripts/dl_dep.sh @@ -199,13 +199,13 @@ if [ "${NA_LAYER}" == "ofi" ] || [ "${NA_LAYER}" == "all" ]; then fi fi # get Mercury -clonedeps "mercury" "https://github.com/mercury-hpc/mercury" "f7f6955f140426b2a7c9e26dc35f8c8e1654d86a" "--recurse-submodules" & +clonedeps "mercury" "https://github.com/mercury-hpc/mercury" "ef114e7e2831955fb289c1d5df8a8234b794043d" "--recurse-submodules" & # get Argobots clonedeps "argobots" "https://github.com/carns/argobots.git" "4a84e66ed8544db215d6862f527775387418f7f6" "-b dev-fifo-wait" & # get Margo clonedeps "margo" "https://xgitlab.cels.anl.gov/sds/margo.git" "cf673d430ce3d4b4f0a32f19f261e7898a863b81" & # get rocksdb -wgetdeps "rocksdb" "https://github.com/facebook/rocksdb/archive/v5.14.2.tar.gz" & +wgetdeps "rocksdb" "https://github.com/facebook/rocksdb/archive/v5.15.10.tar.gz" & # get syscall_intercept clonedeps "syscall_intercept" "https://github.com/pmem/syscall_intercept.git" "4b3a3b50f9d8d0127a4b39022d78b7369a534673" & diff --git a/ifs/src/daemon/CMakeLists.txt b/ifs/src/daemon/CMakeLists.txt index ad2ee50acaca99e4082ec89b27a6d6ac64408d94..5c6ac9b698cd562fedc7412637f09156c0069564 100644 --- a/ifs/src/daemon/CMakeLists.txt +++ b/ifs/src/daemon/CMakeLists.txt @@ -5,11 +5,11 @@ set(DAEMON_SRC ../global/rpc/rpc_utils.cpp ../global/global_func.cpp ../global/path_util.cpp + ../global/metadata.cpp adafs_daemon.cpp adafs_ops/metadentry.cpp classes/fs_data.cpp classes/rpc_data.cpp - classes/metadata.cpp handler/h_metadentry.cpp handler/h_data.cpp handler/h_preload.cpp @@ -23,10 +23,10 @@ set(DAEMON_HEADERS ../../include/global/rpc/rpc_types.hpp ../../include/global/rpc/rpc_utils.hpp ../../include/global/path_util.hpp + ../../include/global/metadata.hpp ../../include/daemon/adafs_daemon.hpp ../../include/daemon/adafs_ops/metadentry.hpp ../../include/daemon/classes/fs_data.hpp - ../../include/daemon/classes/metadata.hpp ../../include/daemon/classes/rpc_data.hpp ../../include/daemon/handler/rpc_defs.hpp ) diff --git a/ifs/src/daemon/adafs_ops/metadentry.cpp b/ifs/src/daemon/adafs_ops/metadentry.cpp index a279c15cd9f4457d9d5ea6b41973d7770c3ff1df..1f21b0b90a470a977d7cada3292eae306b4649f4 100644 --- a/ifs/src/daemon/adafs_ops/metadentry.cpp +++ b/ifs/src/daemon/adafs_ops/metadentry.cpp @@ -18,7 +18,7 @@ ino_t generate_inode_no() { */ void create_metadentry(const std::string& path, mode_t mode) { - Metadata md{path, mode}; + Metadata md{mode}; // update metadata object based on what metadata is needed if (ADAFS_DATA->atime_state() || ADAFS_DATA->mtime_state() || ADAFS_DATA->ctime_state()) { std::time_t time; @@ -52,7 +52,7 @@ std::string get_metadentry_str(const std::string& path) { * @return */ Metadata get_metadentry(const std::string& path) { - return {path, get_metadentry_str(path)}; + return {get_metadentry_str(path)}; } /** @@ -92,7 +92,7 @@ void update_metadentry_size(const string& path, size_t io_size, off64_t offset, } void update_metadentry(const string& path, Metadata& md) { - ADAFS_DATA->mdb()->update(path, md.path(), md.serialize()); + ADAFS_DATA->mdb()->update(path, path, md.serialize()); } /** @@ -101,49 +101,47 @@ void update_metadentry(const string& path, Metadata& md) { * @return errno */ int check_access_mask(const string& path, const int mask) { - Metadata md; try { - md = get_metadentry(path); - } catch (const NotFoundException& e) { - return ENOENT; - } + Metadata md = get_metadentry_str(path); + /* + * if only check if file exists is wanted, return success. + * According to POSIX (access(2)) the mask is either the value F_OK, + * or a mask consisting of the bitwise OR of one or more of R_OK, W_OK, and X_OK. + */ + if (mask == F_OK) + return 0; - /* - * if only check if file exists is wanted, return success. - * According to POSIX (access(2)) the mask is either the value F_OK, - * or a mask consisting of the bitwise OR of one or more of R_OK, W_OK, and X_OK. - */ - if (mask == F_OK) - return 0; - - // root user is a god - if (ADAFS_DATA->uid_state() && md.uid() == 0) - return 0; - - // We do not check for the actual user here, because the cluster batchsystem should take care of it - // check user leftmost 3 bits for rwx in md->mode - if (ADAFS_DATA->uid_state()) { - // Because mode comes only with the first 3 bits used, the user bits have to be shifted to the right to compare - if ((mask & md.mode() >> 6) == static_cast(mask)) + // root user is a god + if (ADAFS_DATA->uid_state() && md.uid() == 0) return 0; - else - return EACCES; - } - // check group middle 3 bits for rwx in md->mode - if (ADAFS_DATA->gid_state()) { - if ((mask & md.mode() >> 3) == static_cast(mask)) + // We do not check for the actual user here, because the cluster batchsystem should take care of it + // check user leftmost 3 bits for rwx in md->mode + if (ADAFS_DATA->uid_state()) { + // Because mode comes only with the first 3 bits used, the user bits have to be shifted to the right to compare + if ((mask & md.mode() >> 6) == static_cast(mask)) + return 0; + else + return EACCES; + } + + // check group middle 3 bits for rwx in md->mode + if (ADAFS_DATA->gid_state()) { + if ((mask & md.mode() >> 3) == static_cast(mask)) + return 0; + else + return EACCES; + } + + // check other rightmost 3 bits for rwx in md->mode. + // Because they are the rightmost bits they don't need to be shifted + if ((mask & md.mode()) == static_cast(mask)) { return 0; - else - return EACCES; - } + } - // check other rightmost 3 bits for rwx in md->mode. - // Because they are the rightmost bits they don't need to be shifted - if ((mask & md.mode()) == static_cast(mask)) { - return 0; + } catch (const NotFoundException& e) { + return ENOENT; } - return EACCES; } diff --git a/ifs/src/daemon/backend/metadata/db.cpp b/ifs/src/daemon/backend/metadata/db.cpp index 5681b50d09518e5fb4330625946f808dc93defd2..5464cdc049000f45028d9d3489d5d8529e8ab344 100644 --- a/ifs/src/daemon/backend/metadata/db.cpp +++ b/ifs/src/daemon/backend/metadata/db.cpp @@ -4,6 +4,9 @@ #include +#include + + MetadataDB::MetadataDB(const std::string& path): path(path) { // Optimize RocksDB. This is the easiest way to get RocksDB to perform well options.IncreaseParallelism(); diff --git a/ifs/src/daemon/backend/metadata/merge.cpp b/ifs/src/daemon/backend/metadata/merge.cpp index cbb9c98a52e7fe764c033df6f7ee8b7edfdd30df..63e8a49171c4958d17cf30f9936611b1169d532e 100644 --- a/ifs/src/daemon/backend/metadata/merge.cpp +++ b/ifs/src/daemon/backend/metadata/merge.cpp @@ -112,7 +112,7 @@ bool MetadataMergeOperator::FullMergeV2( prev_md_value = merge_in.existing_value->ToString(); } - Metadata md{merge_in.key.ToString(), prev_md_value}; + Metadata md{prev_md_value}; size_t fsize = md.size(); @@ -137,7 +137,7 @@ bool MetadataMergeOperator::FullMergeV2( } else if(operand_id == OperandID::create){ continue; } else { - throw std::runtime_error(fmt::format("Unrecognized merge operand ID: {}", (char)operand_id)); + throw std::runtime_error("Unrecognized merge operand ID: " + (char)operand_id); } } diff --git a/ifs/src/daemon/classes/metadata.cpp b/ifs/src/daemon/classes/metadata.cpp deleted file mode 100644 index dfbb89cceab101a84f1537bdb49d963182f69e5c..0000000000000000000000000000000000000000 --- a/ifs/src/daemon/classes/metadata.cpp +++ /dev/null @@ -1,257 +0,0 @@ - -#include - -using namespace std; - -static const std::string dentry_val_delim = ","s; - -// By default create an empty metadata object - -Metadata::Metadata() : atime_(), - mtime_(), - ctime_(), - uid_(), - gid_(), - mode_(), - inode_no_(INVALID_INODE), - link_count_(0), - size_(0), - blocks_(0) {} - -Metadata::Metadata(const std::string& path, const mode_t mode) : atime_(), - mtime_(), - ctime_(), - uid_(), - gid_(), - mode_(mode), - inode_no_(INVALID_INODE), - link_count_(0), - size_(0), - blocks_(0), - path_(path) {} - -/** - * Creates a metadata object from a value from the database - * @param path - * @param db_val - */ -Metadata::Metadata(const std::string& path, std::string db_val) { - auto pos = db_val.find(dentry_val_delim); - if (pos == std::string::npos) { // no delimiter found => no metadata enabled. fill with dummy values - inode_no_ = std::hash{}(path); - mode_ = static_cast(stoul(db_val)); - link_count_ = 1; - uid_ = 0; - gid_ = 0; - size_ = 0; - blocks_ = 0; - atime_ = 0; - mtime_ = 0; - ctime_ = 0; - return; - } - // some metadata is enabled: mode is always there - mode_ = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - // size is also there - pos = db_val.find(dentry_val_delim); - if (pos != std::string::npos) { // delimiter found. more metadata is coming - size_ = stol(db_val.substr(0, pos)); - db_val.erase(0, pos + 1); - } else { - size_ = stol(db_val); - return; - } - // The order is important. don't change. - if (ADAFS_DATA->atime_state()) { - pos = db_val.find(dentry_val_delim); - atime_ = static_cast(stol(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->mtime_state()) { - pos = db_val.find(dentry_val_delim); - mtime_ = static_cast(stol(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->ctime_state()) { - pos = db_val.find(dentry_val_delim); - ctime_ = static_cast(stol(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->uid_state()) { - pos = db_val.find(dentry_val_delim); - uid_ = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->gid_state()) { - pos = db_val.find(dentry_val_delim); - gid_ = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->inode_no_state()) { - pos = db_val.find(dentry_val_delim); - inode_no_ = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->link_cnt_state()) { - pos = db_val.find(dentry_val_delim); - link_count_ = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - } - if (ADAFS_DATA->blocks_state()) { // last one will not encounter a delimiter anymore - blocks_ = static_cast(stoul(db_val)); - } -} - -void Metadata::init_ACM_time() { - std::time_t time; - std::time(&time); - atime_ = time; - mtime_ = time; - ctime_ = time; -} - -void Metadata::update_ACM_time(bool a, bool c, bool m) { - std::time_t time; - std::time(&time); - if (a) - atime_ = time; - if (c) - ctime_ = time; - if (m) - mtime_ = time; -} - -/** - * Returns the string rapresentation of metadata - */ -std::string Metadata::serialize() const { - std::string s; - // The order is important. don't change. - s += std::to_string(mode_); // add mandatory mode - s += dentry_val_delim; - s += std::to_string(size_); // add mandatory size - if (ADAFS_DATA->atime_state()) { - s += dentry_val_delim; - s += std::to_string(atime_); - } - if (ADAFS_DATA->mtime_state()) { - s += dentry_val_delim; - s += std::to_string(mtime_); - } - if (ADAFS_DATA->ctime_state()) { - s += dentry_val_delim; - s += std::to_string(ctime_); - } - if (ADAFS_DATA->uid_state()) { - s += dentry_val_delim; - s += std::to_string(uid_); - } - if (ADAFS_DATA->gid_state()) { - s += dentry_val_delim; - s += std::to_string(gid_); - } - if (ADAFS_DATA->inode_no_state()) { - s += dentry_val_delim; - s += std::to_string(inode_no_); - } - if (ADAFS_DATA->link_cnt_state()) { - s += dentry_val_delim; - s += std::to_string(link_count_); - } - if (ADAFS_DATA->blocks_state()) { - s += dentry_val_delim; - s += std::to_string(blocks_); - } - return s; -} - -//-------------------------------------------- GETTER/SETTER - -time_t Metadata::atime() const { - return atime_; -} - -void Metadata::atime(time_t atime_) { - Metadata::atime_ = atime_; -} - -time_t Metadata::mtime() const { - return mtime_; -} - -void Metadata::mtime(time_t mtime_) { - Metadata::mtime_ = mtime_; -} - -time_t Metadata::ctime() const { - return ctime_; -} - -void Metadata::ctime(time_t ctime_) { - Metadata::ctime_ = ctime_; -} - -uid_t Metadata::uid() const { - return uid_; -} - -void Metadata::uid(uid_t uid_) { - Metadata::uid_ = uid_; -} - -gid_t Metadata::gid() const { - return gid_; -} - -void Metadata::gid(gid_t gid_) { - Metadata::gid_ = gid_; -} - -mode_t Metadata::mode() const { - return mode_; -} - -void Metadata::mode(mode_t mode_) { - Metadata::mode_ = mode_; -} - -uint64_t Metadata::inode_no() const { - return inode_no_; -} - -void Metadata::inode_no(uint64_t inode_no_) { - Metadata::inode_no_ = inode_no_; -} - -nlink_t Metadata::link_count() const { - return link_count_; -} - -void Metadata::link_count(nlink_t link_count_) { - Metadata::link_count_ = link_count_; -} - -size_t Metadata::size() const { - return size_; -} - -void Metadata::size(size_t size_) { - Metadata::size_ = size_; -} - -blkcnt_t Metadata::blocks() const { - return blocks_; -} - -void Metadata::blocks(blkcnt_t blocks_) { - Metadata::blocks_ = blocks_; -} - -const std::string& Metadata::path() const { - return path_; -} - -void Metadata::path(const std::string& path) { - Metadata::path_ = path; -} diff --git a/ifs/src/global/metadata.cpp b/ifs/src/global/metadata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..beab7a1ab2d5a63d2300ad4905964343704256d5 --- /dev/null +++ b/ifs/src/global/metadata.cpp @@ -0,0 +1,237 @@ +#include "global/metadata.hpp" +#include "global/configure.hpp" + +#include +#include + +#include +#include + + +static const char MSP = '|'; // metadata separator + +Metadata::Metadata(const mode_t mode) : + atime_(), + mtime_(), + ctime_(), + uid_(), + gid_(), + mode_(mode), + inode_no_(0), + link_count_(0), + size_(0), + blocks_(0) +{} + +Metadata::Metadata(const std::string& binary_str) { + size_t read = 0; + + auto ptr = binary_str.data(); + mode_ = static_cast(std::stoul(ptr, &read)); + // we read something + assert(read > 0); + ptr += read; + + // last parsed char is the separator char + assert(*ptr == MSP); + // yet we have some character to parse + + size_ = std::stol(++ptr, &read); + assert(read > 0); + ptr += read; + + // The order is important. don't change. + if (MDATA_USE_ATIME) { + assert(*ptr == MSP); + atime_ = static_cast(std::stol(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_MTIME) { + assert(*ptr == MSP); + mtime_ = static_cast(std::stol(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_CTIME) { + assert(*ptr == MSP); + ctime_ = static_cast(std::stol(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_UID) { + assert(*ptr == MSP); + uid_ = static_cast(std::stoul(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_GID) { + assert(*ptr == MSP); + gid_ = static_cast(std::stoul(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_INODE_NO) { + assert(*ptr == MSP); + inode_no_ = static_cast(std::stoul(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_LINK_CNT) { + assert(*ptr == MSP); + link_count_ = static_cast(std::stoul(++ptr, &read)); + assert(read > 0); + ptr += read; + } + if (MDATA_USE_BLOCKS) { // last one will not encounter a delimiter anymore + assert(*ptr == MSP); + blocks_ = static_cast(std::stoul(++ptr, &read)); + assert(read > 0); + ptr += read; + } + // we consumed all the binary string + assert(*ptr == '\0'); +} + +std::string Metadata::serialize() const +{ + std::string s; + // The order is important. don't change. + s += std::to_string(mode_); // add mandatory mode + s += MSP; + s += std::to_string(size_); // add mandatory size + if (MDATA_USE_ATIME) { + s += MSP; + s += std::to_string(atime_); + } + if (MDATA_USE_MTIME) { + s += MSP; + s += std::to_string(mtime_); + } + if (MDATA_USE_CTIME) { + s += MSP; + s += std::to_string(ctime_); + } + if (MDATA_USE_UID) { + s += MSP; + s += std::to_string(uid_); + } + if (MDATA_USE_GID) { + s += MSP; + s += std::to_string(gid_); + } + if (MDATA_USE_INODE_NO) { + s += MSP; + s += std::to_string(inode_no_); + } + if (MDATA_USE_LINK_CNT) { + s += MSP; + s += std::to_string(link_count_); + } + if (MDATA_USE_BLOCKS) { + s += MSP; + s += std::to_string(blocks_); + } + return s; +} + +void Metadata::init_ACM_time() { + std::time_t time; + std::time(&time); + atime_ = time; + mtime_ = time; + ctime_ = time; +} + +void Metadata::update_ACM_time(bool a, bool c, bool m) { + std::time_t time; + std::time(&time); + if (a) + atime_ = time; + if (c) + ctime_ = time; + if (m) + mtime_ = time; +} + +//-------------------------------------------- GETTER/SETTER + +time_t Metadata::atime() const { + return atime_; +} + +void Metadata::atime(time_t atime_) { + Metadata::atime_ = atime_; +} + +time_t Metadata::mtime() const { + return mtime_; +} + +void Metadata::mtime(time_t mtime_) { + Metadata::mtime_ = mtime_; +} + +time_t Metadata::ctime() const { + return ctime_; +} + +void Metadata::ctime(time_t ctime_) { + Metadata::ctime_ = ctime_; +} + +uid_t Metadata::uid() const { + return uid_; +} + +void Metadata::uid(uid_t uid_) { + Metadata::uid_ = uid_; +} + +gid_t Metadata::gid() const { + return gid_; +} + +void Metadata::gid(gid_t gid_) { + Metadata::gid_ = gid_; +} + +mode_t Metadata::mode() const { + return mode_; +} + +void Metadata::mode(mode_t mode_) { + Metadata::mode_ = mode_; +} + +uint64_t Metadata::inode_no() const { + return inode_no_; +} + +void Metadata::inode_no(uint64_t inode_no_) { + Metadata::inode_no_ = inode_no_; +} + +nlink_t Metadata::link_count() const { + return link_count_; +} + +void Metadata::link_count(nlink_t link_count_) { + Metadata::link_count_ = link_count_; +} + +size_t Metadata::size() const { + return size_; +} + +void Metadata::size(size_t size_) { + Metadata::size_ = size_; +} + +blkcnt_t Metadata::blocks() const { + return blocks_; +} + +void Metadata::blocks(blkcnt_t blocks_) { + Metadata::blocks_ = blocks_; +} diff --git a/ifs/src/preload/CMakeLists.txt b/ifs/src/preload/CMakeLists.txt index 24b272d2d824e85ec4d5e2c9ac437b3fcde675fb..0473ab90478a81ac8dcbd1175f39d5f03f2fe86b 100644 --- a/ifs/src/preload/CMakeLists.txt +++ b/ifs/src/preload/CMakeLists.txt @@ -14,6 +14,7 @@ set(PRELOAD_SRC ../global/rpc/rpc_utils.cpp ../global/global_func.cpp ../global/path_util.cpp + ../global/metadata.cpp ) set(PRELOAD_HEADERS ../../configure_public.hpp @@ -25,6 +26,7 @@ set(PRELOAD_HEADERS ../../include/global/rpc/rpc_utils.hpp ../../include/global/path_util.hpp ../../include/global/chunk_calc_util.hpp + ../../include/global/metadata.hpp ../../include/preload/preload_context.hpp ../../include/preload/adafs_functions.hpp ../../include/preload/intercept.hpp diff --git a/ifs/src/preload/adafs_functions.cpp b/ifs/src/preload/adafs_functions.cpp index fc18fae716652bcbd675cb0de1fd93297dbd2cb6..fb71981287583ec6e96658a72d98bbaa46f455f9 100644 --- a/ifs/src/preload/adafs_functions.cpp +++ b/ifs/src/preload/adafs_functions.cpp @@ -163,10 +163,13 @@ int adafs_access(const std::string& path, const int mask) { } int adafs_stat(const string& path, struct stat* buf) { - string attr = ""s; + std::string attr; auto err = rpc_send_stat(path, attr); - if (err == 0) - db_val_to_stat(path, attr, *buf); + if (err) { + return err; + } + Metadata md(attr); + metadata_to_stat(path, md, *buf); return err; } diff --git a/ifs/src/preload/preload_util.cpp b/ifs/src/preload/preload_util.cpp index 810cb6e1ab1d5d33a55af3a1b8f528e4c31b183a..91ca33713f0c37d7d494f6144ddac5f5da9bd1cc 100644 --- a/ifs/src/preload/preload_util.cpp +++ b/ifs/src/preload/preload_util.cpp @@ -13,21 +13,18 @@ using namespace std; -static const std::string dentry_val_delim = ","s; - bool is_fs_path(const char* path) { return strstr(path, CTX->mountdir().c_str()) == path; } -// TODO merge the two stat functions /** - * Converts the dentry db value into a stat struct, which is needed by Linux + * Converts the Metadata object into a stat struct, which is needed by Linux * @param path - * @param db_val + * @param md * @param attr * @return */ -int db_val_to_stat(const std::string& path, std::string db_val, struct stat& attr) { +int metadata_to_stat(const std::string& path, const Metadata& md, struct stat& attr) { /* Populate default values */ attr.st_dev = makedev(0, 0); @@ -43,69 +40,32 @@ int db_val_to_stat(const std::string& path, std::string db_val, struct stat& att memset(&attr.st_mtim, 0, sizeof(timespec)); memset(&attr.st_ctim, 0, sizeof(timespec)); - auto pos = db_val.find(dentry_val_delim); - if (pos == std::string::npos) { // no delimiter found => no metadata enabled. fill with dummy values - attr.st_mode = static_cast(stoul(db_val)); - attr.st_nlink = 1; - attr.st_uid = CTX->fs_conf()->uid; - attr.st_gid = CTX->fs_conf()->gid; - attr.st_size = 0; - attr.st_blksize = BLOCKSIZE; - attr.st_blocks = 0; - attr.st_atim.tv_sec = 0; - attr.st_mtim.tv_sec = 0; - attr.st_ctim.tv_sec = 0; - return 0; - } - // some metadata is enabled: mode is always there - attr.st_mode = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); - // size is also there XXX - pos = db_val.find(dentry_val_delim); - if (pos != std::string::npos) { // delimiter found. more metadata is coming - attr.st_size = stol(db_val.substr(0, pos)); - db_val.erase(0, pos + 1); - } else { - attr.st_size = stol(db_val); - } - // The order is important. don't change. + attr.st_mode = md.mode(); + attr.st_size = md.size(); + if (CTX->fs_conf()->atime_state) { - pos = db_val.find(dentry_val_delim); - attr.st_atim.tv_sec = static_cast(stol(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_atim.tv_sec = md.atime(); } if (CTX->fs_conf()->mtime_state) { - pos = db_val.find(dentry_val_delim); - attr.st_mtim.tv_sec = static_cast(stol(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_mtim.tv_sec = md.mtime(); } if (CTX->fs_conf()->ctime_state) { - pos = db_val.find(dentry_val_delim); - attr.st_ctim.tv_sec = static_cast(stol(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_ctim.tv_sec = md.ctime(); } if (CTX->fs_conf()->uid_state) { - pos = db_val.find(dentry_val_delim); - attr.st_uid = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_uid = md.uid(); } if (CTX->fs_conf()->gid_state) { - pos = db_val.find(dentry_val_delim); - attr.st_gid = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_gid = md.gid(); } if (CTX->fs_conf()->inode_no_state) { - pos = db_val.find(dentry_val_delim); - attr.st_ino = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_ino = md.inode_no(); } if (CTX->fs_conf()->link_cnt_state) { - pos = db_val.find(dentry_val_delim); - attr.st_nlink = static_cast(stoul(db_val.substr(0, pos))); - db_val.erase(0, pos + 1); + attr.st_nlink = md.link_count(); } if (CTX->fs_conf()->blocks_state) { // last one will not encounter a delimiter anymore - attr.st_blocks = static_cast(stoul(db_val)); + attr.st_blocks = md.blocks(); } return 0; } diff --git a/ifs/src/preload/rpc/ld_rpc_metadentry.cpp b/ifs/src/preload/rpc/ld_rpc_metadentry.cpp index 492616cb3a1675d86685c72ec0ca719abf0c33ed..bacb10491296214594d179d6ed30154fa0442917 100644 --- a/ifs/src/preload/rpc/ld_rpc_metadentry.cpp +++ b/ifs/src/preload/rpc/ld_rpc_metadentry.cpp @@ -297,7 +297,7 @@ int rpc_send_rm_node(const std::string& path, const bool remove_metadentry_only) } -int rpc_send_update_metadentry(const string& path, const Metadentry& md, const MetadentryUpdateFlags& md_flags) { +int rpc_send_update_metadentry(const string& path, const Metadata& md, const MetadentryUpdateFlags& md_flags) { hg_handle_t handle; rpc_update_metadentry_in_t in{}; rpc_err_out_t out{}; @@ -305,15 +305,15 @@ int rpc_send_update_metadentry(const string& path, const Metadentry& md, const M // fill in // add data in.path = path.c_str(); - in.size = md_flags.size ? md.size : 0; - in.nlink = md_flags.link_count ? md.link_count : 0; - in.gid = md_flags.gid ? md.gid : 0; - in.uid = md_flags.uid ? md.uid : 0; - in.blocks = md_flags.blocks ? md.blocks : 0; - in.inode_no = md_flags.inode_no ? md.inode_no : 0; - in.atime = md_flags.atime ? md.atime : 0; - in.mtime = md_flags.mtime ? md.mtime : 0; - in.ctime = md_flags.ctime ? md.ctime : 0; + in.size = md_flags.size ? md.size() : 0; + in.nlink = md_flags.link_count ? md.link_count() : 0; + in.gid = md_flags.gid ? md.gid() : 0; + in.uid = md_flags.uid ? md.uid() : 0; + in.blocks = md_flags.blocks ? md.blocks() : 0; + in.inode_no = md_flags.inode_no ? md.inode_no() : 0; + in.atime = md_flags.atime ? md.atime() : 0; + in.mtime = md_flags.mtime ? md.mtime() : 0; + in.ctime = md_flags.ctime ? md.ctime() : 0; // add data flags in.size_flag = bool_to_merc_bool(md_flags.size); in.nlink_flag = bool_to_merc_bool(md_flags.link_count);