-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor mount code to not depend on slurm
- Loading branch information
Showing
11 changed files
with
200 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,125 +1,90 @@ | ||
#include "mount.hpp" | ||
#include "parse_args.hpp" | ||
#include "util/expected.hpp" | ||
#include "util/helper.hpp" | ||
#include <cstdlib> | ||
#include <string> | ||
|
||
#include <err.h> | ||
#include <fcntl.h> | ||
#include <libmount/libmount.h> | ||
#include <linux/loop.h> | ||
#include <sched.h> | ||
#include <slurm/slurm_errno.h> | ||
#include <sstream> | ||
#include <string.h> | ||
#include <string> | ||
|
||
#include <linux/loop.h> | ||
#include <sys/mount.h> | ||
#include <sys/prctl.h> | ||
#include <sys/stat.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
|
||
extern "C" { | ||
#include <slurm/spank.h> | ||
} | ||
|
||
namespace impl { | ||
#include <libmount/libmount.h> | ||
#include <slurm/slurm_errno.h> | ||
|
||
util::expected<std::string, std::string> get_realpath(const std::string &path) { | ||
char *p = realpath(path.c_str(), nullptr); | ||
if (p) { | ||
std::string ret(p); | ||
free(p); | ||
return ret; | ||
} else { | ||
char *err = strerror(errno); | ||
return util::unexpected(err); | ||
} | ||
} | ||
#include "mount.hpp" | ||
#include "parse_args.hpp" | ||
#include "util/expected.hpp" | ||
#include "util/filesystem.hpp" | ||
|
||
bool is_valid_mountpoint(const std::string &mount_point) { | ||
struct stat mnt_stat; | ||
auto mnt_status = stat(mount_point.c_str(), &mnt_stat); | ||
if (mnt_status) { | ||
slurm_spank_log("Invalid mount point \"%s\"", mount_point.c_str()); | ||
return false; | ||
} | ||
if (!S_ISDIR(mnt_stat.st_mode)) { | ||
slurm_spank_log("Invalid mount point \"%s\" is not a directory", | ||
mount_point.c_str()); | ||
return false; | ||
} | ||
return true; | ||
} | ||
namespace impl { | ||
|
||
int do_mount(spank_t spank, const std::vector<mount_entry> &mount_entries) { | ||
util::expected<std::string, std::string> | ||
do_mount(const std::vector<mount_entry> &mount_entries) { | ||
if (mount_entries.size() == 0) | ||
return ESPANK_SUCCESS; | ||
return "nothing to mount"; | ||
if (unshare(CLONE_NEWNS) != 0) { | ||
slurm_spank_log("Failed to unshare the mount namespace"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("Failed to unshare the mount namespace"); | ||
} | ||
// make all mounts in new namespace slave mounts, changes in the original | ||
// namesapce won't propagate into current namespace | ||
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) != 0) { | ||
slurm_spank_log("mount: unable to change `/` to MS_SLAVE | MS_REC"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("mount: unable to change `/` to MS_SLAVE | MS_REC"); | ||
} | ||
|
||
for (auto &entry : mount_entries) { | ||
std::string mount_point = entry.mount_point; | ||
std::string squashfs_file = entry.image_path; | ||
|
||
if (!is_file(squashfs_file) || !is_valid_mountpoint(mount_point)) { | ||
return -ESPANK_ERROR; | ||
if (!util::is_file(squashfs_file)) { | ||
return util::unexpected("the uenv squashfs file does not exist: " + | ||
squashfs_file); | ||
} | ||
if (!util::is_valid_mountpoint(mount_point)) { | ||
return util::unexpected("the mount point is not a valide path: " + | ||
mount_point); | ||
} | ||
|
||
auto cxt = mnt_new_context(); | ||
|
||
if (mnt_context_disable_mtab(cxt, 1) != 0) { | ||
slurm_spank_log("Failed to disable mtab"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("Failed to disable mtab"); | ||
} | ||
|
||
if (mnt_context_set_fstype(cxt, "squashfs") != 0) { | ||
slurm_spank_log("Failed to set fstype to squashfs"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("Failed to set fstype to squashfs"); | ||
} | ||
|
||
if (mnt_context_append_options(cxt, "loop,nosuid,nodev,ro") != 0) { | ||
slurm_spank_log("Failed to set mount options"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("Failed to set mount options"); | ||
} | ||
|
||
if (mnt_context_set_source(cxt, squashfs_file.c_str()) != 0) { | ||
slurm_spank_log("Failed to set source"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("Failed to set source"); | ||
} | ||
|
||
if (mnt_context_set_target(cxt, mount_point.c_str()) != 0) { | ||
slurm_spank_log("Failed to set target"); | ||
return -ESPANK_ERROR; | ||
return util::unexpected("Failed to set target"); | ||
} | ||
|
||
int rc = mnt_context_mount(cxt); | ||
if (rc != 0) { | ||
// https://ftp.ntu.edu.tw/pub/linux/utils/util-linux/v2.38/libmount-docs/libmount-Mount-context.html#mnt-context-mount | ||
char buf[256]; | ||
rc = mnt_context_get_excode(cxt, rc, buf, sizeof(buf)); | ||
slurm_spank_log("%s:%s", mnt_context_get_target(cxt), buf); | ||
return -ESPANK_ERROR; | ||
// https://ftp.ntu.edu.tw/pub/linux/utils/util-linux/v2.38/libmount-docs/libmount-Mount-context.html#mnt-context-mount | ||
const int rc = mnt_context_mount(cxt); | ||
const bool success = rc == 0 && mnt_context_get_status(cxt) == 1; | ||
if (!success) { | ||
char code_buf[256]; | ||
const auto x = | ||
mnt_context_get_excode(cxt, rc, code_buf, sizeof(code_buf)); | ||
const char *target_buf = mnt_context_get_target(cxt); | ||
// careful: mnt_context_get_target can return NULL | ||
std::string target = (target_buf == nullptr) ? target_buf : "?"; | ||
|
||
return util::unexpected(target + ": " + code_buf); | ||
} | ||
} | ||
|
||
// export image, mountpoints to environment (for nested calls of sbatch) | ||
std::stringstream ss; | ||
for (auto &entry : mount_entries) { | ||
auto abs_image = get_realpath(entry.image_path); | ||
auto abs_mount = get_realpath(entry.mount_point); | ||
ss << "file://" << *abs_image << ":" << *abs_mount << ","; | ||
} | ||
spank_setenv(spank, UENV_MOUNT_LIST, ss.str().c_str(), 1); | ||
|
||
return ESPANK_SUCCESS; | ||
return "succesfully mounted"; | ||
} | ||
|
||
} // namespace impl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.