/*
 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <libxfs.h>
#include "globals.h"
#include "agheader.h"
#include "protos.h"
#include "err_protos.h"

int
verify_set_agf(xfs_mount_t *mp, xfs_agf_t *agf, xfs_agnumber_t i)
{
	xfs_drfsbno_t agblocks;
	int retval = 0;

	/* check common fields */

	if (be32_to_cpu(agf->agf_magicnum) != XFS_AGF_MAGIC)  {
		retval = XR_AG_AGF;
		do_warn(_("bad magic # 0x%x for agf %d\n"),
			be32_to_cpu(agf->agf_magicnum), i);

		if (!no_modify)
			agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
	}

	if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)))  {
		retval = XR_AG_AGF;
		do_warn(_("bad version # %d for agf %d\n"),
			be32_to_cpu(agf->agf_versionnum), i);

		if (!no_modify)
			agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
	}

	if (be32_to_cpu(agf->agf_seqno) != i)  {
		retval = XR_AG_AGF;
		do_warn(_("bad sequence # %d for agf %d\n"),
			be32_to_cpu(agf->agf_seqno), i);

		if (!no_modify)
			agf->agf_seqno = cpu_to_be32(i);
	}

	if (be32_to_cpu(agf->agf_length) != mp->m_sb.sb_agblocks)  {
		if (i != mp->m_sb.sb_agcount - 1)  {
			retval = XR_AG_AGF;
			do_warn(_("bad length %d for agf %d, should be %d\n"),
				be32_to_cpu(agf->agf_length), i,
				mp->m_sb.sb_agblocks);
			if (!no_modify)
				agf->agf_length = 
					cpu_to_be32(mp->m_sb.sb_agblocks);
		} else  {
			agblocks = mp->m_sb.sb_dblocks -
				(xfs_drfsbno_t) mp->m_sb.sb_agblocks * i;

			if (be32_to_cpu(agf->agf_length) != agblocks)  {
				retval = XR_AG_AGF;
				do_warn(
			_("bad length %d for agf %d, should be %llu\n"),
					be32_to_cpu(agf->agf_length),
						i, agblocks);
				if (!no_modify)
					agf->agf_length = cpu_to_be32(agblocks);
			}
		}
	}

	/*
	 * check first/last AGF fields.  if need be, lose the free
	 * space in the AGFL, we'll reclaim it later.
	 */
	if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp))  {
		do_warn(_("flfirst %d in agf %d too large (max = %d)\n"),
			be32_to_cpu(agf->agf_flfirst), i, XFS_AGFL_SIZE(mp));
		if (!no_modify)
			agf->agf_flfirst = cpu_to_be32(0);
	}

	if (be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp))  {
		do_warn(_("fllast %d in agf %d too large (max = %d)\n"),
			be32_to_cpu(agf->agf_fllast), i, XFS_AGFL_SIZE(mp));
		if (!no_modify)
			agf->agf_fllast = cpu_to_be32(0);
	}

	/* don't check freespace btrees -- will be checked by caller */

	return(retval);
}

int
verify_set_agi(xfs_mount_t *mp, xfs_agi_t *agi, xfs_agnumber_t agno)
{
	xfs_drfsbno_t agblocks;
	int retval = 0;

	/* check common fields */

	if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC)  {
		retval = XR_AG_AGI;
		do_warn(_("bad magic # 0x%x for agi %d\n"),
			be32_to_cpu(agi->agi_magicnum), agno);

		if (!no_modify)
			agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
	}

	if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)))  {
		retval = XR_AG_AGI;
		do_warn(_("bad version # %d for agi %d\n"),
			be32_to_cpu(agi->agi_versionnum), agno);

		if (!no_modify)
			agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
	}

	if (be32_to_cpu(agi->agi_seqno) != agno)  {
		retval = XR_AG_AGI;
		do_warn(_("bad sequence # %d for agi %d\n"),
			be32_to_cpu(agi->agi_seqno), agno);

		if (!no_modify)
			agi->agi_seqno = cpu_to_be32(agno);
	}

	if (be32_to_cpu(agi->agi_length) != mp->m_sb.sb_agblocks)  {
		if (agno != mp->m_sb.sb_agcount - 1)  {
			retval = XR_AG_AGI;
			do_warn(_("bad length # %d for agi %d, should be %d\n"),
				be32_to_cpu(agi->agi_length), agno,
					mp->m_sb.sb_agblocks);
			if (!no_modify)
				agi->agi_length = 
					cpu_to_be32(mp->m_sb.sb_agblocks);
		} else  {
			agblocks = mp->m_sb.sb_dblocks -
				(xfs_drfsbno_t) mp->m_sb.sb_agblocks * agno;

			if (be32_to_cpu(agi->agi_length) != agblocks)  {
				retval = XR_AG_AGI;
				do_warn(
			_("bad length # %d for agi %d, should be %llu\n"),
					be32_to_cpu(agi->agi_length),
						agno, agblocks);
				if (!no_modify)
					agi->agi_length = cpu_to_be32(agblocks);
			}
		}
	}

	/* don't check inode btree -- will be checked by caller */

	return(retval);
}

/*
 * superblock comparison - compare arbitrary superblock with
 *			filesystem mount-point superblock
 *
 * the verified fields include id and geometry.

 * the inprogress fields, version numbers, and counters
 * are allowed to differ as well as all fields after the
 * counters to cope with the pre-6.5 mkfs non-zeroed
 * secondary superblock sectors.
 */

int
compare_sb(xfs_mount_t *mp, xfs_sb_t *sb)
{
	fs_geometry_t fs_geo, sb_geo;

	get_sb_geometry(&fs_geo, &mp->m_sb);
	get_sb_geometry(&sb_geo, sb);

	if (memcmp(&fs_geo, &sb_geo,
		   (char *) &fs_geo.sb_shared_vn - (char *) &fs_geo))
		return(XR_SB_GEO_MISMATCH);

	return(XR_OK);
}

/*
 * Possible fields that may have been set at mkfs time,
 * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
 * The quota inode fields in the secondaries should be zero.
 * Likewise, the sb_flags and sb_shared_vn should also be
 * zero and the shared version bit should be cleared for
 * current mkfs's.
 *
 * And everything else in the buffer beyond either sb_width,
 * sb_dirblklog (v2 dirs), or sb_logsectsize can be zeroed.
 *
 * Note: contrary to the name, this routine is called for all
 * superblocks, not just the secondary superblocks.
 */
int
secondary_sb_wack(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb,
	xfs_agnumber_t i)
{
	int do_bzero;
	int size;
	char *ip;
	int rval;

	rval = do_bzero = 0;

	/*
	 * mkfs's that stamped a feature bit besides the ones in the mask
	 * (e.g. were pre-6.5 beta) could leave garbage in the secondary
	 * superblock sectors.  Anything stamping the shared fs bit or better
	 * into the secondaries is ok and should generate clean secondary
	 * superblock sectors.  so only run the zero check on the
	 * potentially garbaged secondaries.
	 */
	if (pre_65_beta ||
	    (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK) == 0 ||
	    sb->sb_versionnum < XFS_SB_VERSION_4)  {
		/*
		 * Check for garbage beyond the last field.
		 * Use field addresses instead so this code will still
		 * work against older filesystems when the superblock
		 * gets rev'ed again with new fields appended.
		 */
		if (xfs_sb_version_hasmorebits(sb))
			size = (__psint_t)&sb->sb_features2
				+ sizeof(sb->sb_features2) - (__psint_t)sb;
		else if (xfs_sb_version_haslogv2(sb))
			size = (__psint_t)&sb->sb_logsunit
				+ sizeof(sb->sb_logsunit) - (__psint_t)sb;
		else if (xfs_sb_version_hassector(sb))
			size = (__psint_t)&sb->sb_logsectsize
				+ sizeof(sb->sb_logsectsize) - (__psint_t)sb;
		else if (xfs_sb_version_hasdirv2(sb))
			size = (__psint_t)&sb->sb_dirblklog
				+ sizeof(sb->sb_dirblklog) - (__psint_t)sb;
		else
			size = (__psint_t)&sb->sb_width
				+ sizeof(sb->sb_width) - (__psint_t)sb;
		for (ip = (char *)((__psint_t)sb + size);
		     ip < (char *)((__psint_t)sb + mp->m_sb.sb_sectsize);
		     ip++)  {
			if (*ip)  {
				do_bzero = 1;
				break;
			}
		}

		if (do_bzero)  {
			rval |= XR_AG_SB_SEC;
			if (!no_modify)  {
				do_warn(
		_("zeroing unused portion of %s superblock (AG #%u)\n"),
					!i ? _("primary") : _("secondary"), i);
				memset((void *)((__psint_t)sb + size), 0,
					mp->m_sb.sb_sectsize - size);
			} else
				do_warn(
		_("would zero unused portion of %s superblock (AG #%u)\n"),
					!i ? _("primary") : _("secondary"), i);
		}
	}

	/*
	 * now look for the fields we can manipulate directly.
	 * if we did a zero and that zero could have included
	 * the field in question, just silently reset it.  otherwise,
	 * complain.
	 *
	 * for now, just zero the flags field since only
	 * the readonly flag is used
	 */
	if (sb->sb_flags)  {
		if (!no_modify)
			sb->sb_flags = 0;
		if (sb->sb_versionnum & XR_PART_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(_("bad flags field in superblock %d\n"), i);
		} else
			rval |= XR_AG_SB_SEC;
	}

	/*
	 * quota inodes and flags in secondary superblocks
	 * are never set by mkfs.  However, they could be set
	 * in a secondary if a fs with quotas was growfs'ed since
	 * growfs copies the new primary into the secondaries.
	 */
	if (sb->sb_inprogress == 1 && sb->sb_uquotino)  {
		if (!no_modify)
			sb->sb_uquotino = 0;
		if (sb->sb_versionnum & XR_PART_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(
		_("non-null user quota inode field in superblock %d\n"),
				i);

		} else
			rval |= XR_AG_SB_SEC;
	}

	if (sb->sb_inprogress == 1 && sb->sb_gquotino)  {
		if (!no_modify)
			sb->sb_gquotino = 0;
		if (sb->sb_versionnum & XR_PART_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(
		_("non-null group quota inode field in superblock %d\n"),
				i);

		} else
			rval |= XR_AG_SB_SEC;
	}

	if (sb->sb_inprogress == 1 && sb->sb_qflags)  {
		if (!no_modify)
			sb->sb_qflags = 0;
		if (sb->sb_versionnum & XR_PART_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(_("non-null quota flags in superblock %d\n"),
				i);
		} else
			rval |= XR_AG_SB_SEC;
	}

	/*
	 * if the secondaries agree on a stripe unit/width or inode
	 * alignment, those fields ought to be valid since they are
	 * written at mkfs time (and the corresponding sb version bits
	 * are set).
	 */
	if (!xfs_sb_version_hasshared(sb) && sb->sb_shared_vn != 0)  {
		if (!no_modify)
			sb->sb_shared_vn = 0;
		if (sb->sb_versionnum & XR_PART_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(
		_("bad shared version number in superblock %d\n"),
				i);
		} else
			rval |= XR_AG_SB_SEC;
	}

	if (!xfs_sb_version_hasalign(sb) && sb->sb_inoalignmt != 0)  {
		if (!no_modify)
			sb->sb_inoalignmt = 0;
		if (sb->sb_versionnum & XR_PART_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(
		_("bad inode alignment field in superblock %d\n"),
				i);
		} else
			rval |= XR_AG_SB_SEC;
	}

	if (!xfs_sb_version_hasdalign(sb) &&
	    (sb->sb_unit != 0 || sb->sb_width != 0))  {
		if (!no_modify)
			sb->sb_unit = sb->sb_width = 0;
		if (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(
		_("bad stripe unit/width fields in superblock %d\n"),
				i);
		} else
			rval |= XR_AG_SB_SEC;
	}

	if (!xfs_sb_version_hassector(sb) &&
	    (sb->sb_sectsize != BBSIZE || sb->sb_sectlog != BBSHIFT ||
	     sb->sb_logsectsize != 0 || sb->sb_logsectlog != 0))  {
		if (!no_modify)  {
			sb->sb_sectsize = BBSIZE;
			sb->sb_sectlog = BBSHIFT;
			sb->sb_logsectsize = 0;
			sb->sb_logsectlog = 0;
		}
		if (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK || !do_bzero)  {
			rval |= XR_AG_SB;
			do_warn(
		_("bad log/data device sector size fields in superblock %d\n"),
				i);
		} else
			rval |= XR_AG_SB_SEC;
	}

	return(rval);
}

/*
 * verify and reset the ag header if required.
 *
 * lower 4 bits of rval are set depending on what got modified.
 * (see agheader.h for more details)
 *
 * NOTE -- this routine does not tell the user that it has
 * altered things.  Rather, it is up to the caller to do so
 * using the bits encoded into the return value.
 */

int
verify_set_agheader(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb,
	xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i)
{
	int rval = 0;
	int status = XR_OK;
	int status_sb = XR_OK;

	status = verify_sb(sb, (i == 0));

	if (status != XR_OK)  {
		do_warn(_("bad on-disk superblock %d - %s\n"),
			i, err_string(status));
	}

	status_sb = compare_sb(mp, sb);

	if (status_sb != XR_OK)  {
		do_warn(_("primary/secondary superblock %d conflict - %s\n"),
			i, err_string(status_sb));
	}

	if (status != XR_OK || status_sb != XR_OK)  {
		if (!no_modify)  {
			*sb = mp->m_sb;

			/*
			 * clear the more transient fields
			 */
			sb->sb_inprogress = 1;

			sb->sb_icount = 0;
			sb->sb_ifree = 0;
			sb->sb_fdblocks = 0;
			sb->sb_frextents = 0;

			sb->sb_qflags = 0;
		}

		rval |= XR_AG_SB;
	}

	rval |= secondary_sb_wack(mp, sbuf, sb, i);

	rval |= verify_set_agf(mp, agf, i);
	rval |= verify_set_agi(mp, agi, i);

	return(rval);
}
