/*
 * osi_sysctl.c: Linux sysctl interface to OpenAFS
 *
 * $Id$
 *
 * Written Jan 30, 2002 by Kris Van Hees (Sine Nomine Associates)
 */

#include <afsconfig.h>
#include "afs/param.h"

#include "afs/sysincludes.h"	/* Standard vendor system headers */
#include "afsincludes.h"	/* Afs-based standard headers */
#include "afs/afs_stats.h"	/* afs statistics */

#include <linux/sysctl.h>
#ifdef HAVE_LINUX_CONFIG_H
#include <linux/config.h>
#endif

/* From afs_util.c */
extern afs_int32 afs_md5inum;

/* From afs_analyze.c */
extern afs_int32 hm_retry_RO;
extern afs_int32 hm_retry_RW;
extern afs_int32 hm_retry_int;
extern afs_int32 afs_blocksUsed_0;
extern afs_int32 afs_blocksUsed_1;
extern afs_int32 afs_blocksUsed_2;
extern afs_int32 afs_pct1;
extern afs_int32 afs_pct2;

#ifdef CONFIG_SYSCTL
static struct ctl_table_header *afs_sysctl = NULL;

static struct ctl_table afs_sysctl_table[] = {
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 1,
#endif
#endif
	.procname	= "hm_retry_RO",
	.data		= &hm_retry_RO,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 2,
#endif
#endif
	.procname	= "hm_retry_RW",
	.data		= &hm_retry_RW,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 3,
#endif
#endif
	.procname	= "hm_retry_int",
	.data		= &hm_retry_int,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 4,
#endif
#endif
	.procname	= "GCPAGs",
	.data		= &afs_gcpags,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 5,
#endif
#endif
	.procname	= "rx_deadtime",
	.data		= &afs_rx_deadtime,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 6,
#endif
#endif
	.procname	= "bkVolPref",
	.data		= &afs_bkvolpref,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 7,
#endif
#endif
	.procname	= "afs_blocksUsed",
	.data		= &afs_blocksUsed,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0444,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 8,
#endif
#endif
	.procname	= "afs_blocksUsed_0",
	.data		= &afs_blocksUsed_0,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 9,
#endif
#endif
	.procname	= "afs_blocksUsed_1",
	.data		= &afs_blocksUsed_1,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 10,
#endif
#endif
	.procname	= "afs_blocksUsed_2",
	.data		= &afs_blocksUsed_2,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 11,
#endif
#endif
	.procname	= "afs_pct1",
	.data		= &afs_pct1,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 12,
#endif
#endif
	.procname	= "afs_pct2",
	.data		= &afs_pct2,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler   = &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 13,
#endif
#endif
	.procname	= "afs_cacheBlocks",
	.data		= &afs_cacheBlocks,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 14,
#endif
#endif
	.procname	= "md5inum",
	.data		= &afs_md5inum,
	.maxlen		= sizeof(afs_int32),
	.mode		= 0644,
	.proc_handler	= &proc_dointvec
    },
    {
	.procname	= 0
    }
};

static struct ctl_table fs_sysctl_table[] = {
    {
#if defined(STRUCT_CTL_TABLE_HAS_CTL_NAME)
#if defined(CTL_UNNUMBERED)
	.ctl_name	= CTL_UNNUMBERED,
#else
	.ctl_name	= 1,
#endif
#endif
	.procname	= "afs",
	.mode		= 0555,
	.child		= afs_sysctl_table
    },
    {
	.procname	= 0
    }
};

int
osi_sysctl_init()
{
#if defined(REGISTER_SYSCTL_TABLE_NOFLAG)
    afs_sysctl = register_sysctl_table(fs_sysctl_table);
#else
    afs_sysctl = register_sysctl_table(fs_sysctl_table, 0);
#endif
    if (!afs_sysctl)
	return -1;

    return 0;
}

void
osi_sysctl_clean()
{
    if (afs_sysctl) {
	unregister_sysctl_table(afs_sysctl);
	afs_sysctl = NULL;
    }
}

#endif /* CONFIG_SYSCTL */
