Module: xenomai-forge
Branch: rtdm-api-waitqueues
Commit: aa44c70383cf68e37cb57c3a05ce4de15fef1974
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=aa44c70383cf68e37cb57c3a05ce4de15fef1974

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Apr 11 11:47:17 2014 +0200

copperplate/regd: rebase systemfs handlers over fsobstacks

This fixes a long-standing bug which caused random duplicate output
from the systemfs handlers, due to misusing the fuse read() method.

---

 include/copperplate/registry-obstack.h |    2 ++
 lib/copperplate/regd/fs-cobalt.c       |   47 +++++++++---------------
 lib/copperplate/regd/fs-common.c       |   61 ++++++++++++++++++--------------
 lib/copperplate/regd/fs-mercury.c      |   12 +++++--
 lib/copperplate/regd/regd.c            |    2 +-
 lib/copperplate/regd/sysregfs.h        |   14 +++-----
 6 files changed, 68 insertions(+), 70 deletions(-)

diff --git a/include/copperplate/registry-obstack.h 
b/include/copperplate/registry-obstack.h
index 0fd1e1c..aaafaa5 100644
--- a/include/copperplate/registry-obstack.h
+++ b/include/copperplate/registry-obstack.h
@@ -32,6 +32,8 @@
 #define obstack_chunk_alloc    pvmalloc
 #define obstack_chunk_free     pvfree
 
+struct threadobj;
+
 struct fsobstack {
        struct obstack obstack;
        void *data;
diff --git a/lib/copperplate/regd/fs-cobalt.c b/lib/copperplate/regd/fs-cobalt.c
index 1260e59..b7c1034 100644
--- a/lib/copperplate/regd/fs-cobalt.c
+++ b/lib/copperplate/regd/fs-cobalt.c
@@ -88,43 +88,24 @@ char *format_thread_status(const struct thread_data *p, 
char *buf, size_t len)
  */
 
 #define PROC_PULL_HANDLER(__name, __path)                              \
-ssize_t read_ ## __name(struct fsobj *fsobj, char *buf,                        
\
-                       size_t size, off_t offset,                      \
-                       void *priv)                                     \
+int open_ ## __name(struct fsobj *fsobj, void *priv)                   \
 {                                                                      \
-       return pull_proc_data("/proc/xenomai/" __path, buf, size);      \
+       return pull_proc_data("/proc/xenomai/" __path, priv);           \
 }
 
 /*
  * Cobalt-specific helper to pull the /proc vfile data provided by the
  * nucleus over a fuse-managed vfile.
  */
-static ssize_t pull_proc_data(const char *procpath, char *buf, size_t size)
+static int pull_proc_data(const char *path, struct fsobstack *o)
 {
-       size_t len = 0;
-       FILE *fp;
-       int c;
-
-       if (size == 0)
-               return 0;
-
-       fp = fopen(procpath, "r");
-       if (fp == NULL)
-               return -errno;
-
-       while (len < size) {
-               c = fgetc(fp);
-               if (c == EOF) {
-                       if (ferror(fp))
-                               len = -errno;
-                       break;
-               }
-               buf[len++] = c;
-       }
+       int len;
 
-       fclose(fp);
+       fsobstack_init(o);
+       len = fsobstack_grow_file(o, path);
+       fsobstack_finish(o);
 
-       return (ssize_t)len;
+       return len < 0 ? len : 0;
 }
 
 PROC_PULL_HANDLER(threads, "/sched/threads");
@@ -143,21 +124,27 @@ struct sysreg_fsfile sysreg_files[] = {
                .path = "/threads",
                .mode = O_RDONLY,
                .ops = {
-                       .read = read_threads,
+                       .open = open_threads,
+                       .release = fsobj_obstack_release,
+                       .read = fsobj_obstack_read
                },
        },
        {
                .path = "/heaps",
                .mode = O_RDONLY,
                .ops = {
-                       .read = read_heaps,
+                       .open = open_heaps,
+                       .release = fsobj_obstack_release,
+                       .read = fsobj_obstack_read
                },
        },
        {
                .path = "/version",
                .mode = O_RDONLY,
                .ops = {
-                       .read = read_version,
+                       .open = open_version,
+                       .release = fsobj_obstack_release,
+                       .read = fsobj_obstack_read
                },
        },
        {
diff --git a/lib/copperplate/regd/fs-common.c b/lib/copperplate/regd/fs-common.c
index b689b44..6346320 100644
--- a/lib/copperplate/regd/fs-common.c
+++ b/lib/copperplate/regd/fs-common.c
@@ -67,23 +67,23 @@ static char *format_time(ticks_t value, char *buf, size_t 
bufsz)
        return buf;
 }
 
-ssize_t read_threads(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset,
-                    void *priv)
+int open_threads(struct fsobj *fsobj, void *priv)
 {
        struct thread_data *thread_data, *p;
        char sbuf[64], pbuf[16], tbuf[64];
        struct threadobj_stat statbuf;
        struct sysgroup_memspec *obj;
+       struct fsobstack *o = priv;
        struct threadobj *thobj;
        const char *sched_class;
-       ssize_t len = 0;
-       int ret, count;
+       int ret, count, len = 0;
 
        ret = heapobj_bind_session(__node_info.session_label);
        if (ret)
                return ret;
 
+       fsobstack_init(o);
+
        sysgroup_lock();
        count = sysgroup_count(thread);
        sysgroup_unlock();
@@ -132,9 +132,9 @@ ssize_t read_threads(struct fsobj *fsobj, char *buf,
        if (count == 0)
                goto out_free;
 
-       len = sprintf(buf, "%-3s  %-6s %-5s  %-8s %-8s  %-10s %s\n",
-                       "CPU", "PID", "CLASS", "PRI", "TIMEOUT",
-                       "STAT", "NAME");
+       len = fsobstack_grow_format(o, "%-3s  %-6s %-5s  %-8s %-8s  %-10s %s\n",
+                                   "CPU", "PID", "CLASS", "PRI", "TIMEOUT",
+                                   "STAT", "NAME");
 
        for (p = thread_data; count > 0; count--) {
                if (kill(p->pid, 0))
@@ -173,10 +173,10 @@ ssize_t read_threads(struct fsobj *fsobj, char *buf,
                        sched_class = "other";
                        break;
                }
-               len += sprintf(buf + len,
-                              "%3u  %-6d %-5s  %-8s %-8s  %-10s %s\n",
-                              p->cpu, p->pid, sched_class, pbuf,
-                              tbuf, sbuf, p->name);
+               len += fsobstack_grow_format(o,
+                                            "%3u  %-6d %-5s  %-8s %-8s  %-10s 
%s\n",
+                                            p->cpu, p->pid, sched_class, pbuf,
+                                            tbuf, sbuf, p->name);
                p++;
        }
 
@@ -185,7 +185,9 @@ out_free:
 out:
        heapobj_unbind_session();
 
-       return len;
+       fsobstack_finish(o);
+
+       return len < 0 ? len : 0;
 }
 
 struct heap_data {
@@ -194,20 +196,20 @@ struct heap_data {
        size_t used;
 };
 
-ssize_t read_heaps(struct fsobj *fsobj, char *buf,
-                  size_t size, off_t offset,
-                  void *priv)
+int open_heaps(struct fsobj *fsobj, void *priv)
 {
        struct heap_data *heap_data, *p;
        struct sysgroup_memspec *obj;
+       struct fsobstack *o = priv;
        struct shared_heap *heap;
-       ssize_t len = 0;
-       int ret, count;
+       int ret, count, len = 0;
 
        ret = heapobj_bind_session(__node_info.session_label);
        if (ret)
                return ret;
 
+       fsobstack_init(o);
+
        sysgroup_lock();
        count = sysgroup_count(heap);
        sysgroup_unlock();
@@ -245,11 +247,12 @@ ssize_t read_heaps(struct fsobj *fsobj, char *buf,
        if (count == 0)
                goto out_free;
 
-       len = sprintf(buf, "%9s %9s  %s\n", "TOTAL", "USED", "NAME");
+       len = fsobstack_grow_format(o, "%9s %9s  %s\n",
+                                   "TOTAL", "USED", "NAME");
 
        for (p = heap_data; count > 0; count--) {
-               len += sprintf(buf + len, "%9Zu %9Zu  %s\n",
-                              p->total, p->used, p->name);
+               len += fsobstack_grow_format(o, "%9Zu %9Zu  %s\n",
+                                            p->total, p->used, p->name);
                p++;
        }
 
@@ -258,14 +261,20 @@ out_free:
 out:
        heapobj_unbind_session();
 
-       return len;
+       fsobstack_finish(o);
+
+       return len < 0 ? len : 0;
 }
 
 #endif /* CONFIG_XENO_PSHARED */
 
-ssize_t read_version(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset,
-                    void *priv)
+int open_version(struct fsobj *fsobj, void *priv)
 {
-       return sprintf(buf, "%s\n", XENO_VERSION_STRING);
+       struct fsobstack *o = priv;
+
+       fsobstack_init(o);
+       fsobstack_grow_format(o, "%s\n", XENO_VERSION_STRING);
+       fsobstack_finish(o);
+
+       return 0;
 }
diff --git a/lib/copperplate/regd/fs-mercury.c 
b/lib/copperplate/regd/fs-mercury.c
index a6a95a5..c1fed37 100644
--- a/lib/copperplate/regd/fs-mercury.c
+++ b/lib/copperplate/regd/fs-mercury.c
@@ -97,14 +97,18 @@ struct sysreg_fsfile sysreg_files[] = {
                .path = "/threads",
                .mode = O_RDONLY,
                .ops = {
-                       .read = read_threads,
+                       .open = open_threads,
+                       .release = fsobj_obstack_release,
+                       .read = fsobj_obstack_read
                },
        },
        {
                .path = "/heaps",
                .mode = O_RDONLY,
                .ops = {
-                       .read = read_heaps,
+                       .open = open_heaps,
+                       .release = fsobj_obstack_release,
+                       .read = fsobj_obstack_read
                },
        },
 #endif /* CONFIG_XENO_PSHARED */
@@ -112,7 +116,9 @@ struct sysreg_fsfile sysreg_files[] = {
                .path = "/version",
                .mode = O_RDONLY,
                .ops = {
-                       .read = read_version,
+                       .open = open_version,
+                       .release = fsobj_obstack_release,
+                       .read = fsobj_obstack_read
                },
        },
        {
diff --git a/lib/copperplate/regd/regd.c b/lib/copperplate/regd/regd.c
index b65c677..547f71d 100644
--- a/lib/copperplate/regd/regd.c
+++ b/lib/copperplate/regd/regd.c
@@ -380,7 +380,7 @@ static void create_system_fs(const char *arg0, const char 
*rootdir)
                registry_add_dir(d->path);
 
        for (f = sysreg_files; f->path != NULL; f++) {
-               registry_init_file(&f->fsobj, &f->ops, 0);
+               registry_init_file_obstack(&f->fsobj, &f->ops);
                ret = registry_add_file(&f->fsobj, f->mode, f->path);
                if (ret)
                        error(1, -ret, "failed to register %s", f->path);
diff --git a/lib/copperplate/regd/sysregfs.h b/lib/copperplate/regd/sysregfs.h
index dc2db31..0f9cca7 100644
--- a/lib/copperplate/regd/sysregfs.h
+++ b/lib/copperplate/regd/sysregfs.h
@@ -20,7 +20,7 @@
 #define _REGD_SYSREGFS_H
 
 #include <copperplate/clockobj.h>
-#include <copperplate/registry.h>
+#include <copperplate/registry-obstack.h>
 
 struct sysreg_fsdir {
        const char *path;
@@ -48,17 +48,11 @@ extern struct sysreg_fsdir sysreg_dirs[];
 
 extern struct sysreg_fsfile sysreg_files[];
 
-ssize_t read_threads(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset,
-                    void *priv);
+int open_threads(struct fsobj *fsobj, void *priv);
 
-ssize_t read_heaps(struct fsobj *fsobj, char *buf,
-                  size_t size, off_t offset,
-                  void *priv);
+int open_heaps(struct fsobj *fsobj, void *priv);
 
-ssize_t read_version(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset,
-                    void *priv);
+int open_version(struct fsobj *fsobj, void *priv);
 
 char *format_thread_status(const struct thread_data *p,
                           char *buf, size_t len);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to