Hi, > Signed-off-by: Rasmus Rohde <rohde@xxxxxxx> Interesting character before Signed-off-by :). > --- 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; 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 accordingly. > + > + 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]; > }; > }; 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 <jack@xxxxxxx> SUSE Labs, CR - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html