1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2000-2001 Christoph Hellwig. 4 * Copyright (c) 2016 Krzysztof Blaszkowski 5 */ 6 7 /* 8 * Veritas filesystem driver - fileset header routines. 9 */ 10 #include <linux/fs.h> 11 #include <linux/buffer_head.h> 12 #include <linux/kernel.h> 13 #include <linux/slab.h> 14 #include <linux/string.h> 15 16 #include "vxfs.h" 17 #include "vxfs_inode.h" 18 #include "vxfs_extern.h" 19 #include "vxfs_fshead.h" 20 21 22 #ifdef DIAGNOSTIC 23 static void 24 vxfs_dumpfsh(struct vxfs_fsh *fhp) 25 { 26 printk("\n\ndumping fileset header:\n"); 27 printk("----------------------------\n"); 28 printk("version: %u\n", fhp->fsh_version); 29 printk("fsindex: %u\n", fhp->fsh_fsindex); 30 printk("iauino: %u\tninodes:%u\n", 31 fhp->fsh_iauino, fhp->fsh_ninodes); 32 printk("maxinode: %u\tlctino: %u\n", 33 fhp->fsh_maxinode, fhp->fsh_lctino); 34 printk("nau: %u\n", fhp->fsh_nau); 35 printk("ilistino[0]: %u\tilistino[1]: %u\n", 36 fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]); 37 } 38 #endif 39 40 /** 41 * vxfs_getfsh - read fileset header into memory 42 * @ip: the (fake) fileset header inode 43 * @which: 0 for the structural, 1 for the primary fsh. 44 * 45 * Description: 46 * vxfs_getfsh reads either the structural or primary fileset header 47 * described by @ip into memory. 48 * 49 * Returns: 50 * The fileset header structure on success, else Zero. 51 */ 52 static struct vxfs_fsh * 53 vxfs_getfsh(struct inode *ip, int which) 54 { 55 struct buffer_head *bp; 56 57 bp = vxfs_bread(ip, which); 58 if (bp) { 59 struct vxfs_fsh *fhp; 60 61 if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL))) 62 goto out; 63 memcpy(fhp, bp->b_data, sizeof(*fhp)); 64 65 put_bh(bp); 66 return (fhp); 67 } 68 out: 69 brelse(bp); 70 return NULL; 71 } 72 73 /** 74 * vxfs_read_fshead - read the fileset headers 75 * @sbp: superblock to which the fileset belongs 76 * 77 * Description: 78 * vxfs_read_fshead will fill the inode and structural inode list in @sb. 79 * 80 * Returns: 81 * Zero on success, else a negative error code (-EINVAL). 82 */ 83 int 84 vxfs_read_fshead(struct super_block *sbp) 85 { 86 struct vxfs_sb_info *infp = VXFS_SBI(sbp); 87 struct vxfs_fsh *pfp, *sfp; 88 struct vxfs_inode_info *vip; 89 90 infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); 91 if (!infp->vsi_fship) { 92 printk(KERN_ERR "vxfs: unable to read fsh inode\n"); 93 return -EINVAL; 94 } 95 96 vip = VXFS_INO(infp->vsi_fship); 97 if (!VXFS_ISFSH(vip)) { 98 printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", 99 vip->vii_mode & VXFS_TYPE_MASK); 100 goto out_iput_fship; 101 } 102 103 #ifdef DIAGNOSTIC 104 printk("vxfs: fsh inode dump:\n"); 105 vxfs_dumpi(vip, infp->vsi_fshino); 106 #endif 107 108 sfp = vxfs_getfsh(infp->vsi_fship, 0); 109 if (!sfp) { 110 printk(KERN_ERR "vxfs: unable to get structural fsh\n"); 111 goto out_iput_fship; 112 } 113 114 #ifdef DIAGNOSTIC 115 vxfs_dumpfsh(sfp); 116 #endif 117 118 pfp = vxfs_getfsh(infp->vsi_fship, 1); 119 if (!pfp) { 120 printk(KERN_ERR "vxfs: unable to get primary fsh\n"); 121 goto out_free_sfp; 122 } 123 124 #ifdef DIAGNOSTIC 125 vxfs_dumpfsh(pfp); 126 #endif 127 128 infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext, 129 fs32_to_cpu(infp, sfp->fsh_ilistino[0])); 130 if (!infp->vsi_stilist) { 131 printk(KERN_ERR "vxfs: unable to get structural list inode\n"); 132 goto out_free_pfp; 133 } 134 if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { 135 printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n", 136 VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 137 goto out_iput_stilist; 138 } 139 140 infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0])); 141 if (!infp->vsi_ilist) { 142 printk(KERN_ERR "vxfs: unable to get inode list inode\n"); 143 goto out_iput_stilist; 144 } 145 if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { 146 printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", 147 VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); 148 goto out_iput_ilist; 149 } 150 151 kfree(pfp); 152 kfree(sfp); 153 return 0; 154 155 out_iput_ilist: 156 iput(infp->vsi_ilist); 157 out_iput_stilist: 158 iput(infp->vsi_stilist); 159 out_free_pfp: 160 kfree(pfp); 161 out_free_sfp: 162 kfree(sfp); 163 out_iput_fship: 164 iput(infp->vsi_fship); 165 return -EINVAL; 166 } 167