xref: /openbmc/linux/fs/coda/inode.c (revision 79c98128)
1 /*
2  * Super block/filesystem wide operations
3  *
4  * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
5  * Michael Callahan <callahan@maths.ox.ac.uk>
6  *
7  * Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
8  * Copyright (C) Carnegie Mellon University
9  */
10 
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/string.h>
15 #include <linux/stat.h>
16 #include <linux/errno.h>
17 #include <linux/unistd.h>
18 #include <linux/mutex.h>
19 #include <linux/spinlock.h>
20 #include <linux/file.h>
21 #include <linux/vfs.h>
22 #include <linux/slab.h>
23 
24 #include <asm/system.h>
25 #include <asm/uaccess.h>
26 
27 #include <linux/fs.h>
28 #include <linux/vmalloc.h>
29 
30 #include <linux/coda.h>
31 #include <linux/coda_linux.h>
32 #include <linux/coda_psdev.h>
33 #include <linux/coda_fs_i.h>
34 #include <linux/coda_cache.h>
35 
36 #include "coda_int.h"
37 
38 /* VFS super_block ops */
39 static void coda_evict_inode(struct inode *);
40 static void coda_put_super(struct super_block *);
41 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf);
42 
43 static struct kmem_cache * coda_inode_cachep;
44 
45 static struct inode *coda_alloc_inode(struct super_block *sb)
46 {
47 	struct coda_inode_info *ei;
48 	ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, GFP_KERNEL);
49 	if (!ei)
50 		return NULL;
51 	memset(&ei->c_fid, 0, sizeof(struct CodaFid));
52 	ei->c_flags = 0;
53 	ei->c_uid = 0;
54 	ei->c_cached_perm = 0;
55 	spin_lock_init(&ei->c_lock);
56 	return &ei->vfs_inode;
57 }
58 
59 static void coda_destroy_inode(struct inode *inode)
60 {
61 	kmem_cache_free(coda_inode_cachep, ITOC(inode));
62 }
63 
64 static void init_once(void *foo)
65 {
66 	struct coda_inode_info *ei = (struct coda_inode_info *) foo;
67 
68 	inode_init_once(&ei->vfs_inode);
69 }
70 
71 int coda_init_inodecache(void)
72 {
73 	coda_inode_cachep = kmem_cache_create("coda_inode_cache",
74 				sizeof(struct coda_inode_info),
75 				0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
76 				init_once);
77 	if (coda_inode_cachep == NULL)
78 		return -ENOMEM;
79 	return 0;
80 }
81 
82 void coda_destroy_inodecache(void)
83 {
84 	kmem_cache_destroy(coda_inode_cachep);
85 }
86 
87 static int coda_remount(struct super_block *sb, int *flags, char *data)
88 {
89 	*flags |= MS_NOATIME;
90 	return 0;
91 }
92 
93 /* exported operations */
94 static const struct super_operations coda_super_operations =
95 {
96 	.alloc_inode	= coda_alloc_inode,
97 	.destroy_inode	= coda_destroy_inode,
98 	.evict_inode	= coda_evict_inode,
99 	.put_super	= coda_put_super,
100 	.statfs		= coda_statfs,
101 	.remount_fs	= coda_remount,
102 };
103 
104 static int get_device_index(struct coda_mount_data *data)
105 {
106 	struct file *file;
107 	struct inode *inode;
108 	int idx;
109 
110 	if(data == NULL) {
111 		printk("coda_read_super: Bad mount data\n");
112 		return -1;
113 	}
114 
115 	if(data->version != CODA_MOUNT_VERSION) {
116 		printk("coda_read_super: Bad mount version\n");
117 		return -1;
118 	}
119 
120 	file = fget(data->fd);
121 	inode = NULL;
122 	if(file)
123 		inode = file->f_path.dentry->d_inode;
124 
125 	if(!inode || !S_ISCHR(inode->i_mode) ||
126 	   imajor(inode) != CODA_PSDEV_MAJOR) {
127 		if(file)
128 			fput(file);
129 
130 		printk("coda_read_super: Bad file\n");
131 		return -1;
132 	}
133 
134 	idx = iminor(inode);
135 	fput(file);
136 
137 	if(idx < 0 || idx >= MAX_CODADEVS) {
138 		printk("coda_read_super: Bad minor number\n");
139 		return -1;
140 	}
141 
142 	return idx;
143 }
144 
145 static int coda_fill_super(struct super_block *sb, void *data, int silent)
146 {
147 	struct inode *root = NULL;
148 	struct venus_comm *vc;
149 	struct CodaFid fid;
150 	int error;
151 	int idx;
152 
153 	idx = get_device_index((struct coda_mount_data *) data);
154 
155 	/* Ignore errors in data, for backward compatibility */
156 	if(idx == -1)
157 		idx = 0;
158 
159 	printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
160 
161 	vc = &coda_comms[idx];
162 	mutex_lock(&vc->vc_mutex);
163 
164 	if (!vc->vc_inuse) {
165 		printk("coda_read_super: No pseudo device\n");
166 		error = -EINVAL;
167 		goto unlock_out;
168 	}
169 
170 	if (vc->vc_sb) {
171 		printk("coda_read_super: Device already mounted\n");
172 		error = -EBUSY;
173 		goto unlock_out;
174 	}
175 
176 	error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
177 	if (error)
178 		goto unlock_out;
179 
180 	vc->vc_sb = sb;
181 	mutex_unlock(&vc->vc_mutex);
182 
183 	sb->s_fs_info = vc;
184 	sb->s_flags |= MS_NOATIME;
185 	sb->s_blocksize = 4096;	/* XXXXX  what do we put here?? */
186 	sb->s_blocksize_bits = 12;
187 	sb->s_magic = CODA_SUPER_MAGIC;
188 	sb->s_op = &coda_super_operations;
189 	sb->s_bdi = &vc->bdi;
190 
191 	/* get root fid from Venus: this needs the root inode */
192 	error = venus_rootfid(sb, &fid);
193 	if ( error ) {
194 	        printk("coda_read_super: coda_get_rootfid failed with %d\n",
195 		       error);
196 		goto error;
197 	}
198 	printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
199 
200 	/* make root inode */
201         error = coda_cnode_make(&root, &fid, sb);
202         if ( error || !root ) {
203 	    printk("Failure of coda_cnode_make for root: error %d\n", error);
204 	    goto error;
205 	}
206 
207 	printk("coda_read_super: rootinode is %ld dev %s\n",
208 	       root->i_ino, root->i_sb->s_id);
209 	sb->s_root = d_alloc_root(root);
210 	if (!sb->s_root) {
211 		error = -EINVAL;
212 		goto error;
213 	}
214 	return 0;
215 
216 error:
217 	if (root)
218 		iput(root);
219 
220 	mutex_lock(&vc->vc_mutex);
221 	bdi_destroy(&vc->bdi);
222 	vc->vc_sb = NULL;
223 	sb->s_fs_info = NULL;
224 unlock_out:
225 	mutex_unlock(&vc->vc_mutex);
226 	return error;
227 }
228 
229 static void coda_put_super(struct super_block *sb)
230 {
231 	struct venus_comm *vcp = coda_vcp(sb);
232 	mutex_lock(&vcp->vc_mutex);
233 	bdi_destroy(&vcp->bdi);
234 	vcp->vc_sb = NULL;
235 	sb->s_fs_info = NULL;
236 	mutex_unlock(&vcp->vc_mutex);
237 
238 	printk("Coda: Bye bye.\n");
239 }
240 
241 static void coda_evict_inode(struct inode *inode)
242 {
243 	truncate_inode_pages(&inode->i_data, 0);
244 	end_writeback(inode);
245 	coda_cache_clear_inode(inode);
246 }
247 
248 int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
249 {
250 	int err = coda_revalidate_inode(dentry);
251 	if (!err)
252 		generic_fillattr(dentry->d_inode, stat);
253 	return err;
254 }
255 
256 int coda_setattr(struct dentry *de, struct iattr *iattr)
257 {
258 	struct inode *inode = de->d_inode;
259 	struct coda_vattr vattr;
260 	int error;
261 
262 	memset(&vattr, 0, sizeof(vattr));
263 
264 	inode->i_ctime = CURRENT_TIME_SEC;
265 	coda_iattr_to_vattr(iattr, &vattr);
266 	vattr.va_type = C_VNON; /* cannot set type */
267 
268 	/* Venus is responsible for truncating the container-file!!! */
269 	error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
270 
271 	if (!error) {
272 	        coda_vattr_to_iattr(inode, &vattr);
273 		coda_cache_clear_inode(inode);
274 	}
275 	return error;
276 }
277 
278 const struct inode_operations coda_file_inode_operations = {
279 	.permission	= coda_permission,
280 	.getattr	= coda_getattr,
281 	.setattr	= coda_setattr,
282 };
283 
284 static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
285 {
286 	int error;
287 
288 	error = venus_statfs(dentry, buf);
289 
290 	if (error) {
291 		/* fake something like AFS does */
292 		buf->f_blocks = 9000000;
293 		buf->f_bfree  = 9000000;
294 		buf->f_bavail = 9000000;
295 		buf->f_files  = 9000000;
296 		buf->f_ffree  = 9000000;
297 	}
298 
299 	/* and fill in the rest */
300 	buf->f_type = CODA_SUPER_MAGIC;
301 	buf->f_bsize = 4096;
302 	buf->f_namelen = CODA_MAXNAMLEN;
303 
304 	return 0;
305 }
306 
307 /* init_coda: used by filesystems.c to register coda */
308 
309 static int coda_get_sb(struct file_system_type *fs_type,
310 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
311 {
312 	return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt);
313 }
314 
315 struct file_system_type coda_fs_type = {
316 	.owner		= THIS_MODULE,
317 	.name		= "coda",
318 	.get_sb		= coda_get_sb,
319 	.kill_sb	= kill_anon_super,
320 	.fs_flags	= FS_BINARY_MOUNTDATA,
321 };
322 
323