/** * __vxfs_iget - generic find inode facility * @sbp: VFS superblock * @ino: inode number * @ilistp: inode list * * Description: * Search the for inode number @ino in the filesystem * described by @sbp. Use the specified inode table (@ilistp). * Returns the matching VxFS inode on success, else a NULL pointer. */ static struct vxfs_inode_info * __vxfs_iget(ino_t ino, struct inode *ilistp) { struct page *pp; u_long offset; offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); if (!IS_ERR(pp)) { struct vxfs_inode_info *vip; struct vxfs_dinode *dip; caddr_t kaddr = (char *)page_address(pp); if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL))) goto fail; dip = (struct vxfs_dinode *)(kaddr + offset); memcpy(vip, dip, sizeof(*vip)); #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif vxfs_put_page(pp); return (vip); } printk(KERN_WARNING "vxfs: error on page %p\n", pp); return NULL; fail: printk(KERN_WARNING "vxfs: unable to read inode %ld\n", ino); vxfs_put_page(pp); return NULL; }
/** * vxfs_blkiget - find inode based on extent # * @sbp: superblock of the filesystem we search in * @extent: number of the extent to search * @ino: inode number to search * * Description: * vxfs_blkiget searches inode @ino in the filesystem described by * @sbp in the extent @extent. * Returns the matching VxFS inode on success, else a NULL pointer. * * NOTE: * While __vxfs_iget uses the pagecache vxfs_blkiget uses the * buffercache. This function should not be used outside the * read_super() method, otherwise the data may be incoherent. */ struct vxfs_inode_info * vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) { struct buffer_head *bp; u_long block, offset; block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); bp = sb_bread(sbp, block); if (buffer_mapped(bp)) { struct vxfs_inode_info *vip; struct vxfs_dinode *dip; if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL))) goto fail; dip = (struct vxfs_dinode *)(bp->b_data + offset); memcpy(vip, dip, sizeof(*vip)); #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif brelse(bp); return (vip); } fail: printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); brelse(bp); return NULL; }
/** * vxfs_read_fshead - read the fileset headers * @sbp: superblock to which the fileset belongs * * Description: * vxfs_read_fshead will fill the inode and structural inode list in @sb. * * Returns: * Zero on success, else a negative error code (-EINVAL). */ int vxfs_read_fshead(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); struct vxfs_fsh *pfp, *sfp; struct vxfs_inode_info *vip, *tip; if (!(vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino))) { printk(KERN_ERR "vxfs: unabled to read fsh inode\n"); return -EINVAL; } else if (!VXFS_ISFSH(vip)) { printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", vip->vii_mode & VXFS_TYPE_MASK); return -EINVAL; } #ifdef DIAGNOSTIC printk("vxfs: fsh inode dump:\n"); vxfs_dumpi(vip, infp->vsi_fshino); #endif if (!(infp->vsi_fship = vxfs_get_fake_inode(sbp, vip))) { printk(KERN_ERR "vxfs: unabled to get fsh inode\n"); return -EINVAL; } if (!(sfp = vxfs_getfsh(infp->vsi_fship, 0))) { printk(KERN_ERR "vxfs: unabled to get structural fsh\n"); return -EINVAL; } #ifdef DIAGNOSTIC vxfs_dumpfsh(sfp); #endif if (!(pfp = vxfs_getfsh(infp->vsi_fship, 1))) { printk(KERN_ERR "vxfs: unabled to get primary fsh\n"); return -EINVAL; } #ifdef DIAGNOSTIC vxfs_dumpfsh(pfp); #endif tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); if (!tip || ((infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip)) == NULL)) { printk(KERN_ERR "vxfs: unabled to get structual list inode\n"); return -EINVAL; } else if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); return -EINVAL; } tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); if (!tip || ((infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip)) == NULL)) { printk(KERN_ERR "vxfs: unabled to get inode list inode\n"); return -EINVAL; } else if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); return -EINVAL; } return 0; }
/** * vxfs_read_fshead - read the fileset headers * @sbp: superblock to which the fileset belongs * * Description: * vxfs_read_fshead will fill the inode and structural inode list in @sb. * * Returns: * Zero on success, else a negative error code (-EINVAL). */ int vxfs_read_fshead(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); struct vxfs_fsh *pfp, *sfp; struct vxfs_inode_info *vip, *tip; vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); if (!vip) { printk(KERN_ERR "vxfs: unable to read fsh inode\n"); return -EINVAL; } if (!VXFS_ISFSH(vip)) { printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", vip->vii_mode & VXFS_TYPE_MASK); goto out_free_fship; } #ifdef DIAGNOSTIC printk(KERN_INFO "vxfs: fsh inode dump:\n"); vxfs_dumpi(vip, infp->vsi_fshino); #endif infp->vsi_fship = vxfs_get_fake_inode(sbp, vip); if (!infp->vsi_fship) { printk(KERN_ERR "vxfs: unable to get fsh inode\n"); goto out_free_fship; } sfp = vxfs_getfsh(infp->vsi_fship, 0); if (!sfp) { printk(KERN_ERR "vxfs: unable to get structural fsh\n"); goto out_iput_fship; } #ifdef DIAGNOSTIC vxfs_dumpfsh(sfp); #endif pfp = vxfs_getfsh(infp->vsi_fship, 1); if (!pfp) { printk(KERN_ERR "vxfs: unable to get primary fsh\n"); goto out_free_sfp; } #ifdef DIAGNOSTIC vxfs_dumpfsh(pfp); #endif tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); if (!tip) goto out_free_pfp; infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip); if (!infp->vsi_stilist) { printk(KERN_ERR "vxfs: unable to get structural list inode\n"); kfree(tip); goto out_free_pfp; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n", VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); goto out_iput_stilist; } tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); if (!tip) goto out_iput_stilist; infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); if (!infp->vsi_ilist) { printk(KERN_ERR "vxfs: unable to get inode list inode\n"); kfree(tip); goto out_iput_stilist; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n", VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK); goto out_iput_ilist; } return 0; out_iput_ilist: iput(infp->vsi_ilist); out_iput_stilist: iput(infp->vsi_stilist); out_free_pfp: kfree(pfp); out_free_sfp: kfree(sfp); out_iput_fship: iput(infp->vsi_fship); return -EINVAL; out_free_fship: kfree(vip); return -EINVAL; }