/*
 * 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 "xfs.h"
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_log.h"
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_bmap_btree.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_utils.h"
#include "xfs_error.h"

#ifdef DEBUG

int	xfs_etrap[XFS_ERROR_NTRAP] = {
	0,
};

int
xfs_error_trap(int e)
{
	int i;

	if (!e)
		return 0;
	for (i = 0; i < XFS_ERROR_NTRAP; i++) {
		if (xfs_etrap[i] == 0)
			break;
		if (e != xfs_etrap[i])
			continue;
		cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
		BUG();
		break;
	}
	return e;
}
#endif

#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))

int	xfs_etest[XFS_NUM_INJECT_ERROR];
int64_t	xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
char *	xfs_etest_fsname[XFS_NUM_INJECT_ERROR];

void
xfs_error_test_init(void)
{
	memset(xfs_etest, 0, sizeof(xfs_etest));
	memset(xfs_etest_fsid, 0, sizeof(xfs_etest_fsid));
	memset(xfs_etest_fsname, 0, sizeof(xfs_etest_fsname));
}

int
xfs_error_test(int error_tag, int *fsidp, char *expression,
	       int line, char *file, unsigned long randfactor)
{
	int i;
	int64_t fsid;

	if (random() % randfactor)
		return 0;

	memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));

	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
		if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
			cmn_err(CE_WARN,
	"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
				expression, file, line, xfs_etest_fsname[i]);
			return 1;
		}
	}

	return 0;
}

int
xfs_errortag_add(int error_tag, xfs_mount_t *mp)
{
	int i;
	int len;
	int64_t fsid;

	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));

	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
			cmn_err(CE_WARN, "XFS error tag #%d on", error_tag);
			return 0;
		}
	}

	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
		if (xfs_etest[i] == 0) {
			cmn_err(CE_WARN, "Turned on XFS error tag #%d",
				error_tag);
			xfs_etest[i] = error_tag;
			xfs_etest_fsid[i] = fsid;
			len = strlen(mp->m_fsname);
			xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
			strcpy(xfs_etest_fsname[i], mp->m_fsname);
			return 0;
		}
	}

	cmn_err(CE_WARN, "error tag overflow, too many turned on");

	return 1;
}

int
xfs_errortag_clear(int error_tag, xfs_mount_t *mp)
{
	int i;
	int64_t fsid;

	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));

	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
			xfs_etest[i] = 0;
			xfs_etest_fsid[i] = 0LL;
			kmem_free(xfs_etest_fsname[i],
				  strlen(xfs_etest_fsname[i]) + 1);
			xfs_etest_fsname[i] = NULL;
			cmn_err(CE_WARN, "Cleared XFS error tag #%d",
				error_tag);
			return 0;
		}
	}

	cmn_err(CE_WARN, "XFS error tag %d not on", error_tag);

	return 1;
}

int
xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
{
	int i;
	int cleared = 0;

	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
		if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
		     xfs_etest[i] != 0) {
			cleared = 1;
			cmn_err(CE_WARN, "Clearing XFS error tag #%d",
				xfs_etest[i]);
			xfs_etest[i] = 0;
			xfs_etest_fsid[i] = 0LL;
			kmem_free(xfs_etest_fsname[i],
				  strlen(xfs_etest_fsname[i]) + 1);
			xfs_etest_fsname[i] = NULL;
		}
	}

	if (loud || cleared)
		cmn_err(CE_WARN,
			"Cleared all XFS error tags for filesystem \"%s\"",
			fsname);

	return 0;
}

int
xfs_errortag_clearall(xfs_mount_t *mp)
{
	int64_t fsid;

	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));

	return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1);
}
#endif /* DEBUG || INDUCE_IO_ERROR */

static void
xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
{
	if (mp != NULL) {
		char	*newfmt;
		int	len = 16 + mp->m_fsname_len + strlen(fmt);

		newfmt = kmem_alloc(len, KM_SLEEP);
		sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
		icmn_err(level, newfmt, ap);
		kmem_free(newfmt, len);
	} else {
		icmn_err(level, fmt, ap);
	}
}

void
xfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	xfs_fs_vcmn_err(level, mp, fmt, ap);
	va_end(ap);
}

void
xfs_cmn_err(int panic_tag, int level, xfs_mount_t *mp, char *fmt, ...)
{
	va_list ap;

#ifdef DEBUG
	xfs_panic_mask |= XFS_PTAG_SHUTDOWN_CORRUPT;
#endif

	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)
	    && (level & CE_ALERT)) {
		level &= ~CE_ALERT;
		level |= CE_PANIC;
		cmn_err(CE_ALERT, "XFS: Transforming an alert into a BUG.");
	}
	va_start(ap, fmt);
	xfs_fs_vcmn_err(level, mp, fmt, ap);
	va_end(ap);
}

void
xfs_error_report(
	char		*tag,
	int		level,
	xfs_mount_t	*mp,
	char		*fname,
	int		linenum,
	inst_t		*ra)
{
	if (level <= xfs_error_level) {
		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
			    CE_ALERT, mp,
		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
			    tag, linenum, fname, ra);

		xfs_stack_trace();
	}
}

STATIC void
xfs_hex_dump(void *p, int length)
{
	__uint8_t *uip = (__uint8_t*)p;
	int	i;
	char	sbuf[128], *s;

	s = sbuf;
	*s = '\0';
	for (i=0; i<length; i++, uip++) {
		if ((i % 16) == 0) {
			if (*s != '\0')
				cmn_err(CE_ALERT, "%s\n", sbuf);
			s = sbuf;
			sprintf(s, "0x%x: ", i);
			while( *s != '\0')
				s++;
		}
		sprintf(s, "%02x ", *uip);

		/*
		 * the kernel sprintf is a void; user sprintf returns
		 * the sprintf'ed string's length.  Find the new end-
		 * of-string
		 */
		while( *s != '\0')
			s++;
	}
	cmn_err(CE_ALERT, "%s\n", sbuf);
}

void
xfs_corruption_error(
	char		*tag,
	int		level,
	xfs_mount_t	*mp,
	void		*p,
	char		*fname,
	int		linenum,
	inst_t		*ra)
{
	if (level <= xfs_error_level)
		xfs_hex_dump(p, 16);
	xfs_error_report(tag, level, mp, fname, linenum, ra);
}
