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