#include <linux/buffer_head.h>
#include <linux/string.h>
-#include <linux/efs_fs.h>
#include <linux/smp_lock.h>
+#include <linux/exportfs.h>
+#include "efs.h"
+
static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) {
struct buffer_head *bh;
lock_kernel();
inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
if (inodenum) {
- if (!(inode = iget(dir->i_sb, inodenum))) {
+ inode = efs_iget(dir->i_sb, inodenum);
+ if (IS_ERR(inode)) {
unlock_kernel();
- return ERR_PTR(-EACCES);
+ return ERR_CAST(inode);
}
}
unlock_kernel();
- d_add(dentry, inode);
- return NULL;
+ return d_splice_alias(inode, dentry);
}
-struct dentry *efs_get_parent(struct dentry *child)
+static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
+ u32 generation)
{
- struct dentry *parent;
struct inode *inode;
- efs_ino_t ino;
- int error;
- lock_kernel();
+ if (ino == 0)
+ return ERR_PTR(-ESTALE);
+ inode = efs_iget(sb, ino);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
- error = -ENOENT;
- ino = efs_find_entry(child->d_inode, "..", 2);
- if (!ino)
- goto fail;
+ if (generation && inode->i_generation != generation) {
+ iput(inode);
+ return ERR_PTR(-ESTALE);
+ }
- error = -EACCES;
- inode = iget(child->d_inode->i_sb, ino);
- if (!inode)
- goto fail;
+ return inode;
+}
- error = -ENOMEM;
- parent = d_alloc_anon(inode);
- if (!parent)
- goto fail_iput;
+struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ efs_nfs_get_inode);
+}
- unlock_kernel();
- return parent;
+struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ efs_nfs_get_inode);
+}
+
+struct dentry *efs_get_parent(struct dentry *child)
+{
+ struct dentry *parent = ERR_PTR(-ENOENT);
+ efs_ino_t ino;
- fail_iput:
- iput(inode);
- fail:
+ lock_kernel();
+ ino = efs_find_entry(child->d_inode, "..", 2);
+ if (ino)
+ parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino));
unlock_kernel();
- return ERR_PTR(error);
+
+ return parent;
}