* better
[mascara-docs.git] / i386 / linux-2.3.21 / fs / coda / cnode.c
blobfaa983e0f4283d75ee8bb44cd3ac6418aabb656e
1 /* cnode related routines for the coda kernel code
2 (C) 1996 Peter Braam
3 */
5 #include <linux/types.h>
6 #include <linux/string.h>
7 #include <linux/time.h>
9 #include <linux/coda.h>
10 #include <linux/coda_linux.h>
11 #include <linux/coda_fs_i.h>
12 #include <linux/coda_psdev.h>
14 extern int coda_debug;
15 extern int coda_print_entry;
17 inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
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;
28 /* cnode.c */
29 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
31 CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino);
33 if (coda_debug & D_SUPER )
34 print_vattr(attr);
36 coda_vattr_to_iattr(inode, attr);
38 if (S_ISREG(inode->i_mode))
39 inode->i_op = &coda_file_inode_operations;
40 else if (S_ISDIR(inode->i_mode))
41 inode->i_op = &coda_dir_inode_operations;
42 else if (S_ISLNK(inode->i_mode))
43 inode->i_op = &coda_symlink_inode_operations;
44 else
45 init_special_inode(inode, inode->i_mode, attr->va_rdev);
48 /* this is effectively coda_iget:
49 - get attributes (might be cached)
50 - get the inode for the fid using vfs iget
51 - link the two up if this is needed
52 - fill in the attributes
54 int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
56 struct coda_inode_info *cnp;
57 struct coda_sb_info *sbi= coda_sbp(sb);
58 struct coda_vattr attr;
59 int error;
60 ino_t ino;
62 ENTRY;
64 /*
65 * We get inode numbers from Venus -- see venus source
68 error = venus_getattr(sb, fid, &attr);
69 if ( error ) {
70 CDEBUG(D_CNODE,
71 "coda_cnode_make: coda_getvattr returned %d for %s.\n",
72 error, coda_f2s(fid));
73 *inode = NULL;
74 return error;
77 ino = attr.va_fileid;
78 *inode = iget(sb, ino);
79 if ( !*inode ) {
80 printk("coda_cnode_make: iget failed\n");
81 return -ENOMEM;
84 cnp = ITOC(*inode);
85 /* see if we've got it already */
86 if ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) {
87 return 0;
90 /* not fresh: collision */
91 if ( cnp->c_magic != 0 ) {
92 printk("coda_cnode_make on initialized inode %ld, old %s new
93 %s!\n",
94 (*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid));
95 iput(*inode);
96 return -ENOENT;
99 memset(cnp, 0, (int) sizeof(struct coda_inode_info));
100 cnp->c_fid = *fid;
101 cnp->c_magic = CODA_CNODE_MAGIC;
102 cnp->c_flags = 0;
103 cnp->c_vnode = *inode;
104 INIT_LIST_HEAD(&(cnp->c_cnhead));
105 INIT_LIST_HEAD(&(cnp->c_volrootlist));
107 /* fill in the inode attributes */
108 if ( coda_f2i(fid) != ino ) {
109 if ( !coda_fid_is_weird(fid) )
110 printk("Coda: unknown weird fid: ino %ld, fid %s."
111 "Tell Peter.\n", (long)ino, coda_f2s(&cnp->c_fid));
112 list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
113 CDEBUG(D_UPCALL, "Added %ld ,%s to volroothead\n",
114 (long)ino, coda_f2s(&cnp->c_fid));
117 coda_fill_inode(*inode, &attr);
118 CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
119 (*inode)->i_ino, (*inode)->i_count,
120 coda_f2s(&cnp->c_fid));
122 EXIT;
123 return 0;
127 void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
128 struct ViceFid *newfid)
130 struct coda_inode_info *cnp;
131 struct coda_sb_info *sbi= coda_sbp(inode->i_sb);
133 cnp = ITOC(inode);
135 if ( ! coda_fideq(&cnp->c_fid, oldfid) )
136 printk("What? oldfid != cnp->c_fid. Call 911.\n");
138 cnp->c_fid = *newfid;
140 list_del(&cnp->c_volrootlist);
141 if ( !coda_fid_is_weird(newfid) )
142 list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
144 return;
150 /* convert a fid to an inode. Mostly we can compute
151 the inode number from the FID, but not for volume
152 mount points: those are in a list */
153 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
155 ino_t nr;
156 struct inode *inode;
157 struct coda_inode_info *cnp;
158 ENTRY;
161 if ( !sb ) {
162 printk("coda_fid_to_inode: no sb!\n");
163 return NULL;
166 if ( !fid ) {
167 printk("coda_fid_to_inode: no fid!\n");
168 return NULL;
170 CDEBUG(D_INODE, "%s\n", coda_f2s(fid));
173 if ( coda_fid_is_weird(fid) ) {
174 struct coda_inode_info *cii;
175 struct list_head *lh, *le;
176 struct coda_sb_info *sbi = coda_sbp(sb);
177 le = lh = &sbi->sbi_volroothead;
179 while ( (le = le->next) != lh ) {
180 cii = list_entry(le, struct coda_inode_info,
181 c_volrootlist);
182 CDEBUG(D_DOWNCALL, "iterating, now doing %s, ino %ld\n",
183 coda_f2s(&cii->c_fid), cii->c_vnode->i_ino);
184 if ( coda_fideq(&cii->c_fid, fid) ) {
185 inode = cii->c_vnode;
186 CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino);
187 if ( cii->c_magic != CODA_CNODE_MAGIC )
188 printk("%s: Bad magic in inode, tell Peter.\n",
189 __FUNCTION__);
190 return cii->c_vnode;
194 return NULL;
197 /* fid is not weird: ino should be computable */
198 nr = coda_f2i(fid);
199 inode = iget(sb, nr);
200 if ( !inode ) {
201 printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
202 sb, (long)nr);
203 return NULL;
206 /* check if this inode is linked to a cnode */
207 cnp = ITOC(inode);
208 if ( cnp->c_magic != CODA_CNODE_MAGIC ) {
209 CDEBUG(D_INODE, "uninitialized inode. Return.\n");
210 iput(inode);
211 return NULL;
214 /* make sure fid is the one we want;
215 unfortunately Venus will shamelessly send us mount-symlinks.
216 These have the same inode as the root of the volume they
217 mount, but the fid will be wrong.
219 if ( !coda_fideq(fid, &(cnp->c_fid)) ) {
220 /* printk("coda_fid2inode: bad cnode (ino %ld, fid %s)"
221 "Tell Peter.\n", nr, coda_f2s(fid)); */
222 iput(inode);
223 return NULL;
226 CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
227 iput(inode);
228 return inode;
231 /* the CONTROL inode is made without asking attributes from Venus */
232 int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
234 int error = 0;
236 *inode = iget(sb, CTL_INO);
237 if ( *inode ) {
238 (*inode)->i_op = &coda_ioctl_inode_operations;
239 (*inode)->i_mode = 00444;
240 error = 0;
241 } else {
242 error = -ENOMEM;
245 return error;