1*0b1e987cSChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Copyright (c) 2000-2001 Christoph Hellwig.
41da177e4SLinus Torvalds */
51da177e4SLinus Torvalds
61da177e4SLinus Torvalds /*
71da177e4SLinus Torvalds * Veritas filesystem driver - object location table support.
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds #include <linux/fs.h>
101da177e4SLinus Torvalds #include <linux/buffer_head.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #include "vxfs.h"
141da177e4SLinus Torvalds #include "vxfs_olt.h"
156e1e8e11SAdrian Bunk #include "vxfs_extern.h"
161da177e4SLinus Torvalds
171da177e4SLinus Torvalds
188cb681b9SPekka Enberg static inline void
vxfs_get_fshead(struct vxfs_oltfshead * fshp,struct vxfs_sb_info * infp)191da177e4SLinus Torvalds vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
201da177e4SLinus Torvalds {
217ec70738SEric Sesterhenn BUG_ON(infp->vsi_fshino);
220d83f7fcSKrzysztof Błaszkowski infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);
231da177e4SLinus Torvalds }
241da177e4SLinus Torvalds
258cb681b9SPekka Enberg static inline void
vxfs_get_ilist(struct vxfs_oltilist * ilistp,struct vxfs_sb_info * infp)261da177e4SLinus Torvalds vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
271da177e4SLinus Torvalds {
287ec70738SEric Sesterhenn BUG_ON(infp->vsi_iext);
290d83f7fcSKrzysztof Błaszkowski infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);
301da177e4SLinus Torvalds }
311da177e4SLinus Torvalds
328cb681b9SPekka Enberg static inline u_long
vxfs_oblock(struct super_block * sbp,daddr_t block,u_long bsize)331da177e4SLinus Torvalds vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
341da177e4SLinus Torvalds {
357ec70738SEric Sesterhenn BUG_ON(sbp->s_blocksize % bsize);
361da177e4SLinus Torvalds return (block * (sbp->s_blocksize / bsize));
371da177e4SLinus Torvalds }
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds /**
411da177e4SLinus Torvalds * vxfs_read_olt - read olt
421da177e4SLinus Torvalds * @sbp: superblock of the filesystem
431da177e4SLinus Torvalds * @bsize: blocksize of the filesystem
441da177e4SLinus Torvalds *
451da177e4SLinus Torvalds * Description:
461da177e4SLinus Torvalds * vxfs_read_olt reads the olt of the filesystem described by @sbp
471da177e4SLinus Torvalds * into main memory and does some basic setup.
481da177e4SLinus Torvalds *
491da177e4SLinus Torvalds * Returns:
501da177e4SLinus Torvalds * Zero on success, else a negative error code.
511da177e4SLinus Torvalds */
521da177e4SLinus Torvalds int
vxfs_read_olt(struct super_block * sbp,u_long bsize)531da177e4SLinus Torvalds vxfs_read_olt(struct super_block *sbp, u_long bsize)
541da177e4SLinus Torvalds {
551da177e4SLinus Torvalds struct vxfs_sb_info *infp = VXFS_SBI(sbp);
561da177e4SLinus Torvalds struct buffer_head *bp;
571da177e4SLinus Torvalds struct vxfs_olt *op;
581da177e4SLinus Torvalds char *oaddr, *eaddr;
591da177e4SLinus Torvalds
601da177e4SLinus Torvalds bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
611da177e4SLinus Torvalds if (!bp || !bp->b_data)
621da177e4SLinus Torvalds goto fail;
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds op = (struct vxfs_olt *)bp->b_data;
650d83f7fcSKrzysztof Błaszkowski if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {
661da177e4SLinus Torvalds printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
671da177e4SLinus Torvalds goto fail;
681da177e4SLinus Torvalds }
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds /*
711da177e4SLinus Torvalds * It is in theory possible that vsi_oltsize is > 1.
721da177e4SLinus Torvalds * I've not seen any such filesystem yet and I'm lazy.. --hch
731da177e4SLinus Torvalds */
741da177e4SLinus Torvalds if (infp->vsi_oltsize > 1) {
751da177e4SLinus Torvalds printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
761da177e4SLinus Torvalds printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
771da177e4SLinus Torvalds goto fail;
781da177e4SLinus Torvalds }
791da177e4SLinus Torvalds
800d83f7fcSKrzysztof Błaszkowski oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
818cb681b9SPekka Enberg eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
821da177e4SLinus Torvalds
831da177e4SLinus Torvalds while (oaddr < eaddr) {
841da177e4SLinus Torvalds struct vxfs_oltcommon *ocp =
851da177e4SLinus Torvalds (struct vxfs_oltcommon *)oaddr;
861da177e4SLinus Torvalds
870d83f7fcSKrzysztof Błaszkowski switch (fs32_to_cpu(infp, ocp->olt_type)) {
881da177e4SLinus Torvalds case VXFS_OLT_FSHEAD:
891da177e4SLinus Torvalds vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
901da177e4SLinus Torvalds break;
911da177e4SLinus Torvalds case VXFS_OLT_ILIST:
921da177e4SLinus Torvalds vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
931da177e4SLinus Torvalds break;
941da177e4SLinus Torvalds }
951da177e4SLinus Torvalds
960d83f7fcSKrzysztof Błaszkowski oaddr += fs32_to_cpu(infp, ocp->olt_size);
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds
991da177e4SLinus Torvalds brelse(bp);
1000d83f7fcSKrzysztof Błaszkowski return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
1011da177e4SLinus Torvalds
1021da177e4SLinus Torvalds fail:
1031da177e4SLinus Torvalds brelse(bp);
1041da177e4SLinus Torvalds return -EINVAL;
1051da177e4SLinus Torvalds }
106