Module: xenomai-forge
Branch: next
Commit: b6c8adb2c2b967c93b1c52c5b01bd653b0488f4d
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=b6c8adb2c2b967c93b1c52c5b01bd653b0488f4d

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Feb  3 15:04:25 2014 +0100

copperplate/registry: introduce per-file private data, downgrade to FUSE_2.5 API

In order to make use of the private fuse_file_info::fh data passed to
the fs handlers, we have to work around a glibc dynamic linker bug (*):
https://sourceware.org/bugzilla/show_bug.cgi?id=12977
http://www.xenomai.org/pipermail/xenomai/2013-October/029301.html

We do this by downgrading to the fuse API rev 2.5, which binds
references to versioned fuse symbols explicitly to the proper
implementation for FUSE_2.5, working around the symbol lookup in dl.

(*) otherwise, the dl bug causes a reference to fuse_main() to be
resolved as a call to fuse_mail_real_compat22() instead of
fuse_mail_real_compat25(), introducing a nasty mismatch with the
fuse_file_info layout.

---

 configure                        |    4 ++--
 configure.ac                     |    4 ++--
 include/copperplate/registry.h   |   20 +++++++++-------
 lib/copperplate/regd/fs-cobalt.c |    3 ++-
 lib/copperplate/regd/fs-common.c |   17 +++++++++++---
 lib/copperplate/regd/regd.c      |    2 +-
 lib/copperplate/regd/sysregfs.h  |    9 ++++---
 lib/copperplate/registry.c       |   48 ++++++++++++++++++++++++++++----------
 8 files changed, 75 insertions(+), 32 deletions(-)

diff --git a/configure b/configure
index 28d6ce4..b3ec7ac 100755
--- a/configure
+++ b/configure
@@ -12937,7 +12937,7 @@ fi
 $as_echo "${use_registry:-no}" >&6; }
 
 if test x$use_registry = xy; then
-       fuse_cflags="-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26"
+       fuse_cflags="-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=25"
        fuse_ldflags="-lfuse"
 
        ac_ext=c
@@ -13019,7 +13019,7 @@ $as_echo "#define CONFIG_XENO_REGISTRY 1" >>confdefs.h
 $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h
 
 
-$as_echo "#define FUSE_USE_VERSION 26" >>confdefs.h
+$as_echo "#define FUSE_USE_VERSION 25" >>confdefs.h
 
 fi
  if test x$use_registry = xy; then
diff --git a/configure.ac b/configure.ac
index f3e37d3..791f12e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,7 +286,7 @@ AC_ARG_ENABLE(registry,
 AC_MSG_RESULT(${use_registry:-no})
 
 if test x$use_registry = xy; then
-       fuse_cflags="-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26"
+       fuse_cflags="-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=25"
        fuse_ldflags="-lfuse"
        AC_LANG_SAVE
        AC_LANG_C
@@ -303,7 +303,7 @@ if test x$use_registry = xy; then
        AC_LANG_RESTORE
        AC_DEFINE(CONFIG_XENO_REGISTRY,1,[config])
        AC_DEFINE(_FILE_OFFSET_BITS,64,[config])
-       AC_DEFINE(FUSE_USE_VERSION,26,[config])
+       AC_DEFINE(FUSE_USE_VERSION,25,[config])
 fi
 AM_CONDITIONAL(XENO_REGISTRY,[test x$use_registry = xy])
 
diff --git a/include/copperplate/registry.h b/include/copperplate/registry.h
index 84a7d84..2de86a6 100644
--- a/include/copperplate/registry.h
+++ b/include/copperplate/registry.h
@@ -32,12 +32,14 @@ struct fsobj;
 #ifdef CONFIG_XENO_REGISTRY
 
 struct registry_operations {
-       int (*open)(struct fsobj *fsobj);
-       int (*release)(struct fsobj *fsobj);
+       int (*open)(struct fsobj *fsobj, void *priv);
+       int (*release)(struct fsobj *fsobj, void *priv);
        ssize_t (*read)(struct fsobj *fsobj,
-                       char *buf, size_t size, off_t offset);
+                       char *buf, size_t size, off_t offset,
+                       void *priv);
        ssize_t (*write)(struct fsobj *fsobj,
-                        const char *buf, size_t size, off_t offset);
+                        const char *buf, size_t size, off_t offset,
+                        void *priv);
 };
 
 struct regfs_dir;
@@ -47,6 +49,7 @@ struct fsobj {
        char *path;
        const char *basename;
        int mode;
+       size_t privsz;
        struct regfs_dir *dir;
        struct timespec ctime;
        struct timespec mtime;
@@ -62,7 +65,8 @@ extern "C" {
 int registry_add_dir(const char *fmt, ...);
 
 void registry_init_file(struct fsobj *fsobj,
-                       const struct registry_operations *ops);
+                       const struct registry_operations *ops,
+                       size_t privsz);
 
 int registry_add_file(struct fsobj *fsobj,
                      int mode,
@@ -97,10 +101,10 @@ int registry_add_dir(const char *fmt, ...)
 }
 
 static inline
-int registry_init_file(struct fsobj *fsobj,
-                      const struct registry_operations *ops)
+void registry_init_file(struct fsobj *fsobj,
+                       const struct registry_operations *ops,
+                       size_t privsz)
 {
-       return 0;
 }
 
 static inline
diff --git a/lib/copperplate/regd/fs-cobalt.c b/lib/copperplate/regd/fs-cobalt.c
index c2a7a0d..1260e59 100644
--- a/lib/copperplate/regd/fs-cobalt.c
+++ b/lib/copperplate/regd/fs-cobalt.c
@@ -89,7 +89,8 @@ 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)                      \
+                       size_t size, off_t offset,                      \
+                       void *priv)                                     \
 {                                                                      \
        return pull_proc_data("/proc/xenomai/" __path, buf, size);      \
 }
diff --git a/lib/copperplate/regd/fs-common.c b/lib/copperplate/regd/fs-common.c
index ea34148..b689b44 100644
--- a/lib/copperplate/regd/fs-common.c
+++ b/lib/copperplate/regd/fs-common.c
@@ -68,7 +68,8 @@ static char *format_time(ticks_t value, char *buf, size_t 
bufsz)
 }
 
 ssize_t read_threads(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset)
+                    size_t size, off_t offset,
+                    void *priv)
 {
        struct thread_data *thread_data, *p;
        char sbuf[64], pbuf[16], tbuf[64];
@@ -148,18 +149,26 @@ ssize_t read_threads(struct fsobj *fsobj, char *buf,
                case SCHED_RR:
                        sched_class = "rr";
                        break;
+#ifdef SCHED_SPORADIC
                case SCHED_SPORADIC:
                        sched_class = "pss";
                        break;
+#endif
+#ifdef SCHED_TP
                case SCHED_TP:
                        sched_class = "tp";
                        break;
+#endif
+#ifdef SCHED_QUOTA
                case SCHED_QUOTA:
                        sched_class = "quota";
                        break;
+#endif
+#ifdef SCHED_QUOTA
                case SCHED_WEAK:
                        sched_class = "weak";
                        break;
+#endif
                default:
                        sched_class = "other";
                        break;
@@ -186,7 +195,8 @@ struct heap_data {
 };
 
 ssize_t read_heaps(struct fsobj *fsobj, char *buf,
-                  size_t size, off_t offset)
+                  size_t size, off_t offset,
+                  void *priv)
 {
        struct heap_data *heap_data, *p;
        struct sysgroup_memspec *obj;
@@ -254,7 +264,8 @@ out:
 #endif /* CONFIG_XENO_PSHARED */
 
 ssize_t read_version(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset)
+                    size_t size, off_t offset,
+                    void *priv)
 {
        return sprintf(buf, "%s\n", XENO_VERSION_STRING);
 }
diff --git a/lib/copperplate/regd/regd.c b/lib/copperplate/regd/regd.c
index 1956425..b65c677 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);
+               registry_init_file(&f->fsobj, &f->ops, 0);
                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 13f7e61..dc2db31 100644
--- a/lib/copperplate/regd/sysregfs.h
+++ b/lib/copperplate/regd/sysregfs.h
@@ -49,13 +49,16 @@ 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);
+                    size_t size, off_t offset,
+                    void *priv);
 
 ssize_t read_heaps(struct fsobj *fsobj, char *buf,
-                  size_t size, off_t offset);
+                  size_t size, off_t offset,
+                  void *priv);
 
 ssize_t read_version(struct fsobj *fsobj, char *buf,
-                    size_t size, off_t offset);
+                    size_t size, off_t offset,
+                    void *priv);
 
 char *format_thread_status(const struct thread_data *p,
                           char *buf, size_t len);
diff --git a/lib/copperplate/registry.c b/lib/copperplate/registry.c
index d074243..f3e7b56 100644
--- a/lib/copperplate/registry.c
+++ b/lib/copperplate/registry.c
@@ -151,7 +151,8 @@ done:
 }
 
 void registry_init_file(struct fsobj *fsobj, 
-                       const struct registry_operations *ops)
+                       const struct registry_operations *ops,
+                       size_t privsz)
 {
        pthread_mutexattr_t mattr;
 
@@ -160,6 +161,7 @@ void registry_init_file(struct fsobj *fsobj,
 
        fsobj->path = NULL;
        fsobj->ops = ops;
+       fsobj->privsz = privsz;
        pvholder_init(&fsobj->link);
 
        __RT(pthread_mutexattr_init(&mattr));
@@ -362,6 +364,7 @@ static int regfs_open(const char *path, struct 
fuse_file_info *fi)
        struct pvhashobj *hobj;
        struct fsobj *fsobj;
        int ret = 0;
+       void *priv;
 
        read_lock_nocancel(&p->lock);
 
@@ -372,10 +375,23 @@ static int regfs_open(const char *path, struct 
fuse_file_info *fi)
        }
 
        fsobj = container_of(hobj, struct fsobj, hobj);
-       if (((fi->flags + 1) & (fsobj->mode + 1)) == 0)
+       if (((fi->flags + 1) & (fsobj->mode + 1)) == 0) {
                ret = -EACCES;
-       else if (fsobj->ops->open)
-               ret = __bt(fsobj->ops->open(fsobj));
+               goto done;
+       }
+
+       if (fsobj->privsz) {
+               priv = __STD(malloc(fsobj->privsz));
+               if (priv == NULL) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+       } else
+               priv = NULL;
+
+       fi->fh = (uintptr_t)priv;
+       if (fsobj->ops->open)
+               ret = __bt(fsobj->ops->open(fsobj, priv));
 done:
        read_unlock(&p->lock);
 
@@ -388,6 +404,7 @@ static int regfs_release(const char *path, struct 
fuse_file_info *fi)
        struct pvhashobj *hobj;
        struct fsobj *fsobj;
        int ret = 0;
+       void *priv;
 
        read_lock_nocancel(&p->lock);
 
@@ -398,8 +415,11 @@ static int regfs_release(const char *path, struct 
fuse_file_info *fi)
        }
 
        fsobj = container_of(hobj, struct fsobj, hobj);
+       priv = (void *)(uintptr_t)fi->fh;
        if (fsobj->ops->release)
-               ret = __bt(fsobj->ops->release(fsobj));
+               ret = __bt(fsobj->ops->release(fsobj, priv));
+       if (priv)
+               __STD(free(priv));
 done:
        read_unlock(&p->lock);
 
@@ -412,6 +432,7 @@ static int regfs_read(const char *path, char *buf, size_t 
size, off_t offset,
        struct regfs_data *p = regfs_get_context();
        struct pvhashobj *hobj;
        struct fsobj *fsobj;
+       void *priv;
        int ret;
 
        read_lock_nocancel(&p->lock);
@@ -431,7 +452,8 @@ static int regfs_read(const char *path, char *buf, size_t 
size, off_t offset,
        push_cleanup_lock(&fsobj->lock);
        read_lock(&fsobj->lock);
        read_unlock(&p->lock);
-       ret = fsobj->ops->read(fsobj, buf, size, offset);
+       priv = (void *)(uintptr_t)fi->fh;
+       ret = fsobj->ops->read(fsobj, buf, size, offset, priv);
        read_unlock(&fsobj->lock);
        pop_cleanup_lock(&fsobj->lock);
 
@@ -444,6 +466,7 @@ static int regfs_write(const char *path, const char *buf, 
size_t size, off_t off
        struct regfs_data *p = regfs_get_context();
        struct pvhashobj *hobj;
        struct fsobj *fsobj;
+       void *priv;
        int ret;
 
        read_lock_nocancel(&p->lock);
@@ -463,7 +486,8 @@ static int regfs_write(const char *path, const char *buf, 
size_t size, off_t off
        push_cleanup_lock(&fsobj->lock);
        read_lock(&fsobj->lock);
        read_unlock(&p->lock);
-       ret = fsobj->ops->write(fsobj, buf, size, offset);
+       priv = (void *)(uintptr_t)fi->fh;
+       ret = fsobj->ops->write(fsobj, buf, size, offset, priv);
        read_unlock(&fsobj->lock);
        pop_cleanup_lock(&fsobj->lock);
 
@@ -485,7 +509,7 @@ static int regfs_chown(const char *path, uid_t uid, gid_t 
gid)
        return 0;
 }
 
-static void *regfs_init(struct fuse_conn_info *conn)
+static void *regfs_init(void)
 {
        struct regfs_data *p = regfs_get_context();
        struct sigaction sa;
@@ -540,7 +564,7 @@ static void *registry_thread(void *arg)
         * Once connected to sysregd, we don't have to care for the
         * mount point, sysregd will umount(2) it when we go away.
         */
-       ret = fuse_main(6, av, &regfs_opts, NULL);
+       ret = fuse_main(6, av, &regfs_opts);
        if (ret) {
                warning("can't mount registry onto %s", p->mountpt);
                /* Attempt to figure out why we failed. */
@@ -593,7 +617,7 @@ static int connect_regd(const char *sessdir, char **mountpt)
        unsigned int hash;
        socklen_t addrlen;
 
-       *mountpt = malloc(PATH_MAX);
+       *mountpt = __STD(malloc(PATH_MAX));
        if (*mountpt == NULL)
                return -ENOMEM;
 
@@ -748,13 +772,13 @@ int fsobstack_grow_format(struct fsobstack *o, const char 
*fmt, ...)
                       obstack_grow(&o->obstack, p, n);
 
               if (p != buf)
-                      xnfree(p);
+                      pvfree(p);
 
                if (n < len)
                       return n < 0 ? -EINVAL : n;
 
               len = n + 1;
-              p = xnmalloc(len);
+              p = pvmalloc(len);
               if (p == NULL)
                       break;
            }


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

Reply via email to