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