summaryrefslogtreecommitdiff
path: root/0005-2163-add-bind-mount-file-lock.patch
diff options
context:
space:
mode:
Diffstat (limited to '0005-2163-add-bind-mount-file-lock.patch')
-rw-r--r--0005-2163-add-bind-mount-file-lock.patch936
1 files changed, 936 insertions, 0 deletions
diff --git a/0005-2163-add-bind-mount-file-lock.patch b/0005-2163-add-bind-mount-file-lock.patch
new file mode 100644
index 0000000..78f91f1
--- /dev/null
+++ b/0005-2163-add-bind-mount-file-lock.patch
@@ -0,0 +1,936 @@
+From c1c5159675073450fe13906771cec6f666053380 Mon Sep 17 00:00:00 2001
+From: zhangxiaoyu <zhangxiaoyu58@huawei.com>
+Date: Thu, 31 Aug 2023 13:14:02 +0000
+Subject: [PATCH 05/33] !2163 add bind mount file lock * add bind mount file
+ lock
+
+---
+ src/cmd/isula/stream/cp.c | 66 ++++++-
+ src/cmd/isulad/main.c | 51 ++++++
+ src/common/constants.h | 4 +
+ .../executor/container_cb/execution_stream.c | 23 ++-
+ src/daemon/modules/image/oci/oci_export.c | 13 +-
+ src/daemon/modules/image/oci/oci_load.c | 13 +-
+ .../graphdriver/devmapper/driver_devmapper.c | 12 +-
+ .../graphdriver/overlay2/driver_overlay2.c | 12 +-
+ src/utils/tar/isulad_tar.c | 16 +-
+ src/utils/tar/isulad_tar.h | 4 +-
+ src/utils/tar/util_archive.c | 163 +++++++++++++++---
+ src/utils/tar/util_archive.h | 8 +-
+ 12 files changed, 332 insertions(+), 53 deletions(-)
+
+diff --git a/src/cmd/isula/stream/cp.c b/src/cmd/isula/stream/cp.c
+index f0cd99c9..b1e3bbd6 100644
+--- a/src/cmd/isula/stream/cp.c
++++ b/src/cmd/isula/stream/cp.c
+@@ -73,6 +73,44 @@ static void print_copy_from_container_error(const char *ops_err, const char *arc
+ }
+ }
+
++static int client_get_root_dir(const isula_connect_ops *ops, const client_connect_config_t *config, char **root_dir)
++{
++ int ret = 0;
++ struct isula_info_request request = { 0 };
++ struct isula_info_response *response = NULL;
++
++ response = util_common_calloc_s(sizeof(struct isula_info_response));
++ if (response == NULL) {
++ COMMAND_ERROR("Info: Out of memory");
++ return -1;
++ }
++
++ if (!ops->container.info) {
++ COMMAND_ERROR("Unimplemented info op");
++ ret = -1;
++ goto out;
++ }
++
++ ret = ops->container.info(&request, response, (void *)config);
++ if (ret != 0) {
++ client_print_error(response->cc, response->server_errono, response->errmsg);
++ ret = -1;
++ goto out;
++ }
++
++ if (response->isulad_root_dir == NULL) {
++ COMMAND_ERROR("None root dir");
++ ret = -1;
++ goto out;
++ }
++
++ *root_dir = util_strdup_s(response->isulad_root_dir);
++
++out:
++ isula_info_response_free(response);
++ return ret;
++}
++
+ static int client_copy_from_container(const struct client_arguments *args, const char *id, const char *srcpath,
+ const char *destpath)
+ {
+@@ -84,6 +122,7 @@ static int client_copy_from_container(const struct client_arguments *args, const
+ char *archive_err = NULL;
+ char *ops_err = NULL;
+ char *resolved = NULL;
++ char *root_dir = NULL;
+ struct archive_copy_info *srcinfo = NULL;
+ client_connect_config_t config;
+
+@@ -92,18 +131,24 @@ static int client_copy_from_container(const struct client_arguments *args, const
+ COMMAND_ERROR("Unimplemented copy from container operation");
+ return -1;
+ }
++ config = get_connect_config(args);
++
++ ret = client_get_root_dir(ops, &config, &root_dir);
++ if (ret != 0) {
++ return -1;
++ }
+
+ response = util_common_calloc_s(sizeof(struct isula_copy_from_container_response));
+ if (response == NULL) {
+ ERROR("Event: Out of memory");
+- return -1;
++ ret = -1;
++ goto out;
+ }
+
+ request.id = (char *)id;
+ request.runtime = args->runtime;
+ request.srcpath = (char *)srcpath;
+
+- config = get_connect_config(args);
+ ret = ops->container.copy_from_container(&request, response, &config);
+ if (ret) {
+ ops_err = (response->errmsg != NULL) ? util_strdup_s(response->errmsg) : NULL;
+@@ -125,7 +170,7 @@ static int client_copy_from_container(const struct client_arguments *args, const
+ srcinfo->path = util_strdup_s(srcpath);
+ srcinfo->isdir = S_ISDIR(response->stat->mode);
+
+- nret = archive_copy_to(&response->reader, srcinfo, resolved, &archive_err);
++ nret = archive_copy_to(&response->reader, srcinfo, resolved, root_dir, &archive_err);
+ if (nret != 0) {
+ ret = nret;
+ }
+@@ -137,6 +182,7 @@ static int client_copy_from_container(const struct client_arguments *args, const
+
+ out:
+ print_copy_from_container_error(ops_err, archive_err, ret, args);
++ free(root_dir);
+ free(resolved);
+ free(archive_err);
+ free(ops_err);
+@@ -167,6 +213,7 @@ static int client_copy_to_container(const struct client_arguments *args, const c
+ int nret = 0;
+ char *archive_err = NULL;
+ char *resolved = NULL;
++ char *root_dir = NULL;
+ struct archive_copy_info *srcinfo = NULL;
+ struct io_read_wrapper archive_reader = { 0 };
+ client_connect_config_t config = { 0 };
+@@ -176,11 +223,18 @@ static int client_copy_to_container(const struct client_arguments *args, const c
+ COMMAND_ERROR("Unimplemented copy to container operation");
+ return -1;
+ }
++ config = get_connect_config(args);
++
++ ret = client_get_root_dir(ops, &config, &root_dir);
++ if (ret != 0) {
++ return -1;
++ }
+
+ response = util_common_calloc_s(sizeof(struct isula_copy_to_container_response));
+ if (response == NULL) {
+ ERROR("Event: Out of memory");
+- return -1;
++ ret = -1;
++ goto out;
+ }
+
+ request.id = (char *)id;
+@@ -199,7 +253,7 @@ static int client_copy_to_container(const struct client_arguments *args, const c
+ goto out;
+ }
+
+- nret = tar_resource(srcinfo, &archive_reader, &archive_err);
++ nret = tar_resource(srcinfo, root_dir, &archive_reader, &archive_err);
+ if (nret != 0) {
+ ret = -1;
+ goto out;
+@@ -212,7 +266,6 @@ static int client_copy_to_container(const struct client_arguments *args, const c
+ request.reader.read = archive_reader.read;
+ request.reader.close = archive_reader.close;
+
+- config = get_connect_config(args);
+ ret = ops->container.copy_to_container(&request, response, &config);
+
+ // archive reader close if copy to container failed
+@@ -223,6 +276,7 @@ static int client_copy_to_container(const struct client_arguments *args, const c
+
+ out:
+ print_copy_to_container_error(response, archive_err, ret, args);
++ free(root_dir);
+ free(resolved);
+ free(archive_err);
+ free_archive_copy_info(srcinfo);
+diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c
+index 681dcf03..b32b6626 100644
+--- a/src/cmd/isulad/main.c
++++ b/src/cmd/isulad/main.c
+@@ -72,6 +72,7 @@
+ #include "utils_file.h"
+ #include "utils_string.h"
+ #include "utils_verify.h"
++#include "path.h"
+ #include "volume_api.h"
+ #ifndef DISABLE_CLEANUP
+ #include "leftover_cleanup_api.h"
+@@ -1383,6 +1384,50 @@ out:
+ return ret;
+ }
+
++static int create_mount_flock_file(const struct service_arguments *args)
++{
++ int nret = 0;
++ int fd = -1;
++ char path[PATH_MAX] = { 0 };
++ char cleanpath[PATH_MAX] = { 0 };
++
++ nret = snprintf(path, PATH_MAX, "%s/%s", args->json_confs->graph, MOUNT_FLOCK_FILE_PATH);
++ if (nret < 0 || (size_t)nret >= PATH_MAX) {
++ ERROR("Failed to snprintf");
++ return -1;
++ }
++
++ if (util_clean_path(path, cleanpath, sizeof(cleanpath)) == NULL) {
++ ERROR("clean path for %s failed", path);
++ return -1;
++ }
++
++ if (util_fileself_exists(cleanpath)) {
++ int err = 0;
++ // recreate mount flock file
++ // and make file uid/gid and permission correct
++ if (!util_force_remove_file(cleanpath, &err)) {
++ ERROR("Failed to delete %s, error: %s. Please delete %s manually.", path, strerror(err), path);
++ return -1;
++ }
++ }
++
++ fd = util_open(cleanpath, O_RDWR | O_CREAT, MOUNT_FLOCK_FILE_MODE);
++ if (fd < 0) {
++ ERROR("Failed to create file %s", cleanpath);
++ return -1;
++ }
++ close(fd);
++
++ nret = util_set_file_group(cleanpath, args->json_confs->group);
++ if (nret < 0) {
++ ERROR("set group of the path %s failed", cleanpath);
++ return -1;
++ }
++
++ return 0;
++}
++
+ static int isulad_server_init_service()
+ {
+ int ret = -1;
+@@ -1413,6 +1458,12 @@ static int isulad_server_init_service()
+ goto unlock_out;
+ }
+
++ ret = create_mount_flock_file(args);
++ if (ret != 0) {
++ ERROR("Failed to create mount flock file");
++ goto unlock_out;
++ }
++
+ unlock_out:
+ if (isulad_server_conf_unlock()) {
+ ret = -1;
+diff --git a/src/common/constants.h b/src/common/constants.h
+index 409a83a1..d93bb464 100644
+--- a/src/common/constants.h
++++ b/src/common/constants.h
+@@ -68,6 +68,8 @@ extern "C" {
+
+ #define DEFAULT_HIGHEST_DIRECTORY_MODE 0755
+
++#define MOUNT_FLOCK_FILE_MODE 0660
++
+ #define ISULAD_CONFIG SYSCONFDIR_PREFIX"/etc/isulad"
+
+ #define ISULAD_DAEMON_CONTAINER_CONTEXTS ISULAD_CONFIG "/container_contexts"
+@@ -119,6 +121,8 @@ extern "C" {
+ #define OCI_VERSION "1.0.1"
+ #endif
+
++#define MOUNT_FLOCK_FILE_PATH "isulad-chroot-mount.flock"
++
+ #define OCI_IMAGE_GRAPH_ROOTPATH_NAME "storage"
+
+ #ifdef ENABLE_GRPC_REMOTE_CONNECT
+diff --git a/src/daemon/executor/container_cb/execution_stream.c b/src/daemon/executor/container_cb/execution_stream.c
+index 32721e68..244ec6a0 100644
+--- a/src/daemon/executor/container_cb/execution_stream.c
++++ b/src/daemon/executor/container_cb/execution_stream.c
+@@ -62,6 +62,7 @@
+ #include "utils.h"
+ #include "utils_file.h"
+ #include "utils_verify.h"
++#include "isulad_config.h"
+
+ #if defined (__ANDROID__) || defined(__MUSL__)
+ #define SIG_CANCEL_SIGNAL SIGUSR1
+@@ -442,6 +443,7 @@ static int archive_and_send_copy_data(const stream_func_wrapper *stream,
+ char *absbase = NULL;
+ char *err = NULL;
+ char *buf = NULL;
++ char *root_dir = NULL;
+ char cleaned[PATH_MAX + 2] = { 0 };
+ struct io_read_wrapper reader = { 0 };
+ char *tar_path = NULL;
+@@ -474,9 +476,15 @@ static int archive_and_send_copy_data(const stream_func_wrapper *stream,
+ goto cleanup;
+ }
+
++ root_dir = conf_get_isulad_rootdir();
++ if (root_dir == NULL) {
++ ERROR("Failed to get isulad rootdir");
++ goto cleanup;
++ }
++
+ DEBUG("archive chroot tar stream container_fs(%s) srcdir(%s) relative(%s) srcbase(%s) absbase(%s)",
+ container_fs, srcdir, tar_path, srcbase, absbase);
+- nret = archive_chroot_tar_stream(container_fs, tar_path, srcbase, absbase, &reader);
++ nret = archive_chroot_tar_stream(container_fs, tar_path, srcbase, absbase, root_dir, &reader);
+ if (nret != 0) {
+ ERROR("Archive %s failed", resolvedpath);
+ goto cleanup;
+@@ -504,6 +512,7 @@ cleanup:
+ free(srcdir);
+ free(srcbase);
+ free(absbase);
++ free(root_dir);
+ if (reader.close != NULL) {
+ int cret = reader.close(reader.context, &err);
+ if (err != NULL) {
+@@ -776,15 +785,25 @@ static int read_and_extract_archive(stream_func_wrapper *stream, const char *con
+ {
+ int ret = -1;
+ char *err = NULL;
++ char *root_dir = NULL;
+ struct io_read_wrapper content = { 0 };
+ content.context = stream;
+ content.read = extract_stream_to_io_read;
+- ret = archive_chroot_untar_stream(&content, container_fs, dstdir_in_container, src_rebase, dst_rebase, &err);
++
++ root_dir = conf_get_isulad_rootdir();
++ if (root_dir == NULL) {
++ ERROR("Failed to get isulad rootdir");
++ isulad_set_error_message("Failed to get isulad rootdir");
++ return -1;
++ }
++
++ ret = archive_chroot_untar_stream(&content, container_fs, dstdir_in_container, src_rebase, dst_rebase, root_dir, &err);
+ if (ret != 0) {
+ ERROR("Can not untar to container: %s", (err != NULL) ? err : "unknown");
+ isulad_set_error_message("Can not untar to container: %s", (err != NULL) ? err : "unknown");
+ }
+ free(err);
++ free(root_dir);
+ return ret;
+ }
+
+diff --git a/src/daemon/modules/image/oci/oci_export.c b/src/daemon/modules/image/oci/oci_export.c
+index e27ed6d8..6bfcf4d5 100644
+--- a/src/daemon/modules/image/oci/oci_export.c
++++ b/src/daemon/modules/image/oci/oci_export.c
+@@ -23,6 +23,7 @@
+ #include "util_archive.h"
+ #include "path.h"
+ #include "utils_file.h"
++#include "isulad_config.h"
+
+ int oci_do_export(char *id, char *file)
+ {
+@@ -30,6 +31,7 @@ int oci_do_export(char *id, char *file)
+ int ret2 = 0;
+ char *mount_point = NULL;
+ char *errmsg = NULL;
++ char *root_dir = NULL;
+ char cleanpath[PATH_MAX] = { 0 };
+
+ if (id == NULL || file == NULL) {
+@@ -56,7 +58,15 @@ int oci_do_export(char *id, char *file)
+ return -1;
+ }
+
+- ret = archive_chroot_tar(mount_point, cleanpath, &errmsg);
++ root_dir = conf_get_isulad_rootdir();
++ if (root_dir == NULL) {
++ ERROR("Failed to get isulad rootdir");
++ isulad_set_error_message("Failed to get isulad rootdir");
++ ret = -1;
++ goto out;
++ }
++
++ ret = archive_chroot_tar(mount_point, cleanpath, root_dir, &errmsg);
+ if (ret != 0) {
+ ERROR("failed to export container %s to file %s: %s", id, cleanpath, errmsg);
+ isulad_set_error_message("Failed to export rootfs with error: %s", errmsg);
+@@ -68,6 +78,7 @@ out:
+ mount_point = NULL;
+ free(errmsg);
+ errmsg = NULL;
++ free(root_dir);
+
+ ret2 = storage_rootfs_umount(id, false);
+ if (ret2 != 0) {
+diff --git a/src/daemon/modules/image/oci/oci_load.c b/src/daemon/modules/image/oci/oci_load.c
+index 04a9f947..4385e55e 100644
+--- a/src/daemon/modules/image/oci/oci_load.c
++++ b/src/daemon/modules/image/oci/oci_load.c
+@@ -41,6 +41,7 @@
+ #include "utils_file.h"
+ #include "utils_verify.h"
+ #include "oci_image.h"
++#include "isulad_config.h"
+
+ #define MANIFEST_BIG_DATA_KEY "manifest"
+ #define OCI_SCHEMA_VERSION 2
+@@ -1068,6 +1069,7 @@ int oci_do_load(const im_load_request *request)
+ char *digest = NULL;
+ char *dstdir = NULL;
+ char *err = NULL;
++ char *root_dir = NULL;
+
+ if (request == NULL || request->file == NULL) {
+ ERROR("Invalid input arguments, cannot load image");
+@@ -1088,8 +1090,16 @@ int oci_do_load(const im_load_request *request)
+ goto out;
+ }
+
++ root_dir = conf_get_isulad_rootdir();
++ if (root_dir == NULL) {
++ ERROR("Failed to get isulad rootdir");
++ isulad_try_set_error_message("Failed to get isulad rootdir");
++ ret = -1;
++ goto out;
++ }
++
+ options.whiteout_format = NONE_WHITEOUT_FORMATE;
+- if (archive_unpack(&reader, dstdir, &options, &err) != 0) {
++ if (archive_unpack(&reader, dstdir, &options, root_dir, &err) != 0) {
+ ERROR("Failed to unpack to %s: %s", dstdir, err);
+ isulad_try_set_error_message("Failed to unpack to %s: %s", dstdir, err);
+ ret = -1;
+@@ -1175,5 +1185,6 @@ out:
+ }
+ free(dstdir);
+ free(err);
++ free(root_dir);
+ return ret;
+ }
+diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c
+index 998ea8c2..ecb62f79 100644
+--- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c
++++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c
+@@ -32,6 +32,7 @@
+ #include "utils_file.h"
+ #include "utils_fs.h"
+ #include "utils_string.h"
++#include "isulad_config.h"
+
+ struct io_read_wrapper;
+
+@@ -346,6 +347,7 @@ int devmapper_apply_diff(const char *id, const struct graphdriver *driver, const
+ int ret = 0;
+ struct archive_options options = { 0 };
+ char *err = NULL;
++ char *root_dir = NULL;
+
+ if (!util_valid_str(id) || driver == NULL || content == NULL) {
+ ERROR("invalid argument to apply diff with id(%s)", id);
+@@ -366,8 +368,15 @@ int devmapper_apply_diff(const char *id, const struct graphdriver *driver, const
+ goto out;
+ }
+
++ root_dir = conf_get_isulad_rootdir();
++ if (root_dir == NULL) {
++ ERROR("Failed to get isulad rootdir");
++ ret = -1;
++ goto umount_out;
++ }
++
+ options.whiteout_format = REMOVE_WHITEOUT_FORMATE;
+- if (archive_unpack(content, layer_fs, &options, &err) != 0) {
++ if (archive_unpack(content, layer_fs, &options, root_dir, &err) != 0) {
+ ERROR("devmapper: failed to unpack to %s: %s", layer_fs, err);
+ ret = -1;
+ goto umount_out;
+@@ -384,6 +393,7 @@ out:
+ free_driver_mount_opts(mount_opts);
+ free(layer_fs);
+ free(err);
++ free(root_dir);
+ return ret;
+ }
+
+diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c
+index c5864c90..b177f594 100644
+--- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c
++++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c
+@@ -45,6 +45,7 @@
+ #include "utils_timestamp.h"
+ #include "selinux_label.h"
+ #include "err_msg.h"
++#include "isulad_config.h"
+ #ifdef ENABLE_REMOTE_LAYER_STORE
+ #include "ro_symlink_maintain.h"
+ #endif
+@@ -1886,6 +1887,7 @@ int overlay2_apply_diff(const char *id, const struct graphdriver *driver, const
+ char *layer_diff = NULL;
+ struct archive_options options = { 0 };
+ char *err = NULL;
++ char *root_dir = NULL;
+
+ if (id == NULL || driver == NULL || content == NULL) {
+ ERROR("invalid argument");
+@@ -1919,7 +1921,14 @@ int overlay2_apply_diff(const char *id, const struct graphdriver *driver, const
+ }
+ #endif
+
+- ret = archive_unpack(content, layer_diff, &options, &err);
++ root_dir = conf_get_isulad_rootdir();
++ if (root_dir == NULL) {
++ ERROR("Failed to get isulad rootdir");
++ ret = -1;
++ goto out;
++ }
++
++ ret = archive_unpack(content, layer_diff, &options, root_dir ,&err);
+ if (ret != 0) {
+ ERROR("Failed to unpack to %s: %s", layer_diff, err);
+ ret = -1;
+@@ -1928,6 +1937,7 @@ int overlay2_apply_diff(const char *id, const struct graphdriver *driver, const
+
+ out:
+ free(err);
++ free(root_dir);
+ free(layer_dir);
+ free(layer_diff);
+ #ifdef ENABLE_USERNS_REMAP
+diff --git a/src/utils/tar/isulad_tar.c b/src/utils/tar/isulad_tar.c
+index 74176b12..24269c70 100644
+--- a/src/utils/tar/isulad_tar.c
++++ b/src/utils/tar/isulad_tar.c
+@@ -385,7 +385,7 @@ cleanup:
+ }
+
+ int archive_copy_to(const struct io_read_wrapper *content, const struct archive_copy_info *srcinfo,
+- const char *dstpath, char **err)
++ const char *dstpath, const char *root_dir, char **err)
+ {
+ int ret = -1;
+ struct archive_copy_info *dstinfo = NULL;
+@@ -393,7 +393,7 @@ int archive_copy_to(const struct io_read_wrapper *content, const struct archive_
+ char *src_base = NULL;
+ char *dst_base = NULL;
+
+- if (err == NULL || dstpath == NULL || srcinfo == NULL || content == NULL) {
++ if (err == NULL || dstpath == NULL || srcinfo == NULL || content == NULL || root_dir == NULL) {
+ return -1;
+ }
+
+@@ -409,7 +409,7 @@ int archive_copy_to(const struct io_read_wrapper *content, const struct archive_
+ goto cleanup;
+ }
+
+- ret = archive_chroot_untar_stream(content, dstdir, ".", src_base, dst_base, err);
++ ret = archive_chroot_untar_stream(content, dstdir, ".", src_base, dst_base, root_dir, err);
+
+ cleanup:
+ free_archive_copy_info(dstinfo);
+@@ -419,7 +419,7 @@ cleanup:
+ return ret;
+ }
+
+-static int tar_resource_rebase(const char *path, const char *rebase, struct io_read_wrapper *archive_reader, char **err)
++static int tar_resource_rebase(const char *path, const char *rebase, const char *root_dir, struct io_read_wrapper *archive_reader, char **err)
+ {
+ int ret = -1;
+ int nret;
+@@ -438,7 +438,7 @@ static int tar_resource_rebase(const char *path, const char *rebase, struct io_r
+ }
+
+ DEBUG("chroot tar stream srcdir(%s) srcbase(%s) rebase(%s)", srcdir, srcbase, rebase);
+- nret = archive_chroot_tar_stream(srcdir, srcbase, srcbase, rebase, archive_reader);
++ nret = archive_chroot_tar_stream(srcdir, srcbase, srcbase, rebase, root_dir, archive_reader);
+ if (nret < 0) {
+ ERROR("Can not archive path: %s", path);
+ goto cleanup;
+@@ -450,11 +450,11 @@ cleanup:
+ return ret;
+ }
+
+-int tar_resource(const struct archive_copy_info *info, struct io_read_wrapper *archive_reader, char **err)
++int tar_resource(const struct archive_copy_info *info, const char *root_dir, struct io_read_wrapper *archive_reader, char **err)
+ {
+- if (info == NULL || archive_reader == NULL || err == NULL) {
++ if (info == NULL || root_dir == NULL || archive_reader == NULL || err == NULL) {
+ return -1;
+ }
+
+- return tar_resource_rebase(info->path, info->rebase_name, archive_reader, err);
++ return tar_resource_rebase(info->path, info->rebase_name, root_dir, archive_reader, err);
+ }
+diff --git a/src/utils/tar/isulad_tar.h b/src/utils/tar/isulad_tar.h
+index cdd9858a..414bb024 100644
+--- a/src/utils/tar/isulad_tar.h
++++ b/src/utils/tar/isulad_tar.h
+@@ -43,10 +43,10 @@ struct archive_copy_info *copy_info_source_path(const char *path, bool follow_li
+ char *prepare_archive_copy(const struct archive_copy_info *srcinfo, const struct archive_copy_info *dstinfo,
+ char **src_base, char **dst_base, char **err);
+
+-int tar_resource(const struct archive_copy_info *info, struct io_read_wrapper *archive_reader, char **err);
++int tar_resource(const struct archive_copy_info *info, const char *root_dir, struct io_read_wrapper *archive_reader, char **err);
+
+ int archive_copy_to(const struct io_read_wrapper *content, const struct archive_copy_info *srcinfo,
+- const char *dstpath, char **err);
++ const char *dstpath, const char *root_dir, char **err);
+
+ #ifdef __cplusplus
+ }
+diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c
+index 0fb7769b..d2fc5488 100644
+--- a/src/utils/tar/util_archive.c
++++ b/src/utils/tar/util_archive.c
+@@ -33,10 +33,12 @@
+ #include <netdb.h>
+ #include <sys/mount.h>
+ #include <sys/capability.h>
++#include <sys/file.h>
+
+ #include <isula_libutils/log.h>
+ #include <isula_libutils/go_crc64.h>
+ #include <isula_libutils/storage_entry.h>
++#include <isula_libutils/auto_cleanup.h>
+
+ #include "error.h"
+ #include "map.h"
+@@ -83,6 +85,31 @@ static ssize_t read_content(struct archive *a, void *client_data, const void **b
+ return mydata->content->read(mydata->content->context, mydata->buff, sizeof(mydata->buff));
+ }
+
++static char *generate_flock_path(const char *root_dir)
++{
++ int nret = 0;
++ char path[PATH_MAX] = { 0 };
++ char cleanpath[PATH_MAX] = { 0 };
++
++ nret = snprintf(path, PATH_MAX, "%s/%s", root_dir, MOUNT_FLOCK_FILE_PATH);
++ if (nret < 0 || (size_t)nret >= PATH_MAX) {
++ ERROR("Failed to snprintf");
++ return NULL;
++ }
++
++ if (util_clean_path(path, cleanpath, sizeof(cleanpath)) == NULL) {
++ ERROR("clean path for %s failed", path);
++ return NULL;
++ }
++
++ if (!util_file_exists(cleanpath)) {
++ ERROR("flock file %s doesn't exist", cleanpath);
++ return NULL;
++ }
++
++ return util_strdup_s(cleanpath);
++}
++
+ static void do_disable_unneccessary_caps()
+ {
+ cap_t caps;
+@@ -104,7 +131,58 @@ static void do_disable_unneccessary_caps()
+ cap_free(caps);
+ }
+
+-static int make_safedir_is_noexec(const char *dstdir, char **safe_dir)
++// Add flock when bind mount and make it private.
++// Because bind mount usually makes safedir shared mount point,
++// and sometimes it will cause "mount point explosion".
++// E.g. concurrently execute isula cp /tmp/<XXX-File> <CONTAINER-ID>:<CONTAINER-PAT>
++static int bind_mount_with_flock(const char *flock_path, const char *dstdir, const char *tmp_dir)
++{
++ __isula_auto_close int fd = -1;
++ int ret = -1;
++
++ fd = open(flock_path, O_RDWR | O_CLOEXEC);
++ if (fd < 0) {
++ SYSERROR("Failed to open file %s", flock_path);
++ return -1;
++ }
++
++ if (flock(fd, LOCK_EX) != 0) {
++ SYSERROR("Failed to lock file %s", flock_path);
++ return -1;
++ }
++
++ if (mount(dstdir, tmp_dir, "none", MS_BIND, NULL) != 0) {
++ SYSERROR("Mount safe dir failed");
++ goto unlock_out;
++ }
++
++ if (mount(tmp_dir, tmp_dir, "none", MS_BIND | MS_REMOUNT | MS_NOEXEC, NULL) != 0) {
++ SYSERROR("Mount safe dir failed");
++ if (umount(tmp_dir) != 0) {
++ SYSERROR("Failed to umount target %s", tmp_dir);
++ }
++ goto unlock_out;
++ }
++
++ // Change the propagation type.
++ if (mount("", tmp_dir, "", MS_PRIVATE, "") != 0) {
++ SYSERROR("Failed to change the propagation type");
++ if (umount(tmp_dir) != 0) {
++ SYSERROR("Failed to umount target %s", tmp_dir);
++ }
++ goto unlock_out;
++ }
++
++ ret = 0;
++
++unlock_out:
++ if (flock(fd, LOCK_UN) != 0) {
++ SYSERROR("Failed to unlock file %s", flock_path);
++ }
++ return ret;
++}
++
++static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, char **safe_dir)
+ {
+ struct stat buf;
+ char *isulad_tmpdir_env = NULL;
+@@ -156,19 +234,8 @@ static int make_safedir_is_noexec(const char *dstdir, char **safe_dir)
+ return -1;
+ }
+
+- if (mount(dstdir, tmp_dir, "none", MS_BIND, NULL) != 0) {
+- SYSERROR("Mount safe dir failed");
+- if (util_path_remove(tmp_dir) != 0) {
+- ERROR("Failed to remove path %s", tmp_dir);
+- }
+- return -1;
+- }
+-
+- if (mount(tmp_dir, tmp_dir, "none", MS_BIND | MS_REMOUNT | MS_NOEXEC, NULL) != 0) {
+- SYSERROR("Mount safe dir failed");
+- if (umount(tmp_dir) != 0) {
+- ERROR("Failed to umount target %s", tmp_dir);
+- }
++ if (bind_mount_with_flock(flock_path, dstdir, tmp_dir) != 0) {
++ ERROR("Failed to bind mount from %s to %s with flock", dstdir, tmp_dir);
+ if (util_path_remove(tmp_dir) != 0) {
+ ERROR("Failed to remove path %s", tmp_dir);
+ }
+@@ -723,7 +790,7 @@ static void set_child_process_pdeathsig(void)
+ }
+
+ int archive_unpack(const struct io_read_wrapper *content, const char *dstdir, const struct archive_options *options,
+- char **errmsg)
++ const char *root_dir, char **errmsg)
+ {
+ int ret = 0;
+ pid_t pid = -1;
+@@ -731,12 +798,24 @@ int archive_unpack(const struct io_read_wrapper *content, const char *dstdir, co
+ int pipe_stderr[2] = { -1, -1 };
+ char errbuf[BUFSIZ + 1] = { 0 };
+ char *safe_dir = NULL;
++ char *flock_path = NULL;
+
+- if (make_safedir_is_noexec(dstdir, &safe_dir) != 0) {
+- ERROR("Prepare safe dir failed");
++ if (content == NULL || dstdir == NULL || options == NULL || root_dir == NULL) {
+ return -1;
+ }
+
++ flock_path = generate_flock_path(root_dir);
++ if (flock_path == NULL) {
++ ERROR("Failed to generate flock path");
++ return -1;
++ }
++
++ if (make_safedir_is_noexec(flock_path, dstdir, &safe_dir) != 0) {
++ ERROR("Prepare safe dir failed");
++ ret = -1;
++ goto cleanup;
++ }
++
+ if (pipe2(pipe_stderr, O_CLOEXEC) != 0) {
+ ERROR("Failed to create pipe");
+ ret = -1;
+@@ -816,6 +895,7 @@ cleanup:
+ ERROR("Failed to remove path %s", safe_dir);
+ }
+ free(safe_dir);
++ free(flock_path);
+ return ret;
+ }
+
+@@ -1126,7 +1206,7 @@ static ssize_t fd_write(void *context, const void *data, size_t len)
+ return util_write_nointr(*(int *)context, data, len);
+ }
+
+-int archive_chroot_tar(char *path, char *file, char **errmsg)
++int archive_chroot_tar(const char *path, const char *file, const char *root_dir, char **errmsg)
+ {
+ struct io_write_wrapper pipe_context = { 0 };
+ int ret = 0;
+@@ -1136,12 +1216,24 @@ int archive_chroot_tar(char *path, char *file, char **errmsg)
+ char errbuf[BUFSIZ + 1] = { 0 };
+ int fd = 0;
+ char *safe_dir = NULL;
++ char *flock_path = NULL;
+
+- if (make_safedir_is_noexec(path, &safe_dir) != 0) {
+- ERROR("Prepare safe dir failed");
++ if (path == NULL || file == NULL || root_dir == NULL) {
++ return -1;
++ }
++
++ flock_path = generate_flock_path(root_dir);
++ if (flock_path == NULL) {
++ ERROR("Failed to generate flock path");
+ return -1;
+ }
+
++ if (make_safedir_is_noexec(flock_path, path, &safe_dir) != 0) {
++ ERROR("Prepare safe dir failed");
++ ret = -1;
++ goto cleanup;
++ }
++
+ if (pipe2(pipe_for_read, O_CLOEXEC) != 0) {
+ ERROR("Failed to create pipe");
+ ret = -1;
+@@ -1232,6 +1324,7 @@ cleanup:
+ ERROR("Failed to remove path %s", safe_dir);
+ }
+ free(safe_dir);
++ free(flock_path);
+ return ret;
+ }
+
+@@ -1352,7 +1445,7 @@ static int archive_context_close(void *context, char **err)
+ }
+
+ int archive_chroot_untar_stream(const struct io_read_wrapper *context, const char *chroot_dir, const char *untar_dir,
+- const char *src_base, const char *dst_base, char **errmsg)
++ const char *src_base, const char *dst_base, const char *root_dir, char **errmsg)
+ {
+ struct io_read_wrapper pipe_context = { 0 };
+ int pipe_stream[2] = { -1, -1 };
+@@ -1370,12 +1463,19 @@ int archive_chroot_untar_stream(const struct io_read_wrapper *context, const cha
+ .dst_base = dst_base
+ };
+ char *safe_dir = NULL;
++ char *flock_path = NULL;
+
+- if (make_safedir_is_noexec(chroot_dir, &safe_dir) != 0) {
+- ERROR("Prepare safe dir failed");
++ flock_path = generate_flock_path(root_dir);
++ if (flock_path == NULL) {
++ ERROR("Failed to generate flock path");
+ return -1;
+ }
+
++ if (make_safedir_is_noexec(flock_path, chroot_dir, &safe_dir) != 0) {
++ ERROR("Prepare safe dir failed");
++ goto cleanup;
++ }
++
+ if (pipe(pipe_stderr) != 0) {
+ ERROR("Failed to create pipe: %s", strerror(errno));
+ goto cleanup;
+@@ -1483,12 +1583,13 @@ cleanup:
+ ERROR("Failed to remove path %s", safe_dir);
+ }
+ free(safe_dir);
++ free(flock_path);
+
+ return ret;
+ }
+
+ int archive_chroot_tar_stream(const char *chroot_dir, const char *tar_path, const char *src_base, const char *dst_base,
+- struct io_read_wrapper *reader)
++ const char *root_dir, struct io_read_wrapper *reader)
+ {
+ struct io_write_wrapper pipe_context = { 0 };
+ int keepfds[] = { -1, -1, -1 };
+@@ -1498,12 +1599,19 @@ int archive_chroot_tar_stream(const char *chroot_dir, const char *tar_path, cons
+ pid_t pid;
+ struct archive_context *ctx = NULL;
+ char *safe_dir = NULL;
++ char *flock_path = NULL;
+
+- if (make_safedir_is_noexec(chroot_dir, &safe_dir) != 0) {
+- ERROR("Prepare safe dir failed");
++ flock_path = generate_flock_path(root_dir);
++ if (flock_path == NULL) {
++ ERROR("Failed to generate flock path");
+ return -1;
+ }
+
++ if (make_safedir_is_noexec(flock_path, chroot_dir, &safe_dir) != 0) {
++ ERROR("Prepare safe dir failed");
++ goto free_out;
++ }
++
+ if (pipe(pipe_stderr) != 0) {
+ ERROR("Failed to create pipe: %s", strerror(errno));
+ goto free_out;
+@@ -1607,6 +1715,7 @@ free_out:
+ close_archive_pipes_fd(pipe_stderr, 2);
+ close_archive_pipes_fd(pipe_stream, 2);
+ free(ctx);
++ free(flock_path);
+ if (safe_dir != NULL) {
+ if (umount(safe_dir) != 0) {
+ ERROR("Failed to umount target %s", safe_dir);
+@@ -1848,4 +1957,4 @@ int archive_copy_oci_tar_split_and_ret_size(int src_fd, const char *dist_file, i
+ }
+
+ return foreach_archive_entry(archive_entry_parse, src_fd, dist_file, ret_size);
+-}
+\ No newline at end of file
++}
+diff --git a/src/utils/tar/util_archive.h b/src/utils/tar/util_archive.h
+index 5cc2c5ec..8f0ab2a4 100644
+--- a/src/utils/tar/util_archive.h
++++ b/src/utils/tar/util_archive.h
+@@ -45,17 +45,17 @@ struct archive_options {
+ };
+
+ int archive_unpack(const struct io_read_wrapper *content, const char *dstdir, const struct archive_options *options,
+- char **errmsg);
++ const char *root_dir, char **errmsg);
+
+ bool valid_archive_format(const char *file);
+
+-int archive_chroot_tar(char *path, char *file, char **errmsg);
++int archive_chroot_tar(const char *path, const char *file, const char *root_dir, char **errmsg);
+
+ int archive_chroot_tar_stream(const char *chroot_dir, const char *tar_path, const char *src_base,
+- const char *dst_base, struct io_read_wrapper *content);
++ const char *dst_base, const char *root_dir, struct io_read_wrapper *content);
+ int archive_chroot_untar_stream(const struct io_read_wrapper *content, const char *chroot_dir,
+ const char *untar_dir, const char *src_base, const char *dst_base,
+- char **errmsg);
++ const char *root_dir, char **errmsg);
+
+ int archive_copy_oci_tar_split_and_ret_size(int src_fd, const char *dist_file, int64_t *ret_size);
+
+--
+2.40.1
+