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> 41405f5571SAlexey Dobriyan #include <linux/smp_lock.h> 421da177e4SLinus Torvalds #include <linux/stat.h> 431da177e4SLinus Torvalds #include <linux/vfs.h> 44726c3342SDavid Howells #include <linux/mount.h> 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds #include "vxfs.h" 471da177e4SLinus Torvalds #include "vxfs_extern.h" 481da177e4SLinus Torvalds #include "vxfs_dir.h" 491da177e4SLinus Torvalds #include "vxfs_inode.h" 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds MODULE_AUTHOR("Christoph Hellwig"); 531da177e4SLinus Torvalds MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); 541da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL"); 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */ 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds static void vxfs_put_super(struct super_block *); 60726c3342SDavid Howells static int vxfs_statfs(struct dentry *, struct kstatfs *); 611da177e4SLinus Torvalds static int vxfs_remount(struct super_block *, int *, char *); 621da177e4SLinus Torvalds 63ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations vxfs_super_ops = { 64*b57922d9SAl Viro .evict_inode = vxfs_evict_inode, 651da177e4SLinus Torvalds .put_super = vxfs_put_super, 661da177e4SLinus Torvalds .statfs = vxfs_statfs, 671da177e4SLinus Torvalds .remount_fs = vxfs_remount, 681da177e4SLinus Torvalds }; 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds /** 711da177e4SLinus Torvalds * vxfs_put_super - free superblock resources 721da177e4SLinus Torvalds * @sbp: VFS superblock. 731da177e4SLinus Torvalds * 741da177e4SLinus Torvalds * Description: 751da177e4SLinus Torvalds * vxfs_put_super frees all resources allocated for @sbp 761da177e4SLinus Torvalds * after the last instance of the filesystem is unmounted. 771da177e4SLinus Torvalds */ 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds static void 801da177e4SLinus Torvalds vxfs_put_super(struct super_block *sbp) 811da177e4SLinus Torvalds { 821da177e4SLinus Torvalds struct vxfs_sb_info *infp = VXFS_SBI(sbp); 831da177e4SLinus Torvalds 846cfd0148SChristoph Hellwig lock_kernel(); 856cfd0148SChristoph Hellwig 861da177e4SLinus Torvalds vxfs_put_fake_inode(infp->vsi_fship); 871da177e4SLinus Torvalds vxfs_put_fake_inode(infp->vsi_ilist); 881da177e4SLinus Torvalds vxfs_put_fake_inode(infp->vsi_stilist); 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds brelse(infp->vsi_bp); 911da177e4SLinus Torvalds kfree(infp); 926cfd0148SChristoph Hellwig 936cfd0148SChristoph Hellwig unlock_kernel(); 941da177e4SLinus Torvalds } 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /** 971da177e4SLinus Torvalds * vxfs_statfs - get filesystem information 98726c3342SDavid Howells * @dentry: VFS dentry to locate superblock 991da177e4SLinus Torvalds * @bufp: output buffer 1001da177e4SLinus Torvalds * 1011da177e4SLinus Torvalds * Description: 1021da177e4SLinus Torvalds * vxfs_statfs fills the statfs buffer @bufp with information 103726c3342SDavid Howells * about the filesystem described by @dentry. 1041da177e4SLinus Torvalds * 1051da177e4SLinus Torvalds * Returns: 1061da177e4SLinus Torvalds * Zero. 1071da177e4SLinus Torvalds * 1081da177e4SLinus Torvalds * Locking: 1091da177e4SLinus Torvalds * No locks held. 1101da177e4SLinus Torvalds * 1111da177e4SLinus Torvalds * Notes: 1121da177e4SLinus Torvalds * This is everything but complete... 1131da177e4SLinus Torvalds */ 1141da177e4SLinus Torvalds static int 115726c3342SDavid Howells vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) 1161da177e4SLinus Torvalds { 117726c3342SDavid Howells struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds bufp->f_type = VXFS_SUPER_MAGIC; 120726c3342SDavid Howells bufp->f_bsize = dentry->d_sb->s_blocksize; 1211da177e4SLinus Torvalds bufp->f_blocks = infp->vsi_raw->vs_dsize; 1221da177e4SLinus Torvalds bufp->f_bfree = infp->vsi_raw->vs_free; 1231da177e4SLinus Torvalds bufp->f_bavail = 0; 1241da177e4SLinus Torvalds bufp->f_files = 0; 1251da177e4SLinus Torvalds bufp->f_ffree = infp->vsi_raw->vs_ifree; 1261da177e4SLinus Torvalds bufp->f_namelen = VXFS_NAMELEN; 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds return 0; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds static int vxfs_remount(struct super_block *sb, int *flags, char *data) 1321da177e4SLinus Torvalds { 1331da177e4SLinus Torvalds *flags |= MS_RDONLY; 1341da177e4SLinus Torvalds return 0; 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds /** 1381da177e4SLinus Torvalds * vxfs_read_super - read superblock into memory and initalize filesystem 1391da177e4SLinus Torvalds * @sbp: VFS superblock (to fill) 1401da177e4SLinus Torvalds * @dp: fs private mount data 1411da177e4SLinus Torvalds * @silent: do not complain loudly when sth is wrong 1421da177e4SLinus Torvalds * 1431da177e4SLinus Torvalds * Description: 1441da177e4SLinus Torvalds * We are called on the first mount of a filesystem to read the 1451da177e4SLinus Torvalds * superblock into memory and do some basic setup. 1461da177e4SLinus Torvalds * 1471da177e4SLinus Torvalds * Returns: 1481da177e4SLinus Torvalds * The superblock on success, else %NULL. 1491da177e4SLinus Torvalds * 1501da177e4SLinus Torvalds * Locking: 1511da177e4SLinus Torvalds * We are under the bkl and @sbp->s_lock. 1521da177e4SLinus Torvalds */ 1531da177e4SLinus Torvalds static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) 1541da177e4SLinus Torvalds { 1551da177e4SLinus Torvalds struct vxfs_sb_info *infp; 1561da177e4SLinus Torvalds struct vxfs_sb *rsbp; 1571da177e4SLinus Torvalds struct buffer_head *bp = NULL; 1581da177e4SLinus Torvalds u_long bsize; 1591da177e4SLinus Torvalds struct inode *root; 160d0b07948SDavid Howells int ret = -EINVAL; 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds sbp->s_flags |= MS_RDONLY; 1631da177e4SLinus Torvalds 164e915fc49SPekka Enberg infp = kzalloc(sizeof(*infp), GFP_KERNEL); 1651da177e4SLinus Torvalds if (!infp) { 1661da177e4SLinus Torvalds printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n"); 1671da177e4SLinus Torvalds return -ENOMEM; 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds bsize = sb_min_blocksize(sbp, BLOCK_SIZE); 1711da177e4SLinus Torvalds if (!bsize) { 1721da177e4SLinus Torvalds printk(KERN_WARNING "vxfs: unable to set blocksize\n"); 1731da177e4SLinus Torvalds goto out; 1741da177e4SLinus Torvalds } 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds bp = sb_bread(sbp, 1); 1771da177e4SLinus Torvalds if (!bp || !buffer_mapped(bp)) { 1781da177e4SLinus Torvalds if (!silent) { 1791da177e4SLinus Torvalds printk(KERN_WARNING 1801da177e4SLinus Torvalds "vxfs: unable to read disk superblock\n"); 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds goto out; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds rsbp = (struct vxfs_sb *)bp->b_data; 1861da177e4SLinus Torvalds if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { 1871da177e4SLinus Torvalds if (!silent) 1881da177e4SLinus Torvalds printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); 1891da177e4SLinus Torvalds goto out; 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { 1931da177e4SLinus Torvalds printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", 1941da177e4SLinus Torvalds rsbp->vs_version); 1951da177e4SLinus Torvalds goto out; 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds #ifdef DIAGNOSTIC 1991da177e4SLinus Torvalds printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); 2001da177e4SLinus Torvalds printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); 2011da177e4SLinus Torvalds #endif 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds sbp->s_magic = rsbp->vs_magic; 2048cb681b9SPekka Enberg sbp->s_fs_info = infp; 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds infp->vsi_raw = rsbp; 2071da177e4SLinus Torvalds infp->vsi_bp = bp; 2081da177e4SLinus Torvalds infp->vsi_oltext = rsbp->vs_oltext[0]; 2091da177e4SLinus Torvalds infp->vsi_oltsize = rsbp->vs_oltsize; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) { 2121da177e4SLinus Torvalds printk(KERN_WARNING "vxfs: unable to set final block size\n"); 2131da177e4SLinus Torvalds goto out; 2141da177e4SLinus Torvalds } 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds if (vxfs_read_olt(sbp, bsize)) { 2171da177e4SLinus Torvalds printk(KERN_WARNING "vxfs: unable to read olt\n"); 2181da177e4SLinus Torvalds goto out; 2191da177e4SLinus Torvalds } 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds if (vxfs_read_fshead(sbp)) { 2221da177e4SLinus Torvalds printk(KERN_WARNING "vxfs: unable to read fshead\n"); 2231da177e4SLinus Torvalds goto out; 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds sbp->s_op = &vxfs_super_ops; 227d0b07948SDavid Howells root = vxfs_iget(sbp, VXFS_ROOT_INO); 228d0b07948SDavid Howells if (IS_ERR(root)) { 229d0b07948SDavid Howells ret = PTR_ERR(root); 230d0b07948SDavid Howells goto out; 231d0b07948SDavid Howells } 2321da177e4SLinus Torvalds sbp->s_root = d_alloc_root(root); 2331da177e4SLinus Torvalds if (!sbp->s_root) { 2341da177e4SLinus Torvalds iput(root); 2351da177e4SLinus Torvalds printk(KERN_WARNING "vxfs: unable to get root dentry.\n"); 2361da177e4SLinus Torvalds goto out_free_ilist; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds return 0; 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds out_free_ilist: 2421da177e4SLinus Torvalds vxfs_put_fake_inode(infp->vsi_fship); 2431da177e4SLinus Torvalds vxfs_put_fake_inode(infp->vsi_ilist); 2441da177e4SLinus Torvalds vxfs_put_fake_inode(infp->vsi_stilist); 2451da177e4SLinus Torvalds out: 2461da177e4SLinus Torvalds brelse(bp); 2471da177e4SLinus Torvalds kfree(infp); 248d0b07948SDavid Howells return ret; 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds /* 2521da177e4SLinus Torvalds * The usual module blurb. 2531da177e4SLinus Torvalds */ 254454e2398SDavid Howells static int vxfs_get_sb(struct file_system_type *fs_type, 255454e2398SDavid Howells int flags, const char *dev_name, void *data, struct vfsmount *mnt) 2561da177e4SLinus Torvalds { 257454e2398SDavid Howells return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super, 258454e2398SDavid Howells mnt); 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds static struct file_system_type vxfs_fs_type = { 2621da177e4SLinus Torvalds .owner = THIS_MODULE, 2631da177e4SLinus Torvalds .name = "vxfs", 2641da177e4SLinus Torvalds .get_sb = vxfs_get_sb, 2651da177e4SLinus Torvalds .kill_sb = kill_block_super, 2661da177e4SLinus Torvalds .fs_flags = FS_REQUIRES_DEV, 2671da177e4SLinus Torvalds }; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds static int __init 2701da177e4SLinus Torvalds vxfs_init(void) 2711da177e4SLinus Torvalds { 272a4376e13SAlexey Dobriyan int rv; 273a4376e13SAlexey Dobriyan 2741da177e4SLinus Torvalds vxfs_inode_cachep = kmem_cache_create("vxfs_inode", 2751da177e4SLinus Torvalds sizeof(struct vxfs_inode_info), 0, 27620c2df83SPaul Mundt SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL); 277a4376e13SAlexey Dobriyan if (!vxfs_inode_cachep) 2781da177e4SLinus Torvalds return -ENOMEM; 279a4376e13SAlexey Dobriyan rv = register_filesystem(&vxfs_fs_type); 280a4376e13SAlexey Dobriyan if (rv < 0) 281a4376e13SAlexey Dobriyan kmem_cache_destroy(vxfs_inode_cachep); 282a4376e13SAlexey Dobriyan return rv; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds static void __exit 2861da177e4SLinus Torvalds vxfs_cleanup(void) 2871da177e4SLinus Torvalds { 2881da177e4SLinus Torvalds unregister_filesystem(&vxfs_fs_type); 2891da177e4SLinus Torvalds kmem_cache_destroy(vxfs_inode_cachep); 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds module_init(vxfs_init); 2931da177e4SLinus Torvalds module_exit(vxfs_cleanup); 294