]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
This patch store the last errno value to last_errno value and add
authorBalbir Singh <balbir@linux.vnet.ibm.com>
Mon, 16 Feb 2009 13:34:12 +0000 (13:34 +0000)
committerBalbir Singh <balbir@linux.vnet.ibm.com>
Mon, 16 Feb 2009 13:34:12 +0000 (13:34 +0000)
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

api.c
cgclassify.c
cgconfig.c
config.c
libcgroup.h
libcgroup.map

diff --git a/api.c b/api.c
index 647841f2c5ae380a5771a83d94d0ee3bc0bf27d7..72f8c69ba6d074ae311532b4f4e5651903e4beda 100644 (file)
--- a/api.c
+++ b/api.c
 
 #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.
  */
@@ -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;
+}
index c41f52983b845ea4ba4da5f920fa33787c05d5cd..4f7adb4e566e7e5e5c93873833878c9cac701499 100644 (file)
@@ -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;
                }
        }
index 043678a76055c93d0ac9f326cda8a5eb6db7e3df..cc33ad9fa812f2651234f826e9f277de588e525d 100644 (file)
@@ -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);
                        }
index 154ebadf5bf0b726a2766c82f33804defb2720c6..95782f6b4db374049ada7f83d351cbeabe9f82b1 100644 (file)
--- a/config.c
+++ b/config.c
@@ -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;
        }
 
index 37bc8887ba1c29e89a24706330f50f1f010db399..dee4648619cfe134f7b68d8de9b500cd04e7913f 100644 (file)
@@ -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);
index 3b55ff284334bdd930ed8b9a277ef77b8f2aaf9d..fffe44806dbfe376516ecc694603a077c9da71bd 100644 (file)
@@ -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;
+