106 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2000-2001 Christoph Hellwig.4 */5 6/* 7 * Veritas filesystem driver - object location table support.8 */9#include <linux/fs.h>10#include <linux/buffer_head.h>11#include <linux/kernel.h>12 13#include "vxfs.h"14#include "vxfs_olt.h"15#include "vxfs_extern.h"16 17 18static inline void19vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)20{21 BUG_ON(infp->vsi_fshino);22 infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);23}24 25static inline void26vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)27{28 BUG_ON(infp->vsi_iext);29 infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);30}31 32static inline u_long33vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)34{35 BUG_ON(sbp->s_blocksize % bsize);36 return (block * (sbp->s_blocksize / bsize));37}38 39 40/**41 * vxfs_read_olt - read olt42 * @sbp: superblock of the filesystem43 * @bsize: blocksize of the filesystem44 *45 * Description:46 * vxfs_read_olt reads the olt of the filesystem described by @sbp47 * into main memory and does some basic setup.48 *49 * Returns:50 * Zero on success, else a negative error code.51 */52int53vxfs_read_olt(struct super_block *sbp, u_long bsize)54{55 struct vxfs_sb_info *infp = VXFS_SBI(sbp);56 struct buffer_head *bp;57 struct vxfs_olt *op;58 char *oaddr, *eaddr;59 60 bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));61 if (!bp || !bp->b_data)62 goto fail;63 64 op = (struct vxfs_olt *)bp->b_data;65 if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {66 printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");67 goto fail;68 }69 70 /*71 * It is in theory possible that vsi_oltsize is > 1.72 * I've not seen any such filesystem yet and I'm lazy.. --hch73 */74 if (infp->vsi_oltsize > 1) {75 printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");76 printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");77 goto fail;78 }79 80 oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);81 eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);82 83 while (oaddr < eaddr) {84 struct vxfs_oltcommon *ocp =85 (struct vxfs_oltcommon *)oaddr;86 87 switch (fs32_to_cpu(infp, ocp->olt_type)) {88 case VXFS_OLT_FSHEAD:89 vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);90 break;91 case VXFS_OLT_ILIST:92 vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);93 break;94 }95 96 oaddr += fs32_to_cpu(infp, ocp->olt_size);97 }98 99 brelse(bp);100 return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;101 102fail:103 brelse(bp);104 return -EINVAL;105}106