提交 ecdf5fad 编写于 作者: L LiFeng 提交者: lifeng68

Driver: support set quota

Signed-off-by: NLiFeng <lifeng68@huawei.com>
上级 457b7d16
......@@ -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)
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册