All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <htejun@gmail.com>
To: ebiederm@xmission.com, cornelia.huck@de.ibm.com, greg@kroah.com,
	stern@rowland.harvard.edu, kay.sievers@vrfy.org,
	linux-kernel@vger.kernel.org, htejun@gmail.com
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 19/22] sysfs: implement sysfs_dirent based rename - sysfs_rename()
Date: Thu, 20 Sep 2007 17:05:42 +0900	[thread overview]
Message-ID: <1190275542331-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <11902755392688-git-send-email-htejun@gmail.com>

sysfs_rename() takes target @sd, @new_parent and @new_name and rename
@sd to @new_name and move it under @new_parent.  @new_parent and/or
@new_name can be NULL if the specific operation is not needed.

To handle both move and rename && prepare for multiple renames in one
shot for easier symlink handling and shadow dirents, sysfs_rename() is
implemented to be able to handle arbitrary number of rename/move
operations.

During sysfs_prep_rename(), it acquires all the resources it will need
during the operations including dentries and copied names.  After all
are acquired, all needed i_mutexes are locked.  Deadlock is avoided by
using trylock.  If any lock acquisition fails, it releases all
i_mutexes and retries after 1ms.  Because i_mutexes are used very
lightly in sysfs, almost like spinlocks just to satisfy VFS locking
rules, I don't think there will be any starvation issues.

This makes rename a heavy operation but sysfs_rename() may fail and
it's shady-side-of-the-moon cold path where programming convenience
dominates performance by all measures.

sysfs_rename() can be called on any type of sysfs_dirent and always
copies @new_name.

Kobject based sysfs_rename_dir() and sysfs_move_dir() are
reimplemented using sysfs_remove().

This patch doesn't introduce any behavior change to the original API.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 fs/sysfs/dir.c        |  433 +++++++++++++++++++++++++++++++++----------------
 fs/sysfs/kobject.c    |   31 ++++
 include/linux/sysfs.h |    9 +
 3 files changed, 337 insertions(+), 136 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 986718c..d0eb9bf 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -11,6 +11,7 @@
 #include <linux/idr.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
+#include <linux/delay.h>
 #include "sysfs.h"
 
 /* verify all mode flags are inside S_IFMT */
@@ -948,142 +949,6 @@ void sysfs_remove(struct sysfs_dirent *sd)
 }
 EXPORT_SYMBOL_GPL(sysfs_remove);
 
-int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
-{
-	struct sysfs_dirent *sd = kobj->sd;
-	struct dentry *parent = NULL;
-	struct dentry *old_dentry = NULL, *new_dentry = NULL;
-	const char *dup_name = NULL;
-	int error;
-
-	mutex_lock(&sysfs_op_mutex);
-
-	error = 0;
-	if (strcmp(sd->s_name, new_name) == 0)
-		goto out;	/* nothing to rename */
-
-	/* get the original dentry */
-	old_dentry = sysfs_get_dentry(sd);
-	if (IS_ERR(old_dentry)) {
-		error = PTR_ERR(old_dentry);
-		goto out;
-	}
-
-	parent = old_dentry->d_parent;
-
-	/* lock parent and get dentry for new name */
-	mutex_lock(&parent->d_inode->i_mutex);
-	mutex_lock(&sysfs_mutex);
-
-	error = -EEXIST;
-	if (sysfs_find_dirent(sd->s_parent, new_name))
-		goto out_unlock;
-
-	error = -ENOMEM;
-	new_dentry = d_alloc_name(parent, new_name);
-	if (!new_dentry)
-		goto out_unlock;
-
-	/* rename kobject and sysfs_dirent */
-	error = -ENOMEM;
-	new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
-	if (!new_name)
-		goto out_unlock;
-
-	error = kobject_set_name(kobj, "%s", new_name);
-	if (error)
-		goto out_unlock;
-
-	dup_name = sd->s_name;
-	sd->s_name = new_name;
-
-	/* rename */
-	d_add(new_dentry, NULL);
-	d_move(old_dentry, new_dentry);
-
-	error = 0;
- out_unlock:
-	mutex_unlock(&sysfs_mutex);
-	mutex_unlock(&parent->d_inode->i_mutex);
-	kfree(dup_name);
-	dput(old_dentry);
-	dput(new_dentry);
- out:
-	mutex_unlock(&sysfs_op_mutex);
-	return error;
-}
-
-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
-{
-	struct sysfs_dirent *sd = kobj->sd;
-	struct sysfs_dirent *new_parent_sd;
-	struct dentry *old_parent, *new_parent = NULL;
-	struct dentry *old_dentry = NULL, *new_dentry = NULL;
-	int error;
-
-	mutex_lock(&sysfs_op_mutex);
-	BUG_ON(!sd->s_parent);
-	new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : sysfs_root;
-
-	error = 0;
-	if (sd->s_parent == new_parent_sd)
-		goto out;	/* nothing to move */
-
-	/* get dentries */
-	old_dentry = sysfs_get_dentry(sd);
-	if (IS_ERR(old_dentry)) {
-		error = PTR_ERR(old_dentry);
-		goto out;
-	}
-	old_parent = old_dentry->d_parent;
-
-	new_parent = sysfs_get_dentry(new_parent_sd);
-	if (IS_ERR(new_parent)) {
-		error = PTR_ERR(new_parent);
-		goto out;
-	}
-
-again:
-	mutex_lock(&old_parent->d_inode->i_mutex);
-	if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
-		mutex_unlock(&old_parent->d_inode->i_mutex);
-		goto again;
-	}
-	mutex_lock(&sysfs_mutex);
-
-	error = -EEXIST;
-	if (sysfs_find_dirent(new_parent_sd, sd->s_name))
-		goto out_unlock;
-
-	error = -ENOMEM;
-	new_dentry = d_alloc_name(new_parent, sd->s_name);
-	if (!new_dentry)
-		goto out_unlock;
-
-	error = 0;
-	d_add(new_dentry, NULL);
-	d_move(old_dentry, new_dentry);
-	dput(new_dentry);
-
-	/* Remove from old parent's list and insert into new parent's list. */
-	sysfs_unlink_sibling(sd);
-	sysfs_get(new_parent_sd);
-	sysfs_put(sd->s_parent);
-	sd->s_parent = new_parent_sd;
-	sysfs_link_sibling(sd);
-
- out_unlock:
-	mutex_unlock(&sysfs_mutex);
-	mutex_unlock(&new_parent->d_inode->i_mutex);
-	mutex_unlock(&old_parent->d_inode->i_mutex);
- out:
-	dput(new_parent);
-	dput(old_dentry);
-	dput(new_dentry);
-	mutex_unlock(&sysfs_op_mutex);
-	return error;
-}
-
 /* Relationship between s_mode and the DT_xxx types */
 static inline unsigned char dt_type(struct sysfs_dirent *sd)
 {
@@ -1143,6 +1008,302 @@ const struct file_operations sysfs_dir_operations = {
 	.readdir	= sysfs_readdir,
 };
 
+/*
+ * Renaming a single node can result in renames of multiple nodes as
+ * symlinks pointing to the node are renamed together.  To rename
+ * multiple nodes atogether atomically, all resources including
+ * i_mutexes and dentries are grabbed before committing the operation.
+ *
+ * i_mutexes are recorded using sysfs_rcxt_mutex_ent as they might not
+ * correspond one to one to renames (e.g. two symlinks to the same
+ * target in the same directory).  All other resources are recorded in
+ * sysfs_rcxt_rename_ent.  Both are chained to sysfs_rename_context to
+ * be used later.
+ */
+struct sysfs_rcxt_rename_ent {
+	struct list_head	list;
+	struct sysfs_dirent	*sd;
+	struct sysfs_dirent	*new_parent;
+	const char		*old_name;
+	const char		*new_name;
+	int			old_name_copied;
+	int			new_name_copied;
+	struct dentry		*old_dentry;
+	struct dentry		*new_dentry;
+};
+
+struct sysfs_rcxt_mutex_ent {
+	struct list_head	list;
+	struct mutex		*mutex;
+	int			locked;
+};
+
+struct sysfs_rename_context {
+	struct list_head	mutexes;
+	struct list_head	renames;
+};
+
+static struct sysfs_rcxt_rename_ent *
+sysfs_rcxt_add(struct sysfs_rename_context *rcxt, struct sysfs_dirent *sd,
+	       struct sysfs_dirent *new_parent)
+{
+	struct sysfs_rcxt_rename_ent *rent;
+
+	rent = kzalloc(sizeof(*rent), GFP_KERNEL);
+	if (!rent)
+		return NULL;
+
+	rent->sd = sysfs_get(sd);
+	rent->new_parent = sysfs_get(new_parent);
+	rent->old_name = sd->s_name;
+	rent->old_name_copied = !!(sd->s_flags & SYSFS_FLAG_NAME_COPIED);
+
+	list_add_tail(&rent->list, &rcxt->renames);
+
+	return rent;
+}
+
+static int sysfs_rcxt_add_mutex(struct sysfs_rename_context *rcxt,
+				struct mutex *mutex)
+{
+	struct sysfs_rcxt_mutex_ent *ment;
+
+	list_for_each_entry(ment, &rcxt->mutexes, list)
+		if (ment->mutex == mutex)
+			return 0;
+
+	ment = kzalloc(sizeof(*ment), GFP_KERNEL);
+	if (!ment)
+		return -ENOMEM;
+
+	ment->mutex = mutex;
+
+	list_add_tail(&ment->list, &rcxt->mutexes);
+
+	return 0;
+}
+
+static int sysfs_rcxt_get_dentries(struct sysfs_rename_context *rcxt,
+				   struct sysfs_rcxt_rename_ent *rent)
+{
+	struct dentry *old_dentry, *new_parent_dentry, *new_dentry;
+	int rc;
+
+	/* get old dentry */
+	old_dentry = sysfs_get_dentry(rent->sd);
+	if (IS_ERR(old_dentry))
+		return PTR_ERR(old_dentry);
+	rent->old_dentry = old_dentry;
+
+	/* allocate new dentry */
+	new_parent_dentry = sysfs_get_dentry(rent->new_parent);
+	if (IS_ERR(new_parent_dentry))
+		return PTR_ERR(new_parent_dentry);
+
+	new_dentry = d_alloc_name(new_parent_dentry, rent->new_name);
+	dput(new_parent_dentry);
+	if (!new_dentry)
+		return -ENOMEM;
+	rent->new_dentry = new_dentry;
+
+	/* add i_mutexes to mutex list */
+	rc = sysfs_rcxt_add_mutex(rcxt, &old_dentry->d_parent->d_inode->i_mutex);
+	if (rc)
+		return rc;
+
+	rc = sysfs_rcxt_add_mutex(rcxt, &new_dentry->d_parent->d_inode->i_mutex);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static void sysfs_post_rename(struct sysfs_rename_context *rcxt, int error)
+{
+	struct sysfs_rcxt_mutex_ent *ment, *next_ment;
+	struct sysfs_rcxt_rename_ent *rent, *next_rent;
+
+	/* release all mutexes */
+	list_for_each_entry_safe(ment, next_ment, &rcxt->mutexes, list) {
+		if (ment->locked)
+			mutex_unlock(ment->mutex);
+
+		list_del(&ment->list);
+		kfree(ment);
+	}
+
+	/* release all renames */
+	list_for_each_entry_safe(rent, next_rent, &rcxt->renames, list) {
+		/* If rename succeeded, old name is unused; otherwise,
+		 * new name is unused.  Free accordingly.
+		 */
+		if (!error) {
+			if (rent->old_name_copied)
+				kfree(rent->old_name);
+		} else {
+			if (rent->new_name_copied)
+				kfree(rent->new_name);
+		}
+
+		dput(rent->old_dentry);
+		dput(rent->new_dentry);
+		sysfs_put(rent->sd);
+		sysfs_put(rent->new_parent);
+
+		list_del(&rent->list);
+		kfree(rent);
+	}
+}
+
+static int sysfs_prep_rename(struct sysfs_rename_context *rcxt,
+			     struct sysfs_dirent *sd,
+			     struct sysfs_dirent *new_parent,
+			     const char *new_name)
+{
+	struct sysfs_rcxt_rename_ent *rent;
+	struct sysfs_rcxt_mutex_ent *ment;
+	int rc;
+
+	INIT_LIST_HEAD(&rcxt->mutexes);
+	INIT_LIST_HEAD(&rcxt->renames);
+
+	/*
+	 * prep @sd
+	 */
+	rc = -ENOMEM;
+	rent = sysfs_rcxt_add(rcxt, sd, new_parent);
+	if (!rent)
+		goto err;
+
+	rc = -ENOMEM;
+	rent->new_name = kstrdup(new_name, GFP_KERNEL);
+	if (!rent->new_name)
+		goto err;
+	rent->new_name_copied = 1;
+
+	rc = sysfs_rcxt_get_dentries(rcxt, rent);
+	if (rc)
+		goto err;
+
+	/*
+	 * lock all i_mutexes
+	 */
+ try_lock:
+	list_for_each_entry(ment, &rcxt->mutexes, list) {
+		if (!mutex_trylock(ment->mutex)) {
+			/* unlock all and retry */
+			list_for_each_entry(ment, &rcxt->mutexes, list) {
+				if (ment->locked) {
+					mutex_unlock(ment->mutex);
+					ment->locked = 0;
+				}
+			}
+
+			/* No need to be over-anxious, let's take it
+			 * slow.  Sysfs i_mutexes are lightly loaded
+			 * and starvation is highly unlikely.
+			 */
+			msleep(1);
+			goto try_lock;
+		}
+
+		ment->locked = 1;
+	}
+
+	return 0;
+
+ err:
+	sysfs_post_rename(rcxt, rc);
+	return rc;
+}
+
+/**
+ *	sysfs_rename - rename and/or move sysfs node
+ *	@sd: sysfs_dirent to rename
+ *	@new_parent: new parent to move @sd under (NULL if only renaming)
+ *	@new_name: new name to rename @sd to (NULL if only moving)
+ *
+ *	Rename and/or move @sd.  If both @new_parent and @new_name are
+ *	specified, @sd is renamed to @new_name and moved under
+ *	@new_parent atomically.  If only one of the two is specified,
+ *	only the specified operation is performed.
+ *
+ *	Renaming and/or moving a sysfs node which is pointed to by
+ *	symlinks causes the symlinks to be renamed according to their
+ *	name formats.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success -errno on failure.
+ */
+int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
+		 const char *new_name)
+{
+	struct sysfs_rename_context rcxt;
+	struct sysfs_rcxt_rename_ent *rent;
+	int error;
+
+	mutex_lock(&sysfs_op_mutex);
+
+	if (!new_parent)
+		new_parent = sd->s_parent;
+	if (!new_name)
+		new_name = sd->s_name;
+
+	error = 0;
+	if (sd->s_parent == new_parent && !strcmp(sd->s_name, new_name))
+		goto out;	/* nothing to rename */
+
+	error = sysfs_prep_rename(&rcxt, sd, new_parent, new_name);
+	if (error)
+		goto out;
+
+	/* check whether there are duplicate names */
+	error = -EEXIST;
+	list_for_each_entry(rent, &rcxt.renames, list)
+		if (sysfs_find_dirent(rent->new_parent, rent->new_name))
+			goto out_post;
+
+	mutex_lock(&sysfs_mutex);
+
+	/* rename sysfs_dirents and dentries */
+	list_for_each_entry(rent, &rcxt.renames, list) {
+		/* rename sd */
+		rent->sd->s_name = rent->new_name;
+		rent->sd->s_flags &= ~SYSFS_FLAG_NAME_COPIED;
+		if (rent->new_name_copied)
+			rent->sd->s_flags |= SYSFS_FLAG_NAME_COPIED;
+
+		/* move sd */
+		if (rent->sd->s_parent != rent->new_parent) {
+			sysfs_unlink_sibling(rent->sd);
+			sysfs_put(rent->sd->s_parent);
+			rent->sd->s_parent = sysfs_get(rent->new_parent);
+			sysfs_link_sibling(rent->sd);
+		}
+
+		/* update dcache and inode accordingly */
+		if (sysfs_type(rent->sd) == SYSFS_DIR) {
+			drop_nlink(rent->old_dentry->d_parent->d_inode);
+			inc_nlink(rent->new_dentry->d_parent->d_inode);
+		}
+		d_add(rent->new_dentry, NULL);
+		d_move(rent->old_dentry, rent->new_dentry);
+	}
+
+	mutex_unlock(&sysfs_mutex);
+	error = 0;
+	/* fall through */
+ out_post:
+	sysfs_post_rename(&rcxt, error);
+ out:
+	mutex_unlock(&sysfs_op_mutex);
+	return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_rename);
+
 /**
  *	sysfs_chmod - chmod a sysfs_dirent
  *	@sd: sysfs_dirent to chmod
diff --git a/fs/sysfs/kobject.c b/fs/sysfs/kobject.c
index 0a0d583..55b884b 100644
--- a/fs/sysfs/kobject.c
+++ b/fs/sysfs/kobject.c
@@ -75,6 +75,37 @@ void sysfs_remove_dir(struct kobject * kobj)
 	__sysfs_remove(sd, 0);
 }
 
+int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+{
+	const char *dup_name;
+	int rc;
+
+	dup_name = kstrdup(new_name, GFP_KERNEL);
+	if (!dup_name)
+		return -ENOMEM;
+
+	rc = sysfs_rename(kobj->sd, NULL, new_name);
+	if (rc) {
+		kfree(dup_name);
+		return rc;
+	}
+
+	__kobject_set_name(kobj, dup_name);
+
+	return 0;
+}
+
+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
+{
+	struct sysfs_dirent *sd = kobj->sd;
+	struct sysfs_dirent *new_parent_sd = new_parent_kobj->sd;
+
+	if (!new_parent_sd)
+		new_parent_sd = sysfs_root;
+
+	return sysfs_rename(sd, new_parent_sd, NULL);
+}
+
 /*
  * Subsystem file operations.  These operations allow subsystems to
  * have files that can be read/written.
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 08ed1b0..f0279a7 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -67,6 +67,8 @@ struct sysfs_dirent *sysfs_add_link(struct sysfs_dirent *parent,
 struct sysfs_dirent *sysfs_find_child(struct sysfs_dirent *parent,
 				      const char *name);
 void sysfs_remove(struct sysfs_dirent *sd);
+int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
+		 const char *new_name);
 
 void sysfs_notify_file(struct sysfs_dirent *sd);
 int sysfs_chmod(struct sysfs_dirent *sd, mode_t mode);
@@ -114,6 +116,13 @@ static inline void sysfs_remove(struct sysfs_dirent *sd)
 {
 }
 
+static inline int sysfs_rename(struct sysfs_dirent *sd,
+			       struct sysfs_dirent *new_parent,
+			       const char *new_name)
+{
+	return 0;
+}
+
 static inline void sysfs_notify_file(struct sysfs_dirent *sd)
 {
 }
-- 
1.5.0.3



  parent reply	other threads:[~2007-09-20  8:13 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-20  8:05 [PATCHSET 3/4] sysfs: divorce sysfs from kobject and driver model Tejun Heo
2007-09-20  8:05 ` [PATCH 05/22] sysfs: implement sysfs_find_child() Tejun Heo
2007-09-20  8:05 ` [PATCH 06/22] sysfs: restructure addrm helpers Tejun Heo
2007-09-20  8:05 ` [PATCH 01/22] sysfs: make sysfs_root a pointer Tejun Heo
2007-09-20  8:05 ` [PATCH 03/22] sysfs: make sysfs_new_dirent() normalize @mode and determine file type Tejun Heo
2007-09-20  8:05 ` [PATCH 04/22] sysfs: make SYSFS_COPY_NAME a flag Tejun Heo
2007-09-20  8:05 ` [PATCH 02/22] sysfs: separate out sysfs-kobject.h and fs/sysfs/kobject.c Tejun Heo
2007-09-20  8:05 ` [PATCH 13/22] sysfs: implement sysfs_dirent based bin interface Tejun Heo
2007-09-20  8:05 ` [PATCH 14/22] sysfs: s/symlink/link/g Tejun Heo
2007-09-20  8:05 ` [PATCH 11/22] sysfs: implement sysfs_dirent based file interface Tejun Heo
2007-09-20  8:05 ` [PATCH 10/22] sysfs: drop kobj and attr from file related symbols Tejun Heo
2007-09-20  8:05 ` [PATCH 09/22] sysfs: rename internal function sysfs_add_file() Tejun Heo
2007-09-20  8:05 ` [PATCH 07/22] sysfs: implement sysfs_dirent based remove interface sysfs_remove() Tejun Heo
2007-09-20  8:05 ` [PATCH 08/22] sysfs: implement sysfs_dirent based directory interface Tejun Heo
2007-09-20  8:05 ` [PATCH 12/22] sysfs: drop kobj and attr from bin related symbols Tejun Heo
2007-09-20  8:05 ` [PATCH 17/22] sysfs: s/sysfs_rename_mutex/sysfs_op_mutex/ and protect all tree modifying ops Tejun Heo
2007-09-20  8:05 ` [PATCH 15/22] sysfs: implement sysfs_dirent based link interface Tejun Heo
2007-09-20  8:05 ` [PATCH 16/22] sysfs: convert group implementation to use sd-based interface Tejun Heo
2007-09-20  8:05 ` [PATCH 18/22] kobject: implement __kobject_set_name() Tejun Heo
2007-09-20  8:05 ` [PATCH 22/22] sysfs: move sysfs_assoc_lock into fs/sysfs/kobject.c and make it static Tejun Heo
2007-09-20  8:05 ` Tejun Heo [this message]
2007-09-20  8:05 ` [PATCH 21/22] sysfs: kill sysfs_hash_and_remove() Tejun Heo
2007-09-20  8:05 ` [PATCH 20/22] sysfs: kill now unused __sysfs_add_file() Tejun Heo
2007-09-25 22:17 ` [PATCHSET 3/4] sysfs: divorce sysfs from kobject and driver model Greg KH
2007-09-27 11:35   ` Tejun Heo
2007-09-27 19:25     ` Eric W. Biederman
2007-09-29 22:06       ` Tejun Heo
2007-10-05  6:23       ` Greg KH
2007-10-05 12:12         ` Eric W. Biederman
2007-10-05 13:03           ` [Devel] " Kirill Korotaev
2007-10-05 13:24             ` Eric W. Biederman
2007-10-09 22:51           ` Greg KH
     [not found]             ` <20071009225139.GF21228-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2007-10-10 13:16               ` Eric W. Biederman
2007-10-10 13:16                 ` Eric W. Biederman
2007-10-10 20:44                 ` Greg KH
2007-10-10 21:16                   ` Eric W. Biederman
2007-10-16 22:18                 ` sukadev
2007-10-16 23:54                   ` Eric W. Biederman
2007-10-05 12:44         ` Eric W. Biederman
2007-10-09 22:53           ` Greg KH
2007-10-05  6:18     ` Greg KH
2007-10-05  8:00       ` Tejun Heo
2007-10-09  9:29         ` Cornelia Huck
2007-10-09 22:26           ` Greg KH
2007-10-09 23:20             ` Roland Dreier
2007-10-09 23:28               ` Greg KH
2007-10-10  9:11                 ` Cornelia Huck
2007-10-10  9:05             ` Cornelia Huck
2007-10-09 22:48         ` Greg KH
2007-10-10 15:38           ` Alan Stern
2007-10-10 16:16             ` Cornelia Huck
2007-10-10 17:24           ` Martin Bligh
2007-10-10 17:30             ` Greg KH
2007-10-10 18:26               ` Martin Bligh
2007-10-10 18:44                 ` Greg KH

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=1190275542331-git-send-email-htejun@gmail.com \
    --to=htejun@gmail.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=ebiederm@xmission.com \
    --cc=greg@kroah.com \
    --cc=kay.sievers@vrfy.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.