1 /* cnode related routines for the coda kernel code
2 (C) 1996 Peter Braam
3 */
4
5 #include <linux/types.h>
6 #include <linux/string.h>
7 #include <linux/time.h>
8
9 #include <linux/coda.h>
10 #include <linux/coda_linux.h>
11 #include <linux/coda_fs_i.h>
12 #include <linux/coda_psdev.h>
13
14 extern int coda_debug;
15
coda_fideq(ViceFid * fid1,ViceFid * fid2)16 inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
17 {
18 if (fid1->Vnode != fid2->Vnode) return 0;
19 if (fid1->Volume != fid2->Volume) return 0;
20 if (fid1->Unique != fid2->Unique) return 0;
21 return 1;
22 }
23
coda_isnullfid(ViceFid * fid)24 inline int coda_isnullfid(ViceFid *fid)
25 {
26 if (fid->Vnode || fid->Volume || fid->Unique) return 0;
27 return 1;
28 }
29
coda_inocmp(struct inode * inode,unsigned long ino,void * opaque)30 static int coda_inocmp(struct inode *inode, unsigned long ino, void *opaque)
31 {
32 return (coda_fideq((ViceFid *)opaque, &(ITOC(inode)->c_fid)));
33 }
34
35 static struct inode_operations coda_symlink_inode_operations = {
36 readlink: page_readlink,
37 follow_link: page_follow_link,
38 setattr: coda_notify_change,
39 };
40
41 /* cnode.c */
coda_fill_inode(struct inode * inode,struct coda_vattr * attr)42 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
43 {
44 CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino);
45
46 if (coda_debug & D_SUPER )
47 print_vattr(attr);
48
49 coda_vattr_to_iattr(inode, attr);
50
51 if (S_ISREG(inode->i_mode)) {
52 inode->i_op = &coda_file_inode_operations;
53 inode->i_fop = &coda_file_operations;
54 } else if (S_ISDIR(inode->i_mode)) {
55 inode->i_op = &coda_dir_inode_operations;
56 inode->i_fop = &coda_dir_operations;
57 } else if (S_ISLNK(inode->i_mode)) {
58 inode->i_op = &coda_symlink_inode_operations;
59 inode->i_data.a_ops = &coda_symlink_aops;
60 inode->i_mapping = &inode->i_data;
61 } else
62 init_special_inode(inode, inode->i_mode, attr->va_rdev);
63 }
64
coda_iget(struct super_block * sb,ViceFid * fid,struct coda_vattr * attr)65 struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
66 struct coda_vattr * attr)
67 {
68 struct inode *inode;
69 struct coda_inode_info *cii;
70 ino_t ino = coda_f2i(fid);
71 struct coda_sb_info *sbi = coda_sbp(sb);
72
73 down(&sbi->sbi_iget4_mutex);
74 inode = iget4(sb, ino, coda_inocmp, fid);
75
76 if ( !inode ) {
77 CDEBUG(D_CNODE, "coda_iget: no inode\n");
78 up(&sbi->sbi_iget4_mutex);
79 return ERR_PTR(-ENOMEM);
80 }
81
82 /* check if the inode is already initialized */
83 cii = ITOC(inode);
84 if (coda_isnullfid(&cii->c_fid))
85 /* new, empty inode found... initializing */
86 cii->c_fid = *fid;
87 up(&sbi->sbi_iget4_mutex);
88
89 /* always replace the attributes, type might have changed */
90 coda_fill_inode(inode, attr);
91 return inode;
92 }
93
94 /* this is effectively coda_iget:
95 - get attributes (might be cached)
96 - get the inode for the fid using vfs iget
97 - link the two up if this is needed
98 - fill in the attributes
99 */
coda_cnode_make(struct inode ** inode,ViceFid * fid,struct super_block * sb)100 int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
101 {
102 struct coda_vattr attr;
103 int error;
104
105 /* We get inode numbers from Venus -- see venus source */
106 error = venus_getattr(sb, fid, &attr);
107 if ( error ) {
108 CDEBUG(D_CNODE,
109 "coda_cnode_make: coda_getvattr returned %d for %s.\n",
110 error, coda_f2s(fid));
111 *inode = NULL;
112 return error;
113 }
114
115 *inode = coda_iget(sb, fid, &attr);
116 if ( IS_ERR(*inode) ) {
117 printk("coda_cnode_make: coda_iget failed\n");
118 return PTR_ERR(*inode);
119 }
120
121 CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
122 (*inode)->i_ino, atomic_read(&(*inode)->i_count),
123 coda_f2s(&ITOC(*inode)->c_fid));
124 return 0;
125 }
126
127
coda_replace_fid(struct inode * inode,struct ViceFid * oldfid,struct ViceFid * newfid)128 void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
129 struct ViceFid *newfid)
130 {
131 struct coda_inode_info *cii;
132
133 cii = ITOC(inode);
134
135 if (!coda_fideq(&cii->c_fid, oldfid))
136 BUG();
137
138 /* replace fid and rehash inode */
139 /* XXX we probably need to hold some lock here! */
140 remove_inode_hash(inode);
141 cii->c_fid = *newfid;
142 inode->i_ino = coda_f2i(newfid);
143 insert_inode_hash(inode);
144 }
145
146 /* convert a fid to an inode. */
coda_fid_to_inode(ViceFid * fid,struct super_block * sb)147 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
148 {
149 ino_t nr;
150 struct inode *inode;
151 struct coda_inode_info *cii;
152 struct coda_sb_info *sbi;
153
154 if ( !sb ) {
155 printk("coda_fid_to_inode: no sb!\n");
156 return NULL;
157 }
158
159 CDEBUG(D_INODE, "%s\n", coda_f2s(fid));
160
161 sbi = coda_sbp(sb);
162 nr = coda_f2i(fid);
163 down(&sbi->sbi_iget4_mutex);
164 inode = iget4(sb, nr, coda_inocmp, fid);
165 if ( !inode ) {
166 printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
167 sb, (long)nr);
168 goto out_unlock;
169 }
170
171 cii = ITOC(inode);
172
173 /* The inode could already be purged due to memory pressure */
174 if (coda_isnullfid(&cii->c_fid)) {
175 inode->i_nlink = 0;
176 iput(inode);
177 goto out_unlock;
178 }
179
180 CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
181 up(&sbi->sbi_iget4_mutex);
182 return inode;
183
184 out_unlock:
185 up(&sbi->sbi_iget4_mutex);
186 return NULL;
187 }
188
189 /* the CONTROL inode is made without asking attributes from Venus */
coda_cnode_makectl(struct inode ** inode,struct super_block * sb)190 int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
191 {
192 int error = 0;
193
194 *inode = iget(sb, CTL_INO);
195 if ( *inode ) {
196 (*inode)->i_op = &coda_ioctl_inode_operations;
197 (*inode)->i_fop = &coda_ioctl_operations;
198 (*inode)->i_mode = 0444;
199 error = 0;
200 } else {
201 error = -ENOMEM;
202 }
203
204 return error;
205 }
206
207