// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gfs2_ondisk.h>
#include <linux/rcupdate.h>
#include <linux/rculist_bl.h>
#include <linux/atomic.h>
#include <linux/mempool.h>

#include "gfs2.h"
#include "incore.h"
#include "super.h"
#include "sys.h"
#include "util.h"
#include "glock.h"
#include "quota.h"
#include "recovery.h"
#include "dir.h"
#include "glops.h"

struct workqueue_struct *gfs2_control_wq;

static void gfs2_init_inode_once(void *foo)
{
	struct gfs2_inode *ip = foo;

	inode_init_once(&ip->i_inode);
	atomic_set(&ip->i_sizehint, 0);
	init_rwsem(&ip->i_rw_mutex);
	INIT_LIST_HEAD(&ip->i_ordered);
	ip->i_qadata = NULL;
	gfs2_holder_mark_uninitialized(&ip->i_rgd_gh);
	memset(&ip->i_res, 0, sizeof(ip->i_res));
	RB_CLEAR_NODE(&ip->i_res.rs_node);
	ip->i_hash_cache = NULL;
	gfs2_holder_mark_uninitialized(&ip->i_iopen_gh);
}

static void gfs2_init_glock_once(void *foo)
{
	struct gfs2_glock *gl = foo;

	spin_lock_init(&gl->gl_lockref.lock);
	INIT_LIST_HEAD(&gl->gl_holders);
	INIT_LIST_HEAD(&gl->gl_lru);
	INIT_LIST_HEAD(&gl->gl_ail_list);
	atomic_set(&gl->gl_ail_count, 0);
	atomic_set(&gl->gl_revokes, 0);
}

static void gfs2_init_gl_aspace_once(void *foo)
{
	struct gfs2_glock_aspace *gla = foo;

	gfs2_init_glock_once(&gla->glock);
	address_space_init_once(&gla->mapping);
}

/**
 * init_gfs2_fs - Register GFS2 as a filesystem
 *
 * Returns: 0 on success, error code on failure
 */

static int __init init_gfs2_fs(void)
{
	int error;

	gfs2_str2qstr(&gfs2_qdot, ".");
	gfs2_str2qstr(&gfs2_qdotdot, "..");
	gfs2_quota_hash_init();

	error = gfs2_sys_init();
	if (error)
		return error;

	error = list_lru_init(&gfs2_qd_lru);
	if (error)
		goto fail_lru;

	error = gfs2_glock_init();
	if (error)
		goto fail_glock;

	error = -ENOMEM;
	gfs2_glock_cachep = kmem_cache_create("gfs2_glock",
					      sizeof(struct gfs2_glock),
					      0, SLAB_RECLAIM_ACCOUNT,
					      gfs2_init_glock_once);
	if (!gfs2_glock_cachep)
		goto fail_cachep1;

	gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock(aspace)",
					sizeof(struct gfs2_glock_aspace),
					0, 0, gfs2_init_gl_aspace_once);

	if (!gfs2_glock_aspace_cachep)
		goto fail_cachep2;

	gfs2_inode_cachep = kmem_cache_create("gfs2_inode",
					      sizeof(struct gfs2_inode),
					      0,  SLAB_RECLAIM_ACCOUNT|
						  SLAB_ACCOUNT,
					      gfs2_init_inode_once);
	if (!gfs2_inode_cachep)
		goto fail_cachep3;

	gfs2_bufdata_cachep = kmem_cache_create("gfs2_bufdata",
						sizeof(struct gfs2_bufdata),
					        0, 0, NULL);
	if (!gfs2_bufdata_cachep)
		goto fail_cachep4;

	gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd",
					      sizeof(struct gfs2_rgrpd),
					      0, 0, NULL);
	if (!gfs2_rgrpd_cachep)
		goto fail_cachep5;

	gfs2_quotad_cachep = kmem_cache_create("gfs2_quotad",
					       sizeof(struct gfs2_quota_data),
					       0, SLAB_RECLAIM_ACCOUNT, NULL);
	if (!gfs2_quotad_cachep)
		goto fail_cachep6;

	gfs2_qadata_cachep = kmem_cache_create("gfs2_qadata",
					       sizeof(struct gfs2_qadata),
					       0, 0, NULL);
	if (!gfs2_qadata_cachep)
		goto fail_cachep7;

	gfs2_trans_cachep = kmem_cache_create("gfs2_trans",
					       sizeof(struct gfs2_trans),
					       0, 0, NULL);
	if (!gfs2_trans_cachep)
		goto fail_cachep8;

	error = gfs2_qd_shrinker_init();
	if (error)
		goto fail_shrinker;

	error = -ENOMEM;
	gfs2_recovery_wq = alloc_workqueue("gfs2_recovery",
					  WQ_MEM_RECLAIM | WQ_FREEZABLE, 0);
	if (!gfs2_recovery_wq)
		goto fail_wq1;

	gfs2_control_wq = alloc_workqueue("gfs2_control",
					  WQ_UNBOUND | WQ_FREEZABLE, 0);
	if (!gfs2_control_wq)
		goto fail_wq2;

	gfs2_freeze_wq = alloc_workqueue("gfs2_freeze", 0, 0);

	if (!gfs2_freeze_wq)
		goto fail_wq3;

	gfs2_page_pool = mempool_create_page_pool(64, 0);
	if (!gfs2_page_pool)
		goto fail_mempool;

	gfs2_register_debugfs();
	error = register_filesystem(&gfs2_fs_type);
	if (error)
		goto fail_fs1;

	error = register_filesystem(&gfs2meta_fs_type);
	if (error)
		goto fail_fs2;


	pr_info("GFS2 installed\n");

	return 0;

fail_fs2:
	unregister_filesystem(&gfs2_fs_type);
fail_fs1:
	mempool_destroy(gfs2_page_pool);
fail_mempool:
	destroy_workqueue(gfs2_freeze_wq);
fail_wq3:
	destroy_workqueue(gfs2_control_wq);
fail_wq2:
	destroy_workqueue(gfs2_recovery_wq);
fail_wq1:
	gfs2_qd_shrinker_exit();
fail_shrinker:
	kmem_cache_destroy(gfs2_trans_cachep);
fail_cachep8:
	kmem_cache_destroy(gfs2_qadata_cachep);
fail_cachep7:
	kmem_cache_destroy(gfs2_quotad_cachep);
fail_cachep6:
	kmem_cache_destroy(gfs2_rgrpd_cachep);
fail_cachep5:
	kmem_cache_destroy(gfs2_bufdata_cachep);
fail_cachep4:
	kmem_cache_destroy(gfs2_inode_cachep);
fail_cachep3:
	kmem_cache_destroy(gfs2_glock_aspace_cachep);
fail_cachep2:
	kmem_cache_destroy(gfs2_glock_cachep);
fail_cachep1:
	gfs2_glock_exit();
fail_glock:
	list_lru_destroy(&gfs2_qd_lru);
fail_lru:
	gfs2_sys_uninit();
	return error;
}

/**
 * exit_gfs2_fs - Unregister the file system
 *
 */

static void __exit exit_gfs2_fs(void)
{
	gfs2_qd_shrinker_exit();
	gfs2_glock_exit();
	gfs2_unregister_debugfs();
	unregister_filesystem(&gfs2_fs_type);
	unregister_filesystem(&gfs2meta_fs_type);
	destroy_workqueue(gfs2_recovery_wq);
	destroy_workqueue(gfs2_control_wq);
	destroy_workqueue(gfs2_freeze_wq);
	list_lru_destroy(&gfs2_qd_lru);

	rcu_barrier();

	mempool_destroy(gfs2_page_pool);
	kmem_cache_destroy(gfs2_trans_cachep);
	kmem_cache_destroy(gfs2_qadata_cachep);
	kmem_cache_destroy(gfs2_quotad_cachep);
	kmem_cache_destroy(gfs2_rgrpd_cachep);
	kmem_cache_destroy(gfs2_bufdata_cachep);
	kmem_cache_destroy(gfs2_inode_cachep);
	kmem_cache_destroy(gfs2_glock_aspace_cachep);
	kmem_cache_destroy(gfs2_glock_cachep);

	gfs2_sys_uninit();
}

MODULE_DESCRIPTION("Global File System");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");

module_init(init_gfs2_fs);
module_exit(exit_gfs2_fs);

