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 extern int coda_print_entry;
16
17 inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
18 {
19 if (fid1->Vnode != fid2->Vnode)
20 return 0;
21 if (fid1->Volume != fid2->Volume)
22 return 0;
23 if (fid1->Unique != fid2->Unique)
24 return 0;
25 return 1;
26 }
27
28 static struct inode_operations coda_symlink_inode_operations = {
29 readlink: page_readlink,
30 follow_link: page_follow_link,
31 setattr: coda_notify_change,
32 };
33
34 /* cnode.c */
35 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
36 {
37 CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino);
38
39 if (coda_debug & D_SUPER )
40 print_vattr(attr);
41
42 coda_vattr_to_iattr(inode, attr);
43
44 if (S_ISREG(inode->i_mode)) {
45 inode->i_op = &coda_file_inode_operations;
46 inode->i_fop = &coda_file_operations;
47 } else if (S_ISDIR(inode->i_mode)) {
48 inode->i_op = &coda_dir_inode_operations;
49 inode->i_fop = &coda_dir_operations;
50 } else if (S_ISLNK(inode->i_mode)) {
51 inode->i_op = &coda_symlink_inode_operations;
52 inode->i_data.a_ops = &coda_symlink_aops;
53 inode->i_mapping = &inode->i_data;
54 } else
55 init_special_inode(inode, inode->i_mode, attr->va_rdev);
56 }
57
58 struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
59 struct coda_vattr * attr)
60 {
61 struct inode *inode;
62 struct coda_inode_info *cii;
63 ino_t ino = attr->va_fileid;
64
65 inode = iget(sb, ino);
66 if ( !inode ) {
67 CDEBUG(D_CNODE, "coda_iget: no inode\n");
68 return ERR_PTR(-ENOMEM);
69 }
70
71 /* check if the inode is already initialized */
72 cii = ITOC(inode);
73 if (cii->c_fid.Volume != 0 || cii->c_fid.Vnode != 0 || cii->c_fid.Unique != 0) {
74 /* see if it is the right one (might have an inode collision) */
75 if ( !coda_fideq(fid, &cii->c_fid) ) {
76 printk("coda_iget: initialized inode old %s new %s!\n",
77 coda_f2s(&cii->c_fid), coda_f2s2(fid));
78 iput(inode);
79 return ERR_PTR(-ENOENT);
80 }
81 /* we will still replace the attributes, type might have changed */
82 goto out;
83 }
84
85 /* new, empty inode found... initializing */
86
87 /* Initialize the Coda inode info structure */
88 cii->c_fid = *fid;
89 cii->c_vnode = inode;
90
91 out:
92 coda_fill_inode(inode, attr);
93 return inode;
94 }
95
96 /* this is effectively coda_iget:
97 - get attributes (might be cached)
98 - get the inode for the fid using vfs iget
99 - link the two up if this is needed
100 - fill in the attributes
101 */
102 int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
103 {
104 struct coda_vattr attr;
105 int error;
106
107 ENTRY;
108
109 /* We get inode numbers from Venus -- see venus source */
110
111 error = venus_getattr(sb, fid, &attr);
112 if ( error ) {
113 CDEBUG(D_CNODE,
114 "coda_cnode_make: coda_getvattr returned %d for %s.\n",
115 error, coda_f2s(fid));
116 *inode = NULL;
117 EXIT;
118 return error;
119 }
120
121 *inode = coda_iget(sb, fid, &attr);
122 if ( IS_ERR(*inode) ) {
123 printk("coda_cnode_make: coda_iget failed\n");
124 EXIT;
125 return PTR_ERR(*inode);
126 }
127
128 CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
129 (*inode)->i_ino, atomic_read(&(*inode)->i_count),
130 coda_f2s(&(*inode)->u.coda_i.c_fid));
131 EXIT;
132 return 0;
133 }
134
135
136 void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
137 struct ViceFid *newfid)
138 {
139 struct coda_inode_info *cii;
140
141 cii = ITOC(inode);
142
143 if ( ! coda_fideq(&cii->c_fid, oldfid) )
144 printk("What? oldfid != cii->c_fid. Call 911.\n");
145
146 cii->c_fid = *newfid;
147 }
148
149
150
151
152 /* convert a fid to an inode. Mostly we can compute
153 the inode number from the FID, but not for volume
154 mount points: those are in a list */
155 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
156 {
157 ino_t nr;
158 struct inode *inode;
159 struct coda_inode_info *cii;
160 ENTRY;
161
162 if ( !sb ) {
163 printk("coda_fid_to_inode: no sb!\n");
164 return NULL;
165 }
166
167 CDEBUG(D_INODE, "%s\n", coda_f2s(fid));
168
169
170 /* weird fids cannot be hashed, have to look for them the hard way */
171 if ( coda_fid_is_weird(fid) ) {
172 struct coda_sb_info *sbi = coda_sbp(sb);
173 struct list_head *le;
174
175 list_for_each(le, &sbi->sbi_cihead)
176 {
177 cii = list_entry(le, struct coda_inode_info, c_cilist);
178 if ( cii->c_magic != CODA_CNODE_MAGIC ) BUG();
179
180 CDEBUG(D_DOWNCALL, "iterating, now doing %s, ino %ld\n",
181 coda_f2s(&cii->c_fid), cii->c_vnode->i_ino);
182
183 if ( coda_fideq(&cii->c_fid, fid) ) {
184 inode = cii->c_vnode;
185 CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino);
186 iget(sb, inode->i_ino);
187 return inode;
188 }
189 }
190 return NULL;
191 }
192
193 /* fid is not weird: ino should be computable */
194 nr = coda_f2i(fid);
195 inode = iget(sb, nr);
196 if ( !inode ) {
197 printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
198 sb, (long)nr);
199 return NULL;
200 }
201
202 /* check if this inode is linked to a cnode */
203 cii = ITOC(inode);
204
205 /* make sure this is the one we want */
206 if ( coda_fideq(fid, &cii->c_fid) ) {
207 CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
208 return inode;
209 }
210
211 #if 0
212 printk("coda_fid2inode: bad cnode (ino %ld, fid %s)", nr, coda_f2s(fid));
213 #endif
214 iput(inode);
215 return NULL;
216
217 }
218
219 /* the CONTROL inode is made without asking attributes from Venus */
220 int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
221 {
222 int error = 0;
223
224 *inode = iget(sb, CTL_INO);
225 if ( *inode ) {
226 (*inode)->i_op = &coda_ioctl_inode_operations;
227 (*inode)->i_fop = &coda_ioctl_operations;
228 (*inode)->i_mode = 0444;
229 error = 0;
230 } else {
231 error = -ENOMEM;
232 }
233
234 return error;
235 }
236
237
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.