[PATCH 22/62] sysfs: Cache the last sysfs_dirent to improve readdir scalability v2

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Greg Kroah-Hartman
Date: Tuesday, March 2, 2010 - 4:28 pm

From: Eric W. Biederman <ebiederm@xmission.com>

When sysfs_readdir stops short we now cache the next
sysfs_dirent to return to user space in filp->private_data.
There is no impact on the rest of sysfs by doing this and
in the common case it allows us to pick up exactly where
we left off with no seeking.

Additionally I drop and regrab the sysfs_mutex around
filldir to avoid a page fault abritrarily increasing the
hold time on the sysfs_mutex.

v2: Returned to using INT_MAX as the EOF condition.
    seekdir is ambiguous unless all directory entries have
    a unique f_pos value.

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=14949

Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 fs/sysfs/dir.c |   82 +++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 60 insertions(+), 22 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 699f371..5c4703d 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -837,11 +837,46 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
 	return (sd->s_mode >> 12) & 15;
 }
 
+static int sysfs_dir_release(struct inode *inode, struct file *filp)
+{
+	sysfs_put(filp->private_data);
+	return 0;
+}
+
+static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd,
+	ino_t ino, struct sysfs_dirent *pos)
+{
+	if (pos) {
+		int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
+			pos->s_parent == parent_sd &&
+			ino == pos->s_ino;
+		sysfs_put(pos);
+		if (valid)
+			return pos;
+	}
+	pos = NULL;
+	if ((ino > 1) && (ino < INT_MAX)) {
+		pos = parent_sd->s_dir.children;
+		while (pos && (ino > pos->s_ino))
+			pos = pos->s_sibling;
+	}
+	return pos;
+}
+
+static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd,
+	ino_t ino, struct sysfs_dirent *pos)
+{
+	pos = sysfs_dir_pos(parent_sd, ino, pos);
+	if (pos)
+		pos = pos->s_sibling;
+	return pos;
+}
+
 static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
-	struct sysfs_dirent *pos;
+	struct sysfs_dirent *pos = filp->private_data;
 	ino_t ino;
 
 	if (filp->f_pos == 0) {
@@ -857,29 +892,31 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 		if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
 			filp->f_pos++;
 	}
-	if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) {
-		mutex_lock(&sysfs_mutex);
-
-		/* Skip the dentries we have already reported */
-		pos = parent_sd->s_dir.children;
-		while (pos && (filp->f_pos > pos->s_ino))
-			pos = pos->s_sibling;
-
-		for ( ; pos; pos = pos->s_sibling) {
-			const char * name;
-			int len;
-
-			name = pos->s_name;
-			len = strlen(name);
-			filp->f_pos = ino = pos->s_ino;
+	mutex_lock(&sysfs_mutex);
+	for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos);
+	     pos;
+	     pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) {
+		const char * name;
+		unsigned int type;
+		int len, ret;
+
+		name = pos->s_name;
+		len = strlen(name);
+		ino = pos->s_ino;
+		type = dt_type(pos);
+		filp->f_pos = ino;
+		filp->private_data = sysfs_get(pos);
 
-			if (filldir(dirent, name, len, filp->f_pos, ino,
-					 dt_type(pos)) < 0)
-				break;
-		}
-		if (!pos)
-			filp->f_pos = INT_MAX;
 		mutex_unlock(&sysfs_mutex);
+		ret = filldir(dirent, name, len, filp->f_pos, ino, type);
+		mutex_lock(&sysfs_mutex);
+		if (ret < 0)
+			break;
+	}
+	mutex_unlock(&sysfs_mutex);
+	if ((filp->f_pos > 1) && !pos) { /* EOF */
+		filp->f_pos = INT_MAX;
+		filp->private_data = NULL;
 	}
 	return 0;
 }
@@ -888,5 +925,6 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 const struct file_operations sysfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= sysfs_readdir,
+	.release	= sysfs_dir_release,
 	.llseek		= generic_file_llseek,
 };
-- 
1.7.0.1

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[GIT PATCH] driver core patches for 2.6.33-git, Greg KH, (Tue Mar 2, 4:09 pm)
[PATCH 01/62] kobject-example: Spelling fixes., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 02/62] kset-example: Spelling fixes., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 03/62] Driver core: add platform_create_bundle() helper, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 04/62] driver core: make platform_device_id table const, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 05/62] sysdev: Pass attribute in sysdev_class attri ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 06/62] sysdev: Convert node driver class attributes ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 07/62] sysdev: Convert cpu driver sysdev class attr ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 08/62] sysfs: Add sysfs_add/remove_files utility fu ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 09/62] sysfs: Add attribute array to sysdev classes, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 10/62] sysdev: Convert node driver, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 11/62] sysdev: Use sysdev_class attribute arrays in ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 12/62] sysdev: Add sysdev_create/remove_files, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 13/62] sysdev: Fix type of sysdev class attribute i ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 14/62] sysdev: fix missing s390 conversion, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 15/62] driver-core: Add attribute argument to class ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 16/62] driver core: Add class_attr_string for simpl ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 17/62] driver core: Convert some drivers to CLASS_A ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 18/62] Driver-Core: devtmpfs - reset inode permissi ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 19/62] Driver-Core: devtmpfs - remove EXPERIMENTAL ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 20/62] Driver-Core: disable /sbin/hotplug by default, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 21/62] Driver-Core: require valid action string in ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 22/62] sysfs: Cache the last sysfs_dirent to improv ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 23/62] driver-core: firmware_class: remove base.h h ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 24/62] kobject: Constify struct kset_uevent_ops, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 25/62] HOWTO: Updates on subsystem trees, patchwork ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 26/62] sysdev: fix up the probe/release attributes, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 27/62] Driver core: Constify struct sysfs_ops in st ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 28/62] Driver core: make struct platform_driver.id_ ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 29/62] platform-drivers: move probe to .devinit.tex ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 30/62] platform-drivers: move probe to .devinit.tex ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 32/62] x86: move hp-wmi's probe function to .devini ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 33/62] i2c: move i2c_omap's probe function to .devi ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 34/62] w1: move omap_hdq's probe function to .devin ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 35/62] media: move omap24xxcam's probe function to ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 36/62] auxdisplay: move cfag12864bfb's probe functi ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 38/62] UIO: Add a driver for Hilscher netX-based fi ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 39/62] UIO: minor Kconfig fixes, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 40/62] UIO: Remove SMX Cryptengine driver, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 41/62] Driver core: Fix first line of kernel-doc fo ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 42/62] sysfs: Remove sysfs_get/put_active_two, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 43/62] sysfs: Only take active references on attrib ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 44/62] sysfs: Use one lockdep class per sysfs attri ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 45/62] sysfs: Use sysfs_attr_init and sysfs_bin_att ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 46/62] sysfs: Document sysfs_attr_init and sysfs_bi ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 47/62] sysfs: Use sysfs_attr_init and sysfs_bin_att ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 48/62] sysfs: windfarm: init sysfs attributes, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 49/62] sysfs: Serialize updates to the vfs inode, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 50/62] sysfs: Pack sysfs_dirent more tightly., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 51/62] sysfs: Implement sysfs_rename_link, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 52/62] driver core: Use sysfs_rename_link in device ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 53/62] sysfs: Pass super_block to sysfs_get_inode, Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 54/62] sysfs: Kill unused sysfs_sb variable., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 56/62] msi-laptop: Support standard ec 66/62 comman ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 57/62] msi-laptop: Add threeg sysfs file for suppor ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 58/62] msi-laptop: Support some MSI 3G netbook that ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 59/62] msi-laptop: Add resume method for set the SC ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 60/62] msi-laptop: Detect 3G device exists by stand ..., Greg Kroah-Hartman, (Tue Mar 2, 4:28 pm)
[PATCH 61/62] msi-laptop: depends on RFKILL, Greg Kroah-Hartman, (Tue Mar 2, 4:29 pm)
[PATCH 62/62] sysfs: fix for thinko with sysfs_bin_attr_init(), Greg Kroah-Hartman, (Tue Mar 2, 4:29 pm)
Re: [PATCH 61/62] msi-laptop: depends on RFKILL, Dmitry Torokhov, (Tue Mar 2, 11:09 pm)
Re: [GIT PATCH] driver core patches for 2.6.33-git, Linus Torvalds, (Mon Mar 8, 10:28 am)