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 - fileset header routines. 32 */ 33#include <linux/fs.h> 34#include <linux/buffer_head.h> 35#include <linux/kernel.h> 36#include <linux/slab.h> 37#include <linux/string.h> 38 39#include "vxfs.h" 40#include "vxfs_inode.h" 41#include "vxfs_extern.h" 42#include "vxfs_fshead.h" 43 44 45#ifdef DIAGNOSTIC 46static void 47vxfs_dumpfsh(struct vxfs_fsh *fhp) 48{ 49 printk("\n\ndumping fileset header:\n"); 50 printk("----------------------------\n"); 51 printk("version: %u\n", fhp->fsh_version); 52 printk("fsindex: %u\n", fhp->fsh_fsindex); 53 printk("iauino: %u\tninodes:%u\n", 54 fhp->fsh_iauino, fhp->fsh_ninodes); 55 printk("maxinode: %u\tlctino: %u\n", 56 fhp->fsh_maxinode, fhp->fsh_lctino); 57 printk("nau: %u\n", fhp->fsh_nau); 58 printk("ilistino[0]: %u\tilistino[1]: %u\n", 59 fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]); 60} 61#endif 62 63/** 64 * vxfs_getfsh - read fileset header into memory 65 * @ip: the (fake) fileset header inode 66 * @which: 0 for the structural, 1 for the primary fsh. 67 * 68 * Description: 69 * vxfs_getfsh reads either the structural or primary fileset header 70 * described by @ip into memory. 71 * 72 * Returns: 73 * The fileset header structure on success, else Zero. 74 */ 75static struct vxfs_fsh * 76vxfs_getfsh(struct inode *ip, int which) 77{ 78 struct buffer_head *bp; 79 80 bp = vxfs_bread(ip, which); 81 if (bp) { 82 struct vxfs_fsh *fhp; 83 84 if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL))) 85 goto out; 86 memcpy(fhp, bp->b_data, sizeof(*fhp)); 87 88 put_bh(bp); 89 return (fhp); 90 } 91out: 92 brelse(bp); 93 return NULL; 94} 95 96/** 97 * vxfs_read_fshead - read the fileset headers 98 * @sbp: superblock to which the fileset belongs 99 * 100 * Description: 101 * vxfs_read_fshead will fill the inode and structural inode list in @sb. 102 * 103 * Returns: 104 * Zero on success, else a negative error code (-EINVAL). 105 */ 106int 107vxfs_read_fshead(struct super_block *sbp) 108{ 109 struct vxfs_sb_info *infp = VXFS_SBI(sbp); 110 struct vxfs_fsh *pfp, *sfp; 111 struct vxfs_inode_info *vip, *tip; 112 113 vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); 114 if (!vip) { 115 printk(KERN_ERR "vxfs: unable to read fsh inode\n"); 116 return -EINVAL; 117 } 118 if (!VXFS_ISFSH(vip)) { 119 printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", 120 vip->vii_mode & VXFS_TYPE_MASK); 121 goto out_free_fship; 122 } 123 124 125#ifdef DIAGNOSTIC 126 printk("vxfs: fsh inode dump:\n"); 127 vxfs_dumpi(vip, infp->vsi_fshino); 128#endif 129 130 infp->vsi_fship = vxfs_get_fake_inode(sbp, vip); 131 if (!infp->vsi_fship) { 132 printk(KERN_ERR "vxfs: unable to get fsh inode\n"); 133 goto out_free_fship; 134 } 135 136 sfp = vxfs_getfsh(infp->vsi_fship, 0); 137 if (!sfp) { 138 printk(KERN_ERR "vxfs: unable to get structural fsh\n"); 139 goto out_iput_fship; 140 } 141 142#ifdef DIAGNOSTIC 143 vxfs_dumpfsh(sfp); 144#endif 145 146 pfp = vxfs_getfsh(infp->vsi_fship, 1); 147 if (!pfp) { 148 printk(KERN_ERR "vxfs: unable to get primary fsh\n"); 149 goto out_free_sfp; 150 } 151 152#ifdef DIAGNOSTIC 153 vxfs_dumpfsh(pfp); 154#endif 155 156 tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); 157 if (!tip) 158 goto out_free_pfp; 159 160 infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip); 161 if (!infp->vsi_stilist) { 162 printk(KERN_ERR "vxfs: unable to get structural list inode\n"); 163 kfree(tip); 164 goto out_free_pfp; 165 } 166 if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { 167 printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n", 168 VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 169 goto out_iput_stilist; 170 } 171 172 tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); 173 if (!tip) 174 goto out_iput_stilist; 175 infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); 176 if (!infp->vsi_ilist) { 177 printk(KERN_ERR "vxfs: unable to get inode list inode\n"); 178 kfree(tip); 179 goto out_iput_stilist; 180 } 181 if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { 182 printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", 183 VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); 184 goto out_iput_ilist; 185 } 186 187 return 0; 188 189 out_iput_ilist: 190 iput(infp->vsi_ilist); 191 out_iput_stilist: 192 iput(infp->vsi_stilist); 193 out_free_pfp: 194 kfree(pfp); 195 out_free_sfp: 196 kfree(sfp); 197 out_iput_fship: 198 iput(infp->vsi_fship); 199 return -EINVAL; 200 out_free_fship: 201 kfree(vip); 202 return -EINVAL; 203} 204