272 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2000-2001 Christoph Hellwig.4 */5 6/*7 * Veritas filesystem driver - filesystem to disk block mapping.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_inode.h"15#include "vxfs_extern.h"16 17 18#ifdef DIAGNOSTIC19static void20vxfs_typdump(struct vxfs_typed *typ)21{22 printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);23 printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);24 printk("block=%x ", typ->vt_block);25 printk("size=%x\n", typ->vt_size);26}27#endif28 29/**30 * vxfs_bmap_ext4 - do bmap for ext4 extents31 * @ip: pointer to the inode we do bmap for32 * @bn: logical block.33 *34 * Description:35 * vxfs_bmap_ext4 performs the bmap operation for inodes with36 * ext4-style extents (which are much like the traditional UNIX37 * inode organisation).38 *39 * Returns:40 * The physical block number on success, else Zero.41 */42static daddr_t43vxfs_bmap_ext4(struct inode *ip, long bn)44{45 struct super_block *sb = ip->i_sb;46 struct vxfs_inode_info *vip = VXFS_INO(ip);47 struct vxfs_sb_info *sbi = VXFS_SBI(sb);48 unsigned long bsize = sb->s_blocksize;49 u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);50 int i;51 52 if (indsize > sb->s_blocksize)53 goto fail_size;54 55 for (i = 0; i < VXFS_NDADDR; i++) {56 struct direct *d = vip->vii_ext4.ve4_direct + i;57 if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))58 return (bn + fs32_to_cpu(sbi, d->extent));59 bn -= fs32_to_cpu(sbi, d->size);60 }61 62 if ((bn / (indsize * indsize * bsize / 4)) == 0) {63 struct buffer_head *buf;64 daddr_t bno;65 __fs32 *indir;66 67 buf = sb_bread(sb,68 fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));69 if (!buf || !buffer_mapped(buf))70 goto fail_buf;71 72 indir = (__fs32 *)buf->b_data;73 bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +74 (bn % indsize);75 76 brelse(buf);77 return bno;78 } else79 printk(KERN_WARNING "no matching indir?");80 81 return 0;82 83fail_size:84 printk("vxfs: indirect extent too big!\n");85fail_buf:86 return 0;87}88 89/**90 * vxfs_bmap_indir - recursion for vxfs_bmap_typed91 * @ip: pointer to the inode we do bmap for92 * @indir: indirect block we start reading at93 * @size: size of the typed area to search94 * @block: partially result from further searches95 *96 * Description:97 * vxfs_bmap_indir reads a &struct vxfs_typed at @indir98 * and performs the type-defined action.99 *100 * Returns:101 * The physical block number on success, else Zero.102 *103 * Note:104 * Kernelstack is rare. Unrecurse?105 */106static daddr_t107vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)108{109 struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);110 struct buffer_head *bp = NULL;111 daddr_t pblock = 0;112 int i;113 114 for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {115 struct vxfs_typed *typ;116 int64_t off;117 118 bp = sb_bread(ip->i_sb,119 indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));120 if (!bp || !buffer_mapped(bp))121 return 0;122 123 typ = ((struct vxfs_typed *)bp->b_data) +124 (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));125 off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;126 127 if (block < off) {128 brelse(bp);129 continue;130 }131 132 switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>133 VXFS_TYPED_TYPESHIFT)) {134 case VXFS_TYPED_INDIRECT:135 pblock = vxfs_bmap_indir(ip,136 fs32_to_cpu(sbi, typ->vt_block),137 fs32_to_cpu(sbi, typ->vt_size),138 block - off);139 if (pblock == -2)140 break;141 goto out;142 case VXFS_TYPED_DATA:143 if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))144 break;145 pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;146 goto out;147 case VXFS_TYPED_INDIRECT_DEV4:148 case VXFS_TYPED_DATA_DEV4: {149 struct vxfs_typed_dev4 *typ4 =150 (struct vxfs_typed_dev4 *)typ;151 152 printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");153 printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",154 fs64_to_cpu(sbi, typ4->vd4_block),155 fs64_to_cpu(sbi, typ4->vd4_size),156 fs32_to_cpu(sbi, typ4->vd4_dev));157 goto fail;158 }159 default:160 printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,161 __LINE__, fs64_to_cpu(sbi, typ->vt_hdr));162 BUG();163 }164 brelse(bp);165 }166 167fail:168 pblock = 0;169out:170 brelse(bp);171 return (pblock);172}173 174/**175 * vxfs_bmap_typed - bmap for typed extents176 * @ip: pointer to the inode we do bmap for177 * @iblock: logical block178 *179 * Description:180 * Performs the bmap operation for typed extents.181 *182 * Returns:183 * The physical block number on success, else Zero.184 */185static daddr_t186vxfs_bmap_typed(struct inode *ip, long iblock)187{188 struct vxfs_inode_info *vip = VXFS_INO(ip);189 struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);190 daddr_t pblock = 0;191 int i;192 193 for (i = 0; i < VXFS_NTYPED; i++) {194 struct vxfs_typed *typ = vip->vii_org.typed + i;195 u64 hdr = fs64_to_cpu(sbi, typ->vt_hdr);196 int64_t off = (hdr & VXFS_TYPED_OFFSETMASK);197 198#ifdef DIAGNOSTIC199 vxfs_typdump(typ);200#endif201 if (iblock < off)202 continue;203 switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {204 case VXFS_TYPED_INDIRECT:205 pblock = vxfs_bmap_indir(ip,206 fs32_to_cpu(sbi, typ->vt_block),207 fs32_to_cpu(sbi, typ->vt_size),208 iblock - off);209 if (pblock == -2)210 break;211 return (pblock);212 case VXFS_TYPED_DATA:213 if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))214 return (fs32_to_cpu(sbi, typ->vt_block) +215 iblock - off);216 break;217 case VXFS_TYPED_INDIRECT_DEV4:218 case VXFS_TYPED_DATA_DEV4: {219 struct vxfs_typed_dev4 *typ4 =220 (struct vxfs_typed_dev4 *)typ;221 222 printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");223 printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",224 fs64_to_cpu(sbi, typ4->vd4_block),225 fs64_to_cpu(sbi, typ4->vd4_size),226 fs32_to_cpu(sbi, typ4->vd4_dev));227 return 0;228 }229 default:230 BUG();231 }232 }233 234 return 0;235}236 237/**238 * vxfs_bmap1 - vxfs-internal bmap operation239 * @ip: pointer to the inode we do bmap for240 * @iblock: logical block241 *242 * Description:243 * vxfs_bmap1 perfoms a logical to physical block mapping244 * for vxfs-internal purposes.245 *246 * Returns:247 * The physical block number on success, else Zero.248 */249daddr_t250vxfs_bmap1(struct inode *ip, long iblock)251{252 struct vxfs_inode_info *vip = VXFS_INO(ip);253 254 if (VXFS_ISEXT4(vip))255 return vxfs_bmap_ext4(ip, iblock);256 if (VXFS_ISTYPED(vip))257 return vxfs_bmap_typed(ip, iblock);258 if (VXFS_ISNONE(vip))259 goto unsupp;260 if (VXFS_ISIMMED(vip))261 goto unsupp;262 263 printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",264 ip->i_ino, vip->vii_orgtype);265 BUG();266 267unsupp:268 printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",269 ip->i_ino, vip->vii_orgtype);270 return 0;271}272