Skip to content

Commit 94e180d

Browse files
Alexander Aringteigland
authored andcommitted
dlm: async freeing of lockspace resources
This patch handles freeing of lockspace resources asynchronously besides the release_lockspace() context. The release_lockspace() context is sometimes called in a time critical context, e.g. umount syscall. Most every user space init system will timeout if it takes too long. To reduce the potential waiting time we deregister in release_lockspace() the lockspace from the DLM subsystem and do the actual releasing of lockspace resource in a worker of a workqueue following recommendation of: https://lore.kernel.org/all/[email protected]/T/#u as flushing of system workqueues are not allowed. The most time to release the DLM resources are spent to release the data structures "ls->ls_lkbxa" and "ls->ls_rsbtbl" as they iterate over each entries and those data structures can contain millions of entries. This patch handles for now only freeing of those data structures as those operations are the most reason why release_lockspace() blocking of being returned. Signed-off-by: Alexander Aring <[email protected]> Signed-off-by: David Teigland <[email protected]>
1 parent 8a4cf50 commit 94e180d

File tree

3 files changed

+58
-33
lines changed

3 files changed

+58
-33
lines changed

fs/dlm/dlm_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ struct dlm_ls {
660660
const struct dlm_lockspace_ops *ls_ops;
661661
void *ls_ops_arg;
662662

663+
struct work_struct ls_free_work;
664+
663665
int ls_namelen;
664666
char ls_name[DLM_LOCKSPACE_LEN + 1];
665667
};
@@ -803,6 +805,8 @@ static inline void dlm_set_sbflags_val(struct dlm_lkb *lkb, uint32_t val)
803805
__DLM_SBF_MAX_BIT);
804806
}
805807

808+
extern struct workqueue_struct *dlm_wq;
809+
806810
int dlm_plock_init(void);
807811
void dlm_plock_exit(void);
808812

fs/dlm/lockspace.c

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,44 @@ static int threads_start(void)
315315
return error;
316316
}
317317

318+
static int lkb_idr_free(struct dlm_lkb *lkb)
319+
{
320+
if (lkb->lkb_lvbptr && test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags))
321+
dlm_free_lvb(lkb->lkb_lvbptr);
322+
323+
dlm_free_lkb(lkb);
324+
return 0;
325+
}
326+
327+
static void rhash_free_rsb(void *ptr, void *arg)
328+
{
329+
struct dlm_rsb *rsb = ptr;
330+
331+
dlm_free_rsb(rsb);
332+
}
333+
334+
static void free_lockspace(struct work_struct *work)
335+
{
336+
struct dlm_ls *ls = container_of(work, struct dlm_ls, ls_free_work);
337+
struct dlm_lkb *lkb;
338+
unsigned long id;
339+
340+
/*
341+
* Free all lkb's in xa
342+
*/
343+
xa_for_each(&ls->ls_lkbxa, id, lkb) {
344+
lkb_idr_free(lkb);
345+
}
346+
xa_destroy(&ls->ls_lkbxa);
347+
348+
/*
349+
* Free all rsb's on rsbtbl
350+
*/
351+
rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
352+
353+
kfree(ls);
354+
}
355+
318356
static int new_lockspace(const char *name, const char *cluster,
319357
uint32_t flags, int lvblen,
320358
const struct dlm_lockspace_ops *ops, void *ops_arg,
@@ -445,6 +483,8 @@ static int new_lockspace(const char *name, const char *cluster,
445483
spin_lock_init(&ls->ls_cb_lock);
446484
INIT_LIST_HEAD(&ls->ls_cb_delay);
447485

486+
INIT_WORK(&ls->ls_free_work, free_lockspace);
487+
448488
ls->ls_recoverd_task = NULL;
449489
mutex_init(&ls->ls_recoverd_active);
450490
spin_lock_init(&ls->ls_recover_lock);
@@ -627,15 +667,6 @@ int dlm_new_user_lockspace(const char *name, const char *cluster,
627667
ops_arg, ops_result, lockspace);
628668
}
629669

630-
static int lkb_idr_free(struct dlm_lkb *lkb)
631-
{
632-
if (lkb->lkb_lvbptr && test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags))
633-
dlm_free_lvb(lkb->lkb_lvbptr);
634-
635-
dlm_free_lkb(lkb);
636-
return 0;
637-
}
638-
639670
/* NOTE: We check the lkbxa here rather than the resource table.
640671
This is because there may be LKBs queued as ASTs that have been unlinked
641672
from their RSBs and are pending deletion once the AST has been delivered */
@@ -667,17 +698,8 @@ static int lockspace_busy(struct dlm_ls *ls, int force)
667698
return rv;
668699
}
669700

670-
static void rhash_free_rsb(void *ptr, void *arg)
671-
{
672-
struct dlm_rsb *rsb = ptr;
673-
674-
dlm_free_rsb(rsb);
675-
}
676-
677701
static int release_lockspace(struct dlm_ls *ls, int force)
678702
{
679-
struct dlm_lkb *lkb;
680-
unsigned long id;
681703
int busy, rv;
682704

683705
busy = lockspace_busy(ls, force);
@@ -735,19 +757,6 @@ static int release_lockspace(struct dlm_ls *ls, int force)
735757
xa_destroy(&ls->ls_recover_xa);
736758
kfree(ls->ls_recover_buf);
737759

738-
/*
739-
* Free all lkb's in xa
740-
*/
741-
xa_for_each(&ls->ls_lkbxa, id, lkb) {
742-
lkb_idr_free(lkb);
743-
}
744-
xa_destroy(&ls->ls_lkbxa);
745-
746-
/*
747-
* Free all rsb's on rsbtbl
748-
*/
749-
rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
750-
751760
/*
752761
* Free structures on any other lists
753762
*/
@@ -757,9 +766,11 @@ static int release_lockspace(struct dlm_ls *ls, int force)
757766
dlm_clear_members(ls);
758767
dlm_clear_members_gone(ls);
759768
kfree(ls->ls_node_array);
760-
log_rinfo(ls, "release_lockspace final free");
761-
kfree(ls);
762769

770+
log_rinfo(ls, "%s final free", __func__);
771+
772+
/* delayed free of data structures see free_lockspace() */
773+
queue_work(dlm_wq, &ls->ls_free_work);
763774
module_put(THIS_MODULE);
764775
return 0;
765776
}

fs/dlm/main.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#define CREATE_TRACE_POINTS
2323
#include <trace/events/dlm.h>
2424

25+
struct workqueue_struct *dlm_wq;
26+
2527
static int __init init_dlm(void)
2628
{
2729
int error;
@@ -50,10 +52,16 @@ static int __init init_dlm(void)
5052
if (error)
5153
goto out_user;
5254

55+
dlm_wq = alloc_workqueue("dlm_wq", 0, 0);
56+
if (!dlm_wq)
57+
goto out_plock;
58+
5359
printk("DLM installed\n");
5460

5561
return 0;
5662

63+
out_plock:
64+
dlm_plock_exit();
5765
out_user:
5866
dlm_user_exit();
5967
out_debug:
@@ -70,6 +78,8 @@ static int __init init_dlm(void)
7078

7179
static void __exit exit_dlm(void)
7280
{
81+
/* be sure every pending work e.g. freeing is done */
82+
destroy_workqueue(dlm_wq);
7383
dlm_plock_exit();
7484
dlm_user_exit();
7585
dlm_config_exit();

0 commit comments

Comments
 (0)