linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.cz>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Jiri Slaby <jirislaby@gmail.com>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	LKML <linux-kernel@vger.kernel.org>,
	Al Viro <viro@zeniv.linux.org.uk>,
	Maciej Rutecki <maciej.rutecki@gmail.com>
Subject: [PATCH 2/3] sysfs: Maintain usable nlink directory counts.
Date: Thu, 08 Mar 2012 13:36:34 -0800	[thread overview]
Message-ID: <m1linawza5.fsf_-_@fess.ebiederm.org> (raw)
In-Reply-To: <m1r4x2wzdt.fsf_-_@fess.ebiederm.org> (Eric W. Biederman's message of "Thu, 08 Mar 2012 13:34:22 -0800")


When it is easy keep fully accurate nlink counts for sysfs directories,
when it is not easy set nlink to 1.  This maintains as much compatibility
with unix programs that expect directories to have a usable nlink count
as possible, without trying to do the impossible.

Directory nlink count overflows in sysfs are inevitable by design
so only bother to use a byte to store the directory nlink count.
A directory with 254 entries is larger than any sysfs directory
in a normal configruation but small enough we should see tools that
care about large sysfs directories should experience nlink == 1
during their testing.

This fixes libsensors and possibly other applications that get
confused if all sysfs directories return nlink == 1.  The lm_sensors
code that got confused was just wrong is fixed in the lm_sensors
trunk and a fixed version should be released sometime soon.

The nlink of all deleted directories is set to 0.  Returning for the
first time a correct nlink count for deleted sysfs directories.

Once a directory nlink count drops below 2 refuse to increment or decrement
it as there is not enough information available.  It is important that
this works for nlink == 0 as well as nlink == 1 because currently
sysfs supports deleting non-empty directories (the PCI layer requires this behavior).

For tagged directories set the nlink count == 1 because we currently
have one sysfs_dirent and multiple logical sysfs directories making
pre computing nlink impossible.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/sysfs/dir.c   |   14 ++++++++++++++
 fs/sysfs/inode.c |    1 +
 fs/sysfs/sysfs.h |   16 ++++++++++++++++
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index dd3779c..1526567 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -91,6 +91,9 @@ static int sysfs_link_sibling(struct sysfs_dirent *sd)
 	struct rb_node **node = &sd->s_parent->s_dir.children.rb_node;
 	struct rb_node *parent = NULL;
 
+	if (sysfs_type(sd) == SYSFS_DIR)
+		sysfs_inc_nlink(sd->s_parent);
+
 	while (*node) {
 		struct sysfs_dirent *pos;
 		int result;
@@ -123,6 +126,9 @@ static int sysfs_link_sibling(struct sysfs_dirent *sd)
  */
 static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
 {
+	if (sysfs_type(sd) == SYSFS_DIR)
+		sysfs_dec_nlink(sd->s_parent);
+
 	rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
 }
 
@@ -366,6 +372,9 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
 	sd->s_name = name;
 	sd->s_mode = mode;
 	sd->s_flags = type;
+	sd->s_nlink = 1;
+	if (sysfs_type(sd) == SYSFS_DIR)
+		sd->s_nlink = 2;
 
 	return sd;
 
@@ -536,6 +545,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 		ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
 	}
 
+	sd->s_nlink = 0;
 	sd->s_flags |= SYSFS_FLAG_REMOVED;
 	sd->u.removed_list = acxt->removed;
 	acxt->removed = sd;
@@ -660,6 +670,10 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
 	sd->s_ns = ns;
 	sd->s_dir.kobj = kobj;
 
+	/* Accurate nlink count impossible (one field mutiple dirs) */
+	if (sysfs_ns_type(sd))
+		sd->s_nlink = 1;
+
 	/* link in */
 	sysfs_addrm_start(&acxt, parent_sd);
 	rc = sysfs_add_one(&acxt, sd);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4291fd1..f6ebda8 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -216,6 +216,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
 					    iattrs->ia_secdata,
 					    iattrs->ia_secdata_len);
 	}
+	set_nlink(inode, sd->s_nlink);
 }
 
 int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index c76c932..71f9bf7 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -76,6 +76,7 @@ struct sysfs_dirent {
 		struct sysfs_elem_bin_attr	s_bin_attr;
 	};
 
+	unsigned char		s_nlink;
 	unsigned char		s_flags;
 	umode_t 		s_mode;
 	unsigned int		s_ino;
@@ -127,6 +128,21 @@ do {								\
 #define sysfs_dirent_init_lockdep(sd) do {} while(0)
 #endif
 
+static inline void sysfs_inc_nlink(struct sysfs_dirent *sd)
+{
+	if (sd->s_nlink <= 1)
+		return;
+	sd->s_nlink++;
+	if (sd->s_nlink == 0)
+		sd->s_nlink = 1;
+}
+static inline void sysfs_dec_nlink(struct sysfs_dirent *sd)
+{
+	if (sd->s_nlink <= 1)
+		return;
+	sd->s_nlink--;
+}
+
 /*
  * Context structure to be used while adding/removing nodes.
  */
-- 
1.7.2.5


  reply	other threads:[~2012-03-08 21:33 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-30 21:56 sysfs regression: wrong link counts Jiri Slaby
2012-01-30 22:06 ` Greg KH
2012-01-30 22:10   ` Alan Cox
2012-01-30 22:27     ` Greg KH
2012-01-30 22:43       ` Al Viro
2012-01-30 22:56         ` Al Viro
2012-01-31  1:27       ` Eric W. Biederman
2012-01-31 10:48         ` Jiri Slaby
2012-01-31 12:44           ` Eric W. Biederman
2012-01-31 16:45             ` Linus Torvalds
2012-01-31 19:18               ` Al Viro
2012-02-01  5:06               ` Eric W. Biederman
2012-02-01 22:21                 ` [PATCH] sysfs: Optionally count subdirectories to support buggy applications Eric W. Biederman
2012-02-01 22:24                   ` Greg Kroah-Hartman
2012-02-01 22:44                     ` Eric W. Biederman
2012-02-01 22:49                       ` Greg Kroah-Hartman
2012-02-01 22:31                   ` Dave Jones
2012-02-01 22:35                   ` Jiri Slaby
2012-02-01 23:15                   ` Linus Torvalds
2012-02-01 23:18                     ` Linus Torvalds
2012-02-02  1:22                       ` Al Viro
2012-02-02 21:24                         ` [RFC] killing boilerplate checks in ->link/->mkdir/->rename Al Viro
2012-02-02 23:46                           ` Linus Torvalds
2012-02-03  1:16                             ` Al Viro
2012-02-03  1:45                               ` Al Viro
2012-02-03  2:00                                 ` Linus Torvalds
2012-02-03 14:57                               ` Chris Mason
2012-02-03 17:08                               ` Al Viro
2012-02-03 19:34                                 ` Artem Bityutskiy
2012-02-06  8:50                                 ` Artem Bityutskiy
2012-02-06 13:56                                   ` Al Viro
2012-02-06 17:05                                     ` Artem Bityutskiy
2012-02-06 17:11                                       ` Al Viro
2012-02-07  7:21                                         ` Artem Bityutskiy
2012-02-06 22:49                               ` Dave Chinner
2012-02-03  8:25                           ` Andreas Dilger
2012-02-03 17:03                             ` Al Viro
2012-02-04  7:42                               ` Andreas Dilger
2012-03-05 13:30                       ` [PATCH] sysfs: Optionally count subdirectories to support buggy applications Jiri Slaby
2012-03-05 16:09                         ` Greg Kroah-Hartman
2012-03-05 16:47                           ` Linus Torvalds
2012-03-08 21:05                             ` Greg Kroah-Hartman
2012-03-08 22:18                             ` Eric W. Biederman
2012-03-08 23:40                               ` Linus Torvalds
2012-03-08 21:28                           ` Eric W. Biederman
2012-03-08 21:34                           ` [PATCH 1/3] sysfs: Compact sysfs_dirent s_flags into a byte Eric W. Biederman
2012-03-08 21:36                             ` Eric W. Biederman [this message]
2012-03-08 21:37                               ` [PATCH 3/3] sysfs: Remove SYSFS_FLAG_REMOVED and use sd->s_nlink == 0 instead Eric W. Biederman
2012-03-09  3:40                                 ` Linus Torvalds
2012-03-08 22:28                             ` [PATCH 1/3] sysfs: Compact sysfs_dirent s_flags into a byte Greg Kroah-Hartman
2012-03-09  2:49                               ` Eric W. Biederman
2012-01-31  3:45     ` sysfs regression: wrong link counts Eric W. Biederman
2012-01-31 11:54       ` Alan Cox
2012-01-30 22:52 ` Kay Sievers
2012-01-31 10:41   ` network regression: cannot rename netdev twice Jiri Slaby
2012-01-31 10:52     ` Kay Sievers
2012-01-31 11:00       ` Jiri Slaby
2012-01-31 11:13         ` Kay Sievers
2012-01-31 11:17           ` Jiri Slaby
2012-01-31 11:58             ` Kay Sievers
2012-01-31 14:18               ` Eric W. Biederman
2012-01-31 14:40                 ` [PATCH] sysfs: Update the name hash when renaming sysfs entries Eric W. Biederman
2012-01-31 14:41                   ` Jiri Slaby
2012-01-31 14:55                   ` Greg KH
2012-02-04  2:14       ` network regression: cannot rename netdev twice Henrique de Moraes Holschuh
2012-02-06 20:03         ` Kay Sievers
2012-02-08  2:00           ` Henrique de Moraes Holschuh
2012-02-08  3:50             ` Kay Sievers
2012-02-08  6:42               ` Valdis.Kletnieks
2012-02-08 10:57                 ` Kay Sievers
2012-02-08 20:06                   ` Valdis.Kletnieks
2012-02-08 20:27                     ` Stephen Hemminger
2012-02-08 23:48                     ` Kay Sievers
2012-01-31  1:32 ` sysfs regression: wrong link counts Eric W. Biederman
2012-02-01 18:29 ` Maciej Rutecki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m1linawza5.fsf_-_@fess.ebiederm.org \
    --to=ebiederm@xmission.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@gmail.com \
    --cc=jslaby@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maciej.rutecki@gmail.com \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).