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_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
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
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
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
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
0176
0177
0178
0179
0180
0181
0182
0183
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
0239
0240
0241
0242
0243
0244
0245
0246
0247
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 }