diff options
author | Balbir Singh <balbir@linux.vnet.ibm.com> | 2009-02-16 13:34:12 +0000 |
---|---|---|
committer | Balbir Singh <balbir@linux.vnet.ibm.com> | 2009-02-16 13:34:12 +0000 |
commit | dedcfa480ee21b9bb87964eb1e2665fe6a200b4c (patch) | |
tree | 61e4516a1f28071d8cb6604f8adb330eb598d3a0 | |
parent | b4ca5d9b4a38994aa71fbdb14fd5d65c81bf5216 (diff) | |
download | libcg-dedcfa480ee21b9bb87964eb1e2665fe6a200b4c.tar.gz libcg-dedcfa480ee21b9bb87964eb1e2665fe6a200b4c.tar.xz libcg-dedcfa480ee21b9bb87964eb1e2665fe6a200b4c.zip |
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 is returned.
[balbir@linux.vnet.ibm.com: fix last_errno in config.c]
Signed-off-by: Ivana Varekova <varekova@redhat.com>
Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
git-svn-id: https://libcg.svn.sourceforge.net/svnroot/libcg/trunk@329 4f4bb910-9a46-0410-90c8-c897d4f1cd53
-rw-r--r-- | api.c | 70 | ||||
-rw-r--r-- | cgclassify.c | 3 | ||||
-rw-r--r-- | cgconfig.c | 2 | ||||
-rw-r--r-- | config.c | 12 | ||||
-rw-r--r-- | libcgroup.h | 13 | ||||
-rw-r--r-- | libcgroup.map | 6 |
6 files changed, 92 insertions, 14 deletions
@@ -49,6 +49,16 @@ #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]; + +/* * Remember to bump this up for major API changes. */ const static char cg_version[] = VERSION(PACKAGE_VERSION); @@ -94,6 +104,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 +305,15 @@ static int cgroup_parse_rules(bool cache, uid_t muid, gid_t mgid) dbg("Failed to open configuration file %s with" " error: %s\n", CGRULES_CONF_FILE, strerror(errno)); - ret = errno; + last_errno = 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, uid_t muid, gid_t mgid) 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 *cgroup, pid_t tid) 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 *cgroup, pid_t tid) } 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 *cgroup, pid_t tid) } 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 *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 *cgroup, int ignore_ownership) base = strdup(path); if (!base) { + last_errno = errno; error = ECGOTHER; goto err; } @@ -1191,6 +1216,7 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership) 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 *cgroup, int ignore_ownership) 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, int ignore_migration) 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, char *cgroup, char *file, char **value) 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 *cgroup) 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 *cgroup) dir = opendir(path); if (!dir) { + last_errno = errno; error = ECGOTHER; goto unlock_error; } @@ -1739,8 +1775,10 @@ static int cg_prepare_controller_array(char *cstr, char *controllers[]) 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(pid_t pid, const char *controller, */ 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(pid_t pid, const char *controller, == 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) { + snprintf(errtext, MAXLEN, "%s: error message: %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 error. + */ +int cgroup_get_last_errno() +{ + return last_errno; +} diff --git a/cgclassify.c b/cgclassify.c index c41f529..4f7adb4 100644 --- a/cgclassify.c +++ b/cgclassify.c @@ -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; } } @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) ret = cgroup_config_load_config(filename); if (ret) { printf("Loading configuration file %s " - "failed, error: %s\n", filename, + "failed\n%s\n", filename, cgroup_strerror(ret)); exit(3); } @@ -339,17 +339,22 @@ int cgroup_config_mount_fs() struct cg_mount_table_s *curr = &(config_mount_table[i]); ret = stat(curr->path, &buff); - - if (ret < 0 && errno != ENOENT) + + if (ret < 0 && errno != ENOENT) { + last_errno = errno; return ECGOTHER; + } if (errno == ENOENT) { ret = mkdir(curr->path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (ret < 0) + if (ret < 0) { + last_errno = errno; return ECGOTHER; + } } else if (!S_ISDIR(buff.st_mode)) { errno = ENOTDIR; + last_errno = errno; return ECGOTHER; } @@ -432,6 +437,7 @@ int cgroup_config_load_config(const char *pathname) if (!yyin) { dbg("Failed to open file %s\n", pathname); + last_errno = errno; return ECGOTHER; } diff --git a/libcgroup.h b/libcgroup.h index 37bc888..dee4648 100644 --- a/libcgroup.h +++ b/libcgroup.h @@ -68,6 +68,11 @@ enum cgflags { CGFLAG_USECACHE = 0x01, }; +/** + * per thread errno variable, to be used when return code is ECGOTHER + */ +extern __thread int last_errno; + enum cgroup_errors { ECGROUPNOTCOMPILED=50000, ECGROUPNOTMOUNTED, @@ -88,7 +93,7 @@ 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. */ @@ -195,6 +200,12 @@ int cgroup_get_current_controller_path(pid_t pid, const char *controller, */ 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 --git a/libcgroup.map b/libcgroup.map index 3b55ff2..fffe448 100644 --- a/libcgroup.map +++ b/libcgroup.map @@ -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; + |