2006-01-16 19:50:04 +03:00
/*
* Copyright ( C ) Sistina Software , Inc . 1997 - 2003 All rights reserved .
2006-05-18 23:09:15 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2006-01-16 19:50:04 +03:00
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2006-09-01 19:05:15 +04:00
* of the GNU General Public License version 2.
2006-01-16 19:50:04 +03:00
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/string.h>
# include <linux/slab.h>
# include <linux/wait.h>
# include <linux/sched.h>
# include <linux/kmod.h>
# include <linux/fs.h>
# include <linux/delay.h>
2006-09-19 09:56:29 +04:00
# include <linux/lm_interface.h>
2006-01-16 19:50:04 +03:00
struct lmh_wrapper {
struct list_head lw_list ;
2006-09-08 18:17:58 +04:00
const struct lm_lockops * lw_ops ;
2006-01-16 19:50:04 +03:00
} ;
/* 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 . */
2006-09-04 17:49:55 +04:00
static LIST_HEAD ( lmh_list ) ;
static DEFINE_MUTEX ( lmh_lock ) ;
2006-01-16 19:50:04 +03:00
/**
2006-08-07 19:12:30 +04:00
* gfs2_register_lockproto - Register a low - level locking protocol
2006-01-16 19:50:04 +03:00
* @ proto : the protocol definition
*
* Returns : 0 on success , - EXXX on failure
*/
2006-09-08 18:17:58 +04:00
int gfs2_register_lockproto ( const struct lm_lockops * proto )
2006-01-16 19:50:04 +03:00
{
struct lmh_wrapper * lw ;
2006-04-21 23:10:46 +04:00
mutex_lock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
list_for_each_entry ( lw , & lmh_list , lw_list ) {
if ( ! strcmp ( lw - > lw_ops - > lm_proto_name , proto - > lm_proto_name ) ) {
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-02-27 18:57:14 +03:00
printk ( KERN_INFO " GFS2: protocol %s already exists \n " ,
2006-01-16 19:50:04 +03:00
proto - > lm_proto_name ) ;
return - EEXIST ;
}
}
2006-02-27 18:57:14 +03:00
lw = kzalloc ( sizeof ( struct lmh_wrapper ) , GFP_KERNEL ) ;
2006-01-16 19:50:04 +03:00
if ( ! lw ) {
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
return - ENOMEM ;
}
lw - > lw_ops = proto ;
list_add ( & lw - > lw_list , & lmh_list ) ;
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
return 0 ;
}
/**
2006-08-07 19:12:30 +04:00
* gfs2_unregister_lockproto - Unregister a low - level locking protocol
2006-01-16 19:50:04 +03:00
* @ proto : the protocol definition
*
*/
2006-09-08 18:17:58 +04:00
void gfs2_unregister_lockproto ( const struct lm_lockops * proto )
2006-01-16 19:50:04 +03:00
{
struct lmh_wrapper * lw ;
2006-04-21 23:10:46 +04:00
mutex_lock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
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 ) ;
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
kfree ( lw ) ;
return ;
}
}
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
2006-02-27 18:57:14 +03:00
printk ( KERN_WARNING " GFS2: can't unregister lock protocol %s \n " ,
2006-01-16 19:50:04 +03:00
proto - > lm_proto_name ) ;
}
/**
* gfs2_mount_lockproto - Mount a lock protocol
* @ proto_name - the name of the protocol
* @ 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
2006-09-07 23:50:20 +04:00
* @ sdp - The GFS2 superblock
2006-01-16 19:50:04 +03:00
* @ min_lvb_size - the mininum LVB size that the caller can deal with
* @ flags - LM_MFLAG_ *
* @ lockstruct - a structure returned describing the mount
*
* Returns : 0 on success , - EXXX on failure
*/
int gfs2_mount_lockproto ( char * proto_name , char * table_name , char * host_data ,
2006-09-08 18:17:58 +04:00
lm_callback_t cb , void * cb_data ,
2006-01-16 19:50:04 +03:00
unsigned int min_lvb_size , int flags ,
struct lm_lockstruct * lockstruct ,
struct kobject * fskobj )
{
struct lmh_wrapper * lw = NULL ;
int try = 0 ;
int error , found ;
2006-08-07 19:12:30 +04:00
retry :
2006-04-21 23:10:46 +04:00
mutex_lock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
found = 0 ;
list_for_each_entry ( lw , & lmh_list , lw_list ) {
if ( ! strcmp ( lw - > lw_ops - > lm_proto_name , proto_name ) ) {
found = 1 ;
break ;
}
}
if ( ! found ) {
if ( ! try & & capable ( CAP_SYS_MODULE ) ) {
try = 1 ;
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
request_module ( proto_name ) ;
goto retry ;
}
2006-02-27 18:57:14 +03:00
printk ( KERN_INFO " GFS2: can't find protocol %s \n " , proto_name ) ;
2006-01-16 19:50:04 +03:00
error = - ENOENT ;
goto out ;
}
if ( ! try_module_get ( lw - > lw_ops - > lm_owner ) ) {
try = 0 ;
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
msleep ( 1000 ) ;
goto retry ;
}
2006-09-08 18:17:58 +04:00
error = lw - > lw_ops - > lm_mount ( table_name , host_data , cb , cb_data ,
2006-01-16 19:50:04 +03:00
min_lvb_size , flags , lockstruct , fskobj ) ;
if ( error )
module_put ( lw - > lw_ops - > lm_owner ) ;
2006-08-07 19:12:30 +04:00
out :
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
return error ;
}
void gfs2_unmount_lockproto ( struct lm_lockstruct * lockstruct )
{
2006-04-21 23:10:46 +04:00
mutex_lock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
lockstruct - > ls_ops - > lm_unmount ( lockstruct - > ls_lockspace ) ;
if ( lockstruct - > ls_ops - > lm_owner )
module_put ( lockstruct - > ls_ops - > lm_owner ) ;
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
}
/**
* gfs2_withdraw_lockproto - abnormally unmount a lock module
* @ lockstruct : the lockstruct passed into mount
*
*/
void gfs2_withdraw_lockproto ( struct lm_lockstruct * lockstruct )
{
2006-04-21 23:10:46 +04:00
mutex_lock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
lockstruct - > ls_ops - > lm_withdraw ( lockstruct - > ls_lockspace ) ;
if ( lockstruct - > ls_ops - > lm_owner )
module_put ( lockstruct - > ls_ops - > lm_owner ) ;
2006-04-21 23:10:46 +04:00
mutex_unlock ( & lmh_lock ) ;
2006-01-16 19:50:04 +03:00
}
2006-08-07 19:12:30 +04:00
EXPORT_SYMBOL_GPL ( gfs2_register_lockproto ) ;
EXPORT_SYMBOL_GPL ( gfs2_unregister_lockproto ) ;
2006-01-16 19:50:04 +03:00