Import 2.4.0-test2pre7
[davej-history.git] / fs / coda / cnode.c
blob7c554461271f364550009cb55f383d2050910c0f
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 static struct inode_operations coda_symlink_inode_operations = {
29 readlink: page_readlink,
30 follow_link: page_follow_link,
31 setattr: coda_notify_change,
34 /* cnode.c */
35 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
37 CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino);
39 if (coda_debug & D_SUPER )
40 print_vattr(attr);
42 coda_vattr_to_iattr(inode, attr);
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);
58 struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
59 struct coda_vattr * attr)
61 struct inode *inode;
62 struct coda_sb_info *sbi= coda_sbp(sb);
63 struct coda_inode_info *cii;
64 ino_t ino = attr->va_fileid;
66 inode = iget(sb, ino);
67 if ( !inode ) {
68 CDEBUG(D_CNODE, "coda_iget: no inode\n");
69 return ERR_PTR(-ENOMEM);
72 /* check if the inode is already initialized */
73 cii = ITOC(inode);
74 if (cii->c_magic == CODA_CNODE_MAGIC) {
75 /* see if it is the right one (might have an inode collision) */
76 if ( !coda_fideq(fid, &cii->c_fid) ) {
77 printk("coda_iget: initialized inode old %s new %s!\n",
78 coda_f2s(&cii->c_fid), coda_f2s2(fid));
79 iput(inode);
80 return ERR_PTR(-ENOENT);
82 /* replace the attributes, type might have changed */
83 coda_fill_inode(inode, attr);
84 goto out;
87 /* new, empty inode found... initializing */
89 /* Initialize the Coda inode info structure */
90 memset(cii, 0, (int) sizeof(struct coda_inode_info));
91 cii->c_magic = CODA_CNODE_MAGIC;
92 cii->c_fid = *fid;
93 cii->c_flags = 0;
94 cii->c_vnode = inode;
95 INIT_LIST_HEAD(&(cii->c_cnhead));
96 INIT_LIST_HEAD(&(cii->c_volrootlist));
98 coda_fill_inode(inode, attr);
100 /* check if it is a weird fid (hashed fid != ino), f.i mountpoints
101 repair object, expanded local-global conflict trees, etc.
103 if ( coda_f2i(fid) == ino )
104 goto out;
106 /* check if we expected this weird fid */
107 if ( !coda_fid_is_weird(fid) ) {
108 printk("Coda: unknown weird fid: ino %ld, fid %s."
109 "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid));
110 goto out;
113 /* add the inode to a global list so we can find it back later */
114 list_add(&cii->c_volrootlist, &sbi->sbi_volroothead);
115 CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n",
116 (long)ino, coda_f2s(&cii->c_fid));
117 out:
118 return inode;
121 /* this is effectively coda_iget:
122 - get attributes (might be cached)
123 - get the inode for the fid using vfs iget
124 - link the two up if this is needed
125 - fill in the attributes
127 int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
129 struct coda_vattr attr;
130 int error;
132 ENTRY;
134 /* We get inode numbers from Venus -- see venus source */
136 error = venus_getattr(sb, fid, &attr);
137 if ( error ) {
138 CDEBUG(D_CNODE,
139 "coda_cnode_make: coda_getvattr returned %d for %s.\n",
140 error, coda_f2s(fid));
141 *inode = NULL;
142 EXIT;
143 return error;
146 *inode = coda_iget(sb, fid, &attr);
147 if ( IS_ERR(*inode) ) {
148 printk("coda_cnode_make: coda_iget failed\n");
149 EXIT;
150 return PTR_ERR(*inode);
153 CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
154 (*inode)->i_ino, atomic_read(&(*inode)->i_count),
155 coda_f2s(&(*inode)->u.coda_i.c_fid));
156 EXIT;
157 return 0;
161 void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
162 struct ViceFid *newfid)
164 struct coda_inode_info *cnp;
165 struct coda_sb_info *sbi= coda_sbp(inode->i_sb);
167 cnp = ITOC(inode);
169 if ( ! coda_fideq(&cnp->c_fid, oldfid) )
170 printk("What? oldfid != cnp->c_fid. Call 911.\n");
172 cnp->c_fid = *newfid;
174 list_del(&cnp->c_volrootlist);
175 INIT_LIST_HEAD(&cnp->c_volrootlist);
176 if ( coda_fid_is_weird(newfid) )
177 list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
179 return;
185 /* convert a fid to an inode. Mostly we can compute
186 the inode number from the FID, but not for volume
187 mount points: those are in a list */
188 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
190 ino_t nr;
191 struct inode *inode;
192 struct coda_inode_info *cii;
193 ENTRY;
195 if ( !sb ) {
196 printk("coda_fid_to_inode: no sb!\n");
197 return NULL;
200 if ( !fid ) {
201 printk("coda_fid_to_inode: no fid!\n");
202 return NULL;
204 CDEBUG(D_INODE, "%s\n", coda_f2s(fid));
207 if ( coda_fid_is_weird(fid) ) {
208 struct list_head *lh, *le;
209 struct coda_sb_info *sbi = coda_sbp(sb);
210 le = lh = &sbi->sbi_volroothead;
212 while ( (le = le->next) != lh ) {
213 cii = list_entry(le, struct coda_inode_info,
214 c_volrootlist);
215 /* paranoia check, should never trigger */
216 if ( cii->c_magic != CODA_CNODE_MAGIC )
217 printk("coda_fid_to_inode: Bad magic in inode %x.\n", cii->c_magic);
219 CDEBUG(D_DOWNCALL, "iterating, now doing %s, ino %ld\n",
220 coda_f2s(&cii->c_fid), cii->c_vnode->i_ino);
222 if ( coda_fideq(&cii->c_fid, fid) ) {
223 inode = cii->c_vnode;
224 CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino);
225 iget(sb, inode->i_ino);
226 return inode;
229 return NULL;
232 /* fid is not weird: ino should be computable */
233 nr = coda_f2i(fid);
234 inode = iget(sb, nr);
235 if ( !inode ) {
236 printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
237 sb, (long)nr);
238 return NULL;
241 /* check if this inode is linked to a cnode */
242 cii = ITOC(inode);
243 if ( cii->c_magic != CODA_CNODE_MAGIC ) {
244 CDEBUG(D_INODE, "uninitialized inode. Return.\n");
245 goto bad_inode;
248 /* make sure fid is the one we want */
249 if ( !coda_fideq(fid, &(cii->c_fid)) ) {
250 #if 0
251 printk("coda_fid2inode: bad cnode (ino %ld, fid %s)", nr,
252 coda_f2s(fid));
253 #endif
254 goto bad_inode;
257 CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
258 return inode;
260 bad_inode:
261 iput(inode);
262 return NULL;
265 /* the CONTROL inode is made without asking attributes from Venus */
266 int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
268 int error = 0;
270 *inode = iget(sb, CTL_INO);
271 if ( *inode ) {
272 (*inode)->i_op = &coda_ioctl_inode_operations;
273 (*inode)->i_fop = &coda_ioctl_operations;
274 (*inode)->i_mode = 00444;
275 error = 0;
276 } else {
277 error = -ENOMEM;
280 return error;