linux/fs/freevxfs/vxfs_olt.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2001 Christoph Hellwig.
   3 * All rights reserved.
   4 *
   5 * Redistribution and use in source and binary forms, with or without
   6 * modification, are permitted provided that the following conditions
   7 * are met:
   8 * 1. Redistributions of source code must retain the above copyright
   9 *    notice, this list of conditions, and the following disclaimer,
  10 *    without modification.
  11 * 2. The name of the author may not be used to endorse or promote products
  12 *    derived from this software without specific prior written permission.
  13 *
  14 * Alternatively, this software may be distributed under the terms of the
  15 * GNU General Public License ("GPL").
  16 *
  17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27 * SUCH DAMAGE.
  28 */
  29
  30/* 
  31 * Veritas filesystem driver - object location table support.
  32 */
  33#include <linux/fs.h>
  34#include <linux/buffer_head.h>
  35#include <linux/kernel.h>
  36
  37#include "vxfs.h"
  38#include "vxfs_olt.h"
  39#include "vxfs_extern.h"
  40
  41
  42static inline void
  43vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
  44{
  45        BUG_ON(infp->vsi_fshino);
  46        infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);
  47}
  48
  49static inline void
  50vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
  51{
  52        BUG_ON(infp->vsi_iext);
  53        infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);
  54}
  55
  56static inline u_long
  57vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
  58{
  59        BUG_ON(sbp->s_blocksize % bsize);
  60        return (block * (sbp->s_blocksize / bsize));
  61}
  62
  63
  64/**
  65 * vxfs_read_olt - read olt
  66 * @sbp:        superblock of the filesystem
  67 * @bsize:      blocksize of the filesystem
  68 *
  69 * Description:
  70 *   vxfs_read_olt reads the olt of the filesystem described by @sbp
  71 *   into main memory and does some basic setup.
  72 *
  73 * Returns:
  74 *   Zero on success, else a negative error code.
  75 */
  76int
  77vxfs_read_olt(struct super_block *sbp, u_long bsize)
  78{
  79        struct vxfs_sb_info     *infp = VXFS_SBI(sbp);
  80        struct buffer_head      *bp;
  81        struct vxfs_olt         *op;
  82        char                    *oaddr, *eaddr;
  83
  84        bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
  85        if (!bp || !bp->b_data)
  86                goto fail;
  87
  88        op = (struct vxfs_olt *)bp->b_data;
  89        if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {
  90                printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
  91                goto fail;
  92        }
  93
  94        /*
  95         * It is in theory possible that vsi_oltsize is > 1.
  96         * I've not seen any such filesystem yet and I'm lazy..  --hch
  97         */
  98        if (infp->vsi_oltsize > 1) {
  99                printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
 100                printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
 101                goto fail;
 102        }
 103
 104        oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
 105        eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
 106
 107        while (oaddr < eaddr) {
 108                struct vxfs_oltcommon   *ocp =
 109                        (struct vxfs_oltcommon *)oaddr;
 110                
 111                switch (fs32_to_cpu(infp, ocp->olt_type)) {
 112                case VXFS_OLT_FSHEAD:
 113                        vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
 114                        break;
 115                case VXFS_OLT_ILIST:
 116                        vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
 117                        break;
 118                }
 119
 120                oaddr += fs32_to_cpu(infp, ocp->olt_size);
 121        }
 122
 123        brelse(bp);
 124        return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
 125
 126fail:
 127        brelse(bp);
 128        return -EINVAL;
 129}
 130