cgroup_modify_cgroup() and cgroup_create_cgroup() have nearly identical logic to walk the settings beneath the controller and update them. This commit refactors the duplicate logic in these two functions into one location - cgroup_set_values_recursive().
Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com> --- src/api.c | 118 ++++++++++++++++++++------------------- src/libcgroup-internal.h | 3 + 2 files changed, 65 insertions(+), 56 deletions(-) diff --git a/src/api.c b/src/api.c index a18e4cdce4f7..2848e203c976 100644 --- a/src/api.c +++ b/src/api.c @@ -1784,6 +1784,57 @@ static int cg_set_control_value(char *path, const char *val) return 0; } +/** + * Walk the settings in controller and write their values to disk + * + * @param base The full path to the base of this cgroup + * @param controller The controller whose values are being updated + */ +STATIC int cgroup_set_values_recursive(const char * const base, + const struct cgroup_controller * const controller) +{ + char *path = NULL; + int error = 0, ret, j; + + for (j = 0; j < controller->index; j++) { + ret = asprintf(&path, "%s%s", base, + controller->values[j]->name); + if (ret < 0) { + last_errno = errno; + error = ECGOTHER; + goto err; + } + cgroup_dbg("setting %s to \"%s\", pathlen %d\n", path, + controller->values[j]->value, ret); + error = cg_set_control_value(path, + controller->values[j]->value); + + free(path); + path = NULL; + + /* don't consider error in files directly written by + * the user as fatal */ + if (ret && !controller->values[j]->dirty) { + ret = 0; + continue; + } + if (ret) + goto err; + + controller->values[j]->dirty = false; + } + +err: + /* As currently written, path should always be null as we are exiting + * this function, but let's check just in case, and free it if it's + * non-null + */ + if (path) + free(path); + + return error; +} + /** cgroup_modify_cgroup modifies the cgroup control files. * struct cgroup *cgroup: The name will be the cgroup to be modified. * The values will be the values to be modified, those not mentioned @@ -1797,10 +1848,9 @@ static int cg_set_control_value(char *path, const char *val) int cgroup_modify_cgroup(struct cgroup *cgroup) { - char *path, base[FILENAME_MAX]; + char base[FILENAME_MAX]; int i; int error = 0; - int ret; if (!cgroup_initialized) return ECGROUPNOTINITIALIZED; @@ -1817,32 +1867,14 @@ int cgroup_modify_cgroup(struct cgroup *cgroup) } for (i = 0; i < cgroup->index; i++) { - int j; if (!cg_build_path(cgroup->name, base, cgroup->controller[i]->name)) continue; - for (j = 0; j < cgroup->controller[i]->index; j++) { - ret = asprintf(&path, "%s%s", base, - cgroup->controller[i]->values[j]->name); - if (ret < 0) { - last_errno = errno; - error = ECGOTHER; - goto err; - } - error = cg_set_control_value(path, - cgroup->controller[i]->values[j]->value); - free(path); - path = NULL; - /* don't consider error in files directly written by - * the user as fatal */ - if (error && !cgroup->controller[i]->values[j]->dirty) { - error = 0; - continue; - } - if (error) - goto err; - cgroup->controller[i]->values[j]->dirty = false; - } + + error = cgroup_set_values_recursive(base, + cgroup->controller[i]); + if (error) + goto err; } err: return error; @@ -1939,7 +1971,7 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership) char *fts_path[2]; char *base = NULL; char *path = NULL; - int i, j, k; + int i, k; int error = 0; int retval = 0; int ret; @@ -2001,36 +2033,10 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership) if (error) goto err; - for (j = 0; j < cgroup->controller[k]->index; j++) { - ret = snprintf(path, FILENAME_MAX, "%s%s", base, - cgroup->controller[k]->values[j]->name); - cgroup_dbg("setting %s to \"%s\", pathlen %d\n", path, - cgroup->controller[k]->values[j]->value, ret); - if (ret < 0 || ret >= FILENAME_MAX) { - last_errno = errno; - error = ECGOTHER; - goto err; - } - error = cg_set_control_value(path, - cgroup->controller[k]->values[j]->value); - /* - * Should we undo, what we've done in the loops above? - * An error should not be treated as fatal, since we - * have several read-only files and several files that - * are only conditionally created in the child. - * - * A middle ground would be to track that there - * was an error and return a diagnostic value-- - * callers don't get context for the error, but can - * ignore it specifically if they wish. - */ - if (error) { - cgroup_err("Error: failed to set %s: %s\n", - path, cgroup_strerror(error)); - retval = ECGCANTSETVALUE; - continue; - } - } + error = cgroup_set_values_recursive(base, + cgroup->controller[k]); + if (error) + goto err; if (!ignore_ownership) { ret = snprintf(path, FILENAME_MAX, "%s/tasks", base); diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index d16faf4435a5..2a9d9b67242b 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -324,6 +324,9 @@ int cgroup_process_v1_mnt(char *controllers[], struct mntent *ent, int cgroup_process_v2_mnt(struct mntent *ent, int *mnt_tbl_idx); +int cgroup_set_values_recursive(const char * const base, + const struct cgroup_controller * const controller); + #endif /* UNIT_TEST */ __END_DECLS -- 2.25.3 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel