vxfs_bmap.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2000-2001 Christoph Hellwig.
  4. */
  5. /*
  6. * Veritas filesystem driver - filesystem to disk block mapping.
  7. */
  8. #include <linux/fs.h>
  9. #include <linux/buffer_head.h>
  10. #include <linux/kernel.h>
  11. #include "vxfs.h"
  12. #include "vxfs_inode.h"
  13. #include "vxfs_extern.h"
  14. #ifdef DIAGNOSTIC
  15. static void
  16. vxfs_typdump(struct vxfs_typed *typ)
  17. {
  18. printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
  19. printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
  20. printk("block=%x ", typ->vt_block);
  21. printk("size=%x\n", typ->vt_size);
  22. }
  23. #endif
  24. /**
  25. * vxfs_bmap_ext4 - do bmap for ext4 extents
  26. * @ip: pointer to the inode we do bmap for
  27. * @iblock: logical block.
  28. *
  29. * Description:
  30. * vxfs_bmap_ext4 performs the bmap operation for inodes with
  31. * ext4-style extents (which are much like the traditional UNIX
  32. * inode organisation).
  33. *
  34. * Returns:
  35. * The physical block number on success, else Zero.
  36. */
  37. static daddr_t
  38. vxfs_bmap_ext4(struct inode *ip, long bn)
  39. {
  40. struct super_block *sb = ip->i_sb;
  41. struct vxfs_inode_info *vip = VXFS_INO(ip);
  42. struct vxfs_sb_info *sbi = VXFS_SBI(sb);
  43. unsigned long bsize = sb->s_blocksize;
  44. u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);
  45. int i;
  46. if (indsize > sb->s_blocksize)
  47. goto fail_size;
  48. for (i = 0; i < VXFS_NDADDR; i++) {
  49. struct direct *d = vip->vii_ext4.ve4_direct + i;
  50. if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
  51. return (bn + fs32_to_cpu(sbi, d->extent));
  52. bn -= fs32_to_cpu(sbi, d->size);
  53. }
  54. if ((bn / (indsize * indsize * bsize / 4)) == 0) {
  55. struct buffer_head *buf;
  56. daddr_t bno;
  57. __fs32 *indir;
  58. buf = sb_bread(sb,
  59. fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));
  60. if (!buf || !buffer_mapped(buf))
  61. goto fail_buf;
  62. indir = (__fs32 *)buf->b_data;
  63. bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
  64. (bn % indsize);
  65. brelse(buf);
  66. return bno;
  67. } else
  68. printk(KERN_WARNING "no matching indir?");
  69. return 0;
  70. fail_size:
  71. printk("vxfs: indirect extent too big!\n");
  72. fail_buf:
  73. return 0;
  74. }
  75. /**
  76. * vxfs_bmap_indir - recursion for vxfs_bmap_typed
  77. * @ip: pointer to the inode we do bmap for
  78. * @indir: indirect block we start reading at
  79. * @size: size of the typed area to search
  80. * @block: partially result from further searches
  81. *
  82. * Description:
  83. * vxfs_bmap_indir reads a &struct vxfs_typed at @indir
  84. * and performs the type-defined action.
  85. *
  86. * Return Value:
  87. * The physical block number on success, else Zero.
  88. *
  89. * Note:
  90. * Kernelstack is rare. Unrecurse?
  91. */
  92. static daddr_t
  93. vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
  94. {
  95. struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
  96. struct buffer_head *bp = NULL;
  97. daddr_t pblock = 0;
  98. int i;
  99. for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
  100. struct vxfs_typed *typ;
  101. int64_t off;
  102. bp = sb_bread(ip->i_sb,
  103. indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
  104. if (!bp || !buffer_mapped(bp))
  105. return 0;
  106. typ = ((struct vxfs_typed *)bp->b_data) +
  107. (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
  108. off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
  109. if (block < off) {
  110. brelse(bp);
  111. continue;
  112. }
  113. switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>
  114. VXFS_TYPED_TYPESHIFT)) {
  115. case VXFS_TYPED_INDIRECT:
  116. pblock = vxfs_bmap_indir(ip,
  117. fs32_to_cpu(sbi, typ->vt_block),
  118. fs32_to_cpu(sbi, typ->vt_size),
  119. block - off);
  120. if (pblock == -2)
  121. break;
  122. goto out;
  123. case VXFS_TYPED_DATA:
  124. if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
  125. break;
  126. pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
  127. goto out;
  128. case VXFS_TYPED_INDIRECT_DEV4:
  129. case VXFS_TYPED_DATA_DEV4: {
  130. struct vxfs_typed_dev4 *typ4 =
  131. (struct vxfs_typed_dev4 *)typ;
  132. printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
  133. printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
  134. fs64_to_cpu(sbi, typ4->vd4_block),
  135. fs64_to_cpu(sbi, typ4->vd4_size),
  136. fs32_to_cpu(sbi, typ4->vd4_dev));
  137. goto fail;
  138. }
  139. default:
  140. printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
  141. __LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
  142. BUG();
  143. }
  144. brelse(bp);
  145. }
  146. fail:
  147. pblock = 0;
  148. out:
  149. brelse(bp);
  150. return (pblock);
  151. }
  152. /**
  153. * vxfs_bmap_typed - bmap for typed extents
  154. * @ip: pointer to the inode we do bmap for
  155. * @iblock: logical block
  156. *
  157. * Description:
  158. * Performs the bmap operation for typed extents.
  159. *
  160. * Return Value:
  161. * The physical block number on success, else Zero.
  162. */
  163. static daddr_t
  164. vxfs_bmap_typed(struct inode *ip, long iblock)
  165. {
  166. struct vxfs_inode_info *vip = VXFS_INO(ip);
  167. struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
  168. daddr_t pblock = 0;
  169. int i;
  170. for (i = 0; i < VXFS_NTYPED; i++) {
  171. struct vxfs_typed *typ = vip->vii_org.typed + i;
  172. u64 hdr = fs64_to_cpu(sbi, typ->vt_hdr);
  173. int64_t off = (hdr & VXFS_TYPED_OFFSETMASK);
  174. #ifdef DIAGNOSTIC
  175. vxfs_typdump(typ);
  176. #endif
  177. if (iblock < off)
  178. continue;
  179. switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
  180. case VXFS_TYPED_INDIRECT:
  181. pblock = vxfs_bmap_indir(ip,
  182. fs32_to_cpu(sbi, typ->vt_block),
  183. fs32_to_cpu(sbi, typ->vt_size),
  184. iblock - off);
  185. if (pblock == -2)
  186. break;
  187. return (pblock);
  188. case VXFS_TYPED_DATA:
  189. if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
  190. return (fs32_to_cpu(sbi, typ->vt_block) +
  191. iblock - off);
  192. break;
  193. case VXFS_TYPED_INDIRECT_DEV4:
  194. case VXFS_TYPED_DATA_DEV4: {
  195. struct vxfs_typed_dev4 *typ4 =
  196. (struct vxfs_typed_dev4 *)typ;
  197. printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
  198. printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
  199. fs64_to_cpu(sbi, typ4->vd4_block),
  200. fs64_to_cpu(sbi, typ4->vd4_size),
  201. fs32_to_cpu(sbi, typ4->vd4_dev));
  202. return 0;
  203. }
  204. default:
  205. BUG();
  206. }
  207. }
  208. return 0;
  209. }
  210. /**
  211. * vxfs_bmap1 - vxfs-internal bmap operation
  212. * @ip: pointer to the inode we do bmap for
  213. * @iblock: logical block
  214. *
  215. * Description:
  216. * vxfs_bmap1 perfoms a logical to physical block mapping
  217. * for vxfs-internal purposes.
  218. *
  219. * Return Value:
  220. * The physical block number on success, else Zero.
  221. */
  222. daddr_t
  223. vxfs_bmap1(struct inode *ip, long iblock)
  224. {
  225. struct vxfs_inode_info *vip = VXFS_INO(ip);
  226. if (VXFS_ISEXT4(vip))
  227. return vxfs_bmap_ext4(ip, iblock);
  228. if (VXFS_ISTYPED(vip))
  229. return vxfs_bmap_typed(ip, iblock);
  230. if (VXFS_ISNONE(vip))
  231. goto unsupp;
  232. if (VXFS_ISIMMED(vip))
  233. goto unsupp;
  234. printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
  235. ip->i_ino, vip->vii_orgtype);
  236. BUG();
  237. unsupp:
  238. printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
  239. ip->i_ino, vip->vii_orgtype);
  240. return 0;
  241. }