All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <htejun@gmail.com>
To: gregkh@suse.de, dmitry.torokhov@gmail.com,
	cornelia.huck@de.ibm.com, oneukum@suse.de, rpurdie@rpsys.net,
	stern@rowland.harvard.edu, maneesh@in.ibm.com,
	linux-kernel@vger.kernel.org, htejun@gmail.com
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 3/5] sysfs: reorganize sysfs_new_indoe() and sysfs_create()
Date: Tue, 29 May 2007 01:10:26 +0900	[thread overview]
Message-ID: <11803686263828-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <1180368625600-git-send-email-htejun@gmail.com>

Reorganize/clean up sysfs_new_inode() and sysfs_create().

* sysfs_init_inode() is separated out from sysfs_new_inode() and is
  responsible for basic initialization.
* sysfs_instantiate() replaces the last step of sysfs_create() and is
  responsible for dentry instantitaion.
* type-specific initialization is moved out to the callers.
* mode is specified only once when creating a sysfs_dirent.
* spurious list_del_init(&sd->s_sibling) dropped from create_dir()

This change is to

* prepare for inode allocation fix.
* separate alloc and init code for synchronization update.
* make dentry/inode initialization more flexible for later changes.

This patch doesn't introduce visible behavior change.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
 fs/sysfs/dir.c   |  130 ++++++++++++++++++++----------------------------------
 fs/sysfs/inode.c |  108 ++++++++++++++++++++++++---------------------
 fs/sysfs/mount.c |   18 ++++---
 fs/sysfs/sysfs.h |    6 +-
 4 files changed, 118 insertions(+), 144 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index a26e3db..bbf3525 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -191,39 +191,18 @@ int sysfs_dirent_exist(struct sysfs_dire
 	return 0;
 }
 
-static int init_dir(struct inode * inode)
-{
-	inode->i_op = &sysfs_dir_inode_operations;
-	inode->i_fop = &sysfs_dir_operations;
-
-	/* directory inodes start off with i_nlink == 2 (for "." entry) */
-	inc_nlink(inode);
-	return 0;
-}
-
-static int init_file(struct inode * inode)
-{
-	inode->i_size = PAGE_SIZE;
-	inode->i_fop = &sysfs_file_operations;
-	return 0;
-}
-
-static int init_symlink(struct inode * inode)
-{
-	inode->i_op = &sysfs_symlink_inode_operations;
-	return 0;
-}
-
 static int create_dir(struct kobject *kobj, struct dentry *parent,
 		      const char *name, struct dentry **p_dentry)
 {
 	int error;
 	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
 	struct dentry *dentry;
+	struct inode *inode;
 	struct sysfs_dirent *sd;
 
 	mutex_lock(&parent->d_inode->i_mutex);
 
+	/* allocate */
 	dentry = lookup_one_len(name, parent, strlen(name));
 	if (IS_ERR(dentry)) {
 		error = PTR_ERR(dentry);
@@ -231,7 +210,7 @@ static int create_dir(struct kobject *ko
 	}
 
 	error = -EEXIST;
-	if (sysfs_dirent_exist(parent->d_fsdata, name))
+	if (dentry->d_inode)
 		goto out_dput;
 
 	error = -ENOMEM;
@@ -240,19 +219,31 @@ static int create_dir(struct kobject *ko
 		goto out_drop;
 	sd->s_elem.dir.kobj = kobj;
 
-	error = sysfs_create(sd, dentry, mode, init_dir);
-	if (error)
+	inode = sysfs_new_inode(sd);
+	if (!inode)
 		goto out_sput;
 
+	inode->i_op = &sysfs_dir_inode_operations;
+	inode->i_fop = &sysfs_dir_operations;
+	/* directory inodes start off with i_nlink == 2 (for "." entry) */
+	inc_nlink(inode);
+
+	/* link in */
+	error = -EEXIST;
+	if (sysfs_dirent_exist(parent->d_fsdata, name))
+		goto out_iput;
+
+	sysfs_instantiate(dentry, inode);
 	inc_nlink(parent->d_inode);
 	sysfs_attach_dirent(sd, parent->d_fsdata, dentry);
 
 	*p_dentry = dentry;
 	error = 0;
-	goto out_dput;
+	goto out_unlock;	/* pin directory dentry in core */
 
+ out_iput:
+	iput(inode);
  out_sput:
-	list_del_init(&sd->s_sibling);
 	sysfs_put(sd);
  out_drop:
 	d_drop(dentry);
@@ -298,71 +289,46 @@ int sysfs_create_dir(struct kobject * ko
 	return error;
 }
 
-/* attaches attribute's sysfs_dirent to the dentry corresponding to the
- * attribute file
- */
-static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
-{
-	struct attribute * attr = NULL;
-	struct bin_attribute * bin_attr = NULL;
-	int (* init) (struct inode *) = NULL;
-	int error = 0;
-
-        if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
-                bin_attr = sd->s_elem.bin_attr.bin_attr;
-                attr = &bin_attr->attr;
-        } else {
-                attr = sd->s_elem.attr.attr;
-                init = init_file;
-        }
-
-	error = sysfs_create(sd, dentry,
-			     (attr->mode & S_IALLUGO) | S_IFREG, init);
-	if (error)
-		return error;
-
-        if (bin_attr) {
-		dentry->d_inode->i_size = bin_attr->size;
-		dentry->d_inode->i_fop = &bin_fops;
-	}
-
-	sysfs_attach_dentry(sd, dentry);
-
-	return 0;
-}
-
-static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
-{
-	int err;
-
-	err = sysfs_create(sd, dentry, S_IFLNK|S_IRWXUGO, init_symlink);
-	if (!err)
-		sysfs_attach_dentry(sd, dentry);
-
-	return err;
-}
-
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 				struct nameidata *nd)
 {
 	struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
 	struct sysfs_dirent * sd;
-	int err = 0;
+	struct inode *inode;
+	int found = 0;
 
 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-		if (sd->s_type & SYSFS_NOT_PINNED) {
-			if (strcmp(sd->s_name, dentry->d_name.name))
-				continue;
-
-			if (sd->s_type & SYSFS_KOBJ_LINK)
-				err = sysfs_attach_link(sd, dentry);
-			else
-				err = sysfs_attach_attr(sd, dentry);
+		if ((sd->s_type & SYSFS_NOT_PINNED) &&
+		    !strcmp(sd->s_name, dentry->d_name.name)) {
+			found = 1;
 			break;
 		}
 	}
 
-	return ERR_PTR(err);
+	/* no such entry */
+	if (!found)
+		return NULL;
+
+	/* attach dentry and inode */
+	inode = sysfs_new_inode(sd);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	/* initialize inode according to type */
+	if (sd->s_type & SYSFS_KOBJ_ATTR) {
+		inode->i_size = PAGE_SIZE;
+		inode->i_fop = &sysfs_file_operations;
+	} else if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
+		struct bin_attribute *bin_attr = sd->s_elem.bin_attr.bin_attr;
+		inode->i_size = bin_attr->size;
+		inode->i_fop = &bin_fops;
+	} else if (sd->s_type & SYSFS_KOBJ_LINK)
+		inode->i_op = &sysfs_symlink_inode_operations;
+
+	sysfs_instantiate(dentry, inode);
+	sysfs_attach_dentry(sd, dentry);
+
+	return NULL;
 }
 
 const struct inode_operations sysfs_dir_inode_operations = {
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 81460c5..3b2dc2a 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -132,62 +132,68 @@ static inline void set_inode_attr(struct
  */
 static struct lock_class_key sysfs_inode_imutex_key;
 
-struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
+void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 {
-	struct inode * inode = new_inode(sysfs_sb);
-	if (inode) {
-		inode->i_blocks = 0;
-		inode->i_mapping->a_ops = &sysfs_aops;
-		inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
-		inode->i_op = &sysfs_inode_operations;
-		inode->i_ino = sd->s_ino;
-		lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
-
-		if (sd->s_iattr) {
-			/* sysfs_dirent has non-default attributes
-			 * get them for the new inode from persistent copy
-			 * in sysfs_dirent
-			 */
-			set_inode_attr(inode, sd->s_iattr);
-		} else
-			set_default_inode_attr(inode, mode);
-	}
+	inode->i_blocks = 0;
+	inode->i_mapping->a_ops = &sysfs_aops;
+	inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+	inode->i_op = &sysfs_inode_operations;
+	inode->i_ino = sd->s_ino;
+	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
+
+	if (sd->s_iattr) {
+		/* sysfs_dirent has non-default attributes
+		 * get them for the new inode from persistent copy
+		 * in sysfs_dirent
+		 */
+		set_inode_attr(inode, sd->s_iattr);
+	} else
+		set_default_inode_attr(inode, sd->s_mode);
+}
+
+/**
+ *	sysfs_new_inode - allocate new inode for sysfs_dirent
+ *	@sd: sysfs_dirent to allocate inode for
+ *
+ *	Allocate inode for @sd and initialize basics.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	Pointer to allocated inode on success, NULL on failure.
+ */
+struct inode * sysfs_new_inode(struct sysfs_dirent *sd)
+{
+	struct inode *inode;
+
+	inode = new_inode(sysfs_sb);
+	if (inode)
+		sysfs_init_inode(sd, inode);
+
 	return inode;
 }
 
-int sysfs_create(struct sysfs_dirent *sd, struct dentry *dentry, int mode,
-		 int (*init)(struct inode *))
+/**
+ *	sysfs_instantiate - instantiate dentry
+ *	@dentry: dentry to be instantiated
+ *	@inode: inode associated with @sd
+ *
+ *	Instantiate @dentry with @inode.
+ *
+ *	LOCKING:
+ *	None.
+ */
+void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
 {
-	int error = 0;
-	struct inode * inode = NULL;
-	if (dentry) {
-		if (!dentry->d_inode) {
-			if ((inode = sysfs_new_inode(mode, sd))) {
-				if (dentry->d_parent && dentry->d_parent->d_inode) {
-					struct inode *p_inode = dentry->d_parent->d_inode;
-					p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
-				}
-				goto Proceed;
-			}
-			else 
-				error = -ENOMEM;
-		} else
-			error = -EEXIST;
-	} else 
-		error = -ENOENT;
-	goto Done;
-
- Proceed:
-	if (init)
-		error = init(inode);
-	if (!error) {
-		d_instantiate(dentry, inode);
-		if (S_ISDIR(mode))
-			dget(dentry);  /* pin only directory dentry in core */
-	} else
-		iput(inode);
- Done:
-	return error;
+	BUG_ON(!dentry || dentry->d_inode);
+
+	if (dentry->d_parent && dentry->d_parent->d_inode) {
+		struct inode *p_inode = dentry->d_parent->d_inode;
+		p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
+	}
+
+	d_instantiate(dentry, inode);
 }
 
 /**
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index c5fabfe..7f2779e 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -27,6 +27,7 @@ static struct sysfs_dirent sysfs_root =
 	.s_sibling	= LIST_HEAD_INIT(sysfs_root.s_sibling),
 	.s_children	= LIST_HEAD_INIT(sysfs_root.s_children),
 	.s_type		= SYSFS_ROOT,
+	.s_mode		= S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
 	.s_ino		= 1,
 	.s_iattr	= NULL,
 };
@@ -43,18 +44,19 @@ static int sysfs_fill_super(struct super
 	sb->s_time_gran = 1;
 	sysfs_sb = sb;
 
-	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
-				 &sysfs_root);
-	if (inode) {
-		inode->i_op = &sysfs_dir_inode_operations;
-		inode->i_fop = &sysfs_dir_operations;
-		/* directory inodes start off with i_nlink == 2 (for "." entry) */
-		inc_nlink(inode);
-	} else {
+	inode = new_inode(sysfs_sb);
+	if (!inode) {
 		pr_debug("sysfs: could not get root inode\n");
 		return -ENOMEM;
 	}
 
+	sysfs_init_inode(&sysfs_root, inode);
+
+	inode->i_op = &sysfs_dir_inode_operations;
+	inode->i_fop = &sysfs_dir_operations;
+	/* directory inodes start off with i_nlink == 2 (for "." entry) */
+	inc_nlink(inode);
+
 	root = d_alloc_root(inode);
 	if (!root) {
 		pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index fc6aa86..143fdbe 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -57,9 +57,9 @@ extern struct vfsmount * sysfs_mount;
 extern struct kmem_cache *sysfs_dir_cachep;
 
 extern void sysfs_delete_inode(struct inode *inode);
-extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
-extern int sysfs_create(struct sysfs_dirent *sd, struct dentry *dentry,
-			int mode, int (*init)(struct inode *));
+extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
+extern struct inode * sysfs_new_inode(struct sysfs_dirent *sd);
+extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
 
 extern void release_sysfs_dirent(struct sysfs_dirent * sd);
 extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
-- 
1.4.3.4



  parent reply	other threads:[~2007-05-28 16:11 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-28 16:10 [PATCHSET 2.6.22-rc2-mm1] sysfs: assorted fixes Tejun Heo
2007-05-28 16:10 ` [PATCH 2/5] sysfs: fix parent refcounting during rename and move Tejun Heo
2007-05-28 16:10 ` [PATCH 1/5] sysfs: make sysfs_alloc_ino() static Tejun Heo
2007-05-28 16:10 ` [PATCH 4/5] sysfs: use iget_locked() instead of new_inode() Tejun Heo
2007-05-28 16:10 ` Tejun Heo [this message]
2007-05-28 16:10 ` [PATCH 5/5] sysfs: fix root sysfs_dirent -> root dentry association Tejun Heo
2007-05-29 14:02 ` [PATCHSET 2.6.22-rc2-mm1] sysfs: assorted fixes Cornelia Huck
2007-05-29 15:58   ` 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=11803686263828-git-send-email-htejun@gmail.com \
    --to=htejun@gmail.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=gregkh@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maneesh@in.ibm.com \
    --cc=oneukum@suse.de \
    --cc=rpurdie@rpsys.net \
    --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.