提交 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; ...@@ -35,6 +35,7 @@ static struct graphdriver *g_graphdriver = NULL;
static const struct graphdriver_ops g_overlay2_ops = { static const struct graphdriver_ops g_overlay2_ops = {
.init = overlay2_init, .init = overlay2_init,
.create_rw = overlay2_create_rw, .create_rw = overlay2_create_rw,
.create_ro = overlay2_create_ro,
.rm_layer = overlay2_rm_layer, .rm_layer = overlay2_rm_layer,
.mount_layer = overlay2_mount_layer, .mount_layer = overlay2_mount_layer,
.umount_layer = overlay2_umount_layer, .umount_layer = overlay2_umount_layer,
...@@ -95,7 +96,7 @@ struct graphdriver *graphdriver_get() ...@@ -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) { if (g_graphdriver == NULL) {
ERROR("Driver not inited yet"); ERROR("Driver not inited yet");
...@@ -122,7 +123,7 @@ int graphdriver_create_ro(const char *id, const char *parent, const struct drive ...@@ -122,7 +123,7 @@ int graphdriver_create_ro(const char *id, const char *parent, const struct drive
return -1; 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) int graphdriver_rm_layer(const char *id)
......
...@@ -49,6 +49,10 @@ struct graphdriver_ops { ...@@ -49,6 +49,10 @@ struct graphdriver_ops {
int (*init)(struct graphdriver *driver, const char *drvier_home, const char **options, size_t len); 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, 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); const struct driver_create_opts *create_opts);
int (*rm_layer)(const char *id, const struct graphdriver *driver); int (*rm_layer)(const char *id, const struct graphdriver *driver);
...@@ -77,6 +81,9 @@ struct graphdriver { ...@@ -77,6 +81,9 @@ struct graphdriver {
char *backing_fs; char *backing_fs;
bool support_dtype; bool support_dtype;
bool support_quota;
struct pquota_control *quota_ctrl;
// options for overlay2 // options for overlay2
struct overlay_options *overlay_opts; struct overlay_options *overlay_opts;
}; };
...@@ -86,7 +93,7 @@ struct graphdriver *graphdriver_init(const char *name, const char *isulad_root, ...@@ -86,7 +93,7 @@ struct graphdriver *graphdriver_init(const char *name, const char *isulad_root,
struct graphdriver *graphdriver_get(void); 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); int graphdriver_create_ro(const char *id, const char *parent, const struct driver_create_opts *create_opts);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "path.h" #include "path.h"
#include "utils.h" #include "utils.h"
#include "util_archive.h" #include "util_archive.h"
#include "project_quota.h"
#define OVERLAY_LINK_DIR "l" #define OVERLAY_LINK_DIR "l"
#define QUOTA_SIZE_OPTION "overlay2.size" #define QUOTA_SIZE_OPTION "overlay2.size"
...@@ -38,6 +39,34 @@ ...@@ -38,6 +39,34 @@
// ((idLength + len(linkDir) + 1) * maxDepth) <= (pageSize - 512) // ((idLength + len(linkDir) + 1) * maxDepth) <= (pageSize - 512)
#define MAX_LAYER_ID_LENGTH 26 #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) static int overlay2_parse_options(struct graphdriver *driver, const char **options, size_t options_len)
{ {
int ret = 0; int ret = 0;
...@@ -78,7 +107,7 @@ static int overlay2_parse_options(struct graphdriver *driver, const char **optio ...@@ -78,7 +107,7 @@ static int overlay2_parse_options(struct graphdriver *driver, const char **optio
ret = -1; ret = -1;
goto out; goto out;
} }
overlay_opts->quota = converted; overlay_opts->default_quota = converted;
} else if (strcasecmp(dup, QUOTA_BASESIZE_OPTIONS) == 0) { } else if (strcasecmp(dup, QUOTA_BASESIZE_OPTIONS) == 0) {
int64_t converted = 0; int64_t converted = 0;
ret = util_parse_byte_size_string(val, &converted); ret = util_parse_byte_size_string(val, &converted);
...@@ -87,7 +116,7 @@ static int overlay2_parse_options(struct graphdriver *driver, const char **optio ...@@ -87,7 +116,7 @@ static int overlay2_parse_options(struct graphdriver *driver, const char **optio
ret = -1; ret = -1;
goto out; goto out;
} }
overlay_opts->quota_basesize = converted; overlay_opts->default_quota = converted;
} else if (strcasecmp(dup, "overlay2.override_kernel_check") == 0) { } else if (strcasecmp(dup, "overlay2.override_kernel_check") == 0) {
bool converted_bool = 0; bool converted_bool = 0;
ret = util_str_to_bool(val, &converted_bool); ret = util_str_to_bool(val, &converted_bool);
...@@ -188,6 +217,11 @@ static void rm_invalid_symlink(const char *dirpath) ...@@ -188,6 +217,11 @@ static void rm_invalid_symlink(const char *dirpath)
return; 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 overlay2_init(struct graphdriver *driver, const char *drvier_home, const char **options, size_t len)
{ {
int ret = 0; int ret = 0;
...@@ -254,6 +288,16 @@ int overlay2_init(struct graphdriver *driver, const char *drvier_home, const cha ...@@ -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: out:
return ret; return ret;
} }
...@@ -604,16 +648,42 @@ out: ...@@ -604,16 +648,42 @@ out:
return ret; return ret;
} }
int overlay2_create_rw(const char *id, const char *parent, const struct graphdriver *driver, static int set_dir_quota(const char *dir, const json_map_string_string *opts, const struct graphdriver *driver)
const struct driver_create_opts *create_opts)
{ {
int ret = 0; 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) { for (i = 0; i < opts->len; i++) {
return -1; 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); layer_dir = util_path_join(driver->home, id);
if (layer_dir == NULL) { if (layer_dir == NULL) {
ERROR("Failed to join layer dir:%S", id); 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 ...@@ -632,6 +702,14 @@ int overlay2_create_rw(const char *id, const char *parent, const struct graphdri
goto out; 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) { if (mk_sub_directorys(id, parent, layer_dir, driver->home) != 0) {
ret = -1; ret = -1;
goto err_out; goto err_out;
...@@ -649,6 +727,93 @@ out: ...@@ -649,6 +727,93 @@ out:
return ret; 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) static char *read_layer_link_file(const char *layer_dir)
{ {
char *link_file = NULL; char *link_file = NULL;
......
...@@ -26,6 +26,9 @@ int overlay2_init(struct graphdriver *driver, const char *drvier_home, const cha ...@@ -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); 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, 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); const struct driver_create_opts *create_opts);
int overlay2_rm_layer(const char *id, const struct graphdriver *driver); 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 ...@@ -46,6 +49,10 @@ int overlay2_get_driver_status(const struct graphdriver *driver, struct graphdri
int overlay2_clean_up(const struct graphdriver *driver); 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 #ifdef __cplusplus
} }
#endif #endif
......
...@@ -26,8 +26,7 @@ extern "C" { ...@@ -26,8 +26,7 @@ extern "C" {
struct overlay_options { struct overlay_options {
bool override_kernelcheck; bool override_kernelcheck;
uint64_t quota; uint64_t default_quota;
uint64_t quota_basesize;
const char *mount_program; const char *mount_program;
bool skip_mount_home; bool skip_mount_home;
const char *mount_options; const char *mount_options;
......
...@@ -97,11 +97,11 @@ out: ...@@ -97,11 +97,11 @@ out:
return ret; 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; int ret;
struct dqblk d = {0}; 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_bsoftlimit = d.dqb_bhardlimit;
d.dqb_valid = QIF_LIMITS; d.dqb_valid = QIF_LIMITS;
...@@ -113,12 +113,12 @@ static int ext4_set_project_quota(const char *backing_fs_blockdev, uint32_t proj ...@@ -113,12 +113,12 @@ static int ext4_set_project_quota(const char *backing_fs_blockdev, uint32_t proj
return ret; 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; int ret = 0;
uint32_t project_id = 0; uint32_t project_id = 0;
if (target == NULL || pquota == NULL || ctrl == NULL) { if (target == NULL || ctrl == NULL) {
return -1; return -1;
} }
...@@ -136,7 +136,7 @@ static int ext4_set_quota(const char *target, struct pquota_control *ctrl, const ...@@ -136,7 +136,7 @@ static int ext4_set_quota(const char *target, struct pquota_control *ctrl, const
} }
ctrl->next_project_id++; 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); ERROR("Failed to set project id %d to %s.", project_id, target);
ret = -1; ret = -1;
goto unlock; goto unlock;
...@@ -148,7 +148,7 @@ out: ...@@ -148,7 +148,7 @@ out:
return ret; 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; int ret;
fs_disk_quota_t d = {0}; fs_disk_quota_t d = {0};
...@@ -156,7 +156,7 @@ static int xfs_set_project_quota(const char *backing_fs_blockdev, uint32_t proje ...@@ -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_id = project_id;
d.d_flags = FS_PROJ_QUOTA; d.d_flags = FS_PROJ_QUOTA;
d.d_fieldmask = FS_DQ_BHARD | FS_DQ_BSOFT; 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; d.d_blk_softlimit = d.d_blk_hardlimit;
ret = quotactl(QCMD(Q_XSETQLIM, FS_PROJ_QUOTA), backing_fs_blockdev, 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 ...@@ -167,12 +167,12 @@ static int xfs_set_project_quota(const char *backing_fs_blockdev, uint32_t proje
return ret; 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; int ret = 0;
uint32_t project_id = 0; uint32_t project_id = 0;
if (target == NULL || pquota == NULL || ctrl == NULL) { if (target == NULL || ctrl == NULL) {
return -1; return -1;
} }
...@@ -190,7 +190,7 @@ static int xfs_set_quota(const char *target, struct pquota_control *ctrl, const ...@@ -190,7 +190,7 @@ static int xfs_set_quota(const char *target, struct pquota_control *ctrl, const
} }
ctrl->next_project_id++; 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); ERROR("Failed to set project id %d to %s.", project_id, target);
ret = -1; ret = -1;
goto unlock; goto unlock;
......
...@@ -85,19 +85,17 @@ struct fsxattr { ...@@ -85,19 +85,17 @@ struct fsxattr {
#endif #endif
typedef struct {
uint64_t size;
} quota_config;
struct pquota_control { struct pquota_control {
char *backing_fs_type; char *backing_fs_type;
char *backing_fs_device; char *backing_fs_device;
uint32_t next_project_id; uint32_t next_project_id;
pthread_rwlock_t rwlock; pthread_rwlock_t rwlock;
// ops // 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 #ifdef __cplusplus
} }
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册