18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2000-2001 Christoph Hellwig.
38c2ecf20Sopenharmony_ci * Copyright (c) 2016 Krzysztof Blaszkowski
48c2ecf20Sopenharmony_ci * All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
78c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
88c2ecf20Sopenharmony_ci * are met:
98c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
108c2ecf20Sopenharmony_ci *    notice, this list of conditions, and the following disclaimer,
118c2ecf20Sopenharmony_ci *    without modification.
128c2ecf20Sopenharmony_ci * 2. The name of the author may not be used to endorse or promote products
138c2ecf20Sopenharmony_ci *    derived from this software without specific prior written permission.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
168c2ecf20Sopenharmony_ci * GNU General Public License ("GPL").
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
198c2ecf20Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
208c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
218c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
228c2ecf20Sopenharmony_ci * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
238c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
248c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
258c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
268c2ecf20Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
278c2ecf20Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
288c2ecf20Sopenharmony_ci * SUCH DAMAGE.
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * Veritas filesystem driver - fileset header routines.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci#include <linux/fs.h>
358c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
368c2ecf20Sopenharmony_ci#include <linux/kernel.h>
378c2ecf20Sopenharmony_ci#include <linux/slab.h>
388c2ecf20Sopenharmony_ci#include <linux/string.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "vxfs.h"
418c2ecf20Sopenharmony_ci#include "vxfs_inode.h"
428c2ecf20Sopenharmony_ci#include "vxfs_extern.h"
438c2ecf20Sopenharmony_ci#include "vxfs_fshead.h"
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifdef DIAGNOSTIC
478c2ecf20Sopenharmony_cistatic void
488c2ecf20Sopenharmony_civxfs_dumpfsh(struct vxfs_fsh *fhp)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	printk("\n\ndumping fileset header:\n");
518c2ecf20Sopenharmony_ci	printk("----------------------------\n");
528c2ecf20Sopenharmony_ci	printk("version: %u\n", fhp->fsh_version);
538c2ecf20Sopenharmony_ci	printk("fsindex: %u\n", fhp->fsh_fsindex);
548c2ecf20Sopenharmony_ci	printk("iauino: %u\tninodes:%u\n",
558c2ecf20Sopenharmony_ci			fhp->fsh_iauino, fhp->fsh_ninodes);
568c2ecf20Sopenharmony_ci	printk("maxinode: %u\tlctino: %u\n",
578c2ecf20Sopenharmony_ci			fhp->fsh_maxinode, fhp->fsh_lctino);
588c2ecf20Sopenharmony_ci	printk("nau: %u\n", fhp->fsh_nau);
598c2ecf20Sopenharmony_ci	printk("ilistino[0]: %u\tilistino[1]: %u\n",
608c2ecf20Sopenharmony_ci			fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]);
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/**
658c2ecf20Sopenharmony_ci * vxfs_getfsh - read fileset header into memory
668c2ecf20Sopenharmony_ci * @ip:		the (fake) fileset header inode
678c2ecf20Sopenharmony_ci * @which:	0 for the structural, 1 for the primary fsh.
688c2ecf20Sopenharmony_ci *
698c2ecf20Sopenharmony_ci * Description:
708c2ecf20Sopenharmony_ci *   vxfs_getfsh reads either the structural or primary fileset header
718c2ecf20Sopenharmony_ci *   described by @ip into memory.
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * Returns:
748c2ecf20Sopenharmony_ci *   The fileset header structure on success, else Zero.
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_cistatic struct vxfs_fsh *
778c2ecf20Sopenharmony_civxfs_getfsh(struct inode *ip, int which)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	struct buffer_head		*bp;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	bp = vxfs_bread(ip, which);
828c2ecf20Sopenharmony_ci	if (bp) {
838c2ecf20Sopenharmony_ci		struct vxfs_fsh		*fhp;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
868c2ecf20Sopenharmony_ci			goto out;
878c2ecf20Sopenharmony_ci		memcpy(fhp, bp->b_data, sizeof(*fhp));
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci		put_bh(bp);
908c2ecf20Sopenharmony_ci		return (fhp);
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ciout:
938c2ecf20Sopenharmony_ci	brelse(bp);
948c2ecf20Sopenharmony_ci	return NULL;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/**
988c2ecf20Sopenharmony_ci * vxfs_read_fshead - read the fileset headers
998c2ecf20Sopenharmony_ci * @sbp:	superblock to which the fileset belongs
1008c2ecf20Sopenharmony_ci *
1018c2ecf20Sopenharmony_ci * Description:
1028c2ecf20Sopenharmony_ci *   vxfs_read_fshead will fill the inode and structural inode list in @sb.
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci * Returns:
1058c2ecf20Sopenharmony_ci *   Zero on success, else a negative error code (-EINVAL).
1068c2ecf20Sopenharmony_ci */
1078c2ecf20Sopenharmony_ciint
1088c2ecf20Sopenharmony_civxfs_read_fshead(struct super_block *sbp)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
1118c2ecf20Sopenharmony_ci	struct vxfs_fsh			*pfp, *sfp;
1128c2ecf20Sopenharmony_ci	struct vxfs_inode_info		*vip;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
1158c2ecf20Sopenharmony_ci	if (!infp->vsi_fship) {
1168c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
1178c2ecf20Sopenharmony_ci		return -EINVAL;
1188c2ecf20Sopenharmony_ci	}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	vip = VXFS_INO(infp->vsi_fship);
1218c2ecf20Sopenharmony_ci	if (!VXFS_ISFSH(vip)) {
1228c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
1238c2ecf20Sopenharmony_ci				vip->vii_mode & VXFS_TYPE_MASK);
1248c2ecf20Sopenharmony_ci		goto out_iput_fship;
1258c2ecf20Sopenharmony_ci	}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci#ifdef DIAGNOSTIC
1288c2ecf20Sopenharmony_ci	printk("vxfs: fsh inode dump:\n");
1298c2ecf20Sopenharmony_ci	vxfs_dumpi(vip, infp->vsi_fshino);
1308c2ecf20Sopenharmony_ci#endif
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	sfp = vxfs_getfsh(infp->vsi_fship, 0);
1338c2ecf20Sopenharmony_ci	if (!sfp) {
1348c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
1358c2ecf20Sopenharmony_ci		goto out_iput_fship;
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci#ifdef DIAGNOSTIC
1398c2ecf20Sopenharmony_ci	vxfs_dumpfsh(sfp);
1408c2ecf20Sopenharmony_ci#endif
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	pfp = vxfs_getfsh(infp->vsi_fship, 1);
1438c2ecf20Sopenharmony_ci	if (!pfp) {
1448c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: unable to get primary fsh\n");
1458c2ecf20Sopenharmony_ci		goto out_free_sfp;
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci#ifdef DIAGNOSTIC
1498c2ecf20Sopenharmony_ci	vxfs_dumpfsh(pfp);
1508c2ecf20Sopenharmony_ci#endif
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext,
1538c2ecf20Sopenharmony_ci			fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
1548c2ecf20Sopenharmony_ci	if (!infp->vsi_stilist) {
1558c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
1568c2ecf20Sopenharmony_ci		goto out_free_pfp;
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
1598c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n",
1608c2ecf20Sopenharmony_ci				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK);
1618c2ecf20Sopenharmony_ci		goto out_iput_stilist;
1628c2ecf20Sopenharmony_ci	}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
1658c2ecf20Sopenharmony_ci	if (!infp->vsi_ilist) {
1668c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
1678c2ecf20Sopenharmony_ci		goto out_iput_stilist;
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
1708c2ecf20Sopenharmony_ci		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
1718c2ecf20Sopenharmony_ci				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
1728c2ecf20Sopenharmony_ci		goto out_iput_ilist;
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	kfree(pfp);
1768c2ecf20Sopenharmony_ci	kfree(sfp);
1778c2ecf20Sopenharmony_ci	return 0;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci out_iput_ilist:
1808c2ecf20Sopenharmony_ci 	iput(infp->vsi_ilist);
1818c2ecf20Sopenharmony_ci out_iput_stilist:
1828c2ecf20Sopenharmony_ci 	iput(infp->vsi_stilist);
1838c2ecf20Sopenharmony_ci out_free_pfp:
1848c2ecf20Sopenharmony_ci	kfree(pfp);
1858c2ecf20Sopenharmony_ci out_free_sfp:
1868c2ecf20Sopenharmony_ci 	kfree(sfp);
1878c2ecf20Sopenharmony_ci out_iput_fship:
1888c2ecf20Sopenharmony_ci	iput(infp->vsi_fship);
1898c2ecf20Sopenharmony_ci	return -EINVAL;
1908c2ecf20Sopenharmony_ci}
191