Re: [PATCHSET 1/4] sysfs: misc updates

Previous thread: none

Next thread: [git patches] net driver updates by Jeff Garzik on Thursday, September 20, 2007 - 3:26 am. (2 messages)
To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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

-

To: Tejun Heo <htejun@...>
Cc: <ebiederm@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>
Date: Wednesday, September 26, 2007 - 7:04 am

On Thu, 20 Sep 2007 16:05:09 +0900,

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 <cornelia.huck@de.ibm.com>

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

To: Cornelia Huck <cornelia.huck@...>
Cc: Tejun Heo <htejun@...>, <ebiederm@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>
Date: Wednesday, September 26, 2007 - 11:19 am

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
-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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_...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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_NA...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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:...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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(st...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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

-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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

-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
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;...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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

-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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

-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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);
--...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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 sy...

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
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

-

To: Tejun Heo <htejun@...>
Cc: <ebiederm@...>, <cornelia.huck@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>
Date: Tuesday, September 25, 2007 - 5:32 pm

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

thanks,

greg k-h
-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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

-

To: <ebiederm@...>, <cornelia.huck@...>, <greg@...>, <stern@...>, <kay.sievers@...>, <linux-kernel@...>, <htejun@...>
Cc: Tejun Heo <htejun@...>
Date: Thursday, September 20, 2007 - 3:05 am

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 <htejun@gmail.com>
---
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

-

Previous thread: none

Next thread: [git patches] net driver updates by Jeff Garzik on Thursday, September 20, 2007 - 3:26 am. (2 messages)