Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2000-2001 Christoph Hellwig.
0004  * Copyright (c) 2016 Krzysztof Blaszkowski
0005  */
0006 
0007 /*
0008  * Veritas filesystem driver - superblock related routines.
0009  */
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 
0013 #include <linux/blkdev.h>
0014 #include <linux/fs.h>
0015 #include <linux/buffer_head.h>
0016 #include <linux/kernel.h>
0017 #include <linux/slab.h>
0018 #include <linux/stat.h>
0019 #include <linux/vfs.h>
0020 #include <linux/mount.h>
0021 
0022 #include "vxfs.h"
0023 #include "vxfs_extern.h"
0024 #include "vxfs_dir.h"
0025 #include "vxfs_inode.h"
0026 
0027 
0028 MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
0029 MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
0030 MODULE_LICENSE("Dual BSD/GPL");
0031 
0032 static struct kmem_cache *vxfs_inode_cachep;
0033 
0034 /**
0035  * vxfs_put_super - free superblock resources
0036  * @sbp:    VFS superblock.
0037  *
0038  * Description:
0039  *   vxfs_put_super frees all resources allocated for @sbp
0040  *   after the last instance of the filesystem is unmounted.
0041  */
0042 
0043 static void
0044 vxfs_put_super(struct super_block *sbp)
0045 {
0046     struct vxfs_sb_info *infp = VXFS_SBI(sbp);
0047 
0048     iput(infp->vsi_fship);
0049     iput(infp->vsi_ilist);
0050     iput(infp->vsi_stilist);
0051 
0052     brelse(infp->vsi_bp);
0053     kfree(infp);
0054 }
0055 
0056 /**
0057  * vxfs_statfs - get filesystem information
0058  * @dentry: VFS dentry to locate superblock
0059  * @bufp:   output buffer
0060  *
0061  * Description:
0062  *   vxfs_statfs fills the statfs buffer @bufp with information
0063  *   about the filesystem described by @dentry.
0064  *
0065  * Returns:
0066  *   Zero.
0067  *
0068  * Locking:
0069  *   No locks held.
0070  *
0071  * Notes:
0072  *   This is everything but complete...
0073  */
0074 static int
0075 vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
0076 {
0077     struct vxfs_sb_info     *infp = VXFS_SBI(dentry->d_sb);
0078     struct vxfs_sb *raw_sb = infp->vsi_raw;
0079 
0080     bufp->f_type = VXFS_SUPER_MAGIC;
0081     bufp->f_bsize = dentry->d_sb->s_blocksize;
0082     bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
0083     bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
0084     bufp->f_bavail = 0;
0085     bufp->f_files = 0;
0086     bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree);
0087     bufp->f_namelen = VXFS_NAMELEN;
0088 
0089     return 0;
0090 }
0091 
0092 static int vxfs_remount(struct super_block *sb, int *flags, char *data)
0093 {
0094     sync_filesystem(sb);
0095     *flags |= SB_RDONLY;
0096     return 0;
0097 }
0098 
0099 static struct inode *vxfs_alloc_inode(struct super_block *sb)
0100 {
0101     struct vxfs_inode_info *vi;
0102 
0103     vi = alloc_inode_sb(sb, vxfs_inode_cachep, GFP_KERNEL);
0104     if (!vi)
0105         return NULL;
0106     inode_init_once(&vi->vfs_inode);
0107     return &vi->vfs_inode;
0108 }
0109 
0110 static void vxfs_free_inode(struct inode *inode)
0111 {
0112     kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode));
0113 }
0114 
0115 static const struct super_operations vxfs_super_ops = {
0116     .alloc_inode        = vxfs_alloc_inode,
0117     .free_inode     = vxfs_free_inode,
0118     .evict_inode        = vxfs_evict_inode,
0119     .put_super      = vxfs_put_super,
0120     .statfs         = vxfs_statfs,
0121     .remount_fs     = vxfs_remount,
0122 };
0123 
0124 static int vxfs_try_sb_magic(struct super_block *sbp, int silent,
0125         unsigned blk, __fs32 magic)
0126 {
0127     struct buffer_head *bp;
0128     struct vxfs_sb *rsbp;
0129     struct vxfs_sb_info *infp = VXFS_SBI(sbp);
0130     int rc = -ENOMEM;
0131 
0132     bp = sb_bread(sbp, blk);
0133     do {
0134         if (!bp || !buffer_mapped(bp)) {
0135             if (!silent) {
0136                 printk(KERN_WARNING
0137                     "vxfs: unable to read disk superblock at %u\n",
0138                     blk);
0139             }
0140             break;
0141         }
0142 
0143         rc = -EINVAL;
0144         rsbp = (struct vxfs_sb *)bp->b_data;
0145         if (rsbp->vs_magic != magic) {
0146             if (!silent)
0147                 printk(KERN_NOTICE
0148                     "vxfs: WRONG superblock magic %08x at %u\n",
0149                     rsbp->vs_magic, blk);
0150             break;
0151         }
0152 
0153         rc = 0;
0154         infp->vsi_raw = rsbp;
0155         infp->vsi_bp = bp;
0156     } while (0);
0157 
0158     if (rc) {
0159         infp->vsi_raw = NULL;
0160         infp->vsi_bp = NULL;
0161         brelse(bp);
0162     }
0163 
0164     return rc;
0165 }
0166 
0167 /**
0168  * vxfs_read_super - read superblock into memory and initialize filesystem
0169  * @sbp:        VFS superblock (to fill)
0170  * @dp:         fs private mount data
0171  * @silent:     do not complain loudly when sth is wrong
0172  *
0173  * Description:
0174  *   We are called on the first mount of a filesystem to read the
0175  *   superblock into memory and do some basic setup.
0176  *
0177  * Returns:
0178  *   The superblock on success, else %NULL.
0179  *
0180  * Locking:
0181  *   We are under @sbp->s_lock.
0182  */
0183 static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
0184 {
0185     struct vxfs_sb_info *infp;
0186     struct vxfs_sb      *rsbp;
0187     u_long          bsize;
0188     struct inode *root;
0189     int ret = -EINVAL;
0190     u32 j;
0191 
0192     sbp->s_flags |= SB_RDONLY;
0193 
0194     infp = kzalloc(sizeof(*infp), GFP_KERNEL);
0195     if (!infp) {
0196         printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
0197         return -ENOMEM;
0198     }
0199 
0200     bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
0201     if (!bsize) {
0202         printk(KERN_WARNING "vxfs: unable to set blocksize\n");
0203         goto out;
0204     }
0205 
0206     sbp->s_op = &vxfs_super_ops;
0207     sbp->s_fs_info = infp;
0208     sbp->s_time_min = 0;
0209     sbp->s_time_max = U32_MAX;
0210 
0211     if (!vxfs_try_sb_magic(sbp, silent, 1,
0212             (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) {
0213         /* Unixware, x86 */
0214         infp->byte_order = VXFS_BO_LE;
0215     } else if (!vxfs_try_sb_magic(sbp, silent, 8,
0216             (__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) {
0217         /* HP-UX, parisc */
0218         infp->byte_order = VXFS_BO_BE;
0219     } else {
0220         if (!silent)
0221             printk(KERN_NOTICE "vxfs: can't find superblock.\n");
0222         goto out;
0223     }
0224 
0225     rsbp = infp->vsi_raw;
0226     j = fs32_to_cpu(infp, rsbp->vs_version);
0227     if ((j < 2 || j > 4) && !silent) {
0228         printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
0229         goto out;
0230     }
0231 
0232 #ifdef DIAGNOSTIC
0233     printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
0234     printk(KERN_DEBUG "vxfs: blocksize: %d\n",
0235         fs32_to_cpu(infp, rsbp->vs_bsize));
0236 #endif
0237 
0238     sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
0239 
0240     infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
0241     infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
0242 
0243     j = fs32_to_cpu(infp, rsbp->vs_bsize);
0244     if (!sb_set_blocksize(sbp, j)) {
0245         printk(KERN_WARNING "vxfs: unable to set final block size\n");
0246         goto out;
0247     }
0248 
0249     if (vxfs_read_olt(sbp, bsize)) {
0250         printk(KERN_WARNING "vxfs: unable to read olt\n");
0251         goto out;
0252     }
0253 
0254     if (vxfs_read_fshead(sbp)) {
0255         printk(KERN_WARNING "vxfs: unable to read fshead\n");
0256         goto out;
0257     }
0258 
0259     root = vxfs_iget(sbp, VXFS_ROOT_INO);
0260     if (IS_ERR(root)) {
0261         ret = PTR_ERR(root);
0262         goto out;
0263     }
0264     sbp->s_root = d_make_root(root);
0265     if (!sbp->s_root) {
0266         printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
0267         goto out_free_ilist;
0268     }
0269 
0270     return 0;
0271     
0272 out_free_ilist:
0273     iput(infp->vsi_fship);
0274     iput(infp->vsi_ilist);
0275     iput(infp->vsi_stilist);
0276 out:
0277     brelse(infp->vsi_bp);
0278     kfree(infp);
0279     return ret;
0280 }
0281 
0282 /*
0283  * The usual module blurb.
0284  */
0285 static struct dentry *vxfs_mount(struct file_system_type *fs_type,
0286     int flags, const char *dev_name, void *data)
0287 {
0288     return mount_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
0289 }
0290 
0291 static struct file_system_type vxfs_fs_type = {
0292     .owner      = THIS_MODULE,
0293     .name       = "vxfs",
0294     .mount      = vxfs_mount,
0295     .kill_sb    = kill_block_super,
0296     .fs_flags   = FS_REQUIRES_DEV,
0297 };
0298 MODULE_ALIAS_FS("vxfs"); /* makes mount -t vxfs autoload the module */
0299 MODULE_ALIAS("vxfs");
0300 
0301 static int __init
0302 vxfs_init(void)
0303 {
0304     int rv;
0305 
0306     vxfs_inode_cachep = kmem_cache_create_usercopy("vxfs_inode",
0307             sizeof(struct vxfs_inode_info), 0,
0308             SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
0309             offsetof(struct vxfs_inode_info, vii_immed.vi_immed),
0310             sizeof_field(struct vxfs_inode_info,
0311                 vii_immed.vi_immed),
0312             NULL);
0313     if (!vxfs_inode_cachep)
0314         return -ENOMEM;
0315     rv = register_filesystem(&vxfs_fs_type);
0316     if (rv < 0)
0317         kmem_cache_destroy(vxfs_inode_cachep);
0318     return rv;
0319 }
0320 
0321 static void __exit
0322 vxfs_cleanup(void)
0323 {
0324     unregister_filesystem(&vxfs_fs_type);
0325     /*
0326      * Make sure all delayed rcu free inodes are flushed before we
0327      * destroy cache.
0328      */
0329     rcu_barrier();
0330     kmem_cache_destroy(vxfs_inode_cachep);
0331 }
0332 
0333 module_init(vxfs_init);
0334 module_exit(vxfs_cleanup);