-extern void relay_destroy_channel(struct kref *kref);
-
-#endif /* _RELAY_H */
-diff --git a/fs/sysfs/Makefile b/fs/sysfs/Makefile
-index 7a1ceb9..7bd4d8f 100644
---- a/fs/sysfs/Makefile
-+++ b/fs/sysfs/Makefile
-@@ -4,3 +4,4 @@
-
- obj-y := inode.o file.o dir.o symlink.o mount.o bin.o \
- group.o
-+obj-$(CONFIG_RELAY) += relay.o
-diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
-index 49bd219..52a759b 100644
---- a/fs/sysfs/dir.c
-+++ b/fs/sysfs/dir.c
-@@ -87,6 +87,20 @@ static int init_file(struct inode * inod
- return 0;
- }
-
-+#ifdef CONFIG_RELAY
-+static int init_relay_file(struct inode * inode)
-+{
-+ extern struct file_operations relay_file_operations;
-+ inode->i_fop = &relay_file_operations;
-+ return 0;
-+}
-+#else
-+static int init_relay_file(struct inode * inode)
-+{
-+ return -EINVAL;
-+}
-+#endif
-+
- static int init_symlink(struct inode * inode)
- {
- inode->i_op = &sysfs_symlink_inode_operations;
-@@ -165,6 +179,7 @@ int sysfs_create_dir(struct kobject * ko
- static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
- {
- struct attribute * attr = NULL;
-+ struct relay_attribute * rel_attr = NULL;
- struct bin_attribute * bin_attr = NULL;
- int (* init) (struct inode *) = NULL;
- int error = 0;
-@@ -172,6 +187,10 @@ static int sysfs_attach_attr(struct sysf
- if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
- bin_attr = sd->s_element;
- attr = &bin_attr->attr;
-+ } else if (sd->s_type & SYSFS_KOBJ_RELAY_ATTR) {
-+ rel_attr = sd->s_element;
-+ attr = &rel_attr->attr;
-+ init = init_relay_file;
- } else {
- attr = sd->s_element;
- init = init_file;
-@@ -189,6 +208,13 @@ static int sysfs_attach_attr(struct sysf
- dentry->d_inode->i_size = bin_attr->size;
- dentry->d_inode->i_fop = &bin_fops;
- }
-+
-+ if (rel_attr) {
-+ unsigned int size = rel_attr->subbuf_size * rel_attr->n_subbufs;
-+ dentry->d_inode->i_size = ((size - 1) & PAGE_MASK) + PAGE_SIZE;
-+ dentry->d_inode->u.generic_ip = rel_attr->rchan_buf;
-+ }
-+
- dentry->d_op = &sysfs_dentry_ops;
- d_rehash(dentry);
-
-diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
-index 689f7bc..d41cb6d 100644
---- a/fs/sysfs/inode.c
-+++ b/fs/sysfs/inode.c
-@@ -174,6 +174,7 @@ const unsigned char * sysfs_get_name(str
- {
- struct attribute * attr;
- struct bin_attribute * bin_attr;
-+ struct relay_attribute * rel_attr;
- struct sysfs_symlink * sl;
-
- if (!sd || !sd->s_element)
-@@ -192,6 +193,10 @@ const unsigned char * sysfs_get_name(str
- bin_attr = sd->s_element;
- return bin_attr->attr.name;
-
-+ case SYSFS_KOBJ_RELAY_ATTR:
-+ rel_attr = sd->s_element;
-+ return rel_attr->attr.name;
-+
- case SYSFS_KOBJ_LINK:
- sl = sd->s_element;
- return sl->link_name;
-diff --git a/fs/sysfs/relay.c b/fs/sysfs/relay.c
-new file mode 100644
-index 0000000..f40de18
---- /dev/null
-+++ b/fs/sysfs/relay.c
-@@ -0,0 +1,70 @@
-+/*
-+ * relay.c - relay channel buffer support for sysfs
-+ *
-+ * Copyright (C) 2006 Paul Mundt
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file "COPYING" in the main directory of this archive
-+ * for more details.
-+ */
-+#include <linux/relay.h>
-+#include <linux/namei.h>
-+#include <linux/module.h>
-+#include "sysfs.h"
-+
-+static struct dentry *
-+sysfs_create_buf_file(const char *filename, struct dentry *dentry, int mode,
-+ struct rchan_buf *buf, int *is_global)
-+{
-+ struct relay_attribute *attr = (struct relay_attribute *)dentry;
-+ struct dentry *parent = attr->kobj->dentry;
-+ int ret;
-+
-+ attr->attr.mode = mode;
-+ attr->rchan_buf = buf;
-+
-+ ret = sysfs_add_file(parent, &attr->attr, SYSFS_KOBJ_RELAY_ATTR);
-+ if (unlikely(ret != 0))
-+ return NULL;
-+
-+ dentry = lookup_one_len(filename, parent, strlen(filename));
-+ if (IS_ERR(dentry))
-+ sysfs_hash_and_remove(parent, filename);
-+
-+ return dentry;
-+}
-+
-+static int sysfs_remove_buf_file(struct dentry *dentry)
-+{
-+ sysfs_hash_and_remove(dentry, dentry->d_name.name);
-+ return 0;
-+}
-+
-+struct rchan_callbacks sysfs_rchan_callbacks = {
-+ .create_buf_file = sysfs_create_buf_file,
-+ .remove_buf_file = sysfs_remove_buf_file,
-+};
-+
-+int sysfs_create_relay_file(struct kobject *kobj, struct relay_attribute *attr)
-+{
-+ BUG_ON(!kobj || !kobj->dentry || !attr);
-+
-+ attr->kobj = kobj;
-+
-+ attr->rchan = relay_open(attr->attr.name, (void *)attr,
-+ attr->subbuf_size, attr->n_subbufs,
-+ &sysfs_rchan_callbacks);
-+ if (IS_ERR(attr->rchan))
-+ return PTR_ERR(attr->rchan);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(sysfs_create_relay_file);
-+
-+void sysfs_remove_relay_file(struct kobject *kobj, struct relay_attribute *attr)
-+{
-+ BUG_ON(!attr);
-+
-+ relay_close(attr->rchan);
-+}
-+EXPORT_SYMBOL_GPL(sysfs_remove_relay_file);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 860e7a4..266ce9d 100644
--- a/include/linux/blkdev.h
unsigned long sleep_avg;
unsigned long long timestamp, last_ran;
-diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
-index 392da5a..36a078e 100644
---- a/include/linux/sysfs.h
-+++ b/include/linux/sysfs.h
-@@ -44,6 +44,16 @@ struct attribute_group {
- .show = _name##_show, \
- }
-
-+#define __ATTR_RELAY(_name,_buffer_size,_nr_buffers) { \
-+ .attr = { \
-+ .owner = THIS_MODULE, \
-+ .name = __stringify(_name), \
-+ .mode = 0400, \
-+ }, \
-+ .subbuf_size = _buffer_size, \
-+ .n_subbufs = _nr_buffers, \
-+}
-+
- #define __ATTR_NULL { .attr = { .name = NULL } }
-
- #define attr_name(_attr) (_attr).attr.name
-@@ -60,6 +70,15 @@ struct bin_attribute {
- struct vm_area_struct *vma);
- };
-
-+struct relay_attribute {
-+ struct attribute attr;
-+ struct rchan *rchan;
-+ struct rchan_buf *rchan_buf;
-+ struct kobject *kobj;
-+ size_t subbuf_size;
-+ size_t n_subbufs;
-+};
-+
- struct sysfs_ops {
- ssize_t (*show)(struct kobject *, struct attribute *,char *);
- ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
-@@ -81,7 +100,23 @@ struct sysfs_dirent {
- #define SYSFS_KOBJ_ATTR 0x0004
- #define SYSFS_KOBJ_BIN_ATTR 0x0008
- #define SYSFS_KOBJ_LINK 0x0020
--#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
-+#define SYSFS_KOBJ_RELAY_ATTR 0x0040
-+#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | \
-+ SYSFS_KOBJ_LINK | SYSFS_KOBJ_RELAY_ATTR)
-+
-+#if defined(CONFIG_RELAY) && defined(CONFIG_SYSFS)
-+int sysfs_create_relay_file(struct kobject *, struct relay_attribute *);
-+void sysfs_remove_relay_file(struct kobject *, struct relay_attribute *);
-+#else
-+static inline int sysfs_create_relay_file(struct kobject *kobj, struct relay_attribute *attr)
-+{
-+ return 0;
-+}
-+
-+static inline void sysfs_remove_relay_file(struct kobject *kobj, struct relay_attribute *attr)
-+{
-+}
-+#endif /* CONFIG_RELAY && CONFIG_SYSFS */
-
- #ifdef CONFIG_SYSFS
-
diff --git a/init/Kconfig b/init/Kconfig
index 38416a1..fb74fdd 100644
--- a/init/Kconfig
+ bool "Kernel->user space relay support (formerly relayfs)"
+ help
+ This option enables support for relay interface support in
-+ certain file systems (such as sysfs, and trivially debugfs).
++ certain file systems (such as debugfs).
+ It is designed to provide an efficient mechanism for tools and
+ facilities to relay large amounts of data from kernel space to
+ user space.