original comment: +Wilson03172004,marked due to this pci host does not support MWI
[linux-2.4.git] / fs / coda / cnode.c
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
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
24 inline int coda_isnullfid(ViceFid *fid)
25 {
26         if (fid->Vnode || fid->Volume || fid->Unique) return 0;
27         return 1;
28 }
29
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 */
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
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 */
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
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. */
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 */
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