Commit 048bca22 authored by Steven Whitehouse's avatar Steven Whitehouse

[GFS2] No lock_nolock

This patch merges the lock_nolock module into GFS2 itself. As well as removing
some of the overhead of the module, it also means that its now impossible to
build GFS2 without a lock module (which would be a pointless thing to do
anyway).

We also plan to merge lock_dlm into GFS2 in the future, but that is a more
tricky task, and will therefore be a separate patch.
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
Cc: David Teigland <teigland@redhat.com>
parent f3c9d38a
...@@ -14,23 +14,11 @@ config GFS2_FS ...@@ -14,23 +14,11 @@ config GFS2_FS
GFS is perfect consistency -- changes made to the filesystem on one GFS is perfect consistency -- changes made to the filesystem on one
machine show up immediately on all other machines in the cluster. machine show up immediately on all other machines in the cluster.
To use the GFS2 filesystem, you will need to enable one or more of To use the GFS2 filesystem in a cluster, you will need to enable
the below locking modules. Documentation and utilities for GFS2 can the locking module below. Documentation and utilities for GFS2 can
be found here: http://sources.redhat.com/cluster be found here: http://sources.redhat.com/cluster
config GFS2_FS_LOCKING_NOLOCK The "nolock" lock module is now built in to GFS2 by default.
tristate "GFS2 \"nolock\" locking module"
depends on GFS2_FS
help
Single node locking module for GFS2.
Use this module if you want to use GFS2 on a single node without
its clustering features. You can still take advantage of the
large file support, and upgrade to running a full cluster later on
if required.
If you will only be using GFS2 in cluster mode, you do not need this
module.
config GFS2_FS_LOCKING_DLM config GFS2_FS_LOCKING_DLM
tristate "GFS2 DLM locking module" tristate "GFS2 DLM locking module"
......
...@@ -5,6 +5,5 @@ gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ ...@@ -5,6 +5,5 @@ gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
ops_fstype.o ops_inode.o ops_super.o quota.o \ ops_fstype.o ops_inode.o ops_super.o quota.o \
recovery.o rgrp.o super.o sys.o trans.o util.o recovery.o rgrp.o super.o sys.o trans.o util.o
obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/
obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += locking/dlm/ obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += locking/dlm/
...@@ -153,7 +153,7 @@ static void glock_free(struct gfs2_glock *gl) ...@@ -153,7 +153,7 @@ static void glock_free(struct gfs2_glock *gl)
struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_sbd *sdp = gl->gl_sbd;
struct inode *aspace = gl->gl_aspace; struct inode *aspace = gl->gl_aspace;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (sdp->sd_lockstruct.ls_ops->lm_put_lock)
sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock); sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock);
if (aspace) if (aspace)
...@@ -488,6 +488,10 @@ static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, ...@@ -488,6 +488,10 @@ static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
unsigned int flags) unsigned int flags)
{ {
int ret = LM_OUT_ERROR; int ret = LM_OUT_ERROR;
if (!sdp->sd_lockstruct.ls_ops->lm_lock)
return req_state == LM_ST_UNLOCKED ? 0 : req_state;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state, ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
req_state, flags); req_state, flags);
...@@ -631,6 +635,8 @@ static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name, ...@@ -631,6 +635,8 @@ static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
void **lockp) void **lockp)
{ {
int error = -EIO; int error = -EIO;
if (!sdp->sd_lockstruct.ls_ops->lm_get_lock)
return 0;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_get_lock( error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
sdp->sd_lockstruct.ls_lockspace, name, lockp); sdp->sd_lockstruct.ls_lockspace, name, lockp);
...@@ -910,7 +916,8 @@ do_cancel: ...@@ -910,7 +916,8 @@ do_cancel:
gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list); gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list);
if (!(gh->gh_flags & LM_FLAG_PRIORITY)) { if (!(gh->gh_flags & LM_FLAG_PRIORITY)) {
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock); if (sdp->sd_lockstruct.ls_ops->lm_cancel)
sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock);
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
} }
return; return;
...@@ -1187,6 +1194,8 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs) ...@@ -1187,6 +1194,8 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp) static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
{ {
int error = -EIO; int error = -EIO;
if (!sdp->sd_lockstruct.ls_ops->lm_hold_lvb)
return 0;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp); error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
return error; return error;
...@@ -1226,7 +1235,7 @@ void gfs2_lvb_unhold(struct gfs2_glock *gl) ...@@ -1226,7 +1235,7 @@ void gfs2_lvb_unhold(struct gfs2_glock *gl)
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0); gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
if (atomic_dec_and_test(&gl->gl_lvb_count)) { if (atomic_dec_and_test(&gl->gl_lvb_count)) {
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (sdp->sd_lockstruct.ls_ops->lm_unhold_lvb)
sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb); sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb);
gl->gl_lvb = NULL; gl->gl_lvb = NULL;
gfs2_glock_put(gl); gfs2_glock_put(gl);
......
...@@ -23,12 +23,54 @@ struct lmh_wrapper { ...@@ -23,12 +23,54 @@ struct lmh_wrapper {
const struct lm_lockops *lw_ops; const struct lm_lockops *lw_ops;
}; };
static int nolock_mount(char *table_name, char *host_data,
lm_callback_t cb, void *cb_data,
unsigned int min_lvb_size, int flags,
struct lm_lockstruct *lockstruct,
struct kobject *fskobj);
/* List of registered low-level locking protocols. A file system selects one /* List of registered low-level locking protocols. A file system selects one
of them by name at mount time, e.g. lock_nolock, lock_dlm. */ of them by name at mount time, e.g. lock_nolock, lock_dlm. */
static const struct lm_lockops nolock_ops = {
.lm_proto_name = "lock_nolock",
.lm_mount = nolock_mount,
};
static struct lmh_wrapper nolock_proto = {
.lw_list = LIST_HEAD_INIT(nolock_proto.lw_list),
.lw_ops = &nolock_ops,
};
static LIST_HEAD(lmh_list); static LIST_HEAD(lmh_list);
static DEFINE_MUTEX(lmh_lock); static DEFINE_MUTEX(lmh_lock);
static int nolock_mount(char *table_name, char *host_data,
lm_callback_t cb, void *cb_data,
unsigned int min_lvb_size, int flags,
struct lm_lockstruct *lockstruct,
struct kobject *fskobj)
{
char *c;
unsigned int jid;
c = strstr(host_data, "jid=");
if (!c)
jid = 0;
else {
c += 4;
sscanf(c, "%u", &jid);
}
lockstruct->ls_jid = jid;
lockstruct->ls_first = 1;
lockstruct->ls_lvb_size = min_lvb_size;
lockstruct->ls_ops = &nolock_ops;
lockstruct->ls_flags = LM_LSFLAG_LOCAL;
return 0;
}
/** /**
* gfs2_register_lockproto - Register a low-level locking protocol * gfs2_register_lockproto - Register a low-level locking protocol
* @proto: the protocol definition * @proto: the protocol definition
...@@ -116,9 +158,13 @@ int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data, ...@@ -116,9 +158,13 @@ int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
int try = 0; int try = 0;
int error, found; int error, found;
retry: retry:
mutex_lock(&lmh_lock); mutex_lock(&lmh_lock);
if (list_empty(&nolock_proto.lw_list))
list_add(&lmh_list, &nolock_proto.lw_list);
found = 0; found = 0;
list_for_each_entry(lw, &lmh_list, lw_list) { list_for_each_entry(lw, &lmh_list, lw_list) {
if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) { if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) {
...@@ -139,7 +185,8 @@ retry: ...@@ -139,7 +185,8 @@ retry:
goto out; goto out;
} }
if (!try_module_get(lw->lw_ops->lm_owner)) { if (lw->lw_ops->lm_owner &&
!try_module_get(lw->lw_ops->lm_owner)) {
try = 0; try = 0;
mutex_unlock(&lmh_lock); mutex_unlock(&lmh_lock);
msleep(1000); msleep(1000);
...@@ -158,7 +205,8 @@ out: ...@@ -158,7 +205,8 @@ out:
void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct) void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct)
{ {
mutex_lock(&lmh_lock); mutex_lock(&lmh_lock);
lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace); if (lockstruct->ls_ops->lm_unmount)
lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace);
if (lockstruct->ls_ops->lm_owner) if (lockstruct->ls_ops->lm_owner)
module_put(lockstruct->ls_ops->lm_owner); module_put(lockstruct->ls_ops->lm_owner);
mutex_unlock(&lmh_lock); mutex_unlock(&lmh_lock);
......
obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += lock_nolock.o
lock_nolock-y := main.o
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/lm_interface.h>
struct nolock_lockspace {
unsigned int nl_lvb_size;
};
static const struct lm_lockops nolock_ops;
static int nolock_mount(char *table_name, char *host_data,
lm_callback_t cb, void *cb_data,
unsigned int min_lvb_size, int flags,
struct lm_lockstruct *lockstruct,
struct kobject *fskobj)
{
char *c;
unsigned int jid;
struct nolock_lockspace *nl;
c = strstr(host_data, "jid=");
if (!c)
jid = 0;
else {
c += 4;
sscanf(c, "%u", &jid);
}
nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL);
if (!nl)
return -ENOMEM;
nl->nl_lvb_size = min_lvb_size;
lockstruct->ls_jid = jid;
lockstruct->ls_first = 1;
lockstruct->ls_lvb_size = min_lvb_size;
lockstruct->ls_lockspace = nl;
lockstruct->ls_ops = &nolock_ops;
lockstruct->ls_flags = LM_LSFLAG_LOCAL;
return 0;
}
static void nolock_others_may_mount(void *lockspace)
{
}
static void nolock_unmount(void *lockspace)
{
struct nolock_lockspace *nl = lockspace;
kfree(nl);
}
static void nolock_withdraw(void *lockspace)
{
}
/**
* nolock_get_lock - get a lm_lock_t given a descripton of the lock
* @lockspace: the lockspace the lock lives in
* @name: the name of the lock
* @lockp: return the lm_lock_t here
*
* Returns: 0 on success, -EXXX on failure
*/
static int nolock_get_lock(void *lockspace, struct lm_lockname *name,
void **lockp)
{
*lockp = lockspace;
return 0;
}
/**
* nolock_put_lock - get rid of a lock structure
* @lock: the lock to throw away
*
*/
static void nolock_put_lock(void *lock)
{
}
/**
* nolock_lock - acquire a lock
* @lock: the lock to manipulate
* @cur_state: the current state
* @req_state: the requested state
* @flags: modifier flags
*
* Returns: A bitmap of LM_OUT_*
*/
static unsigned int nolock_lock(void *lock, unsigned int cur_state,
unsigned int req_state, unsigned int flags)
{
if (req_state == LM_ST_UNLOCKED)
return 0;
return req_state | LM_OUT_CACHEABLE;
}
/**
* nolock_unlock - unlock a lock
* @lock: the lock to manipulate
* @cur_state: the current state
*
* Returns: 0
*/
static unsigned int nolock_unlock(void *lock, unsigned int cur_state)
{
return 0;
}
static void nolock_cancel(void *lock)
{
}
/**
* nolock_hold_lvb - hold on to a lock value block
* @lock: the lock the LVB is associated with
* @lvbp: return the lm_lvb_t here
*
* Returns: 0 on success, -EXXX on failure
*/
static int nolock_hold_lvb(void *lock, char **lvbp)
{
struct nolock_lockspace *nl = lock;
int error = 0;
*lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS);
if (!*lvbp)
error = -ENOMEM;
return error;
}
/**
* nolock_unhold_lvb - release a LVB
* @lock: the lock the LVB is associated with
* @lvb: the lock value block
*
*/
static void nolock_unhold_lvb(void *lock, char *lvb)
{
kfree(lvb);
}
static int nolock_plock_get(void *lockspace, struct lm_lockname *name,
struct file *file, struct file_lock *fl)
{
posix_test_lock(file, fl);
return 0;
}
static int nolock_plock(void *lockspace, struct lm_lockname *name,
struct file *file, int cmd, struct file_lock *fl)
{
int error;
error = posix_lock_file_wait(file, fl);
return error;
}
static int nolock_punlock(void *lockspace, struct lm_lockname *name,
struct file *file, struct file_lock *fl)
{
int error;
error = posix_lock_file_wait(file, fl);
return error;
}
static void nolock_recovery_done(void *lockspace, unsigned int jid,
unsigned int message)
{
}
static const struct lm_lockops nolock_ops = {
.lm_proto_name = "lock_nolock",
.lm_mount = nolock_mount,
.lm_others_may_mount = nolock_others_may_mount,
.lm_unmount = nolock_unmount,
.lm_withdraw = nolock_withdraw,
.lm_get_lock = nolock_get_lock,
.lm_put_lock = nolock_put_lock,
.lm_lock = nolock_lock,
.lm_unlock = nolock_unlock,
.lm_cancel = nolock_cancel,
.lm_hold_lvb = nolock_hold_lvb,
.lm_unhold_lvb = nolock_unhold_lvb,
.lm_plock_get = nolock_plock_get,
.lm_plock = nolock_plock,
.lm_punlock = nolock_punlock,
.lm_recovery_done = nolock_recovery_done,
.lm_owner = THIS_MODULE,
};
static int __init init_nolock(void)
{
int error;
error = gfs2_register_lockproto(&nolock_ops);
if (error) {
printk(KERN_WARNING
"lock_nolock: can't register protocol: %d\n", error);
return error;
}
printk(KERN_INFO
"Lock_Nolock (built %s %s) installed\n", __DATE__, __TIME__);
return 0;
}
static void __exit exit_nolock(void)
{
gfs2_unregister_lockproto(&nolock_ops);
}
module_init(init_nolock);
module_exit(exit_nolock);
MODULE_DESCRIPTION("GFS Nolock Locking Module");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");
...@@ -364,6 +364,8 @@ static int map_journal_extents(struct gfs2_sbd *sdp) ...@@ -364,6 +364,8 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp) static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
{ {
if (!sdp->sd_lockstruct.ls_ops->lm_others_may_mount)
return;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_others_may_mount( sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
sdp->sd_lockstruct.ls_lockspace); sdp->sd_lockstruct.ls_lockspace);
...@@ -741,8 +743,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) ...@@ -741,8 +743,7 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
goto out; goto out;
} }
if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) || if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
GFS2_MIN_LVB_SIZE)) { GFS2_MIN_LVB_SIZE)) {
gfs2_unmount_lockproto(&sdp->sd_lockstruct); gfs2_unmount_lockproto(&sdp->sd_lockstruct);
......
...@@ -428,6 +428,9 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea ...@@ -428,6 +428,9 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
unsigned int message) unsigned int message)
{ {
if (!sdp->sd_lockstruct.ls_ops->lm_recovery_done)
return;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
sdp->sd_lockstruct.ls_ops->lm_recovery_done( sdp->sd_lockstruct.ls_ops->lm_recovery_done(
sdp->sd_lockstruct.ls_lockspace, jid, message); sdp->sd_lockstruct.ls_lockspace, jid, message);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment