2007-09-20 07:05:59

by Tejun Heo

[permalink] [raw]
Subject: [PATCHSET 1/4] sysfs: misc updates

Hello, all.

There are four patchsets going out today, which are...

PS-1 misc updates
PS-2 allow suicide
PS-3 divorce sysfs from kobject and driver model
PS-4 implement new features - symlink name formatting, plugging, batch
error handling

And this is PS-1. This patchset is on top of
drivers/sysfs-rewrite-sysfs_move_dir-in-terms-of-sysfs-dirents.patch
in gregkh-2.6 as of today (20070920, based on 2.6.23-rc6-git4) and
contains the following 15 patches.

0001-sysfs-kill-SYSFS_FLAG_REMOVED.patch
0002-sysfs-fix-comments-of-sysfs_add-remove_one.patch
0003-sysfs-fix-sysfs_chmod_file-such-that-it-updates-s.patch
0004-sysfs-clean-up-header-files.patch
0005-sysfs-kill-sysfs_update_file.patch
0006-sysfs-reposition-sysfs_dirent-s_mode.patch
0007-sysfs-kill-unnecessary-sysfs_get-in-open-paths.patch
0008-sysfs-kill-unnecessary-NULL-pointer-check-in-sysfs_.patch
0009-sysfs-make-bin-attr-open-get-active-reference-of-pa.patch
0010-sysfs-make-s_elem-an-anonymous-union.patch
0011-sysfs-open-code-sysfs_attach_dentry.patch
0012-sysfs-make-sysfs_root-a-regular-directory-dirent.patch
0013-sysfs-move-sysfs_dirent-s_children-into-sysfs_dire.patch
0014-sysfs-implement-sysfs_open_dirent.patch
0015-sysfs-move-sysfs-file-poll-implementation-to-sysfs_.patch

0001 reverses earlier driver/sysfs-kill-sysfs_flag_removed.patch and
as such both patches can just be dropped.

0002-0003 contains misc fixes. 0004 reorganizes and cleans up sysfs
header files. As these four patchsets are gonna disrupt out-of-tree
changes anyway, this is a good time to clean up. 0005-0013 are also
clean up patches. They change and tune things here and there but
don't really cause behavior changes.

0014-0015 implements sysfs_open_dirent and moves poll implementation
to it. This reduces the size of sysfs_dirent and fixes dangling
sleeper bug in the current poll implementation.

Thanks.

--
tejun



2007-09-20 07:05:32

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 03/15] sysfs: fix sysfs_chmod_file() such that it updates sd->s_mode too

sysfs_chmod_file() looked and updated only inode of the target file.
Dentry and inode are reclaimable and the update mode data will go away
when the inode is reclaimed. This patch makes sysfs_chmod_file()
update sd->s_mode too such that the change is permanent.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/file.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index ff93c92..9fdf8da 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -521,10 +521,19 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
}

inode = victim->d_inode;
+
mutex_lock(&inode->i_mutex);
+
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
rc = notify_change(victim, &newattrs);
+
+ if (rc == 0) {
+ mutex_lock(&sysfs_mutex);
+ victim_sd->s_mode = newattrs.ia_mode;
+ mutex_unlock(&sysfs_mutex);
+ }
+
mutex_unlock(&inode->i_mutex);
out:
dput(victim);
--
1.5.0.3


2007-09-20 07:05:47

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 02/15] sysfs: fix comments of sysfs_add/remove_one()

sysfs_add/remove_one() now link and unlink the target dirent into and
from the children list. Update comments accordingly.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/dir.c | 10 +++-------
1 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index da4bb66..e85206c 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -410,10 +410,8 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
* @sd: sysfs_dirent to be added
*
* Get @acxt->parent_sd and set sd->s_parent to it and increment
- * nlink of parent inode if @sd is a directory. @sd is NOT
- * linked into the children list of the parent. The caller
- * should invoke sysfs_link_sibling() after this function
- * completes if @sd needs to be on the children list.
+ * nlink of parent inode if @sd is a directory and link into the
+ * children list of the parent.
*
* This function should be called between calls to
* sysfs_addrm_start() and sysfs_addrm_finish() and should be
@@ -449,9 +447,7 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
* @sd: sysfs_dirent to be added
*
* Mark @sd removed and drop nlink of parent inode if @sd is a
- * directory. @sd is NOT unlinked from the children list of the
- * parent. The caller is repsonsible for removing @sd from the
- * children list before calling this function.
+ * directory. @sd is unlinked from the children list.
*
* This function should be called between calls to
* sysfs_addrm_start() and sysfs_addrm_finish() and should be
--
1.5.0.3


2007-09-20 07:06:27

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 01/15] sysfs: kill SYSFS_FLAG_REMOVED

With sysfs_get_dentry() simplified, there's no user of
SYSFS_FLAG_REMOVED left. Kill it.

Signed-off-by: Tejun Heo <[email protected]>
---
This patch reverts driver/sysfs-kill-sysfs_flag_removed.patch and thus
can be removed together with it.

fs/sysfs/dir.c | 5 ++++-
include/linux/sysfs.h | 1 +
2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index a493c6f..da4bb66 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -222,7 +222,7 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
DECLARE_COMPLETION_ONSTACK(wait);
int v;

- BUG_ON(sd->s_sibling);
+ BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
sd->s_sibling = (void *)&wait;

/* atomic_add_return() is a mb(), put_active() will always see
@@ -462,8 +462,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
*/
void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
{
+ BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED);
+
sysfs_unlink_sibling(sd);

+ sd->s_flags |= SYSFS_FLAG_REMOVED;
sd->s_sibling = acxt->removed;
acxt->removed = sd;

diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 82c31b2..c16e4c5 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -83,6 +83,7 @@ struct sysfs_ops {
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)

#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
+#define SYSFS_FLAG_REMOVED 0x0100

#ifdef CONFIG_SYSFS

--
1.5.0.3


2007-09-20 07:06:42

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 04/15] sysfs: clean up header files

sysfs is about to go through major overhaul making this a pretty good
opportunity to clean up (out-of-tree changes and pending patches will
need regeneration anyway). Clean up headers.

* Kill space between * and symbolname.

* Move SYSFS_* type constants and flags into fs/sysfs/sysfs.h.
They're internal to sysfs.

* Reformat function prototypes and add argument symbol names.

* Make dummy function definition order match that of function
prototypes.

* Add some comments.

* Reorganize fs/sysfs/sysfs.h according to which file the declared
variable or feature lives in.

This patch does not introduce any behavior change.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/sysfs.h | 148 ++++++++++++++++++++++++++++++------------------
include/linux/sysfs.h | 127 +++++++++++++++++++-----------------------
2 files changed, 149 insertions(+), 126 deletions(-)

diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 791b3ed..63adbec 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,20 +1,24 @@
+/* type-specific structures for sysfs_dirent->s_* union members */
struct sysfs_elem_dir {
- struct kobject * kobj;
+ struct kobject *kobj;
};

struct sysfs_elem_symlink {
- struct sysfs_dirent * target_sd;
+ struct sysfs_dirent *target_sd;
};

struct sysfs_elem_attr {
- struct attribute * attr;
+ struct attribute *attr;
};

struct sysfs_elem_bin_attr {
- struct bin_attribute * bin_attr;
+ struct bin_attribute *bin_attr;
};

/*
+ * sysfs_dirent - the building block of sysfs hierarchy. Each and
+ * every sysfs node is represented by single sysfs_dirent.
+ *
* As long as s_count reference is held, the sysfs_dirent itself is
* accessible. Dereferencing s_elem or any other outer entity
* requires s_active reference.
@@ -22,10 +26,10 @@ struct sysfs_elem_bin_attr {
struct sysfs_dirent {
atomic_t s_count;
atomic_t s_active;
- struct sysfs_dirent * s_parent;
- struct sysfs_dirent * s_sibling;
- struct sysfs_dirent * s_children;
- const char * s_name;
+ struct sysfs_dirent *s_parent;
+ struct sysfs_dirent *s_sibling;
+ struct sysfs_dirent *s_children;
+ const char *s_name;

union {
struct sysfs_elem_dir dir;
@@ -37,12 +41,31 @@ struct sysfs_dirent {
unsigned int s_flags;
umode_t s_mode;
ino_t s_ino;
- struct iattr * s_iattr;
+ struct iattr *s_iattr;
atomic_t s_event;
};

-#define SD_DEACTIVATED_BIAS INT_MIN
+#define SD_DEACTIVATED_BIAS INT_MIN

+#define SYSFS_TYPE_MASK 0x00ff
+#define SYSFS_ROOT 0x0001
+#define SYSFS_DIR 0x0002
+#define SYSFS_KOBJ_ATTR 0x0004
+#define SYSFS_KOBJ_BIN_ATTR 0x0008
+#define SYSFS_KOBJ_LINK 0x0020
+#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
+
+#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
+#define SYSFS_FLAG_REMOVED 0x0200
+
+static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
+{
+ return sd->s_flags & SYSFS_TYPE_MASK;
+}
+
+/*
+ * Context structure to be used while adding/removing nodes.
+ */
struct sysfs_addrm_cxt {
struct sysfs_dirent *parent_sd;
struct inode *parent_inode;
@@ -50,59 +73,47 @@ struct sysfs_addrm_cxt {
int cnt;
};

+/*
+ * mount.c
+ */
extern struct sysfs_dirent sysfs_root;
+extern struct super_block *sysfs_sb;
extern struct kmem_cache *sysfs_dir_cachep;

-extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
-extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
-extern void sysfs_put_active(struct sysfs_dirent *sd);
-extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
-extern void sysfs_put_active_two(struct sysfs_dirent *sd);
-extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
- struct sysfs_dirent *parent_sd);
-extern int sysfs_add_one(struct sysfs_addrm_cxt *acxt,
- struct sysfs_dirent *sd);
-extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
- struct sysfs_dirent *sd);
-extern void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
-
-extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
-
-extern void release_sysfs_dirent(struct sysfs_dirent * sd);
-extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
- const unsigned char *name);
-extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
- const unsigned char *name);
-extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
- int type);
-
-extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
- const struct attribute *attr, int type);
-extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
-extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
-
-extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
- struct sysfs_dirent **p_sd);
-extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
-
-extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
-
-extern spinlock_t sysfs_assoc_lock;
+/*
+ * dir.c
+ */
extern struct mutex sysfs_mutex;
extern struct mutex sysfs_rename_mutex;
-extern struct super_block * sysfs_sb;
+extern spinlock_t sysfs_assoc_lock;
+
extern const struct file_operations sysfs_dir_operations;
-extern const struct file_operations sysfs_file_operations;
-extern const struct file_operations bin_fops;
extern const struct inode_operations sysfs_dir_inode_operations;
-extern const struct inode_operations sysfs_symlink_inode_operations;

-static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
-{
- return sd->s_flags & SYSFS_TYPE_MASK;
-}
-
-static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
+struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+void sysfs_put_active(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
+void sysfs_put_active_two(struct sysfs_dirent *sd);
+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+ struct sysfs_dirent *parent_sd);
+int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
+void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
+void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
+
+struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name);
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name);
+struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
+
+void release_sysfs_dirent(struct sysfs_dirent *sd);
+
+int sysfs_create_subdir(struct kobject *kobj, const char *name,
+ struct sysfs_dirent **p_sd);
+void sysfs_remove_subdir(struct sysfs_dirent *sd);
+
+static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
{
if (sd) {
WARN_ON(!atomic_read(&sd->s_count));
@@ -111,8 +122,33 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
return sd;
}

-static inline void sysfs_put(struct sysfs_dirent * sd)
+static inline void sysfs_put(struct sysfs_dirent *sd)
{
if (sd && atomic_dec_and_test(&sd->s_count))
release_sysfs_dirent(sd);
}
+
+/*
+ * inode.c
+ */
+struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
+int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
+
+/*
+ * file.c
+ */
+extern const struct file_operations sysfs_file_operations;
+
+int sysfs_add_file(struct sysfs_dirent *dir_sd,
+ const struct attribute *attr, int type);
+
+/*
+ * bin.c
+ */
+extern const struct file_operations bin_fops;
+
+/*
+ * symlink.c
+ */
+extern const struct inode_operations sysfs_symlink_inode_operations;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index c16e4c5..b393bb4 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -23,14 +23,14 @@ struct module;
* until the tree gets cleaned up fully.
*/
struct attribute {
- const char * name;
- struct module * owner;
+ const char *name;
+ struct module *owner;
mode_t mode;
};

struct attribute_group {
- const char * name;
- struct attribute ** attrs;
+ const char *name;
+ struct attribute **attrs;
};


@@ -74,65 +74,43 @@ struct sysfs_ops {
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};

-#define SYSFS_TYPE_MASK 0x00ff
-#define SYSFS_ROOT 0x0001
-#define SYSFS_DIR 0x0002
-#define SYSFS_KOBJ_ATTR 0x0004
-#define SYSFS_KOBJ_BIN_ATTR 0x0008
-#define SYSFS_KOBJ_LINK 0x0020
-#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
-
-#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
-#define SYSFS_FLAG_REMOVED 0x0100
-
#ifdef CONFIG_SYSFS

-extern int sysfs_schedule_callback(struct kobject *kobj,
- void (*func)(void *), void *data, struct module *owner);
-
-extern int __must_check
-sysfs_create_dir(struct kobject *);
-
-extern void
-sysfs_remove_dir(struct kobject *);
-
-extern int __must_check
-sysfs_rename_dir(struct kobject *kobj, const char *new_name);
-
-extern int __must_check
-sysfs_move_dir(struct kobject *, struct kobject *);
-
-extern int __must_check
-sysfs_create_file(struct kobject *, const struct attribute *);
-
-extern int __must_check
-sysfs_update_file(struct kobject *, const struct attribute *);
+int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
+ void *data, struct module *owner);

-extern int __must_check
-sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode);
+int __must_check sysfs_create_dir(struct kobject *kobj);
+void sysfs_remove_dir(struct kobject *kobj);
+int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name);
+int __must_check sysfs_move_dir(struct kobject *kobj,
+ struct kobject *new_parent_kobj);

-extern void
-sysfs_remove_file(struct kobject *, const struct attribute *);
-
-extern int __must_check
-sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name);
-
-extern void
-sysfs_remove_link(struct kobject *, const char * name);
+int __must_check sysfs_create_file(struct kobject *kobj,
+ const struct attribute *attr);
+int __must_check sysfs_update_file(struct kobject *kobj,
+ const struct attribute *attr);
+int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
+ mode_t mode);
+void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);

int __must_check sysfs_create_bin_file(struct kobject *kobj,
- struct bin_attribute *attr);
+ struct bin_attribute *attr);
void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);

-int __must_check sysfs_create_group(struct kobject *,
- const struct attribute_group *);
-void sysfs_remove_group(struct kobject *, const struct attribute_group *);
+int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
+ const char *name);
+void sysfs_remove_link(struct kobject *kobj, const char *name);
+
+int __must_check sysfs_create_group(struct kobject *kobj,
+ const struct attribute_group *grp);
+void sysfs_remove_group(struct kobject *kobj,
+ const struct attribute_group *grp);
int sysfs_add_file_to_group(struct kobject *kobj,
- const struct attribute *attr, const char *group);
+ const struct attribute *attr, const char *group);
void sysfs_remove_file_from_group(struct kobject *kobj,
- const struct attribute *attr, const char *group);
+ const struct attribute *attr, const char *group);

-void sysfs_notify(struct kobject * k, char *dir, char *attr);
+void sysfs_notify(struct kobject *kobj, char *dir, char *attr);

extern int __must_check sysfs_init(void);

@@ -144,72 +122,81 @@ static inline int sysfs_schedule_callback(struct kobject *kobj,
return -ENOSYS;
}

-static inline int sysfs_create_dir(struct kobject * kobj)
+static inline int sysfs_create_dir(struct kobject *kobj)
{
return 0;
}

-static inline void sysfs_remove_dir(struct kobject * k)
+static inline void sysfs_remove_dir(struct kobject *kobj)
{
;
}

-static inline int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
{
return 0;
}

-static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent)
+static inline int sysfs_move_dir(struct kobject *kobj,
+ struct kobject *new_parent_kobj)
{
return 0;
}

-static inline int sysfs_create_file(struct kobject * k, const struct attribute * a)
+static inline int sysfs_create_file(struct kobject *kobj,
+ const struct attribute *attr)
{
return 0;
}

-static inline int sysfs_update_file(struct kobject * k, const struct attribute * a)
+static inline int sysfs_update_file(struct kobject *kobj,
+ const struct attribute *attr)
{
return 0;
}
-static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
+static inline int sysfs_chmod_file(struct kobject *kobj,
+ struct attribute *attr, mode_t mode)
{
return 0;
}

-static inline void sysfs_remove_file(struct kobject * k, const struct attribute * a)
+static inline void sysfs_remove_file(struct kobject *kobj,
+ const struct attribute *attr)
{
;
}

-static inline int sysfs_create_link(struct kobject * k, struct kobject * t, const char * n)
+static inline int sysfs_create_bin_file(struct kobject *kobj,
+ struct bin_attribute *attr)
{
return 0;
}

-static inline void sysfs_remove_link(struct kobject * k, const char * name)
+static inline int sysfs_remove_bin_file(struct kobject *kobj,
+ struct bin_attribute *attr)
{
- ;
+ return 0;
}

-
-static inline int sysfs_create_bin_file(struct kobject * k, struct bin_attribute * a)
+static inline int sysfs_create_link(struct kobject *kobj,
+ struct kobject *target, const char *name)
{
return 0;
}

-static inline int sysfs_remove_bin_file(struct kobject * k, struct bin_attribute * a)
+static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
{
- return 0;
+ ;
}

-static inline int sysfs_create_group(struct kobject * k, const struct attribute_group *g)
+static inline int sysfs_create_group(struct kobject *kobj,
+ const struct attribute_group *grp)
{
return 0;
}

-static inline void sysfs_remove_group(struct kobject * k, const struct attribute_group * g)
+static inline void sysfs_remove_group(struct kobject *kobj,
+ const struct attribute_group *grp)
{
;
}
@@ -225,7 +212,7 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj,
{
}

-static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
+static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr)
{
}

--
1.5.0.3


2007-09-20 07:07:01

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 07/15] sysfs: kill unnecessary sysfs_get() in open paths

There's no reason to get an extra reference to sysfs_dirent for an
open file. Open file has a reference to the dentry which in turn has
a reference to sysfs_dirent. This is fairly obvious as otherwise open
itself won't be able to access the sysfs_dirent. Kill the extra
sysfs_get() and matching sysfs_put().

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/bin.c | 4 +---
fs/sysfs/file.c | 6 +-----
2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index a819a7e..e93fe5e 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -193,9 +193,8 @@ static int open(struct inode * inode, struct file * file)
mutex_init(&bb->mutex);
file->private_data = bb;

- /* open succeeded, put active reference and pin attr_sd */
+ /* open succeeded, put active reference */
sysfs_put_active(attr_sd);
- sysfs_get(attr_sd);
return 0;

err_out:
@@ -211,7 +210,6 @@ static int release(struct inode * inode, struct file * file)

if (bb->mmapped)
sysfs_put_active_two(attr_sd);
- sysfs_put(attr_sd);
kfree(bb->buffer);
kfree(bb);
return 0;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 61a8c19..73333dc 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -298,9 +298,8 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
buffer->ops = ops;
file->private_data = buffer;

- /* open succeeded, put active references and pin attr_sd */
+ /* open succeeded, put active references */
sysfs_put_active_two(attr_sd);
- sysfs_get(attr_sd);
return 0;

err_out:
@@ -310,11 +309,8 @@ static int sysfs_open_file(struct inode *inode, struct file *file)

static int sysfs_release(struct inode * inode, struct file * filp)
{
- struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
struct sysfs_buffer *buffer = filp->private_data;

- sysfs_put(attr_sd);
-
if (buffer) {
if (buffer->page)
free_page((unsigned long)buffer->page);
--
1.5.0.3


2007-09-20 07:07:31

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 08/15] sysfs: kill unnecessary NULL pointer check in sysfs_release()

In sysfs_release(), sysfs_buffer pointed to by filp->private_data is
guaranteed to exist. Kill the unnecessary NULL check. This also
makes the code more consistent with the counterpart in fs/sysfs/bin.c.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/file.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 73333dc..8f1ebd8 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -311,11 +311,10 @@ static int sysfs_release(struct inode * inode, struct file * filp)
{
struct sysfs_buffer *buffer = filp->private_data;

- if (buffer) {
- if (buffer->page)
- free_page((unsigned long)buffer->page);
- kfree(buffer);
- }
+ if (buffer->page)
+ free_page((unsigned long)buffer->page);
+ kfree(buffer);
+
return 0;
}

--
1.5.0.3


2007-09-20 07:07:47

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 05/15] sysfs: kill sysfs_update_file()

sysfs_update_file() depends on inode->i_mtime but sysfs iondes are now
reclaimable making the reported modification time unreliable. There's
only one user (pci hotplug) of this notification mechanism and it
reportedly isn't utilized from userland.

Kill sysfs_update_file().

Signed-off-by: Tejun Heo <[email protected]>
---
drivers/pci/hotplug/pci_hotplug_core.c | 60 --------------------------------
fs/sysfs/file.c | 40 ---------------------
include/linux/sysfs.h | 7 ----
3 files changed, 0 insertions(+), 107 deletions(-)

diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index bd433ef..f0eba53 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -694,66 +694,6 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
if ((slot == NULL) || (info == NULL))
return -ENODEV;

- /*
- * check all fields in the info structure, and update timestamps
- * for the files referring to the fields that have now changed.
- */
- if ((has_power_file(slot) == 0) &&
- (slot->info->power_status != info->power_status)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_power.attr);
- if (retval)
- return retval;
- }
-
- if ((has_attention_file(slot) == 0) &&
- (slot->info->attention_status != info->attention_status)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_attention.attr);
- if (retval)
- return retval;
- }
-
- if ((has_latch_file(slot) == 0) &&
- (slot->info->latch_status != info->latch_status)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_latch.attr);
- if (retval)
- return retval;
- }
-
- if ((has_adapter_file(slot) == 0) &&
- (slot->info->adapter_status != info->adapter_status)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_presence.attr);
- if (retval)
- return retval;
- }
-
- if ((has_address_file(slot) == 0) &&
- (slot->info->address != info->address)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_address.attr);
- if (retval)
- return retval;
- }
-
- if ((has_max_bus_speed_file(slot) == 0) &&
- (slot->info->max_bus_speed != info->max_bus_speed)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_max_bus_speed.attr);
- if (retval)
- return retval;
- }
-
- if ((has_cur_bus_speed_file(slot) == 0) &&
- (slot->info->cur_bus_speed != info->cur_bus_speed)) {
- retval = sysfs_update_file(&slot->kobj,
- &hotplug_slot_attr_cur_bus_speed.attr);
- if (retval)
- return retval;
- }
-
memcpy (slot->info, info, sizeof (struct hotplug_slot_info));

return 0;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 9fdf8da..61a8c19 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -3,7 +3,6 @@
*/

#include <linux/module.h>
-#include <linux/fsnotify.h>
#include <linux/kobject.h>
#include <linux/namei.h>
#include <linux/poll.h>
@@ -453,44 +452,6 @@ int sysfs_add_file_to_group(struct kobject *kobj,
}
EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);

-
-/**
- * sysfs_update_file - update the modified timestamp on an object attribute.
- * @kobj: object we're acting for.
- * @attr: attribute descriptor.
- */
-int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
-{
- struct sysfs_dirent *victim_sd = NULL;
- struct dentry *victim = NULL;
- int rc;
-
- rc = -ENOENT;
- victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
- if (!victim_sd)
- goto out;
-
- mutex_lock(&sysfs_rename_mutex);
- victim = sysfs_get_dentry(victim_sd);
- mutex_unlock(&sysfs_rename_mutex);
- if (IS_ERR(victim)) {
- rc = PTR_ERR(victim);
- victim = NULL;
- goto out;
- }
-
- mutex_lock(&victim->d_inode->i_mutex);
- victim->d_inode->i_mtime = CURRENT_TIME;
- fsnotify_modify(victim);
- mutex_unlock(&victim->d_inode->i_mutex);
- rc = 0;
- out:
- dput(victim);
- sysfs_put(victim_sd);
- return rc;
-}
-
-
/**
* sysfs_chmod_file - update the modified mode value on an object attribute.
* @kobj: object we're acting for.
@@ -641,4 +602,3 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback);

EXPORT_SYMBOL_GPL(sysfs_create_file);
EXPORT_SYMBOL_GPL(sysfs_remove_file);
-EXPORT_SYMBOL_GPL(sysfs_update_file);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index b393bb4..db5dd24 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -87,8 +87,6 @@ int __must_check sysfs_move_dir(struct kobject *kobj,

int __must_check sysfs_create_file(struct kobject *kobj,
const struct attribute *attr);
-int __must_check sysfs_update_file(struct kobject *kobj,
- const struct attribute *attr);
int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
mode_t mode);
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
@@ -149,11 +147,6 @@ static inline int sysfs_create_file(struct kobject *kobj,
return 0;
}

-static inline int sysfs_update_file(struct kobject *kobj,
- const struct attribute *attr)
-{
- return 0;
-}
static inline int sysfs_chmod_file(struct kobject *kobj,
struct attribute *attr, mode_t mode)
{
--
1.5.0.3


2007-09-20 07:08:09

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 09/15] sysfs: make bin attr open get active reference of parent too

All bin attr operations require active references of itself and its
parent. There's no reason to allow open when its parent has been
deactivated and allowing it is inconsistent with regular sysfs file.
Use sysfs_get_active_two() in bin attribute open function.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/bin.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index e93fe5e..9c8f882 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -171,8 +171,8 @@ static int open(struct inode * inode, struct file * file)
struct bin_buffer *bb = NULL;
int error;

- /* need attr_sd for attr */
- if (!sysfs_get_active(attr_sd))
+ /* binary file operations requires both @sd and its parent */
+ if (!sysfs_get_active_two(attr_sd))
return -ENODEV;

error = -EACCES;
@@ -193,12 +193,12 @@ static int open(struct inode * inode, struct file * file)
mutex_init(&bb->mutex);
file->private_data = bb;

- /* open succeeded, put active reference */
- sysfs_put_active(attr_sd);
+ /* open succeeded, put active references */
+ sysfs_put_active_two(attr_sd);
return 0;

err_out:
- sysfs_put_active(attr_sd);
+ sysfs_put_active_two(attr_sd);
kfree(bb);
return error;
}
--
1.5.0.3


2007-09-20 07:08:30

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 10/15] sysfs: make s_elem an anonymous union

Make s_elem an anonymous union. Prefixing with s_elem makes things
needlessly longer without any advantage.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/bin.c | 14 +++++++-------
fs/sysfs/dir.c | 4 ++--
fs/sysfs/file.c | 14 +++++++-------
fs/sysfs/inode.c | 2 +-
fs/sysfs/symlink.c | 4 ++--
fs/sysfs/sysfs.h | 10 +++++-----
6 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 9c8f882..247ea19 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -30,8 +30,8 @@ static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
- struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
int rc;

/* need attr_sd for attr, its parent for kobj */
@@ -87,8 +87,8 @@ static int
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
- struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
int rc;

/* need attr_sd for attr, its parent for kobj */
@@ -140,8 +140,8 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
{
struct bin_buffer *bb = file->private_data;
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
- struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
int rc;

mutex_lock(&bb->mutex);
@@ -167,7 +167,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
static int open(struct inode * inode, struct file * file)
{
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
- struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+ struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
struct bin_buffer *bb = NULL;
int error;

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index e85206c..942d8e3 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -273,7 +273,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
parent_sd = sd->s_parent;

if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
- sysfs_put(sd->s_elem.symlink.target_sd);
+ sysfs_put(sd->s_symlink.target_sd);
if (sysfs_type(sd) & SYSFS_COPY_NAME)
kfree(sd->s_name);
kfree(sd->s_iattr);
@@ -626,7 +626,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
if (!sd)
return -ENOMEM;
- sd->s_elem.dir.kobj = kobj;
+ sd->s_dir.kobj = kobj;

/* link in */
sysfs_addrm_start(&acxt, parent_sd);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 8f1ebd8..3c91a57 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -73,7 +73,7 @@ struct sysfs_buffer {
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
struct sysfs_ops * ops = buffer->ops;
int ret = 0;
ssize_t count;
@@ -88,7 +88,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
return -ENODEV;

buffer->event = atomic_read(&attr_sd->s_event);
- count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
+ count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);

sysfs_put_active_two(attr_sd);

@@ -188,7 +188,7 @@ static int
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
struct sysfs_ops * ops = buffer->ops;
int rc;

@@ -196,7 +196,7 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;

- rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
+ rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);

sysfs_put_active_two(attr_sd);

@@ -240,7 +240,7 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
static int sysfs_open_file(struct inode *inode, struct file *file)
{
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
struct sysfs_buffer * buffer;
struct sysfs_ops * ops = NULL;
int error;
@@ -336,7 +336,7 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
{
struct sysfs_buffer * buffer = filp->private_data;
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
- struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;

/* need parent for the kobj, grab both */
if (!sysfs_get_active_two(attr_sd))
@@ -396,7 +396,7 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
sd = sysfs_new_dirent(attr->name, mode, type);
if (!sd)
return -ENOMEM;
- sd->s_elem.attr.attr = (void *)attr;
+ sd->s_attr.attr = (void *)attr;

sysfs_addrm_start(&acxt, dir_sd);
rc = sysfs_add_one(&acxt, sd);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 0d706a8..b6ac4e6 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -172,7 +172,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
inode->i_fop = &sysfs_file_operations;
break;
case SYSFS_KOBJ_BIN_ATTR:
- bin_attr = sd->s_elem.bin_attr.bin_attr;
+ bin_attr = sd->s_bin_attr.bin_attr;
inode->i_size = bin_attr->size;
inode->i_fop = &bin_fops;
break;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 8ad38bc..ffa82e9 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -86,7 +86,7 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
if (!sd)
goto out_put;

- sd->s_elem.symlink.target_sd = target_sd;
+ sd->s_symlink.target_sd = target_sd;
target_sd = NULL; /* reference is now owned by the symlink */

sysfs_addrm_start(&acxt, parent_sd);
@@ -142,7 +142,7 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
{
struct sysfs_dirent *sd = dentry->d_fsdata;
struct sysfs_dirent *parent_sd = sd->s_parent;
- struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
+ struct sysfs_dirent *target_sd = sd->s_symlink.target_sd;
int error;

mutex_lock(&sysfs_mutex);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 6cf61c8..2a68bfa 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -32,11 +32,11 @@ struct sysfs_dirent {
const char *s_name;

union {
- struct sysfs_elem_dir dir;
- struct sysfs_elem_symlink symlink;
- struct sysfs_elem_attr attr;
- struct sysfs_elem_bin_attr bin_attr;
- } s_elem;
+ struct sysfs_elem_dir s_dir;
+ struct sysfs_elem_symlink s_symlink;
+ struct sysfs_elem_attr s_attr;
+ struct sysfs_elem_bin_attr s_bin_attr;
+ };

unsigned int s_flags;
ino_t s_ino;
--
1.5.0.3


2007-09-20 07:08:47

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 11/15] sysfs: open code sysfs_attach_dentry()

sysfs_attach_dentry() now has only one caller and isn't doing much
other than obfuscating the code. Open code and kill it.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/dir.c | 20 ++++----------------
1 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 942d8e3..7500407 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -332,21 +332,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
return NULL;
}

-/**
- * sysfs_attach_dentry - associate sysfs_dirent with dentry
- * @sd: target sysfs_dirent
- * @dentry: dentry to associate
- *
- * LOCKING:
- * mutex_lock(sysfs_mutex)
- */
-static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
-{
- dentry->d_op = &sysfs_dentry_ops;
- dentry->d_fsdata = sysfs_get(sd);
- d_rehash(dentry);
-}
-
static int sysfs_ilookup_test(struct inode *inode, void *arg)
{
struct sysfs_dirent *sd = arg;
@@ -692,8 +677,11 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
goto out_unlock;
}

+ /* instantiate and hash dentry */
+ dentry->d_op = &sysfs_dentry_ops;
+ dentry->d_fsdata = sysfs_get(sd);
d_instantiate(dentry, inode);
- sysfs_attach_dentry(sd, dentry);
+ d_rehash(dentry);

out_unlock:
mutex_unlock(&sysfs_mutex);
--
1.5.0.3


2007-09-20 07:09:14

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 06/15] sysfs: reposition sysfs_dirent->s_mode.

Move s_mode downward such that it's side-by-side with s_iattr which is
used for the same thing.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/sysfs.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 63adbec..6cf61c8 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -39,8 +39,8 @@ struct sysfs_dirent {
} s_elem;

unsigned int s_flags;
- umode_t s_mode;
ino_t s_ino;
+ umode_t s_mode;
struct iattr *s_iattr;
atomic_t s_event;
};
--
1.5.0.3


2007-09-20 07:09:37

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 12/15] sysfs: make sysfs_root a regular directory dirent

sysfs_root is different from a regular directory dirent in that it's
of type SYSFS_ROOT and doesn't have a name. These differences aren't
used by anybody and only adds to complexity. Make sysfs_root a
regular directory dirent.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/inode.c | 5 -----
fs/sysfs/mount.c | 3 ++-
fs/sysfs/sysfs.h | 9 ++++-----
3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index b6ac4e6..c40fb9f 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -157,11 +157,6 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)

/* initialize inode according to type */
switch (sysfs_type(sd)) {
- case SYSFS_ROOT:
- inode->i_op = &sysfs_dir_inode_operations;
- inode->i_fop = &sysfs_dir_operations;
- inc_nlink(inode); /* directory, account for "." */
- break;
case SYSFS_DIR:
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 28bf359..465902c 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -24,8 +24,9 @@ static const struct super_operations sysfs_ops = {
};

struct sysfs_dirent sysfs_root = {
+ .s_name = "",
.s_count = ATOMIC_INIT(1),
- .s_flags = SYSFS_ROOT,
+ .s_flags = SYSFS_DIR,
.s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
.s_ino = 1,
};
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 2a68bfa..60405a6 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -48,11 +48,10 @@ struct sysfs_dirent {
#define SD_DEACTIVATED_BIAS INT_MIN

#define SYSFS_TYPE_MASK 0x00ff
-#define SYSFS_ROOT 0x0001
-#define SYSFS_DIR 0x0002
-#define SYSFS_KOBJ_ATTR 0x0004
-#define SYSFS_KOBJ_BIN_ATTR 0x0008
-#define SYSFS_KOBJ_LINK 0x0020
+#define SYSFS_DIR 0x0001
+#define SYSFS_KOBJ_ATTR 0x0002
+#define SYSFS_KOBJ_BIN_ATTR 0x0004
+#define SYSFS_KOBJ_LINK 0x0008
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)

#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
--
1.5.0.3


2007-09-20 07:09:53

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 14/15] sysfs: implement sysfs_open_dirent

Implement sysfs_open_dirent which represents an open file (attribute)
sysfs_dirent. A file sysfs_dirent with one or more open files have
one sysfs_dirent and all sysfs_buffers (one for each open instance)
are linked to it.

sysfs_open_dirent doesn't actually do anything yet but will be used to
off-load things which are specific for open file sysfs_dirent from it.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/file.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
fs/sysfs/sysfs.h | 3 +
2 files changed, 111 insertions(+), 1 deletions(-)

diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 3c91a57..b13ba94 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -49,6 +49,22 @@ static struct sysfs_ops subsys_sysfs_ops = {
.store = subsys_attr_store,
};

+/*
+ * There's one sysfs_buffer for each open file and one
+ * sysfs_open_dirent for each sysfs_dirent with one or more open
+ * files.
+ *
+ * filp->private_data points to sysfs_buffer and
+ * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open
+ * is protected by sysfs_open_dirent_lock.
+ */
+static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED;
+
+struct sysfs_open_dirent {
+ atomic_t refcnt;
+ struct list_head buffers; /* goes through sysfs_buffer.list */
+};
+
struct sysfs_buffer {
size_t count;
loff_t pos;
@@ -57,6 +73,7 @@ struct sysfs_buffer {
struct mutex mutex;
int needs_read_fill;
int event;
+ struct list_head list;
};

/**
@@ -237,6 +254,86 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
return len;
}

+/**
+ * sysfs_get_open_dirent - get or create sysfs_open_dirent
+ * @sd: target sysfs_dirent
+ * @buffer: sysfs_buffer for this instance of open
+ *
+ * If @sd->s_attr.open exists, increment its reference count;
+ * otherwise, create one. @buffer is chained to the buffers
+ * list.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
+ struct sysfs_buffer *buffer)
+{
+ struct sysfs_open_dirent *od, *new_od = NULL;
+
+ retry:
+ spin_lock(&sysfs_open_dirent_lock);
+
+ if (!sd->s_attr.open && new_od) {
+ sd->s_attr.open = new_od;
+ new_od = NULL;
+ }
+
+ od = sd->s_attr.open;
+ if (od) {
+ atomic_inc(&od->refcnt);
+ list_add_tail(&buffer->list, &od->buffers);
+ }
+
+ spin_unlock(&sysfs_open_dirent_lock);
+
+ if (od) {
+ kfree(new_od);
+ return 0;
+ }
+
+ /* not there, initialize a new one and retry */
+ new_od = kmalloc(sizeof(*new_od), GFP_KERNEL);
+ if (!new_od)
+ return -ENOMEM;
+
+ atomic_set(&new_od->refcnt, 0);
+ INIT_LIST_HEAD(&new_od->buffers);
+ goto retry;
+}
+
+/**
+ * sysfs_put_open_dirent - put sysfs_open_dirent
+ * @sd: target sysfs_dirent
+ * @buffer: associated sysfs_buffer
+ *
+ * Put @sd->s_attr.open and unlink @buffer from the buffers list.
+ * If reference count reaches zero, disassociate and free it.
+ *
+ * LOCKING:
+ * None.
+ */
+static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
+ struct sysfs_buffer *buffer)
+{
+ struct sysfs_open_dirent *od = sd->s_attr.open;
+
+ spin_lock(&sysfs_open_dirent_lock);
+
+ list_del(&buffer->list);
+ if (atomic_dec_and_test(&od->refcnt))
+ sd->s_attr.open = NULL;
+ else
+ od = NULL;
+
+ spin_unlock(&sysfs_open_dirent_lock);
+
+ kfree(od);
+}
+
static int sysfs_open_file(struct inode *inode, struct file *file)
{
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
@@ -298,19 +395,29 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
buffer->ops = ops;
file->private_data = buffer;

+ /* make sure we have open dirent struct */
+ error = sysfs_get_open_dirent(attr_sd, buffer);
+ if (error)
+ goto err_free;
+
/* open succeeded, put active references */
sysfs_put_active_two(attr_sd);
return 0;

+ err_free:
+ kfree(buffer);
err_out:
sysfs_put_active_two(attr_sd);
return error;
}

-static int sysfs_release(struct inode * inode, struct file * filp)
+static int sysfs_release(struct inode *inode, struct file *filp)
{
+ struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata;
struct sysfs_buffer *buffer = filp->private_data;

+ sysfs_put_open_dirent(sd, buffer);
+
if (buffer->page)
free_page((unsigned long)buffer->page);
kfree(buffer);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 42b0327..3adce7d 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,3 +1,5 @@
+struct sysfs_open_dirent;
+
/* type-specific structures for sysfs_dirent->s_* union members */
struct sysfs_elem_dir {
struct kobject *kobj;
@@ -11,6 +13,7 @@ struct sysfs_elem_symlink {

struct sysfs_elem_attr {
struct attribute *attr;
+ struct sysfs_open_dirent *open;
};

struct sysfs_elem_bin_attr {
--
1.5.0.3


2007-09-20 07:10:32

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 15/15] sysfs: move sysfs file poll implementation to sysfs_open_dirent

Sysfs file poll implementation is scattered over sysfs and kobject.
Event numbering is done in sysfs_dirent but wait itself is done on
kobject. This not only unecessarily bloats both kobject and
sysfs_dirent but is also buggy - if a sysfs_dirent is removed while
there still are pollers, the associaton betwen the kobject and
sysfs_dirent breaks and kobject may be freed with the pollers still
sleeping on it.

This patch moves whole poll implementation into sysfs_open_dirent.
Each time a sysfs_open_dirent is created, event number restarts from 1
and pollers sleep on sysfs_open_dirent. As event sequence number is
meaningless without any open file and pollers should have open file
and thus sysfs_open_dirent, this ephemeral event counting works and is
a saner implementation.

This patch fixes the dnagling sleepers bug and reduces the sizes of
kobject and sysfs_dirent by one pointer.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/dir.c | 1 -
fs/sysfs/file.c | 25 +++++++++++++++++++------
fs/sysfs/sysfs.h | 1 -
include/linux/kobject.h | 1 -
lib/kobject.c | 1 -
5 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index b81744b..ad3394a 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -318,7 +318,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)

atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_active, 0);
- atomic_set(&sd->s_event, 1);

sd->s_name = name;
sd->s_mode = mode;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index b13ba94..c05f961 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -62,6 +62,8 @@ static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED;

struct sysfs_open_dirent {
atomic_t refcnt;
+ atomic_t event;
+ wait_queue_head_t poll;
struct list_head buffers; /* goes through sysfs_buffer.list */
};

@@ -104,7 +106,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;

- buffer->event = atomic_read(&attr_sd->s_event);
+ buffer->event = atomic_read(&attr_sd->s_attr.open->event);
count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);

sysfs_put_active_two(attr_sd);
@@ -301,6 +303,8 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
return -ENOMEM;

atomic_set(&new_od->refcnt, 0);
+ atomic_set(&new_od->event, 1);
+ init_waitqueue_head(&new_od->poll);
INIT_LIST_HEAD(&new_od->buffers);
goto retry;
}
@@ -443,17 +447,17 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
{
struct sysfs_buffer * buffer = filp->private_data;
struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
- struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+ struct sysfs_open_dirent *od = attr_sd->s_attr.open;

/* need parent for the kobj, grab both */
if (!sysfs_get_active_two(attr_sd))
goto trigger;

- poll_wait(filp, &kobj->poll, wait);
+ poll_wait(filp, &od->poll, wait);

sysfs_put_active_two(attr_sd);

- if (buffer->event != atomic_read(&attr_sd->s_event))
+ if (buffer->event != atomic_read(&od->event))
goto trigger;

return 0;
@@ -474,8 +478,17 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
if (sd && attr)
sd = sysfs_find_dirent(sd, attr);
if (sd) {
- atomic_inc(&sd->s_event);
- wake_up_interruptible(&k->poll);
+ struct sysfs_open_dirent *od;
+
+ spin_lock(&sysfs_open_dirent_lock);
+
+ od = sd->s_attr.open;
+ if (od) {
+ atomic_inc(&od->event);
+ wake_up_interruptible(&od->poll);
+ }
+
+ spin_unlock(&sysfs_open_dirent_lock);
}

mutex_unlock(&sysfs_mutex);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3adce7d..269c845 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -46,7 +46,6 @@ struct sysfs_dirent {
ino_t s_ino;
umode_t s_mode;
struct iattr *s_iattr;
- atomic_t s_event;
};

#define SD_DEACTIVATED_BIAS INT_MIN
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 0777b3f..a8a84fc 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -66,7 +66,6 @@ struct kobject {
struct kset * kset;
struct kobj_type * ktype;
struct sysfs_dirent * sd;
- wait_queue_head_t poll;
};

extern int kobject_set_name(struct kobject *, const char *, ...)
diff --git a/lib/kobject.c b/lib/kobject.c
index 01f9c3b..a280c62 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -131,7 +131,6 @@ void kobject_init(struct kobject * kobj)
return;
kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry);
- init_waitqueue_head(&kobj->poll);
kobj->kset = kset_get(kobj->kset);
}

--
1.5.0.3


2007-09-20 07:10:52

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 13/15] sysfs: move sysfs_dirent->s_children into sysfs_dirent->s_dir

Children list head is only meaninful for directory nodes. Move it
into s_dir. This doesn't save any space currently but it will with
further changes.

Signed-off-by: Tejun Heo <[email protected]>
---
fs/sysfs/dir.c | 17 +++++++++--------
fs/sysfs/inode.c | 2 +-
fs/sysfs/sysfs.h | 3 ++-
3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 7500407..b81744b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -26,7 +26,7 @@ static DEFINE_IDA(sysfs_ino_ida);
* @sd: sysfs_dirent of interest
*
* Link @sd into its sibling list which starts from
- * sd->s_parent->s_children.
+ * sd->s_parent->s_dir.children.
*
* Locking:
* mutex_lock(sysfs_mutex)
@@ -40,9 +40,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd)

/* Store directory entries in order by ino. This allows
* readdir to properly restart without having to add a
- * cursor into the s_children list.
+ * cursor into the s_dir.children list.
*/
- for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
+ for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) {
if (sd->s_ino < (*pos)->s_ino)
break;
}
@@ -55,7 +55,7 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd)
* @sd: sysfs_dirent of interest
*
* Unlink @sd from its sibling list which starts from
- * sd->s_parent->s_children.
+ * sd->s_parent->s_dir.children.
*
* Locking:
* mutex_lock(sysfs_mutex)
@@ -64,7 +64,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
{
struct sysfs_dirent **pos;

- for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
+ for (pos = &sd->s_parent->s_dir.children; *pos;
+ pos = &(*pos)->s_sibling) {
if (*pos == sd) {
*pos = sd->s_sibling;
sd->s_sibling = NULL;
@@ -566,7 +567,7 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
{
struct sysfs_dirent *sd;

- for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
+ for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling)
if (!strcmp(sd->s_name, name))
return sd;
return NULL;
@@ -718,7 +719,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)

pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
sysfs_addrm_start(&acxt, dir_sd);
- pos = &dir_sd->s_children;
+ pos = &dir_sd->s_dir.children;
while (*pos) {
struct sysfs_dirent *sd = *pos;

@@ -918,7 +919,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
mutex_lock(&sysfs_mutex);

/* Skip the dentries we have already reported */
- pos = parent_sd->s_children;
+ pos = parent_sd->s_dir.children;
while (pos && (filp->f_pos > pos->s_ino))
pos = pos->s_sibling;

diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index c40fb9f..2210cf0 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -127,7 +127,7 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
struct sysfs_dirent *child;
int nr = 0;

- for (child = sd->s_children; child; child = child->s_sibling)
+ for (child = sd->s_dir.children; child; child = child->s_sibling)
if (sysfs_type(child) == SYSFS_DIR)
nr++;

diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 60405a6..42b0327 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,6 +1,8 @@
/* type-specific structures for sysfs_dirent->s_* union members */
struct sysfs_elem_dir {
struct kobject *kobj;
+ /* children list starts here and goes through sd->s_sibling */
+ struct sysfs_dirent *children;
};

struct sysfs_elem_symlink {
@@ -28,7 +30,6 @@ struct sysfs_dirent {
atomic_t s_active;
struct sysfs_dirent *s_parent;
struct sysfs_dirent *s_sibling;
- struct sysfs_dirent *s_children;
const char *s_name;

union {
--
1.5.0.3


2007-09-25 21:34:43

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 01/15] sysfs: kill SYSFS_FLAG_REMOVED

On Thu, Sep 20, 2007 at 04:05:09PM +0900, Tejun Heo wrote:
> With sysfs_get_dentry() simplified, there's no user of
> SYSFS_FLAG_REMOVED left. Kill it.
>
> Signed-off-by: Tejun Heo <[email protected]>
> ---
> This patch reverts driver/sysfs-kill-sysfs_flag_removed.patch and thus
> can be removed together with it.

Ok, I've just removed that original one so this isn't needed either.

thanks,

greg k-h

2007-09-26 11:05:14

by Cornelia Huck

[permalink] [raw]
Subject: Re: [PATCHSET 1/4] sysfs: misc updates

On Thu, 20 Sep 2007 16:05:09 +0900,
Tejun Heo <[email protected]> wrote:

> 0001-sysfs-kill-SYSFS_FLAG_REMOVED.patch
> 0002-sysfs-fix-comments-of-sysfs_add-remove_one.patch
> 0003-sysfs-fix-sysfs_chmod_file-such-that-it-updates-s.patch
> 0004-sysfs-clean-up-header-files.patch
> 0005-sysfs-kill-sysfs_update_file.patch
> 0006-sysfs-reposition-sysfs_dirent-s_mode.patch
> 0007-sysfs-kill-unnecessary-sysfs_get-in-open-paths.patch
> 0008-sysfs-kill-unnecessary-NULL-pointer-check-in-sysfs_.patch
> 0009-sysfs-make-bin-attr-open-get-active-reference-of-pa.patch
> 0010-sysfs-make-s_elem-an-anonymous-union.patch
> 0011-sysfs-open-code-sysfs_attach_dentry.patch
> 0012-sysfs-make-sysfs_root-a-regular-directory-dirent.patch
> 0013-sysfs-move-sysfs_dirent-s_children-into-sysfs_dire.patch
> 0014-sysfs-implement-sysfs_open_dirent.patch
> 0015-sysfs-move-sysfs-file-poll-implementation-to-sysfs_.patch

OK, I finally found some time for these patches.

I did my usual attach/detach etc. testing on s390 and didn't run into
problems. The patches look sane to me as well, so feel free to add

Acked-by: Cornelia Huck <[email protected]>

(or Reviewed-by:, if that's the line-du-jour) to the patches from this
set.

2007-09-26 15:25:38

by Greg KH

[permalink] [raw]
Subject: Re: [PATCHSET 1/4] sysfs: misc updates

On Wed, Sep 26, 2007 at 01:04:24PM +0200, Cornelia Huck wrote:
> On Thu, 20 Sep 2007 16:05:09 +0900,
> Tejun Heo <[email protected]> wrote:
>
> > 0001-sysfs-kill-SYSFS_FLAG_REMOVED.patch
> > 0002-sysfs-fix-comments-of-sysfs_add-remove_one.patch
> > 0003-sysfs-fix-sysfs_chmod_file-such-that-it-updates-s.patch
> > 0004-sysfs-clean-up-header-files.patch
> > 0005-sysfs-kill-sysfs_update_file.patch
> > 0006-sysfs-reposition-sysfs_dirent-s_mode.patch
> > 0007-sysfs-kill-unnecessary-sysfs_get-in-open-paths.patch
> > 0008-sysfs-kill-unnecessary-NULL-pointer-check-in-sysfs_.patch
> > 0009-sysfs-make-bin-attr-open-get-active-reference-of-pa.patch
> > 0010-sysfs-make-s_elem-an-anonymous-union.patch
> > 0011-sysfs-open-code-sysfs_attach_dentry.patch
> > 0012-sysfs-make-sysfs_root-a-regular-directory-dirent.patch
> > 0013-sysfs-move-sysfs_dirent-s_children-into-sysfs_dire.patch
> > 0014-sysfs-implement-sysfs_open_dirent.patch
> > 0015-sysfs-move-sysfs-file-poll-implementation-to-sysfs_.patch
>
> OK, I finally found some time for these patches.
>
> I did my usual attach/detach etc. testing on s390 and didn't run into
> problems. The patches look sane to me as well, so feel free to add
>
> Acked-by: Cornelia Huck <[email protected]>

Thanks for testing, I've added this to the patches in my tree now.

> (or Reviewed-by:, if that's the line-du-jour) to the patches from this
> set.

I don't think we ever came up with a conclusion about this, so I'll
stick with the Acked-by: for now.

thanks again,

greg k-h