vxfs_bmap.c 7.2 KB

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