struct gfs2_sbd *sdp = gl->gl_sbd;
        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);
 
        if (aspace)
                                 unsigned int flags)
 {
        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)))
                ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
                                                         req_state, flags);
                     void **lockp)
 {
        int error = -EIO;
+       if (!sdp->sd_lockstruct.ls_ops->lm_get_lock)
+               return 0;
        if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
                error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
                                sdp->sd_lockstruct.ls_lockspace, name, lockp);
        gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list);
        if (!(gh->gh_flags & LM_FLAG_PRIORITY)) {
                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);
        }
        return;
 static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
 {
        int error = -EIO;
+       if (!sdp->sd_lockstruct.ls_ops->lm_hold_lvb)
+               return 0;
        if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
                error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
        return error;
        gfs2_glock_hold(gl);
        gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
        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);
                gl->gl_lvb = NULL;
                gfs2_glock_put(gl);
 
        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
    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 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
  * @proto: the protocol definition
        int try = 0;
        int error, found;
 
+
 retry:
        mutex_lock(&lmh_lock);
 
+       if (list_empty(&nolock_proto.lw_list))
+               list_add(&lmh_list, &nolock_proto.lw_list);
+
        found = 0;
        list_for_each_entry(lw, &lmh_list, lw_list) {
                if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) {
                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;
                mutex_unlock(&lmh_lock);
                msleep(1000);
 void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct)
 {
        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)
                module_put(lockstruct->ls_ops->lm_owner);
        mutex_unlock(&lmh_lock);
 
+++ /dev/null
-/*
- * 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");
-