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 80866159a040700cb59e00bb21adcf437eb84e48..3ee7e287ea2ae0c9463bc063952c09195687917c 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "log.h" #include "libisulad.h" @@ -2702,5 +2703,144 @@ free_out: free_image_devmapper_device_info(info); free(dm_name); return ret; +} + +void free_devmapper_status(struct status *st) +{ + if (st == NULL) { + return; + } + free(st->pool_name); + st->pool_name = NULL; + free(st->data_file); + st->data_file = NULL; + free(st->data_loopback); + st->data_loopback = NULL; + free(st->metadata_file); + st->metadata_file = NULL; + free(st->metadata_loopback); + st->metadata_loopback = NULL; + free(st->base_device_fs); + st->base_device_fs = NULL; + + free(st); +} + +static bool is_real_file(const char *f) +{ + struct stat st; + int nret; + + if (f == NULL) { + return false; + } + + nret = stat(f, &st); + if (nret < 0) { + return false; + } + + return S_ISREG(st.st_mode); +} + +static int get_underlying_available_space(const char *loop_file, uint64_t *available) +{ + struct statfs buf; + int ret; + + if (loop_file == NULL) { + return -1; + } + + ret = statfs(loop_file, &buf); + if (ret < 0) { + WARN("devmapper: can not stat loopfile filesystem %s", loop_file); + return ret; + } + + *available = buf.f_bfree * buf.f_bsize; + + return 0; +} + +struct status *device_set_status() +{ + int ret = 0; + struct status *st = NULL; + struct device_set *devset = NULL; + uint64_t total_size_in_sectors, transaction_id, data_used; + uint64_t data_total, metadata_used, metadata_total; + uint64_t min_free_data; + + st = util_common_calloc_s(sizeof(struct status)); + if (st == NULL) { + ERROR("devmapper: out of memory"); + return NULL; + } + + if (devmapper_conf_rdlock()) { + ERROR("lock devmapper conf failed"); + free_devmapper_status(st); + st = NULL; + return NULL; + } + + devset = devmapper_driver_devices_get(); + if (devset == NULL) { + free_devmapper_status(st); + st = NULL; + goto free_out; + } + st->pool_name = get_pool_name(devset); + st->data_file = util_strdup_s(devset->data_device); + st->data_loopback = util_strdup_s(devset->data_loop_file); + st->metadata_file = util_strdup_s(devset->metadata_device); + st->metadata_loopback = util_strdup_s(devset->metadata_loop_file); + st->udev_sync_supported = udev_sync_supported(); + st->deferred_remove_enabled = devset->deferred_remove; + st->deferred_delete_enabled = devset->deferred_delete; + st->deferred_deleted_device_count = devset->nr_deleted_devices; + st->base_device_size = get_base_device_size(devset); + st->base_device_fs = util_strdup_s(devset->base_device_filesystem); + + ret = pool_status(devset, &total_size_in_sectors, &transaction_id, &data_used, &data_total, &metadata_used, + &metadata_total); + if (ret == 0) { + uint64_t block_size_in_sectors = total_size_in_sectors / data_total; + st->data.used = data_used * block_size_in_sectors * 512; + st->data.total = data_total * block_size_in_sectors * 512; + st->data.available = st->data.total - st->data.used; + + st->metadata.used = metadata_used * 4096; + st->metadata.total = metadata_total * 4096; + st->metadata.available = st->metadata.total - st->metadata.used; + + st->sector_size = block_size_in_sectors * 512; + + if (is_real_file(devset->data_loop_file)) { + uint64_t actual_space; + ret = get_underlying_available_space(devset->data_loop_file, &actual_space); + if (ret == 0 && actual_space < st->metadata.available) { + st->data.available = actual_space; + } + } + + if (is_real_file(devset->metadata_loop_file)) { + uint64_t actual_space; + ret = get_underlying_available_space(devset->data_loop_file, &actual_space); + if (ret == 0 && actual_space < st->metadata.available) { + st->metadata.available = actual_space; + } + } + + min_free_data = (data_total * (uint64_t)devset->min_free_space_percent) / 100; + st->min_free_space = min_free_data * block_size_in_sectors * 512; + } + +free_out: + if (devmapper_conf_unlock()) { + ERROR("unlock devmapper conf failed"); + } + return st; } \ 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 669dc0fb82ec64b44c3364fa503276dc72c82d07..185e22fd5a63b47127a5f1c0a0f6b09807feb3cb 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.h @@ -76,6 +76,33 @@ struct devmapper_conf { struct device_set *devset; }; +struct disk_usage { + // Used bytes on the disk. + uint64_t used; + // Total bytes on the disk. + uint64_t total; + // Available bytes on the disk. + uint64_t available; +}; + +struct status { + char *pool_name; + char *data_file; + char *data_loopback; + char *metadata_file; + char *metadata_loopback; + struct disk_usage metadata; + struct disk_usage data; + uint64_t base_device_size; + char *base_device_fs; + uint64_t sector_size; + bool udev_sync_supported; + bool deferred_remove_enabled; + bool deferred_delete_enabled; + unsigned int deferred_deleted_device_count; + uint64_t min_free_space; +}; + int device_init(struct graphdriver *driver, const char *drvier_home, const char **options, size_t len); int devmapper_conf_rdlock(); @@ -91,6 +118,9 @@ bool has_device(const char *hash); int delete_device(const char *hash, bool sync_delete); int export_device_metadata(struct device_metadata *dev_metadata, const char *hash); +struct status *device_set_status(); +void free_devmapper_status(struct status *st); + #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 701894be2962264c10dd60a883785dc206bde105..0f3c4192edb6534cc343c5f5245db572f1ad3fbb 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 @@ -32,6 +32,7 @@ #include "device_setup.h" #include "deviceset.h" #include "json_common.h" +#include "util_archive.h" int devmapper_init(struct graphdriver *driver, const char *drvier_home, const char **options, size_t len) { @@ -238,6 +239,20 @@ out: return ret; } +static void free_driver_mount_opts(struct driver_mount_opts *opts) +{ + if (opts == NULL) { + return; + } + free(opts->mount_label); + opts->mount_label = NULL; + + util_free_array_by_len(opts->options, opts->options_len); + opts->options = NULL; + + free(opts); +} + bool devmapper_layer_exists(const char *id, const struct graphdriver *driver) { return has_device(id); @@ -246,7 +261,45 @@ bool devmapper_layer_exists(const char *id, const struct graphdriver *driver) int devmapper_apply_diff(const char *id, const struct graphdriver *driver, const struct io_read_wrapper *content, int64_t *layer_size) { - return 0; + struct driver_mount_opts *mount_opts = NULL; + char *layer_fs = NULL; + int ret = 0; + struct archive_options options = { 0 }; + + if (id == NULL || driver == NULL || content == NULL) { + ERROR("invalid argument"); + return -1; + } + + mount_opts = util_common_calloc_s(sizeof(struct driver_mount_opts)); + if (mount_opts == NULL) { + ERROR("devmapper: out of memory"); + return -1; + } + + layer_fs = devmapper_mount_layer(id, driver, mount_opts); + if (layer_fs == NULL) { + ERROR("devmapper: failed to mount layer %s", id); + ret = -1; + goto out; + } + + options.whiteout_format = OVERLAY_WHITEOUT_FORMATE; + + ret = archive_unpack(content, layer_fs, &options); + if (ret != 0) { + ERROR("devmapper: failed to unpack to :%s", layer_fs); + } + + if (devmapper_umount_layer(id, driver)) { + ERROR("devmapper: failed to umount layer %s", id); + ret = -1; + } + +out: + free_driver_mount_opts(mount_opts); + free(layer_fs); + return ret; } int devmapper_get_layer_metadata(const char *id, const struct graphdriver *driver, json_map_string_string *map_info) @@ -341,5 +394,22 @@ out: int devmapper_get_driver_status(const struct graphdriver *driver, struct graphdriver_status *status) { - return 0; + int ret = 0; + struct status *st = NULL; + + if (driver == NULL || status == NULL) { + return -1; + } + + st = device_set_status(); + if (st == NULL) { + ERROR("Failed to get device set status"); + return -1; + } + + status->driver_name = util_strdup_s(driver->name); + // TODO + + free_devmapper_status(st); + return ret; } diff --git a/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.h b/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.h index daa84476ac897c901636ded571616a27a843b68f..eba33985b90a94ca1346942e83115b7eb7094ed9 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.h +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.h @@ -54,6 +54,7 @@ int devmapper_get_layer_metadata(const char *id, const struct graphdriver *drive int devmapper_get_driver_status(const struct graphdriver *driver, struct graphdriver_status *status); + #ifdef __cplusplus } #endif diff --git a/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c b/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c index eaab034c794a5ae5bc9f3d7af407710628006b6e..4e447965a50b6293e51c09e4cedee3e689f110c6 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c @@ -525,6 +525,11 @@ cleanup: return ret; } +bool udev_sync_supported() +{ + return dm_udev_get_sync_support() != 0; +} + bool udev_set_sync_support(bool enable) { int enable_sync = 1; diff --git a/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.h b/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.h index 1cbc4c4fc8c22c7df5ed6fdba580481bf7db95b5..67acdacc6ebd1568ca4e3ebde109958b732cac77 100644 --- a/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.h +++ b/src/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.h @@ -104,6 +104,8 @@ int dev_remove_device(const char *name); int dev_get_device_list(char ***list, size_t *length); +bool udev_sync_supported(); + bool udev_set_sync_support(bool enable); int dev_create_device(const char *pool_dev_name, int device_id);