dlm for 6.12

- Remove some unnecesary hold/unhold rsb refcounting
   in cases where an existing refcount is known to exist.
 - Remove some unnecessary checking for zero nodeids, which
   should never exist, and add some warning if they do.
 - Make the slow freeing of structs in release_lockspace()
   async, run from a workqueue.
 - Prior rcu freeing allows some further struct lookups to
   run without a lock.
 - Use blocking kernel_connect on sockets to avoid EINPROGRESS.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEcGkeEvkvjdvlR90nOBtzx/yAaaoFAmbpqCEACgkQOBtzx/yA
 aap1FBAAk6qmMoGHLl4pmJtDtPNZlsyCE7/SIdGjeMuszX5ENMl3sdoJ7qxX8ism
 r9v7YqN7K3lLuFb8xnuLw1i5VAp8jkNgTEQ2z4gOKRpHILCsQkJyFHF3CxpqbiOz
 DbyIgOOqo00kgU/sI3NwbuwSr18DZhY8QylIvqk32K2TjhdfxhffocVsfroDJWAH
 NdcH71rAVcPVe+Ls1XW6Bqn+QpDbcaki4V524MImBVVRGHxD1FjFjZ1ppohcqDK0
 Xdrxeh3iVz0ovoyxkpHEvdW0+t3y4jLo4bR9iQnj7MVA5eNX4uwTdd1deSg/ueY2
 6m7WMIZy6hA1Tj6TdAf+dXp+MPm+LhHaXv7wz1yJU6JdTUryvctynLgXBTVhNEcM
 y5TVuLC4ad1NgFsPeGAG7vH1puXoVCxoKT8pPGQhbBoUbILJALGR8ApF/kc+CZms
 AUYB2oQoaZXtaubrF3WoUQ4eakypo3z0MVzNzLsO+AYJAOiqQkLJaa6dVLu1qg7n
 6UjBypNyJjevoWJIUqI0lYlXD7x3HFz3q6LYjhThITDnNo57KzqgqJ2p9KHtEp8/
 WPNm7zPHzH088wk19uEbJP67FySPa34XUqebfOv32je5rHvrF7Ux3TkHI9Dm+by9
 PwI3LtmXQyNbH9nwFdqFda7SuDTnlskTCEr3bZx+Dact6Zwk9Lc=
 =25XB
 -----END PGP SIGNATURE-----

Merge tag 'dlm-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm

Pull dlm updates from David Teigland:

 - Remove some unnecesary hold/unhold rsb refcounting in cases where an
   existing refcount is known to exist

 - Remove some unnecessary checking for zero nodeids, which should never
   exist, and add some warning if they do

 - Make the slow freeing of structs in release_lockspace() async, run
   from a workqueue

 - Prior rcu freeing allows some further struct lookups to run without a
   lock

 - Use blocking kernel_connect on sockets to avoid EINPROGRESS

* tag 'dlm-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm:
  dlm: add missing -ENOMEM if alloc_workqueue() fails
  dlm: do synchronized socket connect call
  dlm: move lkb xarray lookup out of lock
  dlm: move dlm_search_rsb_tree() out of lock
  dlm: use RSB_HASHED to avoid lookup twice
  dlm: async freeing of lockspace resources
  dlm: drop kobject release callback handling
  dlm: warn about invalid nodeid comparsions
  dlm: never return invalid nodeid by dlm_our_nodeid()
  dlm: remove unnecessary refcounts
  dlm: cleanup memory allocation helpers
This commit is contained in:
Linus Torvalds 2024-09-19 07:09:39 +02:00
commit 932d2d1fcb
11 changed files with 164 additions and 167 deletions

View File

@ -928,7 +928,7 @@ int dlm_comm_seq(int nodeid, uint32_t *seq)
int dlm_our_nodeid(void)
{
return local_comm ? local_comm->nodeid : 0;
return local_comm->nodeid;
}
/* num 0 is first addr, num 1 is second addr */

View File

@ -295,6 +295,7 @@ struct dlm_lkb {
void *lkb_astparam; /* caller's ast arg */
struct dlm_user_args *lkb_ua;
};
struct rcu_head rcu;
};
/*
@ -660,6 +661,8 @@ struct dlm_ls {
const struct dlm_lockspace_ops *ls_ops;
void *ls_ops_arg;
struct work_struct ls_free_work;
int ls_namelen;
char ls_name[DLM_LOCKSPACE_LEN + 1];
};
@ -803,6 +806,8 @@ static inline void dlm_set_sbflags_val(struct dlm_lkb *lkb, uint32_t val)
__DLM_SBF_MAX_BIT);
}
extern struct workqueue_struct *dlm_wq;
int dlm_plock_init(void);
void dlm_plock_exit(void);

View File

@ -600,7 +600,7 @@ static int get_rsb_struct(struct dlm_ls *ls, const void *name, int len,
{
struct dlm_rsb *r;
r = dlm_allocate_rsb(ls);
r = dlm_allocate_rsb();
if (!r)
return -ENOMEM;
@ -733,11 +733,13 @@ static int find_rsb_dir(struct dlm_ls *ls, const void *name, int len,
}
retry:
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (error)
goto do_new;
/* check if the rsb is active under read lock - likely path */
read_lock_bh(&ls->ls_rsbtbl_lock);
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (error) {
if (!rsb_flag(r, RSB_HASHED)) {
read_unlock_bh(&ls->ls_rsbtbl_lock);
goto do_new;
}
@ -918,11 +920,13 @@ static int find_rsb_nodir(struct dlm_ls *ls, const void *name, int len,
int error;
retry:
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (error)
goto do_new;
/* check if the rsb is in active state under read lock - likely path */
read_lock_bh(&ls->ls_rsbtbl_lock);
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (error) {
if (!rsb_flag(r, RSB_HASHED)) {
read_unlock_bh(&ls->ls_rsbtbl_lock);
goto do_new;
}
@ -1151,7 +1155,7 @@ static void __dlm_master_lookup(struct dlm_ls *ls, struct dlm_rsb *r, int our_no
r->res_dir_nodeid = our_nodeid;
}
if (fix_master && dlm_is_removed(ls, r->res_master_nodeid)) {
if (fix_master && r->res_master_nodeid && dlm_is_removed(ls, r->res_master_nodeid)) {
/* Recovery uses this function to set a new master when
* the previous master failed. Setting NEW_MASTER will
* force dlm_recover_masters to call recover_master on this
@ -1276,11 +1280,17 @@ static int _dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *na
}
retry:
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (error)
goto not_found;
/* check if the rsb is active under read lock - likely path */
read_lock_bh(&ls->ls_rsbtbl_lock);
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (!error) {
if (!rsb_flag(r, RSB_HASHED)) {
read_unlock_bh(&ls->ls_rsbtbl_lock);
goto not_found;
}
if (rsb_flag(r, RSB_INACTIVE)) {
read_unlock_bh(&ls->ls_rsbtbl_lock);
goto do_inactive;
@ -1302,17 +1312,13 @@ static int _dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *na
put_rsb(r);
return 0;
} else {
read_unlock_bh(&ls->ls_rsbtbl_lock);
goto not_found;
}
do_inactive:
/* unlikely path - relookup under write */
/* unlikely path - check if still part of ls_rsbtbl */
write_lock_bh(&ls->ls_rsbtbl_lock);
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (!error) {
/* see comment in find_rsb_dir */
if (rsb_flag(r, RSB_HASHED)) {
if (!rsb_flag(r, RSB_INACTIVE)) {
write_unlock_bh(&ls->ls_rsbtbl_lock);
/* something as changed, very unlikely but
@ -1403,14 +1409,14 @@ void dlm_dump_rsb_name(struct dlm_ls *ls, const char *name, int len)
struct dlm_rsb *r = NULL;
int error;
read_lock_bh(&ls->ls_rsbtbl_lock);
rcu_read_lock();
error = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (!error)
goto out;
dlm_dump_rsb(r);
out:
read_unlock_bh(&ls->ls_rsbtbl_lock);
rcu_read_unlock();
}
static void deactivate_rsb(struct kref *kref)
@ -1442,18 +1448,6 @@ static void deactivate_rsb(struct kref *kref)
}
}
/* See comment for unhold_lkb */
static void unhold_rsb(struct dlm_rsb *r)
{
int rv;
/* inactive rsbs are not ref counted */
WARN_ON(rsb_flag(r, RSB_INACTIVE));
rv = kref_put(&r->res_ref, deactivate_rsb);
DLM_ASSERT(!rv, dlm_dump_rsb(r););
}
void free_inactive_rsb(struct dlm_rsb *r)
{
WARN_ON_ONCE(!rsb_flag(r, RSB_INACTIVE));
@ -1497,7 +1491,7 @@ static int _create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret,
limit.max = end;
limit.min = start;
lkb = dlm_allocate_lkb(ls);
lkb = dlm_allocate_lkb();
if (!lkb)
return -ENOMEM;
@ -1533,11 +1527,21 @@ static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
{
struct dlm_lkb *lkb;
read_lock_bh(&ls->ls_lkbxa_lock);
rcu_read_lock();
lkb = xa_load(&ls->ls_lkbxa, lkid);
if (lkb)
if (lkb) {
/* check if lkb is still part of lkbxa under lkbxa_lock as
* the lkb_ref is tight to the lkbxa data structure, see
* __put_lkb().
*/
read_lock_bh(&ls->ls_lkbxa_lock);
if (kref_read(&lkb->lkb_ref))
kref_get(&lkb->lkb_ref);
else
lkb = NULL;
read_unlock_bh(&ls->ls_lkbxa_lock);
}
rcu_read_unlock();
*lkb_ret = lkb;
return lkb ? 0 : -ENOENT;
@ -1675,10 +1679,8 @@ static void del_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb)
static void move_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int sts)
{
hold_lkb(lkb);
del_lkb(r, lkb);
add_lkb(r, lkb, sts);
unhold_lkb(lkb);
}
static int msg_reply_type(int mstype)
@ -4323,17 +4325,28 @@ static void receive_remove(struct dlm_ls *ls, const struct dlm_message *ms)
memset(name, 0, sizeof(name));
memcpy(name, ms->m_extra, len);
write_lock_bh(&ls->ls_rsbtbl_lock);
rcu_read_lock();
rv = dlm_search_rsb_tree(&ls->ls_rsbtbl, name, len, &r);
if (rv) {
rcu_read_unlock();
/* should not happen */
log_error(ls, "%s from %d not found %s", __func__,
from_nodeid, name);
write_unlock_bh(&ls->ls_rsbtbl_lock);
return;
}
write_lock_bh(&ls->ls_rsbtbl_lock);
if (!rsb_flag(r, RSB_HASHED)) {
rcu_read_unlock();
write_unlock_bh(&ls->ls_rsbtbl_lock);
/* should not happen */
log_error(ls, "%s from %d got removed during removal %s",
__func__, from_nodeid, name);
return;
}
/* at this stage the rsb can only being freed here */
rcu_read_unlock();
if (!rsb_flag(r, RSB_INACTIVE)) {
if (r->res_master_nodeid != from_nodeid) {
/* should not happen */
@ -5297,7 +5310,7 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
case DLM_MSG_LOOKUP:
case DLM_MSG_REQUEST:
_request_lock(r, lkb);
if (is_master(r))
if (r->res_nodeid != -1 && is_master(r))
confirm_master(r, 0);
break;
case DLM_MSG_CONVERT:
@ -5409,9 +5422,8 @@ void dlm_recover_purge(struct dlm_ls *ls, const struct list_head *root_list)
return;
list_for_each_entry(r, root_list, res_root_list) {
hold_rsb(r);
lock_rsb(r);
if (is_master(r)) {
if (r->res_nodeid != -1 && is_master(r)) {
purge_dead_list(ls, r, &r->res_grantqueue,
nodeid_gone, &lkb_count);
purge_dead_list(ls, r, &r->res_convertqueue,
@ -5420,7 +5432,7 @@ void dlm_recover_purge(struct dlm_ls *ls, const struct list_head *root_list)
nodeid_gone, &lkb_count);
}
unlock_rsb(r);
unhold_rsb(r);
cond_resched();
}

View File

@ -66,6 +66,8 @@ int dlm_debug_add_lkb_to_waiters(struct dlm_ls *ls, uint32_t lkb_id,
static inline int is_master(struct dlm_rsb *r)
{
WARN_ON_ONCE(r->res_nodeid == -1);
return !r->res_nodeid;
}

View File

@ -174,12 +174,6 @@ static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr,
return a->store ? a->store(ls, buf, len) : len;
}
static void lockspace_kobj_release(struct kobject *k)
{
struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj);
kfree(ls);
}
static const struct sysfs_ops dlm_attr_ops = {
.show = dlm_attr_show,
.store = dlm_attr_store,
@ -188,7 +182,6 @@ static const struct sysfs_ops dlm_attr_ops = {
static struct kobj_type dlm_ktype = {
.default_groups = dlm_groups,
.sysfs_ops = &dlm_attr_ops,
.release = lockspace_kobj_release,
};
static struct kset *dlm_kset;
@ -322,13 +315,50 @@ static int threads_start(void)
return error;
}
static int lkb_idr_free(struct dlm_lkb *lkb)
{
if (lkb->lkb_lvbptr && test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags))
dlm_free_lvb(lkb->lkb_lvbptr);
dlm_free_lkb(lkb);
return 0;
}
static void rhash_free_rsb(void *ptr, void *arg)
{
struct dlm_rsb *rsb = ptr;
dlm_free_rsb(rsb);
}
static void free_lockspace(struct work_struct *work)
{
struct dlm_ls *ls = container_of(work, struct dlm_ls, ls_free_work);
struct dlm_lkb *lkb;
unsigned long id;
/*
* Free all lkb's in xa
*/
xa_for_each(&ls->ls_lkbxa, id, lkb) {
lkb_idr_free(lkb);
}
xa_destroy(&ls->ls_lkbxa);
/*
* Free all rsb's on rsbtbl
*/
rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
kfree(ls);
}
static int new_lockspace(const char *name, const char *cluster,
uint32_t flags, int lvblen,
const struct dlm_lockspace_ops *ops, void *ops_arg,
int *ops_result, dlm_lockspace_t **lockspace)
{
struct dlm_ls *ls;
int do_unreg = 0;
int namelen = strlen(name);
int error;
@ -453,6 +483,8 @@ static int new_lockspace(const char *name, const char *cluster,
spin_lock_init(&ls->ls_cb_lock);
INIT_LIST_HEAD(&ls->ls_cb_delay);
INIT_WORK(&ls->ls_free_work, free_lockspace);
ls->ls_recoverd_task = NULL;
mutex_init(&ls->ls_recoverd_active);
spin_lock_init(&ls->ls_recover_lock);
@ -530,9 +562,6 @@ static int new_lockspace(const char *name, const char *cluster,
wait_event(ls->ls_recover_lock_wait,
test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
/* let kobject handle freeing of ls if there's an error */
do_unreg = 1;
ls->ls_kobj.kset = dlm_kset;
error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
"%s", ls->ls_name);
@ -580,9 +609,7 @@ static int new_lockspace(const char *name, const char *cluster,
xa_destroy(&ls->ls_lkbxa);
rhashtable_destroy(&ls->ls_rsbtbl);
out_lsfree:
if (do_unreg)
kobject_put(&ls->ls_kobj);
else
kfree(ls);
out:
module_put(THIS_MODULE);
@ -640,15 +667,6 @@ int dlm_new_user_lockspace(const char *name, const char *cluster,
ops_arg, ops_result, lockspace);
}
static int lkb_idr_free(struct dlm_lkb *lkb)
{
if (lkb->lkb_lvbptr && test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags))
dlm_free_lvb(lkb->lkb_lvbptr);
dlm_free_lkb(lkb);
return 0;
}
/* NOTE: We check the lkbxa here rather than the resource table.
This is because there may be LKBs queued as ASTs that have been unlinked
from their RSBs and are pending deletion once the AST has been delivered */
@ -680,17 +698,8 @@ static int lockspace_busy(struct dlm_ls *ls, int force)
return rv;
}
static void rhash_free_rsb(void *ptr, void *arg)
{
struct dlm_rsb *rsb = ptr;
dlm_free_rsb(rsb);
}
static int release_lockspace(struct dlm_ls *ls, int force)
{
struct dlm_lkb *lkb;
unsigned long id;
int busy, rv;
busy = lockspace_busy(ls, force);
@ -743,22 +752,11 @@ static int release_lockspace(struct dlm_ls *ls, int force)
dlm_delete_debug_file(ls);
kobject_put(&ls->ls_kobj);
xa_destroy(&ls->ls_recover_xa);
kfree(ls->ls_recover_buf);
/*
* Free all lkb's in xa
*/
xa_for_each(&ls->ls_lkbxa, id, lkb) {
lkb_idr_free(lkb);
}
xa_destroy(&ls->ls_lkbxa);
/*
* Free all rsb's on rsbtbl
*/
rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
/*
* Free structures on any other lists
*/
@ -768,10 +766,11 @@ static int release_lockspace(struct dlm_ls *ls, int force)
dlm_clear_members(ls);
dlm_clear_members_gone(ls);
kfree(ls->ls_node_array);
log_rinfo(ls, "release_lockspace final free");
kobject_put(&ls->ls_kobj);
/* The ls structure will be freed when the kobject is done with */
log_rinfo(ls, "%s final free", __func__);
/* delayed free of data structures see free_lockspace() */
queue_work(dlm_wq, &ls->ls_free_work);
module_put(THIS_MODULE);
return 0;
}

View File

@ -161,8 +161,6 @@ struct dlm_proto_ops {
const char *name;
int proto;
int (*connect)(struct connection *con, struct socket *sock,
struct sockaddr *addr, int addr_len);
void (*sockopts)(struct socket *sock);
int (*bind)(struct socket *sock);
int (*listen_validate)(void);
@ -1599,8 +1597,7 @@ static int dlm_connect(struct connection *con)
log_print_ratelimited("connecting to %d", con->nodeid);
make_sockaddr(&addr, dlm_config.ci_tcp_port, &addr_len);
result = dlm_proto_ops->connect(con, sock, (struct sockaddr *)&addr,
addr_len);
result = kernel_connect(sock, (struct sockaddr *)&addr, addr_len, 0);
switch (result) {
case -EINPROGRESS:
/* not an error */
@ -1634,13 +1631,6 @@ static void process_send_sockets(struct work_struct *work)
switch (ret) {
case 0:
break;
case -EINPROGRESS:
/* avoid spamming resched on connection
* we might can switch to a state_change
* event based mechanism if established
*/
msleep(100);
break;
default:
/* CF_SEND_PENDING not cleared */
up_write(&con->sock_lock);
@ -1831,12 +1821,6 @@ static int dlm_tcp_bind(struct socket *sock)
return 0;
}
static int dlm_tcp_connect(struct connection *con, struct socket *sock,
struct sockaddr *addr, int addr_len)
{
return kernel_connect(sock, addr, addr_len, O_NONBLOCK);
}
static int dlm_tcp_listen_validate(void)
{
/* We don't support multi-homed hosts */
@ -1873,7 +1857,6 @@ static int dlm_tcp_listen_bind(struct socket *sock)
static const struct dlm_proto_ops dlm_tcp_ops = {
.name = "TCP",
.proto = IPPROTO_TCP,
.connect = dlm_tcp_connect,
.sockopts = dlm_tcp_sockopts,
.bind = dlm_tcp_bind,
.listen_validate = dlm_tcp_listen_validate,
@ -1886,22 +1869,6 @@ static int dlm_sctp_bind(struct socket *sock)
return sctp_bind_addrs(sock, 0);
}
static int dlm_sctp_connect(struct connection *con, struct socket *sock,
struct sockaddr *addr, int addr_len)
{
int ret;
/*
* Make kernel_connect() function return in specified time,
* since O_NONBLOCK argument in connect() function does not work here,
* then, we should restore the default value of this attribute.
*/
sock_set_sndtimeo(sock->sk, 5);
ret = kernel_connect(sock, addr, addr_len, 0);
sock_set_sndtimeo(sock->sk, 0);
return ret;
}
static int dlm_sctp_listen_validate(void)
{
if (!IS_ENABLED(CONFIG_IP_SCTP)) {
@ -1929,7 +1896,6 @@ static const struct dlm_proto_ops dlm_sctp_ops = {
.name = "SCTP",
.proto = IPPROTO_SCTP,
.try_new_addr = true,
.connect = dlm_sctp_connect,
.sockopts = dlm_sctp_sockopts,
.bind = dlm_sctp_bind,
.listen_validate = dlm_sctp_listen_validate,

View File

@ -22,6 +22,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/dlm.h>
struct workqueue_struct *dlm_wq;
static int __init init_dlm(void)
{
int error;
@ -50,10 +52,18 @@ static int __init init_dlm(void)
if (error)
goto out_user;
dlm_wq = alloc_workqueue("dlm_wq", 0, 0);
if (!dlm_wq) {
error = -ENOMEM;
goto out_plock;
}
printk("DLM installed\n");
return 0;
out_plock:
dlm_plock_exit();
out_user:
dlm_user_exit();
out_debug:
@ -70,6 +80,8 @@ static int __init init_dlm(void)
static void __exit exit_dlm(void)
{
/* be sure every pending work e.g. freeing is done */
destroy_workqueue(dlm_wq);
dlm_plock_exit();
dlm_user_exit();
dlm_config_exit();

View File

@ -366,6 +366,8 @@ int dlm_is_member(struct dlm_ls *ls, int nodeid)
int dlm_is_removed(struct dlm_ls *ls, int nodeid)
{
WARN_ON_ONCE(!nodeid || nodeid == -1);
if (find_memb(&ls->ls_nodes_gone, nodeid))
return 1;
return 0;

View File

@ -84,10 +84,7 @@ void dlm_memory_exit(void)
char *dlm_allocate_lvb(struct dlm_ls *ls)
{
char *p;
p = kzalloc(ls->ls_lvblen, GFP_ATOMIC);
return p;
return kzalloc(ls->ls_lvblen, GFP_ATOMIC);
}
void dlm_free_lvb(char *p)
@ -95,12 +92,9 @@ void dlm_free_lvb(char *p)
kfree(p);
}
struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls)
struct dlm_rsb *dlm_allocate_rsb(void)
{
struct dlm_rsb *r;
r = kmem_cache_zalloc(rsb_cache, GFP_ATOMIC);
return r;
return kmem_cache_zalloc(rsb_cache, GFP_ATOMIC);
}
static void __free_rsb_rcu(struct rcu_head *rcu)
@ -116,16 +110,15 @@ void dlm_free_rsb(struct dlm_rsb *r)
call_rcu(&r->rcu, __free_rsb_rcu);
}
struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls)
struct dlm_lkb *dlm_allocate_lkb(void)
{
struct dlm_lkb *lkb;
lkb = kmem_cache_zalloc(lkb_cache, GFP_ATOMIC);
return lkb;
return kmem_cache_zalloc(lkb_cache, GFP_ATOMIC);
}
void dlm_free_lkb(struct dlm_lkb *lkb)
static void __free_lkb_rcu(struct rcu_head *rcu)
{
struct dlm_lkb *lkb = container_of(rcu, struct dlm_lkb, rcu);
if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) {
struct dlm_user_args *ua;
ua = lkb->lkb_ua;
@ -138,6 +131,11 @@ void dlm_free_lkb(struct dlm_lkb *lkb)
kmem_cache_free(lkb_cache, lkb);
}
void dlm_free_lkb(struct dlm_lkb *lkb)
{
call_rcu(&lkb->rcu, __free_lkb_rcu);
}
struct dlm_mhandle *dlm_allocate_mhandle(void)
{
return kmem_cache_alloc(mhandle_cache, GFP_ATOMIC);

View File

@ -14,9 +14,9 @@
int dlm_memory_init(void);
void dlm_memory_exit(void);
struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls);
struct dlm_rsb *dlm_allocate_rsb(void);
void dlm_free_rsb(struct dlm_rsb *r);
struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls);
struct dlm_lkb *dlm_allocate_lkb(void);
void dlm_free_lkb(struct dlm_lkb *l);
char *dlm_allocate_lvb(struct dlm_ls *ls);
void dlm_free_lvb(char *l);

View File

@ -452,9 +452,10 @@ static int recover_master(struct dlm_rsb *r, unsigned int *count, uint64_t seq)
int is_removed = 0;
int error;
if (is_master(r))
if (r->res_nodeid != -1 && is_master(r))
return 0;
if (r->res_nodeid != -1)
is_removed = dlm_is_removed(ls, r->res_nodeid);
if (!is_removed && !rsb_flag(r, RSB_NEW_MASTER))
@ -664,7 +665,7 @@ int dlm_recover_locks(struct dlm_ls *ls, uint64_t seq,
int error, count = 0;
list_for_each_entry(r, root_list, res_root_list) {
if (is_master(r)) {
if (r->res_nodeid != -1 && is_master(r)) {
rsb_clear_flag(r, RSB_NEW_MASTER);
continue;
}
@ -858,7 +859,7 @@ void dlm_recover_rsbs(struct dlm_ls *ls, const struct list_head *root_list)
list_for_each_entry(r, root_list, res_root_list) {
lock_rsb(r);
if (is_master(r)) {
if (r->res_nodeid != -1 && is_master(r)) {
if (rsb_flag(r, RSB_RECOVER_CONVERT))
recover_conversion(r);