0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/buffer_head.h>
0011 #include <linux/string.h>
0012 #include <linux/exportfs.h>
0013 #include "efs.h"
0014
0015
0016 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
0017 {
0018 struct buffer_head *bh;
0019
0020 int slot, namelen;
0021 char *nameptr;
0022 struct efs_dir *dirblock;
0023 struct efs_dentry *dirslot;
0024 efs_ino_t inodenum;
0025 efs_block_t block;
0026
0027 if (inode->i_size & (EFS_DIRBSIZE-1))
0028 pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
0029 __func__);
0030
0031 for(block = 0; block < inode->i_blocks; block++) {
0032
0033 bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
0034 if (!bh) {
0035 pr_err("%s(): failed to read dir block %d\n",
0036 __func__, block);
0037 return 0;
0038 }
0039
0040 dirblock = (struct efs_dir *) bh->b_data;
0041
0042 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
0043 pr_err("%s(): invalid directory block\n", __func__);
0044 brelse(bh);
0045 return 0;
0046 }
0047
0048 for (slot = 0; slot < dirblock->slots; slot++) {
0049 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
0050
0051 namelen = dirslot->namelen;
0052 nameptr = dirslot->name;
0053
0054 if ((namelen == len) && (!memcmp(name, nameptr, len))) {
0055 inodenum = be32_to_cpu(dirslot->inode);
0056 brelse(bh);
0057 return inodenum;
0058 }
0059 }
0060 brelse(bh);
0061 }
0062 return 0;
0063 }
0064
0065 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
0066 {
0067 efs_ino_t inodenum;
0068 struct inode *inode = NULL;
0069
0070 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
0071 if (inodenum)
0072 inode = efs_iget(dir->i_sb, inodenum);
0073
0074 return d_splice_alias(inode, dentry);
0075 }
0076
0077 static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
0078 u32 generation)
0079 {
0080 struct inode *inode;
0081
0082 if (ino == 0)
0083 return ERR_PTR(-ESTALE);
0084 inode = efs_iget(sb, ino);
0085 if (IS_ERR(inode))
0086 return ERR_CAST(inode);
0087
0088 if (generation && inode->i_generation != generation) {
0089 iput(inode);
0090 return ERR_PTR(-ESTALE);
0091 }
0092
0093 return inode;
0094 }
0095
0096 struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
0097 int fh_len, int fh_type)
0098 {
0099 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
0100 efs_nfs_get_inode);
0101 }
0102
0103 struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
0104 int fh_len, int fh_type)
0105 {
0106 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
0107 efs_nfs_get_inode);
0108 }
0109
0110 struct dentry *efs_get_parent(struct dentry *child)
0111 {
0112 struct dentry *parent = ERR_PTR(-ENOENT);
0113 efs_ino_t ino;
0114
0115 ino = efs_find_entry(d_inode(child), "..", 2);
0116 if (ino)
0117 parent = d_obtain_alias(efs_iget(child->d_sb, ino));
0118
0119 return parent;
0120 }