0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/fs.h>
0010 #include <linux/buffer_head.h>
0011 #include <linux/kernel.h>
0012
0013 #include "vxfs.h"
0014 #include "vxfs_olt.h"
0015 #include "vxfs_extern.h"
0016
0017
0018 static inline void
0019 vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
0020 {
0021 BUG_ON(infp->vsi_fshino);
0022 infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);
0023 }
0024
0025 static inline void
0026 vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
0027 {
0028 BUG_ON(infp->vsi_iext);
0029 infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);
0030 }
0031
0032 static inline u_long
0033 vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
0034 {
0035 BUG_ON(sbp->s_blocksize % bsize);
0036 return (block * (sbp->s_blocksize / bsize));
0037 }
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 int
0053 vxfs_read_olt(struct super_block *sbp, u_long bsize)
0054 {
0055 struct vxfs_sb_info *infp = VXFS_SBI(sbp);
0056 struct buffer_head *bp;
0057 struct vxfs_olt *op;
0058 char *oaddr, *eaddr;
0059
0060 bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
0061 if (!bp || !bp->b_data)
0062 goto fail;
0063
0064 op = (struct vxfs_olt *)bp->b_data;
0065 if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {
0066 printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
0067 goto fail;
0068 }
0069
0070
0071
0072
0073
0074 if (infp->vsi_oltsize > 1) {
0075 printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
0076 printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
0077 goto fail;
0078 }
0079
0080 oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
0081 eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
0082
0083 while (oaddr < eaddr) {
0084 struct vxfs_oltcommon *ocp =
0085 (struct vxfs_oltcommon *)oaddr;
0086
0087 switch (fs32_to_cpu(infp, ocp->olt_type)) {
0088 case VXFS_OLT_FSHEAD:
0089 vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
0090 break;
0091 case VXFS_OLT_ILIST:
0092 vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
0093 break;
0094 }
0095
0096 oaddr += fs32_to_cpu(infp, ocp->olt_size);
0097 }
0098
0099 brelse(bp);
0100 return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
0101
0102 fail:
0103 brelse(bp);
0104 return -EINVAL;
0105 }