mm: vmap fix overflow
[safe/jmp/linux-2.6] / fs / gfs2 / locking.c
index 2d2f8fe..523243a 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2006 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 v.2.
+ * of the GNU General Public License version 2.
  */
 
 #include <linux/module.h>
 #include <linux/kmod.h>
 #include <linux/fs.h>
 #include <linux/delay.h>
-
-#include "lm_interface.h"
+#include <linux/lm_interface.h>
 
 struct lmh_wrapper {
        struct list_head lw_list;
-       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
    of them by name at mount time, e.g. lock_nolock, lock_dlm. */
 
-static struct list_head lmh_list;
-static struct semaphore lmh_lock;
+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;
+}
 
 /**
- * gfs_register_lockproto - Register a low-level locking protocol
+ * gfs2_register_lockproto - Register a low-level locking protocol
  * @proto: the protocol definition
  *
  * Returns: 0 on success, -EXXX on failure
  */
 
-int gfs_register_lockproto(struct lm_lockops *proto)
+int gfs2_register_lockproto(const struct lm_lockops *proto)
 {
        struct lmh_wrapper *lw;
 
-       down(&lmh_lock);
+       mutex_lock(&lmh_lock);
 
        list_for_each_entry(lw, &lmh_list, lw_list) {
                if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
-                       up(&lmh_lock);
-                       printk("GFS2: protocol %s already exists\n",
+                       mutex_unlock(&lmh_lock);
+                       printk(KERN_INFO "GFS2: protocol %s already exists\n",
                               proto->lm_proto_name);
                        return -EEXIST;
                }
        }
 
-       lw = kmalloc(sizeof(struct lmh_wrapper), GFP_KERNEL);
+       lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL);
        if (!lw) {
-               up(&lmh_lock);
+               mutex_unlock(&lmh_lock);
                return -ENOMEM;
        }
-       memset(lw, 0, sizeof(struct lmh_wrapper));
 
        lw->lw_ops = proto;
        list_add(&lw->lw_list, &lmh_list);
 
-       up(&lmh_lock);
+       mutex_unlock(&lmh_lock);
 
        return 0;
 }
 
 /**
- * gfs_unregister_lockproto - Unregister a low-level locking protocol
+ * gfs2_unregister_lockproto - Unregister a low-level locking protocol
  * @proto: the protocol definition
  *
  */
 
-void gfs_unregister_lockproto(struct lm_lockops *proto)
+void gfs2_unregister_lockproto(const struct lm_lockops *proto)
 {
        struct lmh_wrapper *lw;
 
-       down(&lmh_lock);
+       mutex_lock(&lmh_lock);
 
        list_for_each_entry(lw, &lmh_list, lw_list) {
                if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
                        list_del(&lw->lw_list);
-                       up(&lmh_lock);
+                       mutex_unlock(&lmh_lock);
                        kfree(lw);
                        return;
                }
        }
 
-       up(&lmh_lock);
+       mutex_unlock(&lmh_lock);
 
-       printk("GFS2: can't unregister lock protocol %s\n",
+       printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n",
               proto->lm_proto_name);
 }
 
@@ -100,7 +140,7 @@ void gfs_unregister_lockproto(struct lm_lockops *proto)
  * @table_name - the name of the lock space
  * @host_data - data specific to this host
  * @cb - the callback to the code using the lock module
- * @fsdata - data to pass back with the callback
+ * @sdp - The GFS2 superblock
  * @min_lvb_size - the mininum LVB size that the caller can deal with
  * @flags - LM_MFLAG_*
  * @lockstruct - a structure returned describing the mount
@@ -109,7 +149,7 @@ void gfs_unregister_lockproto(struct lm_lockops *proto)
  */
 
 int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
-                        lm_callback_t cb, lm_fsdata_t *fsdata,
+                        lm_callback_t cb, void *cb_data,
                         unsigned int min_lvb_size, int flags,
                         struct lm_lockstruct *lockstruct,
                         struct kobject *fskobj)
@@ -118,8 +158,12 @@ int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
        int try = 0;
        int error, found;
 
- retry:
-       down(&lmh_lock);
+
+retry:
+       mutex_lock(&lmh_lock);
+
+       if (list_empty(&nolock_proto.lw_list))
+               list_add(&nolock_proto.lw_list, &lmh_list);
 
        found = 0;
        list_for_each_entry(lw, &lmh_list, lw_list) {
@@ -132,38 +176,40 @@ int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
        if (!found) {
                if (!try && capable(CAP_SYS_MODULE)) {
                        try = 1;
-                       up(&lmh_lock);
+                       mutex_unlock(&lmh_lock);
                        request_module(proto_name);
                        goto retry;
                }
-               printk("GFS2: can't find protocol %s\n", proto_name);
+               printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name);
                error = -ENOENT;
                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;
-               up(&lmh_lock);
+               mutex_unlock(&lmh_lock);
                msleep(1000);
                goto retry;
        }
 
-       error = lw->lw_ops->lm_mount(table_name, host_data, cb, fsdata,
+       error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data,
                                     min_lvb_size, flags, lockstruct, fskobj);
        if (error)
                module_put(lw->lw_ops->lm_owner);
- out:
-       up(&lmh_lock);
+out:
+       mutex_unlock(&lmh_lock);
        return error;
 }
 
 void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct)
 {
-       down(&lmh_lock);
-       lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace);
+       mutex_lock(&lmh_lock);
+       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);
-       up(&lmh_lock);
+       mutex_unlock(&lmh_lock);
 }
 
 /**
@@ -174,19 +220,13 @@ void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct)
 
 void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct)
 {
-       down(&lmh_lock);
+       mutex_lock(&lmh_lock);
        lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace);
        if (lockstruct->ls_ops->lm_owner)
                module_put(lockstruct->ls_ops->lm_owner);
-       up(&lmh_lock);
-}
-
-void __init gfs2_init_lmh(void)
-{
-       init_MUTEX(&lmh_lock);
-       INIT_LIST_HEAD(&lmh_list);
+       mutex_unlock(&lmh_lock);
 }
 
-EXPORT_SYMBOL_GPL(gfs_register_lockproto);
-EXPORT_SYMBOL_GPL(gfs_unregister_lockproto);
+EXPORT_SYMBOL_GPL(gfs2_register_lockproto);
+EXPORT_SYMBOL_GPL(gfs2_unregister_lockproto);