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 = 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 = 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
  85        bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
  86        if (!bp || !bp->b_data)
  87                goto fail;
  88
  89        op = (struct vxfs_olt *)bp->b_data;
  90        if (op->olt_magic != VXFS_OLT_MAGIC) {
  91                printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
  92                goto fail;
  93        }
  94
  95        /*
  96         * It is in theory possible that vsi_oltsize is > 1.
  97         * I've not seen any such filesystem yet and I'm lazy..  --hch
  98         */
  99        if (infp->vsi_oltsize > 1) {
 100                printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
 101                printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
 102                goto fail;
 103        }
 104
 105        oaddr = bp->b_data + op->olt_size;
 106        eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
 107
 108        while (oaddr < eaddr) {
 109                struct vxfs_oltcommon   *ocp =
 110                        (struct vxfs_oltcommon *)oaddr;
 111                
 112                switch (ocp->olt_type) {
 113                case VXFS_OLT_FSHEAD:
 114                        vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
 115                        break;
 116                case VXFS_OLT_ILIST:
 117                        vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
 118                        break;
 119                }
 120
 121                oaddr += ocp->olt_size;
 122        }
 123
 124        brelse(bp);
 125        return 0;
 126
 127fail:
 128        brelse(bp);
 129        return -EINVAL;
 130}
 131