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