From 458db6cbdb278fe2160c5e0b58bbc54c1837ef48 Mon Sep 17 00:00:00 2001 From: Daniel Trugman Date: Mon, 31 May 2021 15:19:30 +0300 Subject: [PATCH] Refactor namespace inode resolution - Allow resolution of a single namespace inode. - Use stat for resolution (instead of readlinkat) to avoid string parsing and optimize access. --- include/pfs/task.hpp | 2 ++ include/pfs/utils.hpp | 5 +++++ src/task.cpp | 18 +++++++++--------- src/utils.cpp | 13 +++++++++++++ 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/include/pfs/task.hpp b/include/pfs/task.hpp index 5e85374..8e1d5dd 100644 --- a/include/pfs/task.hpp +++ b/include/pfs/task.hpp @@ -71,6 +71,8 @@ class task final net get_net() const; + ino_t get_ns(const std::string& ns) const; + std::unordered_map get_ns() const; std::string get_root() const; diff --git a/include/pfs/utils.hpp b/include/pfs/utils.hpp index 720e582..062a23d 100644 --- a/include/pfs/utils.hpp +++ b/include/pfs/utils.hpp @@ -105,6 +105,11 @@ std::set enumerate_files(const std::string& dir, // etc. std::set enumerate_numeric_files(const std::string& dir); +// Get the inode number of the file. +// If the linkname is relative, then it is interpreted relative to the directory +// referred to by the file descriptor dirfd. +ino_t get_inode(const std::string& path, int dirfd = AT_FDCWD); + // Return the path to which the specified link points. // If the linkname is relative, then it is interpreted relative to the directory // referred to by the file descriptor dirfd. diff --git a/src/task.cpp b/src/task.cpp index bbaba3d..7ed755f 100644 --- a/src/task.cpp +++ b/src/task.cpp @@ -370,6 +370,14 @@ net task::get_net() const return net(_procfs_root); } +ino_t task::get_ns(const std::string& ns) const +{ + static const std::string NS_DIR("ns/"); + auto path = _task_root + NS_DIR + ns; + + return utils::get_inode(path); +} + std::unordered_map task::get_ns() const { static const std::string NS_DIR("ns/"); @@ -388,15 +396,7 @@ std::unordered_map task::get_ns() const for (const auto& file : utils::enumerate_files(path, /* include_dots */ false)) { - std::string link = utils::readlink(file, dirfd); - - ino_t inode; - if (std::sscanf(link.c_str(), "%*[^:]:[%" PRIuMAX "]", &inode) != 1) - { - throw parser_error("Couldn't parse ns link", link); - } - - ns.emplace(file, inode); + ns.emplace(file, utils::get_inode(file, dirfd)); } return ns; diff --git a/src/utils.cpp b/src/utils.cpp index 2d65915..19bac9f 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -100,6 +100,19 @@ std::set enumerate_numeric_files(const std::string& dir) return files; } +ino_t get_inode(const std::string& path, int dirfd) +{ + struct stat st; + int err = fstatat(dirfd, path.c_str(), &st, 0); + if (err) + { + throw std::system_error(errno, std::system_category(), + "Couldn't stat file for inode"); + } + + return st.st_ino; +} + std::string readlink(const std::string& link, int dirfd) { std::string buffer;