Re: [NFS] [PATCH] Make UDF exportable

!MAILaRCHIVE_VOTE_RePLACE
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: Christoph Hellwig <hch@...>
Cc: <nfs@...>, <jack@...>, <linux-fsdevel@...>
Date: Tuesday, February 5, 2008 - 1:44 pm

> > +static struct dentry *udf_export_get_parent(struct dentry *child)
Well - in isofs it was named isofs_export_get_parent, so I tried to stay consistent with that.

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
to your scheme is fine with me if you find it more readable.

Again - this was just copied from isofs.

is_bad_inode(..) is actually already checked so I'll just remove that.


Hehe - need I say isofs? :)

Sounds reasonable including the other length-checks you mention.

Ok.

Attached is a new attempt at a patch.

Signed-off-by: Rasmus Rohde <rohde@duff.dk>

--- 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 <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/sched.h>
+#include <linux/exportfs.h>
 
 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->d_inode, &dotdot, &fibh, &cfi))
+		goto out_unlock;
+	
+	if (fibh.sbh != fibh.ebh)
+		brelse(fibh.ebh);
+	brelse(fibh.sbh);
+		
+	inode = udf_iget(child->d_inode->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);
+
+	loc.logicalBlockNum = block;
+	loc.partitionReferenceNum = partref;
+	inode = udf_iget(sb, loc);
+
+	if (inode == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	if (generation && inode->i_generation != generation) {
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+	result = d_alloc_anon(inode);
+	if (!result) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
+	}
+	return result;
+}
+
+static struct dentry *udf_fh_to_dentry(struct super_block *sb,
+				       struct fid *fid, int fh_len, int fh_type)
+{
+	if ((fh_len != 3 && fh_len != 5) ||
+	    (fh_type != FILEID_UDF_WITH_PARENT &&
+	     fh_type != FILEID_UDF_WITHOUT_PARENT))
+		return NULL;
+
+	return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
+			fid->udf.generation);
+}
+
+static struct dentry *udf_fh_to_parent(struct super_block *sb,
+				       struct fid *fid, int fh_len, int fh_type)
+{
+	if (fh_len != 5 || fh_type != FILEID_UDF_WITHOUT_PARENT)
+		return NULL;
+
+	return udf_nfs_get_inode(sb, fid->udf.parent_block,
+				 fid->udf.parent_partref,
+				 fid->udf.parent_generation);
+}
+static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
+			 int connectable)
+{
+	int len = *lenp;
+	struct inode *inode =  de->d_inode;
+	kernel_lb_addr location = UDF_I_LOCATION(inode);
+	struct fid *fid = (struct fid *)fh;
+	int type = FILEID_UDF_WITHOUT_PARENT;
+
+	if (len < 3 || (connectable && len < 5))
+		return 255;
+
+	*lenp = 3;
+	fid->udf.block = location.logicalBlockNum;
+	fid->udf.partref = location.partitionReferenceNum;
+	fid->udf.generation = inode->i_generation;
+
+	if (connectable && !S_ISDIR(inode->i_mode)) {
+		spin_lock(&de->d_lock);
+		inode = de->d_parent->d_inode;
+		location = UDF_I_LOCATION(inode);
+		fid->udf.parent_block = location.logicalBlockNum;
+		fid->udf.parent_partref = location.partitionReferenceNum;	
+		fid->udf.parent_generation = inode->i_generation;
+		spin_unlock(&de->d_lock);
+		*lenp = 5;
+		type = FILEID_UDF_WITH_PARENT;
+	}
+
+	return type;
+}
+
+struct export_operations udf_export_ops = {
+	.encode_fh	= udf_encode_fh,
+	.fh_to_dentry   = udf_fh_to_dentry,
+	.fh_to_parent   = udf_fh_to_parent,
+	.get_parent     = udf_get_parent,
+};
+
 const struct inode_operations udf_dir_inode_operations = {
 	.lookup				= udf_lookup,
 	.create				= udf_create,

--- fs/udf/super.c.orig	2008-01-30 17:57:23.000000000 +0100
+++ fs/udf/super.c	2008-01-30 21:38:10.000000000 +0100
@@ -71,7 +71,7 @@
 #define VDS_POS_LENGTH			7
 
 static char error_buf[1024];
-
+extern struct export_operations udf_export_ops;
 /* These are the "meat" - everything else is stuffing */
 static int udf_fill_super(struct super_block *, void *, int);
 static void udf_put_super(struct super_block *);
@@ -1490,6 +1490,7 @@ static int udf_fill_super(struct super_b
 
 	/* Fill in the rest of the superblock */
 	sb->s_op = &udf_sb_ops;
+	sb->s_export_op = &udf_export_ops;
 	sb->dq_op = NULL;
 	sb->s_dirt = 0;
 	sb->s_magic = UDF_SUPER_MAGIC;

--- include/linux/exportfs.h.orig	2008-02-05 18:28:44.000000000 +0100
+++ include/linux/exportfs.h	2008-02-05 18:28:51.000000000 +0100
@@ -33,6 +33,19 @@ enum fid_type {
 	 * 32 bit parent directory inode number.
 	 */
 	FILEID_INO32_GEN_PARENT = 2,
+
+	/*
+	 * 32 bit block number, 16 bit partition reference,
+	 * 16 bit unused, 32 bit generation number.
+	 */
+	FILEID_UDF_WITHOUT_PARENT = 0x51,
+
+	/*
+	 * 32 bit block number, 16 bit partition reference,
+	 * 16 bit unused, 32 bit generation number,
+	 * 32 bit parent block number, 32 bit parent generation number
+	 */
+	FILEID_UDF_WITH_PARENT = 0x52,
 };
 
 struct fid {
@@ -43,6 +56,14 @@ struct fid {
 			u32 parent_ino;
 			u32 parent_gen;
 		} i32;
+		struct {
+			u32 block;
+			u16 partref;
+			u16 parent_partref;
+			u32 generation;
+			u32 parent_block;
+			u32 parent_generation;
+		} udf;
 		__u32 raw[6];
 	};
 };


-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
Re: [NFS] [PATCH] Make UDF exportable, Christoph Hellwig, (Tue Feb 5, 6:29 am)
Re: [NFS] [PATCH] Make UDF exportable, Rasmus Rohde, (Tue Feb 5, 1:44 pm)
Re: [NFS] [PATCH] Make UDF exportable, Jan Kara, (Wed Feb 6, 2:08 pm)
Re: [NFS] [PATCH] Make UDF exportable, Rasmus Rohde, (Wed Feb 6, 4:58 pm)
Re: [NFS] [PATCH] Make UDF exportable, Christoph Hellwig, (Thu Feb 7, 1:45 am)
Re: [NFS] [PATCH] Make UDF exportable, Rasmus Rohde, (Thu Feb 7, 3:06 am)
Re: [NFS] [PATCH] Make UDF exportable, Jan Kara, (Thu Feb 7, 10:48 am)
Re: [NFS] [PATCH] Make UDF exportable, Rasmus Rohde, (Thu Feb 7, 11:02 am)
Re: [NFS] [PATCH] Make UDF exportable, Christoph Hellwig, (Tue Apr 29, 10:33 am)
Re: [NFS] [PATCH] Make UDF exportable, Jan Kara, (Wed Apr 30, 11:41 am)
Re: [NFS] [PATCH] Make UDF exportable, Jan Kara, (Thu Feb 7, 11:13 am)
Re: [NFS] [PATCH] Make UDF exportable, Christoph Hellwig, (Wed Feb 6, 11:37 pm)
Re: [NFS] [PATCH] Make UDF exportable, Rasmus Rohde, (Tue Feb 5, 3:26 pm)