vxfs_bmap.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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. #ident "$Id: vxfs_bmap.c,v 1.25 2002/01/02 23:36:55 hch Exp hch $"
  30. /*
  31.  * Veritas filesystem driver - filesystem to disk block mapping.
  32.  */
  33. #include <linux/fs.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=%xn", 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 to 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 "nnTYPED_DEV4 detected!n");
  149. printk(KERN_INFO "block: %Lutsize: %Ldtdev: %dn",
  150. typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev);
  151. goto fail;
  152. }
  153. default:
  154. BUG();
  155. }
  156. brelse(bp);
  157. }
  158. fail:
  159. pblock = 0;
  160. out:
  161. brelse(bp);
  162. return (pblock);
  163. }
  164. /**
  165.  * vxfs_bmap_typed - bmap for typed extents
  166.  * @ip: pointer to the inode we do bmap for
  167.  * @iblock: logical block
  168.  *
  169.  * Description:
  170.  *   Performs the bmap operation for typed extents.
  171.  *
  172.  * Return Value:
  173.  *   The physical block number on success, else Zero.
  174.  */
  175. static daddr_t
  176. vxfs_bmap_typed(struct inode *ip, long iblock)
  177. {
  178. struct vxfs_inode_info *vip = VXFS_INO(ip);
  179. daddr_t pblock = 0;
  180. int i;
  181. for (i = 0; i < VXFS_NTYPED; i++) {
  182. struct vxfs_typed *typ = vip->vii_org.typed + i;
  183. int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
  184. #ifdef DIAGNOSTIC
  185. vxfs_typdump(typ);
  186. #endif
  187. if (iblock < off)
  188. continue;
  189. switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
  190. case VXFS_TYPED_INDIRECT:
  191. pblock = vxfs_bmap_indir(ip, typ->vt_block,
  192. typ->vt_size, iblock - off);
  193. if (pblock == -2)
  194. break;
  195. return (pblock);
  196. case VXFS_TYPED_DATA:
  197. if ((iblock - off) < typ->vt_size)
  198. return (typ->vt_block + iblock - off);
  199. break;
  200. case VXFS_TYPED_INDIRECT_DEV4:
  201. case VXFS_TYPED_DATA_DEV4: {
  202. struct vxfs_typed_dev4 *typ4 =
  203. (struct vxfs_typed_dev4 *)typ;
  204. printk(KERN_INFO "nnTYPED_DEV4 detected!n");
  205. printk(KERN_INFO "block: %Lutsize: %Ldtdev: %dn",
  206. typ4->vd4_block, typ4->vd4_size, typ4->vd4_dev);
  207. return 0;
  208. }
  209. default:
  210. BUG();
  211. }
  212. }
  213. return 0;
  214. }
  215. /**
  216.  * vxfs_bmap1 - vxfs-internal bmap operation
  217.  * @ip: pointer to the inode we do bmap for
  218.  * @iblock: logical block
  219.  *
  220.  * Description:
  221.  *   vxfs_bmap1 perfoms a logical to physical block mapping
  222.  *   for vxfs-internal purposes.
  223.  *
  224.  * Return Value:
  225.  *   The physical block number on success, else Zero.
  226.  */
  227. daddr_t
  228. vxfs_bmap1(struct inode *ip, long iblock)
  229. {
  230. struct vxfs_inode_info *vip = VXFS_INO(ip);
  231. if (VXFS_ISEXT4(vip))
  232. return vxfs_bmap_ext4(ip, iblock);
  233. if (VXFS_ISTYPED(vip))
  234. return vxfs_bmap_typed(ip, iblock);
  235. if (VXFS_ISNONE(vip))
  236. goto unsupp;
  237. if (VXFS_ISIMMED(vip))
  238. goto unsupp;
  239. printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)n",
  240. ip->i_ino, vip->vii_orgtype);
  241. BUG();
  242. unsupp:
  243. printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)n",
  244. ip->i_ino, vip->vii_orgtype);
  245. return 0;
  246. }