From 58fb5fafbee8b03173c60ee48f9cb569b579e89e Mon Sep 17 00:00:00 2001 From: gaohuatao Date: Thu, 16 Apr 2020 05:33:35 -0400 Subject: [PATCH] devmapper: add devmapper_mount_layer func Signed-off-by: gaohuatao --- .../graphdriver/devmapper/deviceset.c | 163 ++++++++++++++++++ .../graphdriver/devmapper/deviceset.h | 3 +- .../graphdriver/devmapper/driver_devmapper.c | 92 +++++++++- 3 files changed, 256 insertions(+), 2 deletions(-) diff --git a/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c b/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c index 1262ab4..ffdb86c 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c @@ -31,6 +31,7 @@ #include "devices_constants.h" #include "device_setup.h" #include "libdevmapper.h" +#include "driver.h" #define DM_LOG_FATAL 2 #define DM_LOG_DEBUG 7 @@ -281,6 +282,23 @@ static char *get_dev_name(const char *name) return util_string_append(name, DEVMAPPER_DECICE_DIRECTORY); } +char *dev_name(struct device_set *devset, image_devmapper_device_info *info) +{ + char *res_str = NULL; + char *dm_name = NULL; + + dm_name = get_dm_name(devset, info->hash); + if (dm_name == NULL) { + goto out; + } + + res_str = get_dev_name(dm_name); + +out: + free(dm_name); + return res_str; +} + // thin-pool or isulad-thinpool static char *get_pool_name(struct device_set *devset) { @@ -2414,4 +2432,149 @@ free_out: free_image_devmapper_device_info(base_info); free_image_devmapper_device_info(info); return ret; +} + +// moptions->options_len > 0 +static char *generate_mount_options(const struct driver_mount_opts *moptions, const char *dev_options) +{ + char *res_str = NULL; + char *options = NULL; + bool add_nouuid = false; + + options = util_strdup_s(dev_options); + if (moptions != NULL && moptions->options_len > 0) { + add_nouuid = !util_valid_str(options) || strings_contains_word("nouuid", options); + free(options); + options = util_string_join(",", (const char **)moptions->options, moptions->options_len); + if (add_nouuid) { + res_str = util_strdup_s("nouuid"); + } + } + + append_mount_options(&res_str, options); + + free(options); + return res_str; +} + +int mount_device(const char *hash, const char *path, const struct driver_mount_opts *mount_opts) +{ + int ret = 0; + image_devmapper_device_info *info = NULL; + struct device_set *devset = NULL; + char *dev_fname = NULL; + char *options = NULL; + + if (hash == NULL || path == NULL || mount_opts == NULL) { + ERROR("devmapper: failed to mount device"); + return -1; + } + + if (devmapper_conf_wrlock()) { + ERROR("lock devmapper conf failed"); + return -1; + } + + devset = devmapper_driver_devices_get(); + if (devset == NULL) { + goto free_out; + } + + info = lookup_device(devset, hash); + if (info == NULL) { + ERROR("devmapper: lookup device %s failed", info); + ret = -1; + goto free_out; + } + + if (info->deleted) { + ret = -1; + ERROR("devmapper: Base device %s has been marked for deferred deletion", info->hash); + goto free_out; + } + dev_fname = dev_name(devset, info); + if (dev_fname) { + ERROR("devmapper: failed to get device full name"); + goto free_out; + } + + ret = activate_device_if_needed(devset, info, false); + if (ret != 0) { + ERROR("devmapper: Error activating devmapper device for %s", hash); + goto free_out; + } + + options = generate_mount_options(mount_opts, devset->mount_options); + + ret = util_mount(dev_fname, path, "ext4", options); + if (ret != 0) { + ERROR("devmapper: Error mounting %s on %s", dev_fname, path); + goto free_out; + } + +free_out: + if (devmapper_conf_unlock()) { + ERROR("unlock devmapper conf failed"); + ret = -1; + } + free_image_devmapper_device_info(info); + free(dev_fname); + free(options); + return ret; +} + +// UnmountDevice unmounts the device and removes it from hash. +int unmount_device(const char *hash, const char *mount_path) +{ + int ret = 0; + image_devmapper_device_info *info = NULL; + struct device_set *devset = NULL; + + if (hash == NULL || mount_path == NULL) { + ERROR("devmapper: failed to unmount device"); + return -1; + } + + if (devmapper_conf_wrlock()) { + ERROR("lock devmapper conf failed"); + return -1; + } + + devset = devmapper_driver_devices_get(); + if (devset == NULL) { + goto free_out; + } + + info = lookup_device(devset, hash); + if (info == NULL) { + ERROR("devmapper: lookup device %s failed", info); + ret = -1; + goto free_out; + } + + if (util_detect_mounted(mount_path)) { + ret = umount2(mount_path, MNT_DETACH); + if (ret < 0 && errno != EINVAL) { + WARN("Failed to umount directory %s:%s", mount_path, strerror(errno)); + goto free_out; + } + } + + ret = util_path_remove(mount_path); + if (ret != 0) { + DEBUG("devmapper: doing remove on a unmounted device %s failed", mount_path); + } + + ret = deactivate_device(devset, info); + if (ret != 0) { + ERROR("devmapper: Error deactivating device"); + } + +free_out: + if (devmapper_conf_unlock()) { + ERROR("unlock devmapper conf failed"); + ret = -1; + } + free_image_devmapper_device_info(info); + return ret; } \ No newline at end of file diff --git a/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h b/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h index ad1a9e5..89719f5 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h @@ -78,7 +78,8 @@ int devmapper_conf_unlock(); struct device_set *devmapper_driver_devices_get(); int add_device(const char *hash, const char *base_hash, const json_map_string_string *storage_opts); - +int mount_device(const char *hash, const char *path, const struct driver_mount_opts *mount_opts); +int unmount_device(const char *hash, const char *mount_path); #ifdef __cplusplus } diff --git a/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c b/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c index d8ea748..1865f13 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c @@ -43,6 +43,7 @@ int do_create(const char *id, const char *parent, const struct driver_create_opt return add_device(id, parent, create_opts->storage_opt); } +// devmapper_create_rw creates a layer that is writable for use as a container file system int devmapper_create_rw(const char *id, const char *parent, const struct graphdriver *driver, const struct driver_create_opts *create_opts) { @@ -64,10 +65,99 @@ int devmapper_rm_layer(const char *id, const struct graphdriver *driver) return 0; } +static int write_file(const char *fpath, const char *buf) +{ + int fd = 0; + ssize_t nwrite; + + if (fpath == NULL || buf == NULL) { + return 0; + } + + fd = util_open(fpath, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0600); + if (fd < 0) { + ERROR("Failed to open file: %s: %s", fpath, strerror(errno)); + return -1; + } + nwrite = util_write_nointr(fd, buf, strlen(buf)); + if (nwrite < 0) { + ERROR("Failed to write %s to %s: %s", buf, fpath, strerror(errno)); + close(fd); + return -1; + } + close(fd); + + return 0; +} + +// devmapper_mount_layer mounts a device with given id into the root filesystem char *devmapper_mount_layer(const char *id, const struct graphdriver *driver, const struct driver_mount_opts *mount_opts) { - return NULL; + char *mnt_point_dir = NULL; + char *mnt_parent_dir = NULL; + char *rootfs = NULL; + char *id_file = NULL; + int ret = 0; + + if (id == NULL || driver == NULL || mount_opts == NULL) { + return NULL; + } + + mnt_parent_dir = util_path_join(driver->home, "mnt"); + if (mnt_parent_dir == NULL) { + ERROR("Failed to join devmapper mnt dir%s", id); + goto out; + } + + mnt_point_dir = util_path_join(mnt_parent_dir, id); + if (mnt_point_dir == NULL) { + ERROR("Failed to join devampper mount point dir:%s", id); + goto out; + } + + DEBUG("devmapper: start to mount container device"); + ret = mount_device(id, mnt_point_dir, mount_opts); + if (ret != 0) { + goto out; + } + + rootfs = util_path_join(mnt_point_dir, "rootfs"); + if (rootfs == NULL) { + ERROR("Failed to join devmapper rootfs %s", mnt_point_dir); + goto out; + } + + if (util_mkdir_p(rootfs, 0755) != 0 || !util_dir_exists(rootfs)) { + ERROR("Unable to create devmapper rootfs directory %s.", rootfs); + ret = -1; + if (unmount_device(id, mnt_point_dir) != 0) { + DEBUG("devmapper: unmount %s failed", mnt_point_dir); + } + goto out; + } + + id_file = util_path_join(mnt_point_dir, "id"); + if (!util_file_exists(id_file)) { + // Create an "id" file with the container/image id in it to help reconstruct this in case + // of later problems + ret = write_file(id_file, id); + if (ret != 0) { + if (unmount_device(id, mnt_point_dir) != 0) { + DEBUG("devmapper: unmount %s failed", mnt_point_dir); + } + } + } + +out: + free(mnt_parent_dir); + free(mnt_point_dir); + free(id_file); + if (ret != 0) { + free(rootfs); + rootfs = NULL; + } + return rootfs; } int devmapper_umount_layer(const char *id, const struct graphdriver *driver) -- GitLab