diff --git a/src/image/oci/graphdriver/driver.c b/src/image/oci/graphdriver/driver.c index a077c41e2686a342b96419bfd8f371b9ac9a0c22..bb5039f23b9a268b2dcf9086ad89e17b2a38a741 100644 --- a/src/image/oci/graphdriver/driver.c +++ b/src/image/oci/graphdriver/driver.c @@ -35,6 +35,7 @@ static struct graphdriver *g_graphdriver = NULL; static const struct graphdriver_ops g_overlay2_ops = { .init = overlay2_init, .create_rw = overlay2_create_rw, + .create_ro = overlay2_create_ro, .rm_layer = overlay2_rm_layer, .mount_layer = overlay2_mount_layer, .umount_layer = overlay2_umount_layer, @@ -95,7 +96,7 @@ struct graphdriver *graphdriver_get() } -int graphdriver_create_rw(const char *id, const char *parent, const struct driver_create_opts *create_opts) +int graphdriver_create_rw(const char *id, const char *parent, struct driver_create_opts *create_opts) { if (g_graphdriver == NULL) { ERROR("Driver not inited yet"); @@ -122,7 +123,7 @@ int graphdriver_create_ro(const char *id, const char *parent, const struct drive return -1; } - return g_graphdriver->ops->create_rw(id, parent, g_graphdriver, create_opts);; + return g_graphdriver->ops->create_ro(id, parent, g_graphdriver, create_opts);; } int graphdriver_rm_layer(const char *id) diff --git a/src/image/oci/graphdriver/driver.h b/src/image/oci/graphdriver/driver.h index bf038c312be61b91f906f3f8c73fea4ce10dd7cd..fb06ea5d7c8e5572f43a10862772cfe712a9df8e 100644 --- a/src/image/oci/graphdriver/driver.h +++ b/src/image/oci/graphdriver/driver.h @@ -49,6 +49,10 @@ struct graphdriver_ops { int (*init)(struct graphdriver *driver, const char *drvier_home, const char **options, size_t len); int (*create_rw)(const char *id, const char *parent, const struct graphdriver *driver, + struct driver_create_opts *create_opts); + + + int (*create_ro)(const char *id, const char *parent, const struct graphdriver *driver, const struct driver_create_opts *create_opts); int (*rm_layer)(const char *id, const struct graphdriver *driver); @@ -77,6 +81,9 @@ struct graphdriver { char *backing_fs; bool support_dtype; + bool support_quota; + struct pquota_control *quota_ctrl; + // options for overlay2 struct overlay_options *overlay_opts; }; @@ -86,7 +93,7 @@ struct graphdriver *graphdriver_init(const char *name, const char *isulad_root, struct graphdriver *graphdriver_get(void); -int graphdriver_create_rw(const char *id, const char *parent, const struct driver_create_opts *create_opts); +int graphdriver_create_rw(const char *id, const char *parent, struct driver_create_opts *create_opts); int graphdriver_create_ro(const char *id, const char *parent, const struct driver_create_opts *create_opts); diff --git a/src/image/oci/graphdriver/overlay2/driver_overlay2.c b/src/image/oci/graphdriver/overlay2/driver_overlay2.c index efbdeedd577a2d684edf3883216bff663cbc5b4e..a231698b62baac4de153d2bae0061cfd88f67907 100644 --- a/src/image/oci/graphdriver/overlay2/driver_overlay2.c +++ b/src/image/oci/graphdriver/overlay2/driver_overlay2.c @@ -28,6 +28,7 @@ #include "path.h" #include "utils.h" #include "util_archive.h" +#include "project_quota.h" #define OVERLAY_LINK_DIR "l" #define QUOTA_SIZE_OPTION "overlay2.size" @@ -38,6 +39,34 @@ // ((idLength + len(linkDir) + 1) * maxDepth) <= (pageSize - 512) #define MAX_LAYER_ID_LENGTH 26 +void free_driver_create_opts(struct driver_create_opts *opts) +{ + if (opts == NULL) { + return; + } + free(opts->mount_label); + opts->mount_label = NULL; + + free_json_map_string_string(opts->storage_opt); + opts->storage_opt = NULL; + + free(opts); +} + +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); +} + static int overlay2_parse_options(struct graphdriver *driver, const char **options, size_t options_len) { int ret = 0; @@ -78,7 +107,7 @@ static int overlay2_parse_options(struct graphdriver *driver, const char **optio ret = -1; goto out; } - overlay_opts->quota = converted; + overlay_opts->default_quota = converted; } else if (strcasecmp(dup, QUOTA_BASESIZE_OPTIONS) == 0) { int64_t converted = 0; ret = util_parse_byte_size_string(val, &converted); @@ -87,7 +116,7 @@ static int overlay2_parse_options(struct graphdriver *driver, const char **optio ret = -1; goto out; } - overlay_opts->quota_basesize = converted; + overlay_opts->default_quota = converted; } else if (strcasecmp(dup, "overlay2.override_kernel_check") == 0) { bool converted_bool = 0; ret = util_str_to_bool(val, &converted_bool); @@ -188,6 +217,11 @@ static void rm_invalid_symlink(const char *dirpath) return; } +static bool check_bk_fs_support_quota(const char *backing_fs) +{ + return strcmp(backing_fs, "xfs") == 0 || strcmp(backing_fs, "extfs") == 0; +} + int overlay2_init(struct graphdriver *driver, const char *drvier_home, const char **options, size_t len) { int ret = 0; @@ -254,6 +288,16 @@ int overlay2_init(struct graphdriver *driver, const char *drvier_home, const cha } } + if (check_bk_fs_support_quota(driver->backing_fs)) { + driver->quota_ctrl = project_quota_control_init(driver->home, driver->backing_fs); + if (driver->quota_ctrl == NULL) { + ERROR("Failed to init quota ctrl"); + ret = -1; + goto out; + } + driver->support_quota = true; + } + out: return ret; } @@ -604,16 +648,42 @@ out: return ret; } -int overlay2_create_rw(const char *id, const char *parent, const struct graphdriver *driver, - const struct driver_create_opts *create_opts) +static int set_dir_quota(const char *dir, const json_map_string_string *opts, const struct graphdriver *driver) { int ret = 0; - char *layer_dir = NULL; + size_t i = 0; + uint64_t quota = 0; - if (id == NULL || parent == NULL || driver == NULL || create_opts == NULL) { - return -1; + for (i = 0; i < opts->len; i++) { + if (strcasecmp("size", opts->keys[i]) == 0) { + int64_t converted = 0; + ret = util_parse_byte_size_string(opts->values[i], &converted); + if (ret != 0) { + ERROR("Invalid size: '%s': %s", opts->values[i], strerror(-ret)); + ret = -1; + goto out; + } + quota = (uint64_t)converted; + break; + } else { + ERROR("Unknown option %s", opts->keys[i]); + ret = -1; + goto out; + } } + ret = driver->quota_ctrl->set_quota(dir, driver->quota_ctrl, quota); + +out: + return ret; +} + +static int do_create(const char *id, const char *parent, const struct graphdriver *driver, + const struct driver_create_opts *create_opts) +{ + int ret = 0; + char *layer_dir = NULL; + layer_dir = util_path_join(driver->home, id); if (layer_dir == NULL) { ERROR("Failed to join layer dir:%S", id); @@ -632,6 +702,14 @@ int overlay2_create_rw(const char *id, const char *parent, const struct graphdri goto out; } + if (create_opts->storage_opt != NULL && create_opts->storage_opt->len != 0) { + if (set_dir_quota(layer_dir, create_opts->storage_opt, driver) != 0) { + ERROR("Unable to set layer quota %s", layer_dir); + ret = -1; + goto out; + } + } + if (mk_sub_directorys(id, parent, layer_dir, driver->home) != 0) { ret = -1; goto err_out; @@ -649,6 +727,93 @@ out: return ret; } +static int apply_quota_opts(struct driver_create_opts *ori_opts, uint64_t quota) +{ + int ret = 0; + size_t i = 0; + char tmp[50] = { 0 };//tmp to hold unit64 + + ret = snprintf(tmp, sizeof(tmp), "%llu", (unsigned long long)quota); + if (ret < 0 || ret >= sizeof(tmp)) { + ERROR("Failed to make quota string"); + ret = -1; + goto out; + } + + if (ori_opts->storage_opt == NULL) { + ori_opts->storage_opt = util_common_calloc_s(sizeof(json_map_string_string)); + if (ori_opts->storage_opt == NULL) { + ERROR("Memory out"); + ret = -1; + goto out; + } + } + + for (i = 0; i < ori_opts->storage_opt->len; i++) { + if (strcasecmp("size", ori_opts->storage_opt->keys[i]) == 0) { + break; + } + } + if (i == ori_opts->storage_opt->len) { + ret = append_json_map_string_string(ori_opts->storage_opt, "size", tmp); + if (ret != 0) { + ERROR("Failed to append quota size option"); + ret = -1; + goto out; + } + } + +out: + return ret; +} + +int overlay2_create_rw(const char *id, const char *parent, const struct graphdriver *driver, + struct driver_create_opts *create_opts) +{ + int ret = 0; + + if (id == NULL || parent == NULL || driver == NULL || create_opts == NULL) { + return -1; + } + + if (create_opts->storage_opt != NULL && create_opts->storage_opt->len != 0 && !driver->support_quota) { + ERROR("--storage-opt is supported only for overlay over xfs or ext4 with 'pquota' mount option"); + ret = -1; + goto out; + } + + if (apply_quota_opts(create_opts, driver->overlay_opts->default_quota) != 0) { + ret = -1; + goto out; + } + + ret = do_create(id, parent, driver, create_opts); + +out: + return ret; +} + +int overlay2_create_ro(const char *id, const char *parent, const struct graphdriver *driver, + const struct driver_create_opts *create_opts) +{ + int ret = 0; + + if (id == NULL || parent == NULL || driver == NULL || create_opts == NULL) { + return -1; + } + + if (create_opts->storage_opt != NULL && create_opts->storage_opt->len != 0) { + ERROR("--storage-opt size is only supported for ReadWrite Layers"); + ret = -1; + goto out; + } + + ret = do_create(id, parent, driver, create_opts); + +out: + return ret; +} + static char *read_layer_link_file(const char *layer_dir) { char *link_file = NULL; diff --git a/src/image/oci/graphdriver/overlay2/driver_overlay2.h b/src/image/oci/graphdriver/overlay2/driver_overlay2.h index b6118a710f48779af7ef142dcfd8eb47a9da46bd..a772b0da8fefa192993b767f38dd8e7c02869230 100644 --- a/src/image/oci/graphdriver/overlay2/driver_overlay2.h +++ b/src/image/oci/graphdriver/overlay2/driver_overlay2.h @@ -26,6 +26,9 @@ int overlay2_init(struct graphdriver *driver, const char *drvier_home, const cha bool overlay2_is_quota_options(struct graphdriver *driver, const char *option); int overlay2_create_rw(const char *id, const char *parent, const struct graphdriver *driver, + struct driver_create_opts *create_opts); + +int overlay2_create_ro(const char *id, const char *parent, const struct graphdriver *driver, const struct driver_create_opts *create_opts); int overlay2_rm_layer(const char *id, const struct graphdriver *driver); @@ -46,6 +49,10 @@ int overlay2_get_driver_status(const struct graphdriver *driver, struct graphdri int overlay2_clean_up(const struct graphdriver *driver); +void free_driver_create_opts(struct driver_create_opts *opts); + +void free_driver_mount_opts(struct driver_mount_opts *opts); + #ifdef __cplusplus } #endif diff --git a/src/image/oci/graphdriver/overlay2/driver_overlay2_types.h b/src/image/oci/graphdriver/overlay2/driver_overlay2_types.h index 9750d5dfa5ddefc9ebdd6f422840500edd8d5869..2b86d769a37565ded704ca1aa98d11c55781aea7 100644 --- a/src/image/oci/graphdriver/overlay2/driver_overlay2_types.h +++ b/src/image/oci/graphdriver/overlay2/driver_overlay2_types.h @@ -26,8 +26,7 @@ extern "C" { struct overlay_options { bool override_kernelcheck; - uint64_t quota; - uint64_t quota_basesize; + uint64_t default_quota; const char *mount_program; bool skip_mount_home; const char *mount_options; diff --git a/src/image/oci/graphdriver/quota/project_quota.c b/src/image/oci/graphdriver/quota/project_quota.c index 531598c4629811a43b22c95b41e592cbfa528036..821c186cfdba967f0264b40104b0cb403b3f6eab 100644 --- a/src/image/oci/graphdriver/quota/project_quota.c +++ b/src/image/oci/graphdriver/quota/project_quota.c @@ -97,11 +97,11 @@ out: return ret; } -static int ext4_set_project_quota(const char *backing_fs_blockdev, uint32_t project_id, const quota_config *pquota) +static int ext4_set_project_quota(const char *backing_fs_blockdev, uint32_t project_id, uint64_t size) { int ret; struct dqblk d = {0}; - d.dqb_bhardlimit = pquota->size / SIZE_KB; + d.dqb_bhardlimit = size / SIZE_KB; d.dqb_bsoftlimit = d.dqb_bhardlimit; d.dqb_valid = QIF_LIMITS; @@ -113,12 +113,12 @@ static int ext4_set_project_quota(const char *backing_fs_blockdev, uint32_t proj return ret; } -static int ext4_set_quota(const char *target, struct pquota_control *ctrl, const quota_config *pquota) +static int ext4_set_quota(const char *target, struct pquota_control *ctrl, uint64_t size) { int ret = 0; uint32_t project_id = 0; - if (target == NULL || pquota == NULL || ctrl == NULL) { + if (target == NULL || ctrl == NULL) { return -1; } @@ -136,7 +136,7 @@ static int ext4_set_quota(const char *target, struct pquota_control *ctrl, const } ctrl->next_project_id++; - if (ext4_set_project_quota(ctrl->backing_fs_device, project_id, pquota) != 0) { + if (ext4_set_project_quota(ctrl->backing_fs_device, project_id, size) != 0) { ERROR("Failed to set project id %d to %s.", project_id, target); ret = -1; goto unlock; @@ -148,7 +148,7 @@ out: return ret; } -static int xfs_set_project_quota(const char *backing_fs_blockdev, uint32_t project_id, const quota_config *pquota) +static int xfs_set_project_quota(const char *backing_fs_blockdev, uint32_t project_id, uint64_t size) { int ret; fs_disk_quota_t d = {0}; @@ -156,7 +156,7 @@ static int xfs_set_project_quota(const char *backing_fs_blockdev, uint32_t proje d.d_id = project_id; d.d_flags = FS_PROJ_QUOTA; d.d_fieldmask = FS_DQ_BHARD | FS_DQ_BSOFT; - d.d_blk_hardlimit = (pquota->size / 512); + d.d_blk_hardlimit = (size / 512); d.d_blk_softlimit = d.d_blk_hardlimit; ret = quotactl(QCMD(Q_XSETQLIM, FS_PROJ_QUOTA), backing_fs_blockdev, @@ -167,12 +167,12 @@ static int xfs_set_project_quota(const char *backing_fs_blockdev, uint32_t proje return ret; } -static int xfs_set_quota(const char *target, struct pquota_control *ctrl, const quota_config *pquota) +static int xfs_set_quota(const char *target, struct pquota_control *ctrl, uint64_t size) { int ret = 0; uint32_t project_id = 0; - if (target == NULL || pquota == NULL || ctrl == NULL) { + if (target == NULL || ctrl == NULL) { return -1; } @@ -190,7 +190,7 @@ static int xfs_set_quota(const char *target, struct pquota_control *ctrl, const } ctrl->next_project_id++; - if (xfs_set_project_quota(ctrl->backing_fs_device, project_id, pquota) != 0) { + if (xfs_set_project_quota(ctrl->backing_fs_device, project_id, size) != 0) { ERROR("Failed to set project id %d to %s.", project_id, target); ret = -1; goto unlock; diff --git a/src/image/oci/graphdriver/quota/project_quota.h b/src/image/oci/graphdriver/quota/project_quota.h index d574bd822692e11a3374ac05177f506e4ecbf4f3..fef58cf77eaef82632c35f8249e03024185cb304 100644 --- a/src/image/oci/graphdriver/quota/project_quota.h +++ b/src/image/oci/graphdriver/quota/project_quota.h @@ -85,19 +85,17 @@ struct fsxattr { #endif -typedef struct { - uint64_t size; -} quota_config; - struct pquota_control { char *backing_fs_type; char *backing_fs_device; uint32_t next_project_id; pthread_rwlock_t rwlock; // ops - int (*set_quota)(const char *target, struct pquota_control *ctrl, const quota_config *pquota); + int (*set_quota)(const char *target, struct pquota_control *ctrl, uint64_t size); }; +struct pquota_control *project_quota_control_init(const char *home_dir, const char *fs); + #ifdef __cplusplus } #endif