diff options
Diffstat (limited to 'fs/efs/namei.c')
| -rw-r--r-- | fs/efs/namei.c | 90 |
1 files changed, 49 insertions, 41 deletions
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index ed4a207fe22..356c044e2cd 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -8,8 +8,9 @@ #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; @@ -22,20 +23,22 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) efs_block_t block; if (inode->i_size & (EFS_DIRBSIZE-1)) - printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n"); + pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n", + __func__); for(block = 0; block < inode->i_blocks; block++) { bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); if (!bh) { - printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block); + pr_err("%s(): failed to read dir block %d\n", + __func__, block); return 0; } dirblock = (struct efs_dir *) bh->b_data; if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { - printk(KERN_ERR "EFS: find_entry(): invalid directory block\n"); + pr_err("%s(): invalid directory block\n", __func__); brelse(bh); return(0); } @@ -57,54 +60,59 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) return(0); } -struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { +struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) +{ efs_ino_t inodenum; - struct inode * inode = NULL; + struct inode *inode = NULL; - lock_kernel(); inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); - if (inodenum) { - if (!(inode = iget(dir->i_sb, inodenum))) { - unlock_kernel(); - return ERR_PTR(-EACCES); - } - } - unlock_kernel(); + if (inodenum) + inode = efs_iget(dir->i_sb, inodenum); - 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: - unlock_kernel(); - return ERR_PTR(error); + ino = efs_find_entry(child->d_inode, "..", 2); + if (ino) + parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); + + return parent; } |
