* Ivana Varekova <[email protected]> [2009-02-16 11:51:51]:
> changelog:
> This patch store the last errno value to last_errno value and add
> cgroup_add_last_errno procedure to show this number.
> Use this procedure to show the cause of the error when ECGOTHER or
> ECGCANTOPENCF is returned.
> standardise error messages form of the second part of
> cgclassify - using cgroup_strerr procedure.
>
>
> Signed-off-by: Ivana Varekova <[email protected]>
>
> Ivana Varekova
> --------------------------------------------------------
>
>
> diff -up ./api.c.orig ./api.c
> --- ./api.c.orig 2009-02-16 10:55:07.000000000 +0100
> +++ ./api.c 2009-02-16 10:58:28.000000000 +0100
> @@ -48,6 +48,15 @@
>
> #define VERSION(ver) #ver
>
> +/* the errno which happend the last time
> + * (have to be thread specific) */
> +__thread int last_errno;
> +
> +#define MAXLEN 256
> +
> +/* the value have to be thread specific */
> +__thread char errtext[MAXLEN];
> +
Why do we need errtext? Can't we do strerror later?
> /*
> * Remember to bump this up for major API changes.
> */
> @@ -94,6 +103,7 @@ char *cgroup_strerror_codes[] = {
> "Cgroup parsing failed",
> "Cgroup, rules file does not exist",
> "Cgroup mounting failed",
> + "The config file can not be opend",
> };
>
> static int cg_chown_file(FTS *fts, FTSENT *ent, uid_t owner, gid_t group)
> @@ -294,14 +304,16 @@ static int cgroup_parse_rules(bool cache
> dbg("Failed to open configuration file %s with"
> " error: %s\n", CGRULES_CONF_FILE,
> strerror(errno));
> - ret = errno;
> + last_errno = errno;
> + ret = ECGCANTOPENCF;
Why do we need an additional error code? ENOFILE is not sufficient
from errno?
> goto finish;
> }
>
> buff = calloc(CGROUP_RULE_MAXLINE, sizeof(char));
> if (!buff) {
> dbg("Out of memory? Error: %s\n", strerror(errno));
> - ret = errno;
> + last_errno = errno;
> + ret = ECGOTHER;
> goto close_unlock;
> }
>
> @@ -442,7 +454,8 @@ static int cgroup_parse_rules(bool cache
> newrule = calloc(1, sizeof(struct cgroup_rule));
> if (!newrule) {
> dbg("Out of memory? Error: %s\n", strerror(errno));
> - ret = errno;
> + last_errno = errno;
> + ret = ECGOTHER;
> goto cleanup;
> }
>
> @@ -565,6 +578,7 @@ int cgroup_init()
> */
> buf = malloc(FILENAME_MAX);
> if (!buf) {
> + last_errno = errno;
> ret = ECGOTHER;
> goto unlock_exit;
> }
> @@ -777,11 +791,13 @@ int cgroup_attach_task_pid(struct cgroup
> dbg("Error writing tid %d to %s:%s\n",
> tid, path, strerror(errno));
> fclose(tasks);
> + last_errno = errno;
> return ECGOTHER;
> }
>
> ret = fflush(tasks);
> if (ret) {
> + last_errno = errno;
> dbg("Error writing tid %d to %s:%s\n",
> tid, path, strerror(errno));
> fclose(tasks);
> @@ -822,6 +838,7 @@ int cgroup_attach_task_pid(struct cgroup
> }
> ret = fprintf(tasks, "%d", tid);
> if (ret < 0) {
> + last_errno = errno;
> dbg("Error writing tid %d to %s:%s\n",
> tid, path, strerror(errno));
> fclose(tasks);
> @@ -829,6 +846,7 @@ int cgroup_attach_task_pid(struct cgroup
> }
> ret = fflush(tasks);
> if (ret) {
> + last_errno = errno;
> dbg("Error writing tid %d to %s:%s\n",
> tid, path, strerror(errno));
> fclose(tasks);
> @@ -872,12 +890,16 @@ static int cg_mkdir_p(const char *path)
>
> buf = getcwd(cwd, FILENAME_MAX);
>
> - if (!buf)
> + if (!buf) {
> + last_errno = errno;
> return ECGOTHER;
> + }
>
> real_path = strdup(path);
> - if (!real_path)
> + if (!real_path) {
> + last_errno = errno;
> return ECGOTHER;
> + }
>
> do {
> while (real_path[j] != '\0' && real_path[j] != '/')
> @@ -892,6 +914,7 @@ static int cg_mkdir_p(const char *path)
> ret = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
> wd = strdup(str);
> if (!wd) {
> + last_errno = errno;
> ret = ECGOTHER;
> break;
> }
> @@ -1030,6 +1053,7 @@ int cgroup_modify_cgroup(struct cgroup *
> ret = asprintf(&path, "%s%s", base,
> cgroup->controller[i]->values[j]->name);
> if (ret < 0) {
> + last_errno = errno;
> error = ECGOTHER;
> goto err;
> }
> @@ -1175,6 +1199,7 @@ int cgroup_create_cgroup(struct cgroup *
> base = strdup(path);
>
> if (!base) {
> + last_errno = errno;
> error = ECGOTHER;
> goto err;
> }
> @@ -1191,6 +1216,7 @@ int cgroup_create_cgroup(struct cgroup *
> ret = asprintf(&path, "%s%s", base,
> cgroup->controller[k]->values[j]->name);
> if (ret < 0) {
> + last_errno = errno;
> error = ECGOTHER;
> goto err;
> }
> @@ -1215,12 +1241,14 @@ int cgroup_create_cgroup(struct cgroup *
> free(path);
> ret = asprintf(&path, "%s/tasks", base);
> if (ret < 0) {
> + last_errno = errno;
> error = ECGOTHER;
> goto err;
> }
> error = chown(path, cgroup->tasks_uid,
> cgroup->tasks_gid);
> if (error) {
> + last_errno = errno;
> error = ECGOTHER;
> goto err;
> }
> @@ -1403,6 +1431,7 @@ int cgroup_delete_cgroup(struct cgroup *
> cgroup->controller[i]->name))
> continue;
> error = rmdir(path);
> + last_errno = errno;
> }
> open_err:
> if (ignore_migration) {
> @@ -1411,8 +1440,10 @@ open_err:
> cgroup->controller[i]->name))
> continue;
> error = rmdir(path);
> - if (error < 0 && errno == ENOENT)
> + if (error < 0 && errno == ENOENT) {
> + last_errno = errno;
> error = 0;
> + }
> }
> }
> if (error)
> @@ -1441,8 +1472,10 @@ static int cg_rd_ctrl_file(char *subsys,
> return ECGROUPVALUENOTEXIST;
>
> *value = malloc(CG_VALUE_MAX);
> - if (!*value)
> + if (!*value) {
> + last_errno = errno;
> return ECGOTHER;
> + }
>
> /*
> * using %as crashes when we try to read from files like
> @@ -1596,11 +1629,13 @@ int cgroup_get_cgroup(struct cgroup *cgr
> ret = asprintf(&control_path, "%s/tasks", path);
>
> if (ret < 0) {
> + last_errno = errno;
> error = ECGOTHER;
> goto unlock_error;
> }
>
> if (stat(control_path, &stat_buffer)) {
> + last_errno = errno;
> free(control_path);
> error = ECGOTHER;
> goto unlock_error;
> @@ -1620,6 +1655,7 @@ int cgroup_get_cgroup(struct cgroup *cgr
>
> dir = opendir(path);
> if (!dir) {
> + last_errno = errno;
> error = ECGOTHER;
> goto unlock_error;
> }
> @@ -1739,8 +1775,10 @@ static int cg_prepare_controller_array(c
>
> if (temp) {
> controllers[j] = strdup(temp);
> - if (!controllers[j])
> + if (!controllers[j]) {
> + last_errno = errno;
> return ECGOTHER;
> + }
> }
> j++;
> } while (temp);
> @@ -2137,6 +2175,7 @@ int cgroup_get_current_controller_path(p
> */
> if (ret != 3 || ret == EOF) {
> dbg("read failed for pid_cgroup_fd ret %d\n", ret);
> + last_errno = errno;
> ret = ECGOTHER;
> goto done;
> }
> @@ -2147,6 +2186,7 @@ int cgroup_get_current_controller_path(p
> == 0) {
> *current_path = strdup(cgroup_path);
> if (!*current_path) {
> + last_errno = errno;
> ret = ECGOTHER;
> goto done;
> }
> @@ -2168,5 +2208,19 @@ cleanup_path:
> char *cgroup_strerror(int code)
> {
> assert((code >= ECGROUPNOTCOMPILED) && (code < ECGSENTINEL));
> + if ((code == ECGOTHER) || (code == ECGCANTOPENCF)) {
> + snprintf(errtext, MAXLEN, "%s: %s",
> + cgroup_strerror_codes[code % ECGROUPNOTCOMPILED],
> + strerror(cgroup_get_last_errno()));
> + return errtext;
> + }
> return cgroup_strerror_codes[code % ECGROUPNOTCOMPILED];
> }
> +
> +/**
> + * Return last errno, which caused ECGOTHER/ECGCANTOPENCF error.
> + */
> +int cgroup_get_last_errno()
> +{
> + return last_errno;
> +}
> diff -up ./cgclassify.c.orig ./cgclassify.c
> --- ./cgclassify.c.orig 2009-02-16 10:55:07.000000000 +0100
> +++ ./cgclassify.c 2009-02-16 10:58:28.000000000 +0100
> @@ -140,7 +140,8 @@ int main(int argc, char *argv[])
> ret = cgroup_change_cgroup_uid_gid(euid, egid, pid);
> if (ret) {
> fprintf(stderr, "Error: change of cgroup failed for"
> - " pid %d\n", pid);
> + " pid %d: %s\n",
> + pid, cgroup_strerror(ret));
> return ret;
> }
> }
> diff -up ./libcgroup.h.orig ./libcgroup.h
> --- ./libcgroup.h.orig 2009-02-16 10:55:07.000000000 +0100
> +++ ./libcgroup.h 2009-02-16 10:58:28.000000000 +0100
> @@ -88,12 +88,13 @@ enum cgroup_errors {
> /* Represents error coming from other libraries like glibc. libcgroup
> * users need to check errno upon encoutering ECGOTHER.
> */
> - ECGOTHER,
> + ECGOTHER, /* OS error, see errno */
> ECGROUPNOTEQUAL,
> ECGCONTROLLERNOTEQUAL,
> ECGROUPPARSEFAIL, /* Failed to parse rules configuration file. */
> ECGROUPNORULES, /* Rules list does not exist. */
> ECGMOUNTFAIL,
> + ECGCANTOPENCF, /* OS error, see errno */
I am sorry, I don't understand the need for this at all
> ECGSENTINEL, /* Please insert further error codes above this */
> };
>
> @@ -195,6 +196,12 @@ int cgroup_get_current_controller_path(p
> */
> char *cgroup_strerror(int code);
>
> +/**
> + * Return last errno, which caused ECGOTHER error.
> + */
> +int cgroup_get_last_errno();
> +
> +
> /* The wrappers for filling libcg structures */
>
> struct cgroup *cgroup_new_cgroup(const char *name);
> diff -up ./libcgroup.map.orig ./libcgroup.map
> --- ./libcgroup.map.orig 2009-02-16 10:55:07.000000000 +0100
> +++ ./libcgroup.map 2009-02-16 11:16:16.000000000 +0100
> @@ -45,3 +45,9 @@ CGROUP_0.32.1 {
> global:
> cgroup_strerror;
> } CGROUP_0.32;
> +
> +CGROUP_0.33 {
> +global:
> + cgroup_get_last_errno;
> +} CGROUP_0.32.1;
> +
>
Overall, I like the patch except for the ECGCANTOPENCF, once I
understand your reason for adding it, I'll test and merge it.
--
Balbir
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel