All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.de>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Neil Brown <neilb@suse.de>,
	linux-kernel@vger.kernel.org,
	Christoph Hellwig <hch@infradead.org>,
	nfs@lists.sourceforge.net, shaggy@austin.ibm.com,
	Christoph Hellwig <hch@lst.de>
Subject: [PATCH 002 of 8] knfsd: exportfs: remove iget abuse
Date: Tue, 15 May 2007 17:16:14 +1000	[thread overview]
Message-ID: <1070515071614.16259@suse.de> (raw)
In-Reply-To: 20070515170405.15621.patches@notabene


From: Christoph Hellwig <hch@infradead.org>

When the exportfs interface was added the expectation was that
filesystems provide an operation to convert from a file handle
to an inode/dentry, but it kept a backwards compat option that
still calls into iget.

Calling into iget from non-filesystem code is very bad, because
it gives too little information to filesystem, and simply crashes
if the filesystem doesn't implement the ->read_inode routine.

Fortunately there are only two filesystems left using this fallback:
efs and jfs.  This patch moves a copy of export_iget to each
of those to implement the get_dentry method.

While this is a temporary increase of lines of code in the kernel
it allows for a much cleaner interface and important code restructuring
in later patches.

Cc: shaggy@austin.ibm.com
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/efs/namei.c         |   32 ++++++++++++++++++++++++++
 ./fs/efs/super.c         |    1 
 ./fs/exportfs/expfs.c    |   56 ++---------------------------------------------
 ./fs/jfs/jfs_inode.h     |    2 -
 ./fs/jfs/namei.c         |   32 ++++++++++++++++++++++++++
 ./fs/jfs/super.c         |    1 
 ./include/linux/efs_fs.h |    1 
 7 files changed, 71 insertions(+), 54 deletions(-)

diff .prev/fs/efs/namei.c ./fs/efs/namei.c
--- .prev/fs/efs/namei.c	2007-05-14 11:14:52.000000000 +1000
+++ ./fs/efs/namei.c	2007-05-14 11:15:29.000000000 +1000
@@ -75,6 +75,38 @@ struct dentry *efs_lookup(struct inode *
 	return NULL;
 }
 
+struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *efs_get_parent(struct dentry *child)
 {
 	struct dentry *parent;

diff .prev/fs/efs/super.c ./fs/efs/super.c
--- .prev/fs/efs/super.c	2007-05-14 11:15:23.000000000 +1000
+++ ./fs/efs/super.c	2007-05-14 11:15:29.000000000 +1000
@@ -115,6 +115,7 @@ static const struct super_operations efs
 };
 
 static struct export_operations efs_export_ops = {
+	.get_dentry	= efs_get_dentry,
 	.get_parent	= efs_get_parent,
 };
 

diff .prev/fs/exportfs/expfs.c ./fs/exportfs/expfs.c
--- .prev/fs/exportfs/expfs.c	2007-05-14 11:15:23.000000000 +1000
+++ ./fs/exportfs/expfs.c	2007-05-14 11:15:29.000000000 +1000
@@ -391,61 +391,11 @@ out:
 	return error;
 }
 
-
-static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
+static struct dentry *get_dentry(struct super_block *sb, void *vobjp)
 {
-
-	/* iget isn't really right if the inode is currently unallocated!!
-	 * This should really all be done inside each filesystem
-	 *
-	 * ext2fs' read_inode has been strengthed to return a bad_inode if
-	 * the inode had been deleted.
-	 *
-	 * Currently we don't know the generation for parent directory, so
-	 * a generation of 0 means "accept any"
-	 */
-	struct inode *inode;
-	struct dentry *result;
-	if (ino == 0)
-		return ERR_PTR(-ESTALE);
-	inode = iget(sb, ino);
-	if (inode == NULL)
-		return ERR_PTR(-ENOMEM);
-	if (is_bad_inode(inode)
-	    || (generation && inode->i_generation != generation)
-		) {
-		/* we didn't find the right inode.. */
-		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
-			inode->i_ino,
-			inode->i_nlink, atomic_read(&inode->i_count),
-			inode->i_generation,
-			generation);
-
-		iput(inode);
-		return ERR_PTR(-ESTALE);
-	}
-	/* now to find a dentry.
-	 * If possible, get a well-connected one
-	 */
-	result = d_alloc_anon(inode);
-	if (!result) {
-		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	return result;
+	return ERR_PTR(-ESTALE);
 }
 
-
-static struct dentry *get_object(struct super_block *sb, void *vobjp)
-{
-	__u32 *objp = vobjp;
-	unsigned long ino = objp[0];
-	__u32 generation = objp[1];
-
-	return export_iget(sb, ino, generation);
-}
-
-
 /**
  * export_encode_fh - default export_operations->encode_fh function
  * @dentry:  the dentry to encode
@@ -524,7 +474,7 @@ struct export_operations export_op_defau
 
 	.get_name	= get_name,
 	.get_parent	= get_parent,
-	.get_dentry	= get_object,
+	.get_dentry	= get_dentry,
 };
 
 EXPORT_SYMBOL(export_op_default);

diff .prev/fs/jfs/jfs_inode.h ./fs/jfs/jfs_inode.h
--- .prev/fs/jfs/jfs_inode.h	2007-05-14 11:14:52.000000000 +1000
+++ ./fs/jfs/jfs_inode.h	2007-05-14 11:15:29.000000000 +1000
@@ -31,7 +31,7 @@ extern void jfs_truncate(struct inode *)
 extern void jfs_truncate_nolock(struct inode *, loff_t);
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
-extern void jfs_get_inode_flags(struct jfs_inode_info *);
+extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp);
 extern void jfs_set_inode_flags(struct inode *);
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 

diff .prev/fs/jfs/namei.c ./fs/jfs/namei.c
--- .prev/fs/jfs/namei.c	2007-05-14 11:14:52.000000000 +1000
+++ ./fs/jfs/namei.c	2007-05-14 11:15:29.000000000 +1000
@@ -1477,6 +1477,38 @@ static struct dentry *jfs_lookup(struct 
 	return dentry;
 }
 
+struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *jfs_get_parent(struct dentry *dentry)
 {
 	struct super_block *sb = dentry->d_inode->i_sb;

diff .prev/fs/jfs/super.c ./fs/jfs/super.c
--- .prev/fs/jfs/super.c	2007-05-14 11:15:23.000000000 +1000
+++ ./fs/jfs/super.c	2007-05-14 11:15:29.000000000 +1000
@@ -738,6 +738,7 @@ static const struct super_operations jfs
 };
 
 static struct export_operations jfs_export_operations = {
+	.get_dentry	= jfs_get_dentry,
 	.get_parent	= jfs_get_parent,
 };
 

diff .prev/include/linux/efs_fs.h ./include/linux/efs_fs.h
--- .prev/include/linux/efs_fs.h	2007-05-14 11:14:52.000000000 +1000
+++ ./include/linux/efs_fs.h	2007-05-14 11:15:29.000000000 +1000
@@ -45,6 +45,7 @@ extern efs_block_t efs_map_block(struct 
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp);
 extern struct dentry *efs_get_parent(struct dentry *);
 extern int efs_bmap(struct inode *, int);
 

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
NFS maillist  -  NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs

WARNING: multiple messages have this Message-ID (diff)
From: NeilBrown <neilb@suse.de>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: nfs@lists.sourceforge.net, linux-kernel@vger.kernel.org
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Neil Brown <neilb@suse.de>
Cc: shaggy@austin.ibm.com
Subject: [PATCH 002 of 8] knfsd: exportfs: remove iget abuse
Date: Tue, 15 May 2007 17:16:14 +1000	[thread overview]
Message-ID: <1070515071614.16259@suse.de> (raw)
In-Reply-To: 20070515170405.15621.patches@notabene


From: Christoph Hellwig <hch@infradead.org>

When the exportfs interface was added the expectation was that
filesystems provide an operation to convert from a file handle
to an inode/dentry, but it kept a backwards compat option that
still calls into iget.

Calling into iget from non-filesystem code is very bad, because
it gives too little information to filesystem, and simply crashes
if the filesystem doesn't implement the ->read_inode routine.

Fortunately there are only two filesystems left using this fallback:
efs and jfs.  This patch moves a copy of export_iget to each
of those to implement the get_dentry method.

While this is a temporary increase of lines of code in the kernel
it allows for a much cleaner interface and important code restructuring
in later patches.

Cc: shaggy@austin.ibm.com
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/efs/namei.c         |   32 ++++++++++++++++++++++++++
 ./fs/efs/super.c         |    1 
 ./fs/exportfs/expfs.c    |   56 ++---------------------------------------------
 ./fs/jfs/jfs_inode.h     |    2 -
 ./fs/jfs/namei.c         |   32 ++++++++++++++++++++++++++
 ./fs/jfs/super.c         |    1 
 ./include/linux/efs_fs.h |    1 
 7 files changed, 71 insertions(+), 54 deletions(-)

diff .prev/fs/efs/namei.c ./fs/efs/namei.c
--- .prev/fs/efs/namei.c	2007-05-14 11:14:52.000000000 +1000
+++ ./fs/efs/namei.c	2007-05-14 11:15:29.000000000 +1000
@@ -75,6 +75,38 @@ struct dentry *efs_lookup(struct inode *
 	return NULL;
 }
 
+struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *efs_get_parent(struct dentry *child)
 {
 	struct dentry *parent;

diff .prev/fs/efs/super.c ./fs/efs/super.c
--- .prev/fs/efs/super.c	2007-05-14 11:15:23.000000000 +1000
+++ ./fs/efs/super.c	2007-05-14 11:15:29.000000000 +1000
@@ -115,6 +115,7 @@ static const struct super_operations efs
 };
 
 static struct export_operations efs_export_ops = {
+	.get_dentry	= efs_get_dentry,
 	.get_parent	= efs_get_parent,
 };
 

diff .prev/fs/exportfs/expfs.c ./fs/exportfs/expfs.c
--- .prev/fs/exportfs/expfs.c	2007-05-14 11:15:23.000000000 +1000
+++ ./fs/exportfs/expfs.c	2007-05-14 11:15:29.000000000 +1000
@@ -391,61 +391,11 @@ out:
 	return error;
 }
 
-
-static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
+static struct dentry *get_dentry(struct super_block *sb, void *vobjp)
 {
-
-	/* iget isn't really right if the inode is currently unallocated!!
-	 * This should really all be done inside each filesystem
-	 *
-	 * ext2fs' read_inode has been strengthed to return a bad_inode if
-	 * the inode had been deleted.
-	 *
-	 * Currently we don't know the generation for parent directory, so
-	 * a generation of 0 means "accept any"
-	 */
-	struct inode *inode;
-	struct dentry *result;
-	if (ino == 0)
-		return ERR_PTR(-ESTALE);
-	inode = iget(sb, ino);
-	if (inode == NULL)
-		return ERR_PTR(-ENOMEM);
-	if (is_bad_inode(inode)
-	    || (generation && inode->i_generation != generation)
-		) {
-		/* we didn't find the right inode.. */
-		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
-			inode->i_ino,
-			inode->i_nlink, atomic_read(&inode->i_count),
-			inode->i_generation,
-			generation);
-
-		iput(inode);
-		return ERR_PTR(-ESTALE);
-	}
-	/* now to find a dentry.
-	 * If possible, get a well-connected one
-	 */
-	result = d_alloc_anon(inode);
-	if (!result) {
-		iput(inode);
-		return ERR_PTR(-ENOMEM);
-	}
-	return result;
+	return ERR_PTR(-ESTALE);
 }
 
-
-static struct dentry *get_object(struct super_block *sb, void *vobjp)
-{
-	__u32 *objp = vobjp;
-	unsigned long ino = objp[0];
-	__u32 generation = objp[1];
-
-	return export_iget(sb, ino, generation);
-}
-
-
 /**
  * export_encode_fh - default export_operations->encode_fh function
  * @dentry:  the dentry to encode
@@ -524,7 +474,7 @@ struct export_operations export_op_defau
 
 	.get_name	= get_name,
 	.get_parent	= get_parent,
-	.get_dentry	= get_object,
+	.get_dentry	= get_dentry,
 };
 
 EXPORT_SYMBOL(export_op_default);

diff .prev/fs/jfs/jfs_inode.h ./fs/jfs/jfs_inode.h
--- .prev/fs/jfs/jfs_inode.h	2007-05-14 11:14:52.000000000 +1000
+++ ./fs/jfs/jfs_inode.h	2007-05-14 11:15:29.000000000 +1000
@@ -31,7 +31,7 @@ extern void jfs_truncate(struct inode *)
 extern void jfs_truncate_nolock(struct inode *, loff_t);
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
-extern void jfs_get_inode_flags(struct jfs_inode_info *);
+extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp);
 extern void jfs_set_inode_flags(struct inode *);
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 

diff .prev/fs/jfs/namei.c ./fs/jfs/namei.c
--- .prev/fs/jfs/namei.c	2007-05-14 11:14:52.000000000 +1000
+++ ./fs/jfs/namei.c	2007-05-14 11:15:29.000000000 +1000
@@ -1477,6 +1477,38 @@ static struct dentry *jfs_lookup(struct 
 	return dentry;
 }
 
+struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp)
+{
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
+	struct inode *inode;
+	struct dentry *result;
+
+	if (ino == 0)
+		return ERR_PTR(-ESTALE);
+	inode = iget(sb, ino);
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (is_bad_inode(inode) ||
+	    (generation && inode->i_generation != generation)) {
+	    	result = ERR_PTR(-ESTALE);
+		goto out_iput;
+	}
+
+	result = d_alloc_anon(inode);
+	if (!result) {
+		result = ERR_PTR(-ENOMEM);
+		goto out_iput;
+	}
+	return result;
+
+ out_iput:
+	iput(inode);
+	return result;
+}
+
 struct dentry *jfs_get_parent(struct dentry *dentry)
 {
 	struct super_block *sb = dentry->d_inode->i_sb;

diff .prev/fs/jfs/super.c ./fs/jfs/super.c
--- .prev/fs/jfs/super.c	2007-05-14 11:15:23.000000000 +1000
+++ ./fs/jfs/super.c	2007-05-14 11:15:29.000000000 +1000
@@ -738,6 +738,7 @@ static const struct super_operations jfs
 };
 
 static struct export_operations jfs_export_operations = {
+	.get_dentry	= jfs_get_dentry,
 	.get_parent	= jfs_get_parent,
 };
 

diff .prev/include/linux/efs_fs.h ./include/linux/efs_fs.h
--- .prev/include/linux/efs_fs.h	2007-05-14 11:14:52.000000000 +1000
+++ ./include/linux/efs_fs.h	2007-05-14 11:15:29.000000000 +1000
@@ -45,6 +45,7 @@ extern efs_block_t efs_map_block(struct 
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp);
 extern struct dentry *efs_get_parent(struct dentry *);
 extern int efs_bmap(struct inode *, int);
 

  parent reply	other threads:[~2007-05-15  7:16 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-15  7:15 [PATCH 000 of 8] knfsd: cleanups for exportfs code NeilBrown
2007-05-15  7:16 ` [PATCH 001 of 8] knfsd: exportfs: add exportfs.h header NeilBrown
2007-05-15  7:16   ` NeilBrown
2007-05-15  7:16 ` NeilBrown [this message]
2007-05-15  7:16   ` [PATCH 002 of 8] knfsd: exportfs: remove iget abuse NeilBrown
2007-05-15 12:30   ` Dave Kleikamp
2007-05-15  7:16 ` [PATCH 003 of 8] knfsd: exportfs: add procedural interface for NFSD NeilBrown
2007-05-15  7:16   ` NeilBrown
2007-05-15  7:16 ` [PATCH 004 of 8] knfsd: exportfs: remove CALL macro NeilBrown
2007-05-15  7:16   ` NeilBrown
2007-05-15  7:16 ` [PATCH 005 of 8] knfsd: exportfs: untangle ISDIR logic in find_exported_dentry NeilBrown
2007-05-15  7:16 ` [PATCH 006 of 8] knfsd: exportfs: move acceptable check into find_acceptable_alias NeilBrown
2007-05-15  7:16   ` NeilBrown
2007-05-15  7:16 ` [PATCH 007 of 8] knfsd: exportfs: add find_disconnected_root helper NeilBrown
2007-05-15  7:16   ` NeilBrown
2007-05-15  7:16 ` [PATCH 008 of 8] knfsd: exportfs: split out reconnecting a dentry from find_exported_dentry NeilBrown
2007-05-15  7:16   ` NeilBrown

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=1070515071614.16259@suse.de \
    --to=neilb@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=hch@infradead.org \
    --cc=hch@lst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nfs@lists.sourceforge.net \
    --cc=shaggy@austin.ibm.com \
    /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.