Add the guts for the new filesystem API to exportfs.
There's now a fh_to_dentry method that returns a dentry for the
object looked for given a filehandle fragment, and a fh_to_parent
operation that returns the dentry for the encoded parent directory
in case the file handle contains it.
There are default implementations for these methods that only take
a callback for an nfs-enhanced iget variant and implement the
rest of the semantics.
Signed-off-by: Christoph Hellwig <[EMAIL PROTECTED]>
Index: linux-2.6/include/linux/exportfs.h
===
--- linux-2.6.orig/include/linux/exportfs.h 2007-09-13 15:11:11.0
+0200
+++ linux-2.6/include/linux/exportfs.h 2007-09-13 15:13:57.0 +0200
@@ -4,6 +4,7 @@
#include
struct dentry;
+struct inode;
struct super_block;
struct vfsmount;
@@ -101,6 +102,21 @@ struct fid {
*the filehandle fragment. encode_fh() should return the number of bytes
*stored or a negative error code such as %-ENOSPC
*
+ * fh_to_dentry:
+ *@fh_to_dentry is given a &struct super_block (@sb) and a file handle
+ *fragment (@fh, @fh_len). It should return a &struct dentry which refers
+ *to the same file that the file handle fragment refers to. If it cannot,
+ *it should return a %NULL pointer if the file was found but no acceptable
+ *&dentries were available, or an %ERR_PTR error code indicating why it
+ *couldn't be found (e.g. %ENOENT or %ENOMEM). Any suitable dentry can be
+ *returned including, if necessary, a new dentry created with d_alloc_root.
+ *The caller can then find any other extant dentries by following the
+ *d_alias links.
+ *
+ * fh_to_parent:
+ *Same as @fh_to_dentry, except that it returns a pointer to the parent
+ *dentry if it was encoded into the filehandle fragment by @encode_fh.
+ *
* get_name:
*@get_name should find a name for the given @child in the given @parent
*directory. The name should be stored in the @name (with the
@@ -139,6 +155,10 @@ struct export_operations {
void *context);
int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
int connectable);
+ struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
+ struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type);
int (*get_name)(struct dentry *parent, char *name,
struct dentry *child);
struct dentry * (*get_parent)(struct dentry *child);
@@ -161,4 +181,14 @@ extern struct dentry *exportfs_decode_fh
int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *),
void *context);
+/*
+ * Generic helpers for filesystems.
+ */
+extern struct dentry *generic_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type,
+ struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));
+extern struct dentry *generic_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len, int fh_type,
+ struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));
+
#endif /* LINUX_EXPORTFS_H */
Index: linux-2.6/fs/exportfs/expfs.c
===
--- linux-2.6.orig/fs/exportfs/expfs.c 2007-09-13 15:13:02.0 +0200
+++ linux-2.6/fs/exportfs/expfs.c 2007-09-13 15:14:42.0 +0200
@@ -514,17 +514,141 @@ struct dentry *exportfs_decode_fh(struct
int (*acceptable)(void *, struct dentry *), void *context)
{
struct export_operations *nop = mnt->mnt_sb->s_export_op;
- struct dentry *result;
+ struct dentry *result, *alias;
+ int err;
- if (nop->decode_fh) {
- result = nop->decode_fh(mnt->mnt_sb, fid->raw, fh_len,
+ /*
+* Old way of doing things. Will go away soon.
+*/
+ if (!nop->fh_to_dentry) {
+ if (nop->decode_fh) {
+ return nop->decode_fh(mnt->mnt_sb, fid->raw, fh_len,
fileid_type, acceptable, context);
+ } else {
+ return export_decode_fh(mnt->mnt_sb, fid->raw, fh_len,
+ fileid_type, acceptable, context);
+ }
+ }
+
+ /*
+* Try to get any dentry for the given file handle from the filesystem.
+*/
+ result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
+ if (!result)
+ result = ERR_PTR(-ESTALE);
+ if (IS_ERR(result))
+ return result;
+
+ if (S_ISDIR(result->d_inode->i_mode)) {
+ /*
+* This request is for a directory.
+*
+* On the positive side there is only one dentry for