Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[wrt350n-kernel.git] / fs / efs / namei.c
blob3082bad42e5074e54ea8ccffb9075b63dfa5e3b6
1 /*
2 * namei.c
4 * Copyright (c) 1999 Al Smith
6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
7 */
9 #include <linux/buffer_head.h>
10 #include <linux/string.h>
11 <<<<<<< HEAD:fs/efs/namei.c
12 #include <linux/efs_fs.h>
13 =======
14 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/efs/namei.c
15 #include <linux/smp_lock.h>
16 #include <linux/exportfs.h>
17 <<<<<<< HEAD:fs/efs/namei.c
18 =======
19 #include "efs.h"
20 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/efs/namei.c
23 static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) {
24 struct buffer_head *bh;
26 int slot, namelen;
27 char *nameptr;
28 struct efs_dir *dirblock;
29 struct efs_dentry *dirslot;
30 efs_ino_t inodenum;
31 efs_block_t block;
33 if (inode->i_size & (EFS_DIRBSIZE-1))
34 printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n");
36 for(block = 0; block < inode->i_blocks; block++) {
38 bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
39 if (!bh) {
40 printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block);
41 return 0;
44 dirblock = (struct efs_dir *) bh->b_data;
46 if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
47 printk(KERN_ERR "EFS: find_entry(): invalid directory block\n");
48 brelse(bh);
49 return(0);
52 for(slot = 0; slot < dirblock->slots; slot++) {
53 dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
55 namelen = dirslot->namelen;
56 nameptr = dirslot->name;
58 if ((namelen == len) && (!memcmp(name, nameptr, len))) {
59 inodenum = be32_to_cpu(dirslot->inode);
60 brelse(bh);
61 return(inodenum);
64 brelse(bh);
66 return(0);
69 struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
70 efs_ino_t inodenum;
71 struct inode * inode = NULL;
73 lock_kernel();
74 inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
75 if (inodenum) {
76 inode = efs_iget(dir->i_sb, inodenum);
77 if (IS_ERR(inode)) {
78 unlock_kernel();
79 return ERR_CAST(inode);
82 unlock_kernel();
84 d_add(dentry, inode);
85 return NULL;
88 static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
89 u32 generation)
91 struct inode *inode;
93 if (ino == 0)
94 return ERR_PTR(-ESTALE);
95 inode = efs_iget(sb, ino);
96 if (IS_ERR(inode))
97 return ERR_CAST(inode);
99 if (generation && inode->i_generation != generation) {
100 iput(inode);
101 return ERR_PTR(-ESTALE);
104 return inode;
107 struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
108 int fh_len, int fh_type)
110 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
111 efs_nfs_get_inode);
114 struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
115 int fh_len, int fh_type)
117 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
118 efs_nfs_get_inode);
121 struct dentry *efs_get_parent(struct dentry *child)
123 struct dentry *parent;
124 struct inode *inode;
125 efs_ino_t ino;
126 long error;
128 lock_kernel();
130 error = -ENOENT;
131 ino = efs_find_entry(child->d_inode, "..", 2);
132 if (!ino)
133 goto fail;
135 inode = efs_iget(child->d_inode->i_sb, ino);
136 if (IS_ERR(inode)) {
137 error = PTR_ERR(inode);
138 goto fail;
141 error = -ENOMEM;
142 parent = d_alloc_anon(inode);
143 if (!parent)
144 goto fail_iput;
146 unlock_kernel();
147 return parent;
149 fail_iput:
150 iput(inode);
151 fail:
152 unlock_kernel();
153 return ERR_PTR(error);