linux/fs/gfs2/locking.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
   3 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
   4 *
   5 * This copyrighted material is made available to anyone wishing to use,
   6 * modify, copy, or redistribute it subject to the terms and conditions
   7 * of the GNU General Public License version 2.
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/init.h>
  12#include <linux/string.h>
  13#include <linux/slab.h>
  14#include <linux/wait.h>
  15#include <linux/sched.h>
  16#include <linux/kmod.h>
  17#include <linux/fs.h>
  18#include <linux/delay.h>
  19#include <linux/lm_interface.h>
  20
  21struct lmh_wrapper {
  22        struct list_head lw_list;
  23        const struct lm_lockops *lw_ops;
  24};
  25
  26static int nolock_mount(char *table_name, char *host_data,
  27                        lm_callback_t cb, void *cb_data,
  28                        unsigned int min_lvb_size, int flags,
  29                        struct lm_lockstruct *lockstruct,
  30                        struct kobject *fskobj);
  31
  32/* List of registered low-level locking protocols.  A file system selects one
  33   of them by name at mount time, e.g. lock_nolock, lock_dlm. */
  34
  35static const struct lm_lockops nolock_ops = {
  36        .lm_proto_name = "lock_nolock",
  37        .lm_mount = nolock_mount,
  38};
  39
  40static struct lmh_wrapper nolock_proto  = {
  41        .lw_list = LIST_HEAD_INIT(nolock_proto.lw_list),
  42        .lw_ops = &nolock_ops,
  43};
  44
  45static LIST_HEAD(lmh_list);
  46static DEFINE_MUTEX(lmh_lock);
  47
  48static int nolock_mount(char *table_name, char *host_data,
  49                        lm_callback_t cb, void *cb_data,
  50                        unsigned int min_lvb_size, int flags,
  51                        struct lm_lockstruct *lockstruct,
  52                        struct kobject *fskobj)
  53{
  54        char *c;
  55        unsigned int jid;
  56
  57        c = strstr(host_data, "jid=");
  58        if (!c)
  59                jid = 0;
  60        else {
  61                c += 4;
  62                sscanf(c, "%u", &jid);
  63        }
  64
  65        lockstruct->ls_jid = jid;
  66        lockstruct->ls_first = 1;
  67        lockstruct->ls_lvb_size = min_lvb_size;
  68        lockstruct->ls_ops = &nolock_ops;
  69        lockstruct->ls_flags = LM_LSFLAG_LOCAL;
  70
  71        return 0;
  72}
  73
  74/**
  75 * gfs2_register_lockproto - Register a low-level locking protocol
  76 * @proto: the protocol definition
  77 *
  78 * Returns: 0 on success, -EXXX on failure
  79 */
  80
  81int gfs2_register_lockproto(const struct lm_lockops *proto)
  82{
  83        struct lmh_wrapper *lw;
  84
  85        mutex_lock(&lmh_lock);
  86
  87        list_for_each_entry(lw, &lmh_list, lw_list) {
  88                if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
  89                        mutex_unlock(&lmh_lock);
  90                        printk(KERN_INFO "GFS2: protocol %s already exists\n",
  91                               proto->lm_proto_name);
  92                        return -EEXIST;
  93                }
  94        }
  95
  96        lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL);
  97        if (!lw) {
  98                mutex_unlock(&lmh_lock);
  99                return -ENOMEM;
 100        }
 101
 102        lw->lw_ops = proto;
 103        list_add(&lw->lw_list, &lmh_list);
 104
 105        mutex_unlock(&lmh_lock);
 106
 107        return 0;
 108}
 109
 110/**
 111 * gfs2_unregister_lockproto - Unregister a low-level locking protocol
 112 * @proto: the protocol definition
 113 *
 114 */
 115
 116void gfs2_unregister_lockproto(const struct lm_lockops *proto)
 117{
 118        struct lmh_wrapper *lw;
 119
 120        mutex_lock(&lmh_lock);
 121
 122        list_for_each_entry(lw, &lmh_list, lw_list) {
 123                if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) {
 124                        list_del(&lw->lw_list);
 125                        mutex_unlock(&lmh_lock);
 126                        kfree(lw);
 127                        return;
 128                }
 129        }
 130
 131        mutex_unlock(&lmh_lock);
 132
 133        printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n",
 134               proto->lm_proto_name);
 135}
 136
 137/**
 138 * gfs2_mount_lockproto - Mount a lock protocol
 139 * @proto_name - the name of the protocol
 140 * @table_name - the name of the lock space
 141 * @host_data - data specific to this host
 142 * @cb - the callback to the code using the lock module
 143 * @sdp - The GFS2 superblock
 144 * @min_lvb_size - the mininum LVB size that the caller can deal with
 145 * @flags - LM_MFLAG_*
 146 * @lockstruct - a structure returned describing the mount
 147 *
 148 * Returns: 0 on success, -EXXX on failure
 149 */
 150
 151int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data,
 152                         lm_callback_t cb, void *cb_data,
 153                         unsigned int min_lvb_size, int flags,
 154                         struct lm_lockstruct *lockstruct,
 155                         struct kobject *fskobj)
 156{
 157        struct lmh_wrapper *lw = NULL;
 158        int try = 0;
 159        int error, found;
 160
 161
 162retry:
 163        mutex_lock(&lmh_lock);
 164
 165        if (list_empty(&nolock_proto.lw_list))
 166                list_add(&nolock_proto.lw_list, &lmh_list);
 167
 168        found = 0;
 169        list_for_each_entry(lw, &lmh_list, lw_list) {
 170                if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) {
 171                        found = 1;
 172                        break;
 173                }
 174        }
 175
 176        if (!found) {
 177                if (!try && capable(CAP_SYS_MODULE)) {
 178                        try = 1;
 179                        mutex_unlock(&lmh_lock);
 180                        request_module(proto_name);
 181                        goto retry;
 182                }
 183                printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name);
 184                error = -ENOENT;
 185                goto out;
 186        }
 187
 188        if (lw->lw_ops->lm_owner &&
 189            !try_module_get(lw->lw_ops->lm_owner)) {
 190                try = 0;
 191                mutex_unlock(&lmh_lock);
 192                msleep(1000);
 193                goto retry;
 194        }
 195
 196        error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data,
 197                                     min_lvb_size, flags, lockstruct, fskobj);
 198        if (error)
 199                module_put(lw->lw_ops->lm_owner);
 200out:
 201        mutex_unlock(&lmh_lock);
 202        return error;
 203}
 204
 205void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct)
 206{
 207        mutex_lock(&lmh_lock);
 208        if (lockstruct->ls_ops->lm_unmount)
 209                lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace);
 210        if (lockstruct->ls_ops->lm_owner)
 211                module_put(lockstruct->ls_ops->lm_owner);
 212        mutex_unlock(&lmh_lock);
 213}
 214
 215/**
 216 * gfs2_withdraw_lockproto - abnormally unmount a lock module
 217 * @lockstruct: the lockstruct passed into mount
 218 *
 219 */
 220
 221void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct)
 222{
 223        mutex_lock(&lmh_lock);
 224        lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace);
 225        if (lockstruct->ls_ops->lm_owner)
 226                module_put(lockstruct->ls_ops->lm_owner);
 227        mutex_unlock(&lmh_lock);
 228}
 229
 230EXPORT_SYMBOL_GPL(gfs2_register_lockproto);
 231EXPORT_SYMBOL_GPL(gfs2_unregister_lockproto);
 232
 233