login
Header Space

 
 

Re: [NFS] [PATCH] Make UDF exportable

Previous thread: [patch 0/3] add perform_write to a_ops by Miklos Szeredi on Monday, February 4, 2008 - 1:04 pm. (4 messages)

Next thread: CONGRATULATIONS by MICROSOFT AWARD 2008 on Tuesday, February 5, 2008 - 3:36 pm. (1 message)
To: Rasmus Rohde <rohde@...>
Cc: <nfs@...>, <jack@...>, <linux-fsdevel@...>
Date: Tuesday, February 5, 2008 - 6:29 am

Thanks, I know some people have been waiting for this for quite a while.
Please make sure Jan Kara who's the new udf maintainer and linux-fsdevel
where we discuss general filesystem related issue for future revisions

isofs might not be the very best example since it's an odd filesystem,
but then so is udf.  I'll go through your patch in a little more detail

Any reason this is not called udf_get_parent to follow the scheme

This if/else block looks little odd, and following the locking is a bit
hard.  What about doing it like the following:

	lock_kernel();
	if (!udf_find_entry(child-&gt;d_inode, &amp;dotdot, &amp;fibh, &amp;cfi))
		goto out_unlock;

	if (fibh.sbh != fibh.ebh)
		brelse(fibh.ebh);
	brelse(fibh.sbh);

	inode = udf_iget(child-&gt;d_inode-&gt;i_sb,
			 lelb_to_cpu(cfi.icb.extLocation));
	if (!inode)
		goto out_unlock;
	unlock_kernel();

	parent = d_alloc_anon(inode);
	if (!parent) {
		iput(inode);
		parent = ERR_PTR(-ENOMEM);
	}

	return parent;
 out_unlock:
	unlock_kernel();
	return ERR_PTR(-EACCESS);

to follow other filesystems this should be called
udf_nfs_get_inode.  Also please decide if you want to put the static
and return type on the same line or on a separate one.  Having it on
the same one is documented in Documentation/Codingstyle but separate

it would be better to introduce a version of udf_iget that can check
the generation and return an error instead of having to check this
later.  If you don't think you're up to modifying code we could do
this later on, though.  In this case please note this in the patch
description and fix up the above formatting to read something like:

	if (is_bad_inode(inode) ||

It would be useful if you could add symbolic constants for the
two fh types you add and chose values not yet used by other filesystems,
e.g. 0x51 and 0x52.  This will help people sniffing the nfs on the
wire protocol to understand what file handle they're dealing with.

Also you migh want to make the fh_len check more explicit and...
To: Christoph Hellwig <hch@...>
Cc: <nfs@...>, <jack@...>, <linux-fsdevel@...>
Date: Tuesday, February 5, 2008 - 1:44 pm

Most of the code is copied from udf_lookup(..)
To me the locking is simple. Before the two returns you have an unlock.
It's pretty clear that all control-paths are covered. However changing
Ok.

Attached is a new attempt at a patch.

Signed-off-by: Rasmus Rohde &lt;rohde@duff.dk&gt;

--- fs/udf/namei.c.orig	2007-10-10 16:22:30.000000000 +0200
+++ fs/udf/namei.c	2008-02-05 18:28:13.000000000 +0100
@@ -31,6 +31,7 @@
 #include &lt;linux/smp_lock.h&gt;
 #include &lt;linux/buffer_head.h&gt;
 #include &lt;linux/sched.h&gt;
+#include &lt;linux/exportfs.h&gt;
 
 static inline int udf_match(int len1, const char *name1, int len2,
 			    const char *name2)
@@ -315,9 +316,8 @@ static struct dentry *udf_lookup(struct 
 		}
 	}
 	unlock_kernel();
-	d_add(dentry, inode);
 
-	return NULL;
+	return d_splice_alias(inode, dentry);
 }
 
 static struct fileIdentDesc *udf_add_entry(struct inode *dir,
@@ -1231,6 +1231,135 @@ end_rename:
 	return retval;
 }
 
+static struct dentry *udf_get_parent(struct dentry *child)
+{
+	struct dentry *parent;
+	struct inode *inode = NULL;
+	struct dentry dotdot;
+	struct fileIdentDesc cfi;
+	struct udf_fileident_bh fibh;
+
+	dotdot.d_name.name = "..";
+	dotdot.d_name.len = 2;
+
+	lock_kernel();
+	if (!udf_find_entry(child-&gt;d_inode, &amp;dotdot, &amp;fibh, &amp;cfi))
+		goto out_unlock;
+	
+	if (fibh.sbh != fibh.ebh)
+		brelse(fibh.ebh);
+	brelse(fibh.sbh);
+		
+	inode = udf_iget(child-&gt;d_inode-&gt;i_sb,
+			 lelb_to_cpu(cfi.icb.extLocation));
+	if (!inode)
+		goto out_unlock;
+	unlock_kernel();
+
+	parent = d_alloc_anon(inode);
+	if (!parent) {
+		iput(inode);
+		parent = ERR_PTR(-ENOMEM);
+	}
+
+	return parent;
+out_unlock:
+	unlock_kernel();
+	return ERR_PTR(-EACCES);
+}
+
+
+static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
+					u16 partref, __u32 generation)
+{
+	struct inode *inode;
+	struct dentry *result;
+	kernel_lb_addr loc;
+
+	if (block == 0)
+		return ERR_PTR(-ESTALE);
+
+...
To: Rasmus Rohde <rohde@...>
Cc: Christoph Hellwig <hch@...>, <nfs@...>, <linux-fsdevel@...>
Date: Wednesday, February 6, 2008 - 2:08 pm

Have you ever tried this? I think this could never work. UDF doesn't have
entry named .. in a directory. You have to search for an entry that has
in fileCharacteristics set bit FID_FILE_CHAR_PARENT. Maybe you could
hack-around udf_find_entry() to recognize .. dentry and do the search
  Otherwise the patch looks fine. But please rediff the patch against
Andrew's development tree (or -mm) because there are some cleanups there...
Thanks.

									Honza
-- 
Jan Kara &lt;jack@suse.cz&gt;
SUSE Labs, CR
-
To: Jan Kara <jack@...>
Cc: Christoph Hellwig <hch@...>, <nfs@...>, <linux-fsdevel@...>
Date: Wednesday, February 6, 2008 - 4:58 pm

Probably not. I just tested that I could read files and navigate the
directory structure. However looking into UDF I think you are right - it
will fail.
I have extended udf_find_entry() to do an explicit check based on
fileCharacteristics as you propose.
Certainly there are. New patch against 2.6.24-mm1:

Signed-off-by: Rasmus Rohde &lt;rohde@duff.dk&gt;

diff -uprN -X linux-2.6.24-mm1-vanilla/Documentation/dontdiff linux-2.6.24-mm1-vanilla/fs/udf/namei.c linux-2.6.24-mm1/fs/udf/namei.c
--- linux-2.6.24-mm1-vanilla/fs/udf/namei.c	2008-02-06 21:23:36.000000000 +0100
+++ linux-2.6.24-mm1/fs/udf/namei.c	2008-02-06 21:41:38.000000000 +0100
@@ -31,6 +31,7 @@
 #include &lt;linux/smp_lock.h&gt;
 #include &lt;linux/buffer_head.h&gt;
 #include &lt;linux/sched.h&gt;
+#include &lt;linux/exportfs.h&gt;
 
 static inline int udf_match(int len1, const char *name1, int len2,
 			    const char *name2)
@@ -159,6 +160,8 @@ static struct fileIdentDesc *udf_find_en
 	sector_t offset;
 	struct extent_position epos = {};
 	struct udf_inode_info *dinfo = UDF_I(dir);
+	int isdotdot = dentry-&gt;d_name.len == 2 &amp;&amp;
+		dentry-&gt;d_name.name[0] == '.' &amp;&amp; dentry-&gt;d_name.name[1] == '.';
 
 	size = udf_ext0_offset(dir) + dir-&gt;i_size;
 	f_pos = udf_ext0_offset(dir);
@@ -232,6 +235,12 @@ static struct fileIdentDesc *udf_find_en
 				continue;
 		}
 
+		if ((cfi-&gt;fileCharacteristics &amp; FID_FILE_CHAR_PARENT) &amp;&amp;
+		    isdotdot) {
+			brelse(epos.bh);
+			return fi;
+		}
+
 		if (!lfi)
 			continue;
 
@@ -324,9 +333,8 @@ static struct dentry *udf_lookup(struct 
 		}
 	}
 	unlock_kernel();
-	d_add(dentry, inode);
 
-	return NULL;
+	return d_splice_alias(inode, dentry);
 }
 
 static struct fileIdentDesc *udf_add_entry(struct inode *dir,
@@ -1298,6 +1306,134 @@ end_rename:
 	return retval;
 }
 
+static struct dentry *udf_get_parent(struct dentry *child)
+{
+	struct dentry *parent;
+	struct inode *inode = NULL;
+	struct dentry dotdot;
+	struct fileIdentDe...
To: Rasmus Rohde <rohde@...>
Cc: Jan Kara <jack@...>, Christoph Hellwig <hch@...>, <linux-fsdevel@...>, <nfs@...>
Date: Thursday, February 7, 2008 - 1:45 am

There's still a few trivial warnings from scripts/checkpatch.pl that
should be fixed up:

ERROR: trailing whitespace
#88: FILE: fs/udf/namei.c:1323:
+^I$

ERROR: trailing whitespace
#92: FILE: fs/udf/namei.c:1327:
+^I^I$

ERROR: trailing whitespace
#185: FILE: fs/udf/namei.c:1420:
+^I^Ifid-&gt;udf.parent_partref = location.partitionReferenceNum;^I$

WARNING: externs should be avoided in .c files
#212: FILE: fs/udf/super.c:79:
+extern struct export_operations udf_export_ops;

total: 3 errors, 1 warnings, 218 lines checked

-
To: Christoph Hellwig <hch@...>
Cc: Jan Kara <jack@...>, <linux-fsdevel@...>, <nfs@...>
Date: Thursday, February 7, 2008 - 3:06 am

Ok - I have checked get_parent and it works as expected.
I used the "Neil Brown"-test mentioned elsewhere in this thread and
Fixed that. Sorry for not running checkpatch.pl before submitting.

Before posting the last and hopefully final patch I'd like to know what
Jan says about open coding the lookup for ..
It will mean a lot of code duplication and I think it makes good sense
for udf_find_entry to be able to handle ..

-
To: Rasmus Rohde <rohde@...>
Cc: Christoph Hellwig <hch@...>, <linux-fsdevel@...>, <nfs@...>
Date: Thursday, February 7, 2008 - 10:48 am

Yes, I think opencoding it would really lead to larger code duplication
than I'd like so please keep the change in udf_find_entry(). Thanks.

								Honza
-- 
Jan Kara &lt;jack@suse.cz&gt;
SUSE Labs, CR
-
To: Jan Kara <jack@...>
Cc: Christoph Hellwig <hch@...>, <linux-fsdevel@...>, <nfs@...>
Date: Thursday, February 7, 2008 - 11:02 am

Great - then I think we are hopefully at a patch that can be accepted.

Signed-off-by: Rasmus Rohde &lt;rohde@duff.dk&gt;

diff -uprN -X linux-2.6.24-mm1-vanilla/Documentation/dontdiff linux-2.6.24-mm1-vanilla/fs/udf/namei.c linux-2.6.24-mm1/fs/udf/namei.c
--- linux-2.6.24-mm1-vanilla/fs/udf/namei.c	2008-02-06 21:23:36.000000000 +0100
+++ linux-2.6.24-mm1/fs/udf/namei.c	2008-02-07 07:13:04.000000000 +0100
@@ -31,6 +31,7 @@
 #include &lt;linux/smp_lock.h&gt;
 #include &lt;linux/buffer_head.h&gt;
 #include &lt;linux/sched.h&gt;
+#include &lt;linux/exportfs.h&gt;
 
 static inline int udf_match(int len1, const char *name1, int len2,
 			    const char *name2)
@@ -159,6 +160,8 @@ static struct fileIdentDesc *udf_find_en
 	sector_t offset;
 	struct extent_position epos = {};
 	struct udf_inode_info *dinfo = UDF_I(dir);
+	int isdotdot = dentry-&gt;d_name.len == 2 &amp;&amp;
+		dentry-&gt;d_name.name[0] == '.' &amp;&amp; dentry-&gt;d_name.name[1] == '.';
 
 	size = udf_ext0_offset(dir) + dir-&gt;i_size;
 	f_pos = udf_ext0_offset(dir);
@@ -232,6 +235,12 @@ static struct fileIdentDesc *udf_find_en
 				continue;
 		}
 
+		if ((cfi-&gt;fileCharacteristics &amp; FID_FILE_CHAR_PARENT) &amp;&amp;
+		    isdotdot) {
+			brelse(epos.bh);
+			return fi;
+		}
+
 		if (!lfi)
 			continue;
 
@@ -324,9 +333,8 @@ static struct dentry *udf_lookup(struct 
 		}
 	}
 	unlock_kernel();
-	d_add(dentry, inode);
 
-	return NULL;
+	return d_splice_alias(inode, dentry);
 }
 
 static struct fileIdentDesc *udf_add_entry(struct inode *dir,
@@ -1298,6 +1306,134 @@ end_rename:
 	return retval;
 }
 
+static struct dentry *udf_get_parent(struct dentry *child)
+{
+	struct dentry *parent;
+	struct inode *inode = NULL;
+	struct dentry dotdot;
+	struct fileIdentDesc cfi;
+	struct udf_fileident_bh fibh;
+
+	dotdot.d_name.name = "..";
+	dotdot.d_name.len = 2;
+
+	lock_kernel();
+	if (!udf_find_entry(child-&gt;d_inode, &amp;dotdot, &amp;fibh, &amp;cfi))
+		goto out_unlock;
+
+	if (fibh.sbh !=...
To: Rasmus Rohde <rohde@...>
Cc: Jan Kara <jack@...>, Christoph Hellwig <hch@...>, <linux-fsdevel@...>, <nfs@...>
Date: Tuesday, April 29, 2008 - 10:33 am

Jan, any reason this patch didn't go in with the last merge?  I'd really
---end quoted text---
--
To: Christoph Hellwig <hch@...>
Cc: Rasmus Rohde <rohde@...>, <linux-fsdevel@...>, <nfs@...>
Date: Wednesday, April 30, 2008 - 11:41 am

Thanks for catching this. It seems I missed the patch when merging all
the UDF patches I had in my mailbox. I have it merged in my git tree and
will push it to Linus with other patches.

-- 
Jan Kara &lt;jack@suse.cz&gt;
SUSE Labs, CR
--
To: Rasmus Rohde <rohde@...>
Cc: Christoph Hellwig <hch@...>, <linux-fsdevel@...>, <nfs@...>
Date: Thursday, February 7, 2008 - 11:13 am

Honza
-- 
Jan Kara &lt;jack@suse.cz&gt;
SUSE Labs, CR
-
To: Rasmus Rohde <rohde@...>
Cc: Jan Kara <jack@...>, Christoph Hellwig <hch@...>, <nfs@...>, <linux-fsdevel@...>
Date: Wednesday, February 6, 2008 - 11:37 pm

Testing this is pretty hard.  You export a filesystem, then cd somewhere
deep into a directory hiearchy in there.  Then unexport the filesystem
and unmount on the server.  mount it back on the server, export it again
and do something with a file from the directory you've cd into before
the unmount.  Make sure you have a printk in your get_parent method
to make sure you're really hitting it.

Btw, I think it would be nicer to opencode the .. lookup in get_parent
instead of changing udf_find_entry.  The lookup for .. is not needed
by anything else, and get_parent only looks for it so it's a natural
place to opencode it there.

-
To: Christoph Hellwig <hch@...>
Cc: <nfs@...>, <jack@...>, <linux-fsdevel@...>
Date: Tuesday, February 5, 2008 - 3:26 pm

^^^^^^^

Argh - this should have been WITH so the line reads:

if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT)

I'll just hold back a little reposting a new patch if other comments
should happen to show up.

-
Previous thread: [patch 0/3] add perform_write to a_ops by Miklos Szeredi on Monday, February 4, 2008 - 1:04 pm. (4 messages)

Next thread: CONGRATULATIONS by MICROSOFT AWARD 2008 on Tuesday, February 5, 2008 - 3:36 pm. (1 message)
speck-geostationary