brintos

brintos / linux-shallow public Read only

0
0
Text · 6.5 KiB · 26d367e Raw
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