Blame view

fs/freevxfs/vxfs_super.c 8.66 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   * Copyright (c) 2000-2001 Christoph Hellwig.
1cce17017   Krzysztof Błaszkowski   freevxfs: update ...
3
   * Copyright (c) 2016 Krzysztof Blaszkowski
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. The name of the author may not be used to endorse or promote products
   *    derived from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL").
   *
   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
  
  /*
   * Veritas filesystem driver - superblock related routines.
   */
  #include <linux/init.h>
  #include <linux/module.h>
  
  #include <linux/blkdev.h>
  #include <linux/fs.h>
  #include <linux/buffer_head.h>
  #include <linux/kernel.h>
  #include <linux/slab.h>
  #include <linux/stat.h>
  #include <linux/vfs.h>
726c33422   David Howells   [PATCH] VFS: Perm...
44
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
  
  #include "vxfs.h"
  #include "vxfs_extern.h"
  #include "vxfs_dir.h"
  #include "vxfs_inode.h"
1cce17017   Krzysztof Błaszkowski   freevxfs: update ...
50
  MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
  MODULE_LICENSE("Dual BSD/GPL");
2f137e31e   Christoph Hellwig   freevxfs: impleme...
53
  static struct kmem_cache *vxfs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
61
62
63
64
65
66
  /**
   * vxfs_put_super - free superblock resources
   * @sbp:	VFS superblock.
   *
   * Description:
   *   vxfs_put_super frees all resources allocated for @sbp
   *   after the last instance of the filesystem is unmounted.
   */
  
  static void
  vxfs_put_super(struct super_block *sbp)
  {
  	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
0e481d3c0   Krzysztof Błaszkowski   freevxfs: remove ...
67
68
69
  	iput(infp->vsi_fship);
  	iput(infp->vsi_ilist);
  	iput(infp->vsi_stilist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
76
  
  	brelse(infp->vsi_bp);
  	kfree(infp);
  }
  
  /**
   * vxfs_statfs - get filesystem information
726c33422   David Howells   [PATCH] VFS: Perm...
77
   * @dentry:	VFS dentry to locate superblock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
   * @bufp:	output buffer
   *
   * Description:
   *   vxfs_statfs fills the statfs buffer @bufp with information
726c33422   David Howells   [PATCH] VFS: Perm...
82
   *   about the filesystem described by @dentry.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
87
88
89
90
91
92
93
   *
   * Returns:
   *   Zero.
   *
   * Locking:
   *   No locks held.
   *
   * Notes:
   *   This is everything but complete...
   */
  static int
726c33422   David Howells   [PATCH] VFS: Perm...
94
  vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  {
726c33422   David Howells   [PATCH] VFS: Perm...
96
  	struct vxfs_sb_info		*infp = VXFS_SBI(dentry->d_sb);
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
97
  	struct vxfs_sb *raw_sb = infp->vsi_raw;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  
  	bufp->f_type = VXFS_SUPER_MAGIC;
726c33422   David Howells   [PATCH] VFS: Perm...
100
  	bufp->f_bsize = dentry->d_sb->s_blocksize;
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
101
102
  	bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
  	bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
  	bufp->f_bavail = 0;
  	bufp->f_files = 0;
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
105
  	bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
110
111
112
  	bufp->f_namelen = VXFS_NAMELEN;
  
  	return 0;
  }
  
  static int vxfs_remount(struct super_block *sb, int *flags, char *data)
  {
02b9984d6   Theodore Ts'o   fs: push sync_fil...
113
  	sync_filesystem(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
  	*flags |= MS_RDONLY;
  	return 0;
  }
2f137e31e   Christoph Hellwig   freevxfs: impleme...
117
118
119
120
121
122
123
  static struct inode *vxfs_alloc_inode(struct super_block *sb)
  {
  	struct vxfs_inode_info *vi;
  
  	vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
  	if (!vi)
  		return NULL;
f2fe2fa1f   Krzysztof Błaszkowski   freevxfs: fix lac...
124
  	inode_init_once(&vi->vfs_inode);
2f137e31e   Christoph Hellwig   freevxfs: impleme...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  	return &vi->vfs_inode;
  }
  
  static void vxfs_i_callback(struct rcu_head *head)
  {
  	struct inode *inode = container_of(head, struct inode, i_rcu);
  
  	kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode));
  }
  
  static void vxfs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, vxfs_i_callback);
  }
f2bf2c704   Christoph Hellwig   freevxfs: avoid t...
139
  static const struct super_operations vxfs_super_ops = {
2f137e31e   Christoph Hellwig   freevxfs: impleme...
140
141
  	.alloc_inode		= vxfs_alloc_inode,
  	.destroy_inode		= vxfs_destroy_inode,
f2bf2c704   Christoph Hellwig   freevxfs: avoid t...
142
143
144
145
146
  	.evict_inode		= vxfs_evict_inode,
  	.put_super		= vxfs_put_super,
  	.statfs			= vxfs_statfs,
  	.remount_fs		= vxfs_remount,
  };
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  
  static int vxfs_try_sb_magic(struct super_block *sbp, int silent,
  		unsigned blk, __fs32 magic)
  {
  	struct buffer_head *bp;
  	struct vxfs_sb *rsbp;
  	struct vxfs_sb_info *infp = VXFS_SBI(sbp);
  	int rc = -ENOMEM;
  
  	bp = sb_bread(sbp, blk);
  	do {
  		if (!bp || !buffer_mapped(bp)) {
  			if (!silent) {
  				printk(KERN_WARNING
  					"vxfs: unable to read disk superblock at %u
  ",
  					blk);
  			}
  			break;
  		}
  
  		rc = -EINVAL;
  		rsbp = (struct vxfs_sb *)bp->b_data;
  		if (rsbp->vs_magic != magic) {
  			if (!silent)
  				printk(KERN_NOTICE
  					"vxfs: WRONG superblock magic %08x at %u
  ",
  					rsbp->vs_magic, blk);
  			break;
  		}
  
  		rc = 0;
  		infp->vsi_raw = rsbp;
  		infp->vsi_bp = bp;
  	} while (0);
  
  	if (rc) {
  		infp->vsi_raw = NULL;
  		infp->vsi_bp = NULL;
  		brelse(bp);
  	}
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  /**
421f91d21   Uwe Kleine-König   fix typos concern...
193
   * vxfs_read_super - read superblock into memory and initialize filesystem
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
202
203
204
205
   * @sbp:		VFS superblock (to fill)
   * @dp:			fs private mount data
   * @silent:		do not complain loudly when sth is wrong
   *
   * Description:
   *   We are called on the first mount of a filesystem to read the
   *   superblock into memory and do some basic setup.
   *
   * Returns:
   *   The superblock on success, else %NULL.
   *
   * Locking:
db7192221   Jan Blunck   BKL: Explicitly a...
206
   *   We are under @sbp->s_lock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
209
210
211
   */
  static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
  {
  	struct vxfs_sb_info	*infp;
  	struct vxfs_sb		*rsbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
  	u_long			bsize;
  	struct inode *root;
d0b079483   David Howells   iget: stop FreeVX...
214
  	int ret = -EINVAL;
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
215
  	u32 j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
  
  	sbp->s_flags |= MS_RDONLY;
e915fc497   Pekka Enberg   [PATCH] fs: conve...
218
  	infp = kzalloc(sizeof(*infp), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
  	if (!infp) {
  		printk(KERN_WARNING "vxfs: unable to allocate incore superblock
  ");
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
230
  
  	bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
  	if (!bsize) {
  		printk(KERN_WARNING "vxfs: unable to set blocksize
  ");
  		goto out;
  	}
2f137e31e   Christoph Hellwig   freevxfs: impleme...
231
  	sbp->s_op = &vxfs_super_ops;
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
232
  	sbp->s_fs_info = infp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233

0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
234
235
236
237
238
239
240
241
242
  	if (!vxfs_try_sb_magic(sbp, silent, 1,
  			(__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) {
  		/* Unixware, x86 */
  		infp->byte_order = VXFS_BO_LE;
  	} else if (!vxfs_try_sb_magic(sbp, silent, 8,
  			(__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) {
  		/* HP-UX, parisc */
  		infp->byte_order = VXFS_BO_BE;
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  		if (!silent)
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
244
245
  			printk(KERN_NOTICE "vxfs: can't find superblock.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  		goto out;
  	}
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
248
249
250
251
252
  	rsbp = infp->vsi_raw;
  	j = fs32_to_cpu(infp, rsbp->vs_version);
  	if ((j < 2 || j > 4) && !silent) {
  		printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)
  ", j);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
  		goto out;
  	}
  
  #ifdef DIAGNOSTIC
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
257
258
259
260
261
  	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)
  ", j);
  	printk(KERN_DEBUG "vxfs: blocksize: %d
  ",
  		fs32_to_cpu(infp, rsbp->vs_bsize));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  #endif
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
263
  	sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264

0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
265
266
  	infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
  	infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267

0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
268
269
  	j = fs32_to_cpu(infp, rsbp->vs_bsize);
  	if (!sb_set_blocksize(sbp, j)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  		printk(KERN_WARNING "vxfs: unable to set final block size
  ");
  		goto out;
  	}
  
  	if (vxfs_read_olt(sbp, bsize)) {
  		printk(KERN_WARNING "vxfs: unable to read olt
  ");
  		goto out;
  	}
  
  	if (vxfs_read_fshead(sbp)) {
  		printk(KERN_WARNING "vxfs: unable to read fshead
  ");
  		goto out;
  	}
d0b079483   David Howells   iget: stop FreeVX...
286
287
288
289
290
  	root = vxfs_iget(sbp, VXFS_ROOT_INO);
  	if (IS_ERR(root)) {
  		ret = PTR_ERR(root);
  		goto out;
  	}
48fde701a   Al Viro   switch open-coded...
291
  	sbp->s_root = d_make_root(root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  	if (!sbp->s_root) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
298
299
300
  		printk(KERN_WARNING "vxfs: unable to get root dentry.
  ");
  		goto out_free_ilist;
  	}
  
  	return 0;
  	
  out_free_ilist:
0e481d3c0   Krzysztof Błaszkowski   freevxfs: remove ...
301
302
303
  	iput(infp->vsi_fship);
  	iput(infp->vsi_ilist);
  	iput(infp->vsi_stilist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  out:
0d83f7fc8   Krzysztof Błaszkowski   freevxfs: handle ...
305
  	brelse(infp->vsi_bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  	kfree(infp);
d0b079483   David Howells   iget: stop FreeVX...
307
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
312
  }
  
  /*
   * The usual module blurb.
   */
152a08366   Al Viro   new helper: mount...
313
314
  static struct dentry *vxfs_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  {
152a08366   Al Viro   new helper: mount...
316
  	return mount_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
320
321
  }
  
  static struct file_system_type vxfs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "vxfs",
152a08366   Al Viro   new helper: mount...
322
  	.mount		= vxfs_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
326
  MODULE_ALIAS_FS("vxfs"); /* makes mount -t vxfs autoload the module */
fa7614ddd   Eric W. Biederman   fs: Readd the fs ...
327
  MODULE_ALIAS("vxfs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
  
  static int __init
  vxfs_init(void)
  {
a4376e13c   Alexey Dobriyan   [PATCH] freevxfs:...
332
  	int rv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
20c2df83d   Paul Mundt   mm: Remove slab d...
334
335
  			sizeof(struct vxfs_inode_info), 0,
  			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
a4376e13c   Alexey Dobriyan   [PATCH] freevxfs:...
336
337
338
339
340
341
  	if (!vxfs_inode_cachep)
  		return -ENOMEM;
  	rv = register_filesystem(&vxfs_fs_type);
  	if (rv < 0)
  		kmem_cache_destroy(vxfs_inode_cachep);
  	return rv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
344
345
346
347
  }
  
  static void __exit
  vxfs_cleanup(void)
  {
  	unregister_filesystem(&vxfs_fs_type);
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
348
349
350
351
352
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
356
357
  	kmem_cache_destroy(vxfs_inode_cachep);
  }
  
  module_init(vxfs_init);
  module_exit(vxfs_cleanup);