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