1 /* 2 * namei.c 3 * 4 * Copyright (c) 1999 Al Smith 5 * 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 7 */ 8 9 #include <linux/buffer_head.h> 10 #include <linux/string.h> 11 #include <linux/exportfs.h> 12 #include "efs.h" 13 14 15 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { 16 struct buffer_head *bh; 17 18 int slot, namelen; 19 char *nameptr; 20 struct efs_dir *dirblock; 21 struct efs_dentry *dirslot; 22 efs_ino_t inodenum; 23 efs_block_t block; 24 25 if (inode->i_size & (EFS_DIRBSIZE-1)) 26 printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n"); 27 28 for(block = 0; block < inode->i_blocks; block++) { 29 30 bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 31 if (!bh) { 32 printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block); 33 return 0; 34 } 35 36 dirblock = (struct efs_dir *) bh->b_data; 37 38 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { 39 printk(KERN_ERR "EFS: find_entry(): invalid directory block\n"); 40 brelse(bh); 41 return(0); 42 } 43 44 for(slot = 0; slot < dirblock->slots; slot++) { 45 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 46 47 namelen = dirslot->namelen; 48 nameptr = dirslot->name; 49 50 if ((namelen == len) && (!memcmp(name, nameptr, len))) { 51 inodenum = be32_to_cpu(dirslot->inode); 52 brelse(bh); 53 return(inodenum); 54 } 55 } 56 brelse(bh); 57 } 58 return(0); 59 } 60 61 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { 62 efs_ino_t inodenum; 63 struct inode *inode = NULL; 64 65 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); 66 if (inodenum) 67 inode = efs_iget(dir->i_sb, inodenum); 68 69 return d_splice_alias(inode, dentry); 70 } 71 72 static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, 73 u32 generation) 74 { 75 struct inode *inode; 76 77 if (ino == 0) 78 return ERR_PTR(-ESTALE); 79 inode = efs_iget(sb, ino); 80 if (IS_ERR(inode)) 81 return ERR_CAST(inode); 82 83 if (generation && inode->i_generation != generation) { 84 iput(inode); 85 return ERR_PTR(-ESTALE); 86 } 87 88 return inode; 89 } 90 91 struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, 92 int fh_len, int fh_type) 93 { 94 return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 95 efs_nfs_get_inode); 96 } 97 98 struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, 99 int fh_len, int fh_type) 100 { 101 return generic_fh_to_parent(sb, fid, fh_len, fh_type, 102 efs_nfs_get_inode); 103 } 104 105 struct dentry *efs_get_parent(struct dentry *child) 106 { 107 struct dentry *parent = ERR_PTR(-ENOENT); 108 efs_ino_t ino; 109 110 ino = efs_find_entry(child->d_inode, "..", 2); 111 if (ino) 112 parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); 113 114 return parent; 115 } 116