xref: /linux/fs/freevxfs/vxfs_super.c (revision 152a08366671080f27b32e0c411ad620c5f88b57)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Copyright (c) 2000-2001 Christoph Hellwig.
31da177e4SLinus Torvalds  * All rights reserved.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Redistribution and use in source and binary forms, with or without
61da177e4SLinus Torvalds  * modification, are permitted provided that the following conditions
71da177e4SLinus Torvalds  * are met:
81da177e4SLinus Torvalds  * 1. Redistributions of source code must retain the above copyright
91da177e4SLinus Torvalds  *    notice, this list of conditions, and the following disclaimer,
101da177e4SLinus Torvalds  *    without modification.
111da177e4SLinus Torvalds  * 2. The name of the author may not be used to endorse or promote products
121da177e4SLinus Torvalds  *    derived from this software without specific prior written permission.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * Alternatively, this software may be distributed under the terms of the
151da177e4SLinus Torvalds  * GNU General Public License ("GPL").
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
181da177e4SLinus Torvalds  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191da177e4SLinus Torvalds  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201da177e4SLinus Torvalds  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
211da177e4SLinus Torvalds  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221da177e4SLinus Torvalds  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231da177e4SLinus Torvalds  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241da177e4SLinus Torvalds  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251da177e4SLinus Torvalds  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261da177e4SLinus Torvalds  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271da177e4SLinus Torvalds  * SUCH DAMAGE.
281da177e4SLinus Torvalds  */
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds /*
311da177e4SLinus Torvalds  * Veritas filesystem driver - superblock related routines.
321da177e4SLinus Torvalds  */
331da177e4SLinus Torvalds #include <linux/init.h>
341da177e4SLinus Torvalds #include <linux/module.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds #include <linux/blkdev.h>
371da177e4SLinus Torvalds #include <linux/fs.h>
381da177e4SLinus Torvalds #include <linux/buffer_head.h>
391da177e4SLinus Torvalds #include <linux/kernel.h>
401da177e4SLinus Torvalds #include <linux/slab.h>
411da177e4SLinus Torvalds #include <linux/stat.h>
421da177e4SLinus Torvalds #include <linux/vfs.h>
43726c3342SDavid Howells #include <linux/mount.h>
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds #include "vxfs.h"
461da177e4SLinus Torvalds #include "vxfs_extern.h"
471da177e4SLinus Torvalds #include "vxfs_dir.h"
481da177e4SLinus Torvalds #include "vxfs_inode.h"
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds MODULE_AUTHOR("Christoph Hellwig");
521da177e4SLinus Torvalds MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
531da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL");
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds static void		vxfs_put_super(struct super_block *);
59726c3342SDavid Howells static int		vxfs_statfs(struct dentry *, struct kstatfs *);
601da177e4SLinus Torvalds static int		vxfs_remount(struct super_block *, int *, char *);
611da177e4SLinus Torvalds 
62ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations vxfs_super_ops = {
63b57922d9SAl Viro 	.evict_inode =		vxfs_evict_inode,
641da177e4SLinus Torvalds 	.put_super =		vxfs_put_super,
651da177e4SLinus Torvalds 	.statfs =		vxfs_statfs,
661da177e4SLinus Torvalds 	.remount_fs =		vxfs_remount,
671da177e4SLinus Torvalds };
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds /**
701da177e4SLinus Torvalds  * vxfs_put_super - free superblock resources
711da177e4SLinus Torvalds  * @sbp:	VFS superblock.
721da177e4SLinus Torvalds  *
731da177e4SLinus Torvalds  * Description:
741da177e4SLinus Torvalds  *   vxfs_put_super frees all resources allocated for @sbp
751da177e4SLinus Torvalds  *   after the last instance of the filesystem is unmounted.
761da177e4SLinus Torvalds  */
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds static void
791da177e4SLinus Torvalds vxfs_put_super(struct super_block *sbp)
801da177e4SLinus Torvalds {
811da177e4SLinus Torvalds 	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds 	vxfs_put_fake_inode(infp->vsi_fship);
841da177e4SLinus Torvalds 	vxfs_put_fake_inode(infp->vsi_ilist);
851da177e4SLinus Torvalds 	vxfs_put_fake_inode(infp->vsi_stilist);
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds 	brelse(infp->vsi_bp);
881da177e4SLinus Torvalds 	kfree(infp);
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds /**
921da177e4SLinus Torvalds  * vxfs_statfs - get filesystem information
93726c3342SDavid Howells  * @dentry:	VFS dentry to locate superblock
941da177e4SLinus Torvalds  * @bufp:	output buffer
951da177e4SLinus Torvalds  *
961da177e4SLinus Torvalds  * Description:
971da177e4SLinus Torvalds  *   vxfs_statfs fills the statfs buffer @bufp with information
98726c3342SDavid Howells  *   about the filesystem described by @dentry.
991da177e4SLinus Torvalds  *
1001da177e4SLinus Torvalds  * Returns:
1011da177e4SLinus Torvalds  *   Zero.
1021da177e4SLinus Torvalds  *
1031da177e4SLinus Torvalds  * Locking:
1041da177e4SLinus Torvalds  *   No locks held.
1051da177e4SLinus Torvalds  *
1061da177e4SLinus Torvalds  * Notes:
1071da177e4SLinus Torvalds  *   This is everything but complete...
1081da177e4SLinus Torvalds  */
1091da177e4SLinus Torvalds static int
110726c3342SDavid Howells vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
1111da177e4SLinus Torvalds {
112726c3342SDavid Howells 	struct vxfs_sb_info		*infp = VXFS_SBI(dentry->d_sb);
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	bufp->f_type = VXFS_SUPER_MAGIC;
115726c3342SDavid Howells 	bufp->f_bsize = dentry->d_sb->s_blocksize;
1161da177e4SLinus Torvalds 	bufp->f_blocks = infp->vsi_raw->vs_dsize;
1171da177e4SLinus Torvalds 	bufp->f_bfree = infp->vsi_raw->vs_free;
1181da177e4SLinus Torvalds 	bufp->f_bavail = 0;
1191da177e4SLinus Torvalds 	bufp->f_files = 0;
1201da177e4SLinus Torvalds 	bufp->f_ffree = infp->vsi_raw->vs_ifree;
1211da177e4SLinus Torvalds 	bufp->f_namelen = VXFS_NAMELEN;
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds 	return 0;
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds static int vxfs_remount(struct super_block *sb, int *flags, char *data)
1271da177e4SLinus Torvalds {
1281da177e4SLinus Torvalds 	*flags |= MS_RDONLY;
1291da177e4SLinus Torvalds 	return 0;
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds /**
133421f91d2SUwe Kleine-König  * vxfs_read_super - read superblock into memory and initialize filesystem
1341da177e4SLinus Torvalds  * @sbp:		VFS superblock (to fill)
1351da177e4SLinus Torvalds  * @dp:			fs private mount data
1361da177e4SLinus Torvalds  * @silent:		do not complain loudly when sth is wrong
1371da177e4SLinus Torvalds  *
1381da177e4SLinus Torvalds  * Description:
1391da177e4SLinus Torvalds  *   We are called on the first mount of a filesystem to read the
1401da177e4SLinus Torvalds  *   superblock into memory and do some basic setup.
1411da177e4SLinus Torvalds  *
1421da177e4SLinus Torvalds  * Returns:
1431da177e4SLinus Torvalds  *   The superblock on success, else %NULL.
1441da177e4SLinus Torvalds  *
1451da177e4SLinus Torvalds  * Locking:
146db719222SJan Blunck  *   We are under @sbp->s_lock.
1471da177e4SLinus Torvalds  */
1481da177e4SLinus Torvalds static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
1491da177e4SLinus Torvalds {
1501da177e4SLinus Torvalds 	struct vxfs_sb_info	*infp;
1511da177e4SLinus Torvalds 	struct vxfs_sb		*rsbp;
1521da177e4SLinus Torvalds 	struct buffer_head	*bp = NULL;
1531da177e4SLinus Torvalds 	u_long			bsize;
1541da177e4SLinus Torvalds 	struct inode *root;
155d0b07948SDavid Howells 	int ret = -EINVAL;
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds 	sbp->s_flags |= MS_RDONLY;
1581da177e4SLinus Torvalds 
159e915fc49SPekka Enberg 	infp = kzalloc(sizeof(*infp), GFP_KERNEL);
1601da177e4SLinus Torvalds 	if (!infp) {
1611da177e4SLinus Torvalds 		printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
1621da177e4SLinus Torvalds 		return -ENOMEM;
1631da177e4SLinus Torvalds 	}
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds 	bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
1661da177e4SLinus Torvalds 	if (!bsize) {
1671da177e4SLinus Torvalds 		printk(KERN_WARNING "vxfs: unable to set blocksize\n");
1681da177e4SLinus Torvalds 		goto out;
1691da177e4SLinus Torvalds 	}
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 	bp = sb_bread(sbp, 1);
1721da177e4SLinus Torvalds 	if (!bp || !buffer_mapped(bp)) {
1731da177e4SLinus Torvalds 		if (!silent) {
1741da177e4SLinus Torvalds 			printk(KERN_WARNING
1751da177e4SLinus Torvalds 				"vxfs: unable to read disk superblock\n");
1761da177e4SLinus Torvalds 		}
1771da177e4SLinus Torvalds 		goto out;
1781da177e4SLinus Torvalds 	}
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds 	rsbp = (struct vxfs_sb *)bp->b_data;
1811da177e4SLinus Torvalds 	if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
1821da177e4SLinus Torvalds 		if (!silent)
1831da177e4SLinus Torvalds 			printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
1841da177e4SLinus Torvalds 		goto out;
1851da177e4SLinus Torvalds 	}
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 	if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
1881da177e4SLinus Torvalds 		printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
1891da177e4SLinus Torvalds 		       rsbp->vs_version);
1901da177e4SLinus Torvalds 		goto out;
1911da177e4SLinus Torvalds 	}
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds #ifdef DIAGNOSTIC
1941da177e4SLinus Torvalds 	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
1951da177e4SLinus Torvalds 	printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
1961da177e4SLinus Torvalds #endif
1971da177e4SLinus Torvalds 
1981da177e4SLinus Torvalds 	sbp->s_magic = rsbp->vs_magic;
1998cb681b9SPekka Enberg 	sbp->s_fs_info = infp;
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	infp->vsi_raw = rsbp;
2021da177e4SLinus Torvalds 	infp->vsi_bp = bp;
2031da177e4SLinus Torvalds 	infp->vsi_oltext = rsbp->vs_oltext[0];
2041da177e4SLinus Torvalds 	infp->vsi_oltsize = rsbp->vs_oltsize;
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds 	if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
2071da177e4SLinus Torvalds 		printk(KERN_WARNING "vxfs: unable to set final block size\n");
2081da177e4SLinus Torvalds 		goto out;
2091da177e4SLinus Torvalds 	}
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 	if (vxfs_read_olt(sbp, bsize)) {
2121da177e4SLinus Torvalds 		printk(KERN_WARNING "vxfs: unable to read olt\n");
2131da177e4SLinus Torvalds 		goto out;
2141da177e4SLinus Torvalds 	}
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds 	if (vxfs_read_fshead(sbp)) {
2171da177e4SLinus Torvalds 		printk(KERN_WARNING "vxfs: unable to read fshead\n");
2181da177e4SLinus Torvalds 		goto out;
2191da177e4SLinus Torvalds 	}
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 	sbp->s_op = &vxfs_super_ops;
222d0b07948SDavid Howells 	root = vxfs_iget(sbp, VXFS_ROOT_INO);
223d0b07948SDavid Howells 	if (IS_ERR(root)) {
224d0b07948SDavid Howells 		ret = PTR_ERR(root);
225d0b07948SDavid Howells 		goto out;
226d0b07948SDavid Howells 	}
2271da177e4SLinus Torvalds 	sbp->s_root = d_alloc_root(root);
2281da177e4SLinus Torvalds 	if (!sbp->s_root) {
2291da177e4SLinus Torvalds 		iput(root);
2301da177e4SLinus Torvalds 		printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
2311da177e4SLinus Torvalds 		goto out_free_ilist;
2321da177e4SLinus Torvalds 	}
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 	return 0;
2351da177e4SLinus Torvalds 
2361da177e4SLinus Torvalds out_free_ilist:
2371da177e4SLinus Torvalds 	vxfs_put_fake_inode(infp->vsi_fship);
2381da177e4SLinus Torvalds 	vxfs_put_fake_inode(infp->vsi_ilist);
2391da177e4SLinus Torvalds 	vxfs_put_fake_inode(infp->vsi_stilist);
2401da177e4SLinus Torvalds out:
2411da177e4SLinus Torvalds 	brelse(bp);
2421da177e4SLinus Torvalds 	kfree(infp);
243d0b07948SDavid Howells 	return ret;
2441da177e4SLinus Torvalds }
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds /*
2471da177e4SLinus Torvalds  * The usual module blurb.
2481da177e4SLinus Torvalds  */
249*152a0836SAl Viro static struct dentry *vxfs_mount(struct file_system_type *fs_type,
250*152a0836SAl Viro 	int flags, const char *dev_name, void *data)
2511da177e4SLinus Torvalds {
252*152a0836SAl Viro 	return mount_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds static struct file_system_type vxfs_fs_type = {
2561da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
2571da177e4SLinus Torvalds 	.name		= "vxfs",
258*152a0836SAl Viro 	.mount		= vxfs_mount,
2591da177e4SLinus Torvalds 	.kill_sb	= kill_block_super,
2601da177e4SLinus Torvalds 	.fs_flags	= FS_REQUIRES_DEV,
2611da177e4SLinus Torvalds };
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds static int __init
2641da177e4SLinus Torvalds vxfs_init(void)
2651da177e4SLinus Torvalds {
266a4376e13SAlexey Dobriyan 	int rv;
267a4376e13SAlexey Dobriyan 
2681da177e4SLinus Torvalds 	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
2691da177e4SLinus Torvalds 			sizeof(struct vxfs_inode_info), 0,
27020c2df83SPaul Mundt 			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
271a4376e13SAlexey Dobriyan 	if (!vxfs_inode_cachep)
2721da177e4SLinus Torvalds 		return -ENOMEM;
273a4376e13SAlexey Dobriyan 	rv = register_filesystem(&vxfs_fs_type);
274a4376e13SAlexey Dobriyan 	if (rv < 0)
275a4376e13SAlexey Dobriyan 		kmem_cache_destroy(vxfs_inode_cachep);
276a4376e13SAlexey Dobriyan 	return rv;
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds 
2791da177e4SLinus Torvalds static void __exit
2801da177e4SLinus Torvalds vxfs_cleanup(void)
2811da177e4SLinus Torvalds {
2821da177e4SLinus Torvalds 	unregister_filesystem(&vxfs_fs_type);
2831da177e4SLinus Torvalds 	kmem_cache_destroy(vxfs_inode_cachep);
2841da177e4SLinus Torvalds }
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds module_init(vxfs_init);
2871da177e4SLinus Torvalds module_exit(vxfs_cleanup);
288