Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vxfs_bmap.c
Go to the documentation of this file.
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 /*
31  * Veritas filesystem driver - filesystem to disk block mapping.
32  */
33 #include <linux/fs.h>
34 #include <linux/buffer_head.h>
35 #include <linux/kernel.h>
36 
37 #include "vxfs.h"
38 #include "vxfs_inode.h"
39 #include "vxfs_extern.h"
40 
41 
42 #ifdef DIAGNOSTIC
43 static void
44 vxfs_typdump(struct vxfs_typed *typ)
45 {
46  printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
47  printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
48  printk("block=%x ", typ->vt_block);
49  printk("size=%x\n", typ->vt_size);
50 }
51 #endif
52 
66 static daddr_t
67 vxfs_bmap_ext4(struct inode *ip, long bn)
68 {
69  struct super_block *sb = ip->i_sb;
70  struct vxfs_inode_info *vip = VXFS_INO(ip);
71  unsigned long bsize = sb->s_blocksize;
72  u32 indsize = vip->vii_ext4.ve4_indsize;
73  int i;
74 
75  if (indsize > sb->s_blocksize)
76  goto fail_size;
77 
78  for (i = 0; i < VXFS_NDADDR; i++) {
79  struct direct *d = vip->vii_ext4.ve4_direct + i;
80  if (bn >= 0 && bn < d->size)
81  return (bn + d->extent);
82  bn -= d->size;
83  }
84 
85  if ((bn / (indsize * indsize * bsize / 4)) == 0) {
86  struct buffer_head *buf;
87  daddr_t bno;
88  u32 *indir;
89 
90  buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]);
91  if (!buf || !buffer_mapped(buf))
92  goto fail_buf;
93 
94  indir = (u32 *)buf->b_data;
95  bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
96 
97  brelse(buf);
98  return bno;
99  } else
100  printk(KERN_WARNING "no matching indir?");
101 
102  return 0;
103 
104 fail_size:
105  printk("vxfs: indirect extent too big!\n");
106 fail_buf:
107  return 0;
108 }
109 
127 static daddr_t
128 vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
129 {
130  struct buffer_head *bp = NULL;
131  daddr_t pblock = 0;
132  int i;
133 
134  for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
135  struct vxfs_typed *typ;
136  int64_t off;
137 
138  bp = sb_bread(ip->i_sb,
139  indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
140  if (!bp || !buffer_mapped(bp))
141  return 0;
142 
143  typ = ((struct vxfs_typed *)bp->b_data) +
144  (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
145  off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
146 
147  if (block < off) {
148  brelse(bp);
149  continue;
150  }
151 
152  switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
153  case VXFS_TYPED_INDIRECT:
154  pblock = vxfs_bmap_indir(ip, typ->vt_block,
155  typ->vt_size, block - off);
156  if (pblock == -2)
157  break;
158  goto out;
159  case VXFS_TYPED_DATA:
160  if ((block - off) >= typ->vt_size)
161  break;
162  pblock = (typ->vt_block + block - off);
163  goto out;
165  case VXFS_TYPED_DATA_DEV4: {
166  struct vxfs_typed_dev4 *typ4 =
167  (struct vxfs_typed_dev4 *)typ;
168 
169  printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
170  printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
171  (unsigned long long) typ4->vd4_block,
172  (unsigned long long) typ4->vd4_size,
173  typ4->vd4_dev);
174  goto fail;
175  }
176  default:
177  BUG();
178  }
179  brelse(bp);
180  }
181 
182 fail:
183  pblock = 0;
184 out:
185  brelse(bp);
186  return (pblock);
187 }
188 
200 static daddr_t
201 vxfs_bmap_typed(struct inode *ip, long iblock)
202 {
203  struct vxfs_inode_info *vip = VXFS_INO(ip);
204  daddr_t pblock = 0;
205  int i;
206 
207  for (i = 0; i < VXFS_NTYPED; i++) {
208  struct vxfs_typed *typ = vip->vii_org.typed + i;
209  int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
210 
211 #ifdef DIAGNOSTIC
212  vxfs_typdump(typ);
213 #endif
214  if (iblock < off)
215  continue;
216  switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
217  case VXFS_TYPED_INDIRECT:
218  pblock = vxfs_bmap_indir(ip, typ->vt_block,
219  typ->vt_size, iblock - off);
220  if (pblock == -2)
221  break;
222  return (pblock);
223  case VXFS_TYPED_DATA:
224  if ((iblock - off) < typ->vt_size)
225  return (typ->vt_block + iblock - off);
226  break;
228  case VXFS_TYPED_DATA_DEV4: {
229  struct vxfs_typed_dev4 *typ4 =
230  (struct vxfs_typed_dev4 *)typ;
231 
232  printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
233  printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
234  (unsigned long long) typ4->vd4_block,
235  (unsigned long long) typ4->vd4_size,
236  typ4->vd4_dev);
237  return 0;
238  }
239  default:
240  BUG();
241  }
242  }
243 
244  return 0;
245 }
246 
259 daddr_t
260 vxfs_bmap1(struct inode *ip, long iblock)
261 {
262  struct vxfs_inode_info *vip = VXFS_INO(ip);
263 
264  if (VXFS_ISEXT4(vip))
265  return vxfs_bmap_ext4(ip, iblock);
266  if (VXFS_ISTYPED(vip))
267  return vxfs_bmap_typed(ip, iblock);
268  if (VXFS_ISNONE(vip))
269  goto unsupp;
270  if (VXFS_ISIMMED(vip))
271  goto unsupp;
272 
273  printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
274  ip->i_ino, vip->vii_orgtype);
275  BUG();
276 
277 unsupp:
278  printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
279  ip->i_ino, vip->vii_orgtype);
280  return 0;
281 }