vxfs_bmap.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Copyright (c) 2000-2001 Christoph Hellwig.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions, and the following disclaimer,
  10. * without modification.
  11. * 2. The name of the author may not be used to endorse or promote products
  12. * derived from this software without specific prior written permission.
  13. *
  14. * Alternatively, this software may be distributed under the terms of the
  15. * GNU General Public License ("GPL").
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * Veritas filesystem driver - filesystem to disk block mapping.
  31. */
  32. #include <linux/fs.h>
  33. #include <linux/buffer_head.h>
  34. #include <linux/kernel.h>
  35. #include "vxfs.h"
  36. #include "vxfs_inode.h"
  37. #ifdef DIAGNOSTIC
  38. static void
  39. vxfs_typdump(struct vxfs_typed *typ)
  40. {
  41. printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
  42. printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
  43. printk("block=%x ", typ->vt_block);
  44. printk("size=%x\n", typ->vt_size);
  45. }
  46. #endif
  47. /**
  48. * vxfs_bmap_ext4 - do bmap for ext4 extents
  49. * @ip: pointer to the inode we do bmap for
  50. * @iblock: logical block.
  51. *
  52. * Description:
  53. * vxfs_bmap_ext4 performs the bmap operation for inodes with
  54. * ext4-style extents (which are much like the traditional UNIX
  55. * inode organisation).
  56. *
  57. * Returns:
  58. * The physical block number on success, else Zero.
  59. */
  60. static daddr_t
  61. vxfs_bmap_ext4(struct inode *ip, long bn)
  62. {
  63. struct super_block *sb = ip->i_sb;
  64. struct vxfs_inode_info *vip = VXFS_INO(ip);
  65. unsigned long bsize = sb->s_blocksize;
  66. u32 indsize = vip->vii_ext4.ve4_indsize;
  67. int i;
  68. if (indsize > sb->s_blocksize)
  69. goto fail_size;
  70. for (i = 0; i < VXFS_NDADDR; i++) {
  71. struct direct *d = vip->vii_ext4.ve4_direct + i;
  72. if (bn >= 0 && bn < d->size)
  73. return (bn + d->extent);
  74. bn -= d->size;
  75. }
  76. if ((bn / (indsize * indsize * bsize / 4)) == 0) {
  77. struct buffer_head *buf;
  78. daddr_t bno;
  79. u32 *indir;
  80. buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]);
  81. if (!buf || !buffer_mapped(buf))
  82. goto fail_buf;
  83. indir = (u32 *)buf->b_data;
  84. bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
  85. brelse(buf);
  86. return bno;
  87. } else
  88. printk(KERN_WARNING "no matching indir?");
  89. return 0;
  90. fail_size:
  91. printk("vxfs: indirect extent too big!\n");
  92. fail_buf:
  93. return 0;
  94. }
  95. /**
  96. * vxfs_bmap_indir - recursion for vxfs_bmap_typed
  97. * @ip: pointer to the inode we do bmap for
  98. * @indir: indirect block we start reading at
  99. * @size: size of the typed area to search
  100. * @block: partially result from further searches
  101. *
  102. * Description:
  103. * vxfs_bmap_indir reads a &struct vxfs_typed at @indir
  104. * and performs the type-defined action.
  105. *
  106. * Return Value:
  107. * The physical block number on success, else Zero.
  108. *
  109. * Note:
  110. * Kernelstack is rare. Unrecurse?
  111. */
  112. static daddr_t
  113. vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
  114. {
  115. struct buffer_head *bp = NULL;
  116. daddr_t pblock = 0;
  117. int i;
  118. for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
  119. struct vxfs_typed *typ;
  120. int64_t off;
  121. bp = sb_bread(ip->i_sb,
  122. indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
  123. if (!buffer_mapped(bp))
  124. return 0;
  125. typ = ((struct vxfs_typed *)bp->b_data) +
  126. (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
  127. off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
  128. if (block < off) {
  129. brelse(bp);
  130. continue;
  131. }
  132. switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
  133. case VXFS_TYPED_INDIRECT:
  134. pblock = vxfs_bmap_indir(ip, typ->vt_block,
  135. typ->vt_size, block - off);
  136. if (pblock == -2)
  137. break;
  138. goto out;
  139. case VXFS_TYPED_DATA:
  140. if ((block - off) >= typ->vt_size)
  141. break;
  142. pblock = (typ->vt_block + block - off);
  143. goto out;
  144. case VXFS_TYPED_INDIRECT_DEV4:
  145. case VXFS_TYPED_DATA_DEV4: {
  146. struct vxfs_typed_dev4 *typ4 =
  147. (struct vxfs_typed_dev4 *)typ;
  148. printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
  149. printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
  150. (unsigned long long) typ4->vd4_block,
  151. (unsigned long long) typ4->vd4_size,
  152. typ4->vd4_dev);
  153. goto fail;
  154. }
  155. default:
  156. BUG();
  157. }
  158. brelse(bp);
  159. }
  160. fail:
  161. pblock = 0;
  162. out:
  163. brelse(bp);
  164. return (pblock);
  165. }
  166. /**
  167. * vxfs_bmap_typed - bmap for typed extents
  168. * @ip: pointer to the inode we do bmap for
  169. * @iblock: logical block
  170. *
  171. * Description:
  172. * Performs the bmap operation for typed extents.
  173. *
  174. * Return Value:
  175. * The physical block number on success, else Zero.
  176. */
  177. static daddr_t
  178. vxfs_bmap_typed(struct inode *ip, long iblock)
  179. {
  180. struct vxfs_inode_info *vip = VXFS_INO(ip);
  181. daddr_t pblock = 0;
  182. int i;
  183. for (i = 0; i < VXFS_NTYPED; i++) {
  184. struct vxfs_typed *typ = vip->vii_org.typed + i;
  185. int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
  186. #ifdef DIAGNOSTIC
  187. vxfs_typdump(typ);
  188. #endif
  189. if (iblock < off)
  190. continue;
  191. switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
  192. case VXFS_TYPED_INDIRECT:
  193. pblock = vxfs_bmap_indir(ip, typ->vt_block,
  194. typ->vt_size, iblock - off);
  195. if (pblock == -2)
  196. break;
  197. return (pblock);
  198. case VXFS_TYPED_DATA:
  199. if ((iblock - off) < typ->vt_size)
  200. return (typ->vt_block + iblock - off);
  201. break;
  202. case VXFS_TYPED_INDIRECT_DEV4:
  203. case VXFS_TYPED_DATA_DEV4: {
  204. struct vxfs_typed_dev4 *typ4 =
  205. (struct vxfs_typed_dev4 *)typ;
  206. printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
  207. printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
  208. (unsigned long long) typ4->vd4_block,
  209. (unsigned long long) typ4->vd4_size,
  210. typ4->vd4_dev);
  211. return 0;
  212. }
  213. default:
  214. BUG();
  215. }
  216. }
  217. return 0;
  218. }
  219. /**
  220. * vxfs_bmap1 - vxfs-internal bmap operation
  221. * @ip: pointer to the inode we do bmap for
  222. * @iblock: logical block
  223. *
  224. * Description:
  225. * vxfs_bmap1 perfoms a logical to physical block mapping
  226. * for vxfs-internal purposes.
  227. *
  228. * Return Value:
  229. * The physical block number on success, else Zero.
  230. */
  231. daddr_t
  232. vxfs_bmap1(struct inode *ip, long iblock)
  233. {
  234. struct vxfs_inode_info *vip = VXFS_INO(ip);
  235. if (VXFS_ISEXT4(vip))
  236. return vxfs_bmap_ext4(ip, iblock);
  237. if (VXFS_ISTYPED(vip))
  238. return vxfs_bmap_typed(ip, iblock);
  239. if (VXFS_ISNONE(vip))
  240. goto unsupp;
  241. if (VXFS_ISIMMED(vip))
  242. goto unsupp;
  243. printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
  244. ip->i_ino, vip->vii_orgtype);
  245. BUG();
  246. unsupp:
  247. printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
  248. ip->i_ino, vip->vii_orgtype);
  249. return 0;
  250. }