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, unsigned int flags) 62 { 63 efs_ino_t inodenum; 64 struct inode *inode = NULL; 65 66 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); 67 if (inodenum) 68 inode = efs_iget(dir->i_sb, inodenum); 69 70 return d_splice_alias(inode, dentry); 71 } 72 73 static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, 74 u32 generation) 75 { 76 struct inode *inode; 77 78 if (ino == 0) 79 return ERR_PTR(-ESTALE); 80 inode = efs_iget(sb, ino); 81 if (IS_ERR(inode)) 82 return ERR_CAST(inode); 83 84 if (generation && inode->i_generation != generation) { 85 iput(inode); 86 return ERR_PTR(-ESTALE); 87 } 88 89 return inode; 90 } 91 92 struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, 93 int fh_len, int fh_type) 94 { 95 return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 96 efs_nfs_get_inode); 97 } 98 99 struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, 100 int fh_len, int fh_type) 101 { 102 return generic_fh_to_parent(sb, fid, fh_len, fh_type, 103 efs_nfs_get_inode); 104 } 105 106 struct dentry *efs_get_parent(struct dentry *child) 107 { 108 struct dentry *parent = ERR_PTR(-ENOENT); 109 efs_ino_t ino; 110 111 ino = efs_find_entry(child->d_inode, "..", 2); 112 if (ino) 113 parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); 114 115 return parent; 116 } 117