forked from Minki/linux
c42b729ef6
- Instantiate glocks ouside of the glock state engine, in the contect of the process taking the glock. This moves unnecessary complexity out of the core glock code. Clean up the instantiate logic to be more sensible. - In gfs2_glock_async_wait(), cancel pending locking request upon failure. Make sure all glocks are left in a consistent state. - Various other minor cleanups and fixes. -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEJZs3krPW0xkhLMTc1b+f6wMTZToFAmLtdg8UHGFncnVlbmJh QHJlZGhhdC5jb20ACgkQ1b+f6wMTZTrqvA//WRdBtVgT7/5pkjljRolkBZ8B3sYx T2KlHuiQdvnTGf2dWnOOoUzEZvPXPUovUZMA4dHx0jcRpOi4BsYGz986K/Zpq5hs vieFEoKQdWk9O9NoNdRJN8Rl1tHTwejZi+kLerhYoJzgMC8AvgieLGO0Ol4Y0joc lxop/8L1Tn2GiCN4NcBN7Eg2CC4ke58KZcMgWhWVBR2ZJe9/qdqlVEiehiSbCiiN l89vsYLrG6bMylvNPc+AiyEvIGF5qkEHAErPIs7SfrjNRRWVhkmvTCWAO6JnehTQ XwqYQiAWCXfxBXUYG1VSCgjmTynmO2yg1Slt+86OauI9ka+ow8epSmHh95TT1JcY pmVF6CYhLI49dNl3R68CFlQ+Ov6iGt6gx9KEud5oE/Ew0vd/WIyi2/jSGrX59S07 zktMzEDjn31+jw31Raxc6+TQEU+0jQHCwzKWjbJ0tYy3nBdkCyefHwm199Ff40M/ 6jHWaH/qcyuq8crrc8PLSJOguSd7FdfdFhXEmpaH2CPybvfuEVJfig4vYee3YtSx KtZvgpy3bxBCfBDD7CPKfKMLrKrklYH+h7/lhCxbuSH0HvyS0ayXhmSvhXgfn+4e uWY5yk7gHAaaKGOBkkYwFAWV7X32LS0ndWzI8Ac8m20ifV0eeveRNEX0A/fHIX2U DlbhYq889mc2P70= =qFus -----END PGP SIGNATURE----- Merge tag 'gfs2-v5.19-rc4-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2 Pull gfs2 updates from Andreas Gruenbacher: - Instantiate glocks ouside of the glock state engine, in the contect of the process taking the glock. This moves unnecessary complexity out of the core glock code. Clean up the instantiate logic to be more sensible. - In gfs2_glock_async_wait(), cancel pending locking request upon failure. Make sure all glocks are left in a consistent state. - Various other minor cleanups and fixes. * tag 'gfs2-v5.19-rc4-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: List traversal in do_promote is safe gfs2: do_promote glock holder stealing fix gfs2: Use better variable name gfs2: Make go_instantiate take a glock gfs2: Add new go_held glock operation gfs2: Revert 'Fix "truncate in progress" hang' gfs2: Instantiate glocks ouside of glock state engine gfs2: Fix up gfs2_glock_async_wait gfs2: Minor gfs2_glock_nq_m cleanup gfs2: Fix spelling mistake in comment gfs2: Rewrap overlong comment in do_promote gfs2: Remove redundant NULL check before kfree
264 lines
6.1 KiB
C
264 lines
6.1 KiB
C
// 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_MEM_SPREAD|
|
|
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 = register_shrinker(&gfs2_qd_shrinker, "gfs2-qd");
|
|
if (error)
|
|
goto fail_shrinker;
|
|
|
|
error = register_filesystem(&gfs2_fs_type);
|
|
if (error)
|
|
goto fail_fs1;
|
|
|
|
error = register_filesystem(&gfs2meta_fs_type);
|
|
if (error)
|
|
goto fail_fs2;
|
|
|
|
error = -ENOMEM;
|
|
gfs_recovery_wq = alloc_workqueue("gfs_recovery",
|
|
WQ_MEM_RECLAIM | WQ_FREEZABLE, 0);
|
|
if (!gfs_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("freeze_workqueue", 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();
|
|
|
|
pr_info("GFS2 installed\n");
|
|
|
|
return 0;
|
|
|
|
fail_mempool:
|
|
destroy_workqueue(gfs2_freeze_wq);
|
|
fail_wq3:
|
|
destroy_workqueue(gfs2_control_wq);
|
|
fail_wq2:
|
|
destroy_workqueue(gfs_recovery_wq);
|
|
fail_wq1:
|
|
unregister_filesystem(&gfs2meta_fs_type);
|
|
fail_fs2:
|
|
unregister_filesystem(&gfs2_fs_type);
|
|
fail_fs1:
|
|
unregister_shrinker(&gfs2_qd_shrinker);
|
|
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)
|
|
{
|
|
unregister_shrinker(&gfs2_qd_shrinker);
|
|
gfs2_glock_exit();
|
|
gfs2_unregister_debugfs();
|
|
unregister_filesystem(&gfs2_fs_type);
|
|
unregister_filesystem(&gfs2meta_fs_type);
|
|
destroy_workqueue(gfs_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);
|
|
|