Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2000-2001 Christoph Hellwig.
0004  */
0005 
0006 /*
0007  * Veritas filesystem driver - filesystem to disk block mapping.
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_inode.h"
0015 #include "vxfs_extern.h"
0016 
0017 
0018 #ifdef DIAGNOSTIC
0019 static void
0020 vxfs_typdump(struct vxfs_typed *typ)
0021 {
0022     printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
0023     printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
0024     printk("block=%x ", typ->vt_block);
0025     printk("size=%x\n", typ->vt_size);
0026 }
0027 #endif
0028 
0029 /**
0030  * vxfs_bmap_ext4 - do bmap for ext4 extents
0031  * @ip:     pointer to the inode we do bmap for
0032  * @iblock: logical block.
0033  *
0034  * Description:
0035  *   vxfs_bmap_ext4 performs the bmap operation for inodes with
0036  *   ext4-style extents (which are much like the traditional UNIX
0037  *   inode organisation).
0038  *
0039  * Returns:
0040  *   The physical block number on success, else Zero.
0041  */
0042 static daddr_t
0043 vxfs_bmap_ext4(struct inode *ip, long bn)
0044 {
0045     struct super_block *sb = ip->i_sb;
0046     struct vxfs_inode_info *vip = VXFS_INO(ip);
0047     struct vxfs_sb_info *sbi = VXFS_SBI(sb);
0048     unsigned long bsize = sb->s_blocksize;
0049     u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);
0050     int i;
0051 
0052     if (indsize > sb->s_blocksize)
0053         goto fail_size;
0054 
0055     for (i = 0; i < VXFS_NDADDR; i++) {
0056         struct direct *d = vip->vii_ext4.ve4_direct + i;
0057         if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
0058             return (bn + fs32_to_cpu(sbi, d->extent));
0059         bn -= fs32_to_cpu(sbi, d->size);
0060     }
0061 
0062     if ((bn / (indsize * indsize * bsize / 4)) == 0) {
0063         struct buffer_head *buf;
0064         daddr_t bno;
0065         __fs32 *indir;
0066 
0067         buf = sb_bread(sb,
0068             fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));
0069         if (!buf || !buffer_mapped(buf))
0070             goto fail_buf;
0071 
0072         indir = (__fs32 *)buf->b_data;
0073         bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
0074             (bn % indsize);
0075 
0076         brelse(buf);
0077         return bno;
0078     } else
0079         printk(KERN_WARNING "no matching indir?");
0080 
0081     return 0;
0082 
0083 fail_size:
0084     printk("vxfs: indirect extent too big!\n");
0085 fail_buf:
0086     return 0;
0087 }
0088 
0089 /**
0090  * vxfs_bmap_indir - recursion for vxfs_bmap_typed
0091  * @ip:     pointer to the inode we do bmap for
0092  * @indir:  indirect block we start reading at
0093  * @size:   size of the typed area to search
0094  * @block:  partially result from further searches
0095  *
0096  * Description:
0097  *   vxfs_bmap_indir reads a &struct vxfs_typed at @indir
0098  *   and performs the type-defined action.
0099  *
0100  * Return Value:
0101  *   The physical block number on success, else Zero.
0102  *
0103  * Note:
0104  *   Kernelstack is rare.  Unrecurse?
0105  */
0106 static daddr_t
0107 vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
0108 {
0109     struct vxfs_sb_info     *sbi = VXFS_SBI(ip->i_sb);
0110     struct buffer_head      *bp = NULL;
0111     daddr_t             pblock = 0;
0112     int             i;
0113 
0114     for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
0115         struct vxfs_typed   *typ;
0116         int64_t         off;
0117 
0118         bp = sb_bread(ip->i_sb,
0119                 indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
0120         if (!bp || !buffer_mapped(bp))
0121             return 0;
0122 
0123         typ = ((struct vxfs_typed *)bp->b_data) +
0124             (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
0125         off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
0126 
0127         if (block < off) {
0128             brelse(bp);
0129             continue;
0130         }
0131 
0132         switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>
0133                 VXFS_TYPED_TYPESHIFT)) {
0134         case VXFS_TYPED_INDIRECT:
0135             pblock = vxfs_bmap_indir(ip,
0136                     fs32_to_cpu(sbi, typ->vt_block),
0137                     fs32_to_cpu(sbi, typ->vt_size),
0138                     block - off);
0139             if (pblock == -2)
0140                 break;
0141             goto out;
0142         case VXFS_TYPED_DATA:
0143             if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
0144                 break;
0145             pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
0146             goto out;
0147         case VXFS_TYPED_INDIRECT_DEV4:
0148         case VXFS_TYPED_DATA_DEV4: {
0149             struct vxfs_typed_dev4  *typ4 =
0150                 (struct vxfs_typed_dev4 *)typ;
0151 
0152             printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
0153             printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
0154                    fs64_to_cpu(sbi, typ4->vd4_block),
0155                    fs64_to_cpu(sbi, typ4->vd4_size),
0156                    fs32_to_cpu(sbi, typ4->vd4_dev));
0157             goto fail;
0158         }
0159         default:
0160             printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
0161                 __LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
0162             BUG();
0163         }
0164         brelse(bp);
0165     }
0166 
0167 fail:
0168     pblock = 0;
0169 out:
0170     brelse(bp);
0171     return (pblock);
0172 }
0173 
0174 /**
0175  * vxfs_bmap_typed - bmap for typed extents
0176  * @ip:     pointer to the inode we do bmap for
0177  * @iblock: logical block
0178  *
0179  * Description:
0180  *   Performs the bmap operation for typed extents.
0181  *
0182  * Return Value:
0183  *   The physical block number on success, else Zero.
0184  */
0185 static daddr_t
0186 vxfs_bmap_typed(struct inode *ip, long iblock)
0187 {
0188     struct vxfs_inode_info      *vip = VXFS_INO(ip);
0189     struct vxfs_sb_info     *sbi = VXFS_SBI(ip->i_sb);
0190     daddr_t             pblock = 0;
0191     int             i;
0192 
0193     for (i = 0; i < VXFS_NTYPED; i++) {
0194         struct vxfs_typed   *typ = vip->vii_org.typed + i;
0195         u64         hdr = fs64_to_cpu(sbi, typ->vt_hdr);
0196         int64_t         off = (hdr & VXFS_TYPED_OFFSETMASK);
0197 
0198 #ifdef DIAGNOSTIC
0199         vxfs_typdump(typ);
0200 #endif
0201         if (iblock < off)
0202             continue;
0203         switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
0204         case VXFS_TYPED_INDIRECT:
0205             pblock = vxfs_bmap_indir(ip,
0206                     fs32_to_cpu(sbi, typ->vt_block),
0207                     fs32_to_cpu(sbi, typ->vt_size),
0208                     iblock - off);
0209             if (pblock == -2)
0210                 break;
0211             return (pblock);
0212         case VXFS_TYPED_DATA:
0213             if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
0214                 return (fs32_to_cpu(sbi, typ->vt_block) +
0215                         iblock - off);
0216             break;
0217         case VXFS_TYPED_INDIRECT_DEV4:
0218         case VXFS_TYPED_DATA_DEV4: {
0219             struct vxfs_typed_dev4  *typ4 =
0220                 (struct vxfs_typed_dev4 *)typ;
0221 
0222             printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
0223             printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
0224                    fs64_to_cpu(sbi, typ4->vd4_block),
0225                    fs64_to_cpu(sbi, typ4->vd4_size),
0226                    fs32_to_cpu(sbi, typ4->vd4_dev));
0227             return 0;
0228         }
0229         default:
0230             BUG();
0231         }
0232     }
0233 
0234     return 0;
0235 }
0236 
0237 /**
0238  * vxfs_bmap1 - vxfs-internal bmap operation
0239  * @ip:         pointer to the inode we do bmap for
0240  * @iblock:     logical block
0241  *
0242  * Description:
0243  *   vxfs_bmap1 perfoms a logical to physical block mapping
0244  *   for vxfs-internal purposes.
0245  *
0246  * Return Value:
0247  *   The physical block number on success, else Zero.
0248  */
0249 daddr_t
0250 vxfs_bmap1(struct inode *ip, long iblock)
0251 {
0252     struct vxfs_inode_info      *vip = VXFS_INO(ip);
0253 
0254     if (VXFS_ISEXT4(vip))
0255         return vxfs_bmap_ext4(ip, iblock);
0256     if (VXFS_ISTYPED(vip))
0257         return vxfs_bmap_typed(ip, iblock);
0258     if (VXFS_ISNONE(vip))
0259         goto unsupp;
0260     if (VXFS_ISIMMED(vip))
0261         goto unsupp;
0262 
0263     printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
0264             ip->i_ino, vip->vii_orgtype);
0265     BUG();
0266 
0267 unsupp:
0268     printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
0269             ip->i_ino, vip->vii_orgtype);
0270     return 0;
0271 }