From 9b41a8d28d3ffbe33eb84d8e254b603012b22b34 Mon Sep 17 00:00:00 2001 From: DriedYellowPeach Date: Sun, 11 Dec 2022 11:12:55 +0000 Subject: [PATCH 60/65] !1761 fix leftover devicemapper mnt dir * fix leftover devicemapper mnt dir --- .../graphdriver/devmapper/deviceset.c | 37 +++++++++++++ .../graphdriver/devmapper/deviceset.h | 2 + .../graphdriver/devmapper/driver_devmapper.c | 55 ++++++++++++------- .../oci/storage/layer_store/layer_store.c | 11 +++- 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c index 4dadc336..b157510a 100644 --- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c +++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c @@ -486,6 +486,43 @@ out: return exist; } +// return true if find the metadata +// or the argument is wrong +// or can't decide +bool has_metadata(const char *hash, struct device_set *devset) +{ + char metadata_file[PATH_MAX] = { 0 }; + char *metadata_path = NULL; + bool ret = true; + int nret = 0; + + if (hash == NULL) { + return true; + } + + metadata_path = metadata_dir(devset); + if (metadata_path == NULL) { + ERROR("Failed to get meta data directory"); + goto out; + } + + nret = snprintf(metadata_file, sizeof(metadata_file), "%s/%s", metadata_path, util_valid_str(hash) ? hash : "base"); + if (nret < 0 || (size_t)nret >= sizeof(metadata_file)) { + ERROR("Failed to snprintf metadata file path with hash:%s, path is too long", hash); + goto out; + } + + if (!util_file_exists(metadata_file)) { + WARN("No such file:%s, need not to load", metadata_file); + ret = false; + goto out; + } + +out: + free(metadata_path); + return ret; +} + static image_devmapper_device_info *load_metadata(const struct device_set *devset, const char *hash) { image_devmapper_device_info *info = NULL; diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h index c11eece6..ec985e40 100644 --- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h +++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h @@ -83,6 +83,8 @@ int delete_device(const char *hash, bool sync_delete, struct device_set *devset) int export_device_metadata(struct device_metadata *dev_metadata, const char *hash, struct device_set *devset); +bool has_metadata(const char *hash, struct device_set *devset); + struct status *device_set_status(struct device_set *devset); void free_devmapper_status(struct status *st); 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 dd231bd6..c83d3e54 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 @@ -144,28 +144,11 @@ int devmapper_create_ro(const char *id, const char *parent, const struct graphdr return do_create(id, parent, driver, create_opts); } -// Remove removes a device with a given id, unmounts the filesystem. -int devmapper_rm_layer(const char *id, const struct graphdriver *driver) +static int devmapper_try_rm_layer_mnt(const char *id, const struct graphdriver *driver) { + int ret = 0; char *mnt_parent_dir = NULL; char *mnt_point_dir = NULL; - int ret = 0; - - if (!util_valid_str(id) || driver == NULL) { - ERROR("invalid argument"); - return -1; - } - - if (!has_device(id, driver->devset)) { - DEBUG("Device with id:%s is not exist", id); - goto out; - } - - if (delete_device(id, false, driver->devset) != 0) { - ERROR("failed to remove device %s", id); - ret = -1; - goto out; - } mnt_parent_dir = util_path_join(driver->home, "mnt"); if (mnt_parent_dir == NULL) { @@ -193,6 +176,40 @@ out: return ret; } +// Remove removes a device with a given id, unmounts the filesystem. +int devmapper_rm_layer(const char *id, const struct graphdriver *driver) +{ + if (!util_valid_str(id) || driver == NULL) { + ERROR("invalid argument"); + return -1; + } + + if (!has_device(id, driver->devset)) { + DEBUG("Device with id:%s is not exist", id); + if (!has_metadata(id, driver->devset)) { + // this means metadata is lost + // if we can rm mnt, then the layer is removed + EVENT("try clean lost metadata and its mnt: %s", id); + return devmapper_try_rm_layer_mnt(id, driver); + } + // if has_metadata and not rm successfully, return -1 + // so next start up of isulad will retry delete the layer. + return -1; + } + + if (delete_device(id, false, driver->devset) != 0) { + ERROR("failed to remove device %s", id); + return -1; + } + + if (devmapper_try_rm_layer_mnt(id, driver) != 0) { + ERROR("failed to remove mnt dir of Device: %s", id); + return -1; + } + + 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) diff --git a/src/daemon/modules/image/oci/storage/layer_store/layer_store.c b/src/daemon/modules/image/oci/storage/layer_store/layer_store.c index b9ab0d65..60aaff22 100644 --- a/src/daemon/modules/image/oci/storage/layer_store/layer_store.c +++ b/src/daemon/modules/image/oci/storage/layer_store/layer_store.c @@ -1813,8 +1813,15 @@ static bool load_layer_json_cb(const char *path_name, const struct dirent *sub_d remove_invalid_dir: (void)graphdriver_umount_layer(sub_dir->d_name); - (void)graphdriver_rm_layer(sub_dir->d_name); - (void)util_recursive_rmdir(tmpdir, 0); + // layer not removed successfully, we can't remove layer.json + if (graphdriver_rm_layer(sub_dir->d_name) != 0) { + ERROR("failed to rm layer: %s when handing invalid rootfs", sub_dir->d_name); + goto free_out; + } + ERROR("tmpdir is %s", tmpdir); + if (util_recursive_rmdir(tmpdir, 0) != 0) { + ERROR("failed to rm rootfs dir: %s when handing invalid rootfs", tmpdir); + } free_out: free(rpath); -- 2.25.1