1 /* 2 * Copyright (c) 2000-2001 Christoph Hellwig. 3 * Copyright (c) 2016 Krzysztof Blaszkowski 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer, 11 * without modification. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * Alternatively, this software may be distributed under the terms of the 16 * GNU General Public License ("GPL"). 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Veritas filesystem driver - fileset header routines. 33 */ 34 #include <linux/fs.h> 35 #include <linux/buffer_head.h> 36 #include <linux/kernel.h> 37 #include <linux/slab.h> 38 #include <linux/string.h> 39 40 #include "vxfs.h" 41 #include "vxfs_inode.h" 42 #include "vxfs_extern.h" 43 #include "vxfs_fshead.h" 44 45 46 #ifdef DIAGNOSTIC 47 static void 48 vxfs_dumpfsh(struct vxfs_fsh *fhp) 49 { 50 printk("\n\ndumping fileset header:\n"); 51 printk("----------------------------\n"); 52 printk("version: %u\n", fhp->fsh_version); 53 printk("fsindex: %u\n", fhp->fsh_fsindex); 54 printk("iauino: %u\tninodes:%u\n", 55 fhp->fsh_iauino, fhp->fsh_ninodes); 56 printk("maxinode: %u\tlctino: %u\n", 57 fhp->fsh_maxinode, fhp->fsh_lctino); 58 printk("nau: %u\n", fhp->fsh_nau); 59 printk("ilistino[0]: %u\tilistino[1]: %u\n", 60 fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]); 61 } 62 #endif 63 64 /** 65 * vxfs_getfsh - read fileset header into memory 66 * @ip: the (fake) fileset header inode 67 * @which: 0 for the structural, 1 for the primary fsh. 68 * 69 * Description: 70 * vxfs_getfsh reads either the structural or primary fileset header 71 * described by @ip into memory. 72 * 73 * Returns: 74 * The fileset header structure on success, else Zero. 75 */ 76 static struct vxfs_fsh * 77 vxfs_getfsh(struct inode *ip, int which) 78 { 79 struct buffer_head *bp; 80 81 bp = vxfs_bread(ip, which); 82 if (bp) { 83 struct vxfs_fsh *fhp; 84 85 if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL))) 86 goto out; 87 memcpy(fhp, bp->b_data, sizeof(*fhp)); 88 89 put_bh(bp); 90 return (fhp); 91 } 92 out: 93 brelse(bp); 94 return NULL; 95 } 96 97 /** 98 * vxfs_read_fshead - read the fileset headers 99 * @sbp: superblock to which the fileset belongs 100 * 101 * Description: 102 * vxfs_read_fshead will fill the inode and structural inode list in @sb. 103 * 104 * Returns: 105 * Zero on success, else a negative error code (-EINVAL). 106 */ 107 int 108 vxfs_read_fshead(struct super_block *sbp) 109 { 110 struct vxfs_sb_info *infp = VXFS_SBI(sbp); 111 struct vxfs_fsh *pfp, *sfp; 112 struct vxfs_inode_info *vip; 113 114 infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); 115 if (!infp->vsi_fship) { 116 printk(KERN_ERR "vxfs: unable to read fsh inode\n"); 117 return -EINVAL; 118 } 119 120 vip = VXFS_INO(infp->vsi_fship); 121 if (!VXFS_ISFSH(vip)) { 122 printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", 123 vip->vii_mode & VXFS_TYPE_MASK); 124 goto out_iput_fship; 125 } 126 127 #ifdef DIAGNOSTIC 128 printk("vxfs: fsh inode dump:\n"); 129 vxfs_dumpi(vip, infp->vsi_fshino); 130 #endif 131 132 sfp = vxfs_getfsh(infp->vsi_fship, 0); 133 if (!sfp) { 134 printk(KERN_ERR "vxfs: unable to get structural fsh\n"); 135 goto out_iput_fship; 136 } 137 138 #ifdef DIAGNOSTIC 139 vxfs_dumpfsh(sfp); 140 #endif 141 142 pfp = vxfs_getfsh(infp->vsi_fship, 1); 143 if (!pfp) { 144 printk(KERN_ERR "vxfs: unable to get primary fsh\n"); 145 goto out_free_sfp; 146 } 147 148 #ifdef DIAGNOSTIC 149 vxfs_dumpfsh(pfp); 150 #endif 151 152 infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext, 153 fs32_to_cpu(infp, sfp->fsh_ilistino[0])); 154 if (!infp->vsi_stilist) { 155 printk(KERN_ERR "vxfs: unable to get structural list inode\n"); 156 goto out_free_pfp; 157 } 158 if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { 159 printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n", 160 VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 161 goto out_iput_stilist; 162 } 163 164 infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0])); 165 if (!infp->vsi_ilist) { 166 printk(KERN_ERR "vxfs: unable to get inode list inode\n"); 167 goto out_iput_stilist; 168 } 169 if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { 170 printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", 171 VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); 172 goto out_iput_ilist; 173 } 174 175 kfree(pfp); 176 kfree(sfp); 177 return 0; 178 179 out_iput_ilist: 180 iput(infp->vsi_ilist); 181 out_iput_stilist: 182 iput(infp->vsi_stilist); 183 out_free_pfp: 184 kfree(pfp); 185 out_free_sfp: 186 kfree(sfp); 187 out_iput_fship: 188 iput(infp->vsi_fship); 189 return -EINVAL; 190 } 191