[Cluster-devel] [PATCH RFC gfs2/for-next] fs: gfs2: release dlm gfs2 ls on withdraw

Alexander Aring aahringo at redhat.com
Mon Aug 23 20:11:47 UTC 2021


Hi,

On Mon, Aug 23, 2021 at 11:56 AM Alexander Aring <aahringo at redhat.com> wrote:
>
> This patch will introduce a new gfs2 lock ops callback for release a
> possible lock infrastructure e.g. dlm. There is currently an issue with
> gfs2 and dlm by hitting ctrl-c during mount operation (sometimes it
> works, most times not). The issue is here that when the gfs2 filesystem
> is not withdrawn we don't release the dlm lockspace again and next mount
> dlm_new_lockspace() will return -EEXIST. This patch will ensure that we
> call dlm_release_lockspace() in the error path of gfs2_fill_super() even if
> the filesystem isn't withdrawn yet. Moreover it will do that in all
> cases even if the filesystem is not withdrawn yet.
>
> Signed-off-by: Alexander Aring <aahringo at redhat.com>
> ---
> Hi,
>
> no idea if the gfs2_withdrawn(sdp) should be always evaluated to
> "false", but then there are cases when it returns "true" and the
> gfs2 dlm lockspace will not be released... next mount there will be
> a -EEXIST, as described in the commit message.
>
> If gfs2_withdrawn(sdp) should return "false" always maybe there is some
> missing wait and we should printout a warning if it's returning true...
> in this case and an error path we have a problem which can be observed
> at the next mount.
>
> - Alex
>
>  fs/gfs2/glock.h      |  1 +
>  fs/gfs2/lock_dlm.c   | 24 ++++++++++++++++++------
>  fs/gfs2/ops_fstype.c |  6 +++++-
>  3 files changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
> index 31a8f2f649b5..c8fd1352b0e1 100644
> --- a/fs/gfs2/glock.h
> +++ b/fs/gfs2/glock.h
> @@ -130,6 +130,7 @@ struct lm_lockops {
>         void (*lm_recovery_result) (struct gfs2_sbd *sdp, unsigned int jid,
>                                     unsigned int result);
>         void (*lm_unmount) (struct gfs2_sbd *sdp);
> +       void (*lm_release) (struct gfs2_sbd *sdp);
>         void (*lm_withdraw) (struct gfs2_sbd *sdp);
>         void (*lm_put_lock) (struct gfs2_glock *gl);
>         int (*lm_lock) (struct gfs2_glock *gl, unsigned int req_state,
> diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
> index 50578f881e6d..776667ca4da1 100644
> --- a/fs/gfs2/lock_dlm.c
> +++ b/fs/gfs2/lock_dlm.c
> @@ -1248,6 +1248,14 @@ static const struct dlm_lockspace_ops gdlm_lockspace_ops = {
>         .recover_done = gdlm_recover_done,
>  };
>
> +static void gdlm_ls_release(struct lm_lockstruct *ls)
> +{
> +       if (ls->ls_dlm) {
> +               dlm_release_lockspace(ls->ls_dlm, 2);
> +               ls->ls_dlm = NULL;
> +       }

I believe there must also be a:
free_recover_size(ls);

> +}
> +
>  static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
>  {
>         struct lm_lockstruct *ls = &sdp->sd_lockstruct;
> @@ -1338,7 +1346,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
>         return 0;
>
>  fail_release:
> -       dlm_release_lockspace(ls->ls_dlm, 2);
> +       gdlm_ls_release(ls);

then don't change this.

>  fail_free:
>         free_recover_size(ls);
>  fail:
> @@ -1374,14 +1382,17 @@ static void gdlm_unmount(struct gfs2_sbd *sdp)
>
>         /* mounted_lock and control_lock will be purged in dlm recovery */
>  release:
> -       if (ls->ls_dlm) {
> -               dlm_release_lockspace(ls->ls_dlm, 2);
> -               ls->ls_dlm = NULL;
> -       }
> -
> +       gdlm_ls_release(ls);
>         free_recover_size(ls);

remove that.

>  }
>
> +static void gdlm_release(struct gfs2_sbd *sdp)
> +{
> +       struct lm_lockstruct *ls = &sdp->sd_lockstruct;
> +
> +       gdlm_ls_release(ls);
> +}
> +
>  static const match_table_t dlm_tokens = {
>         { Opt_jid, "jid=%d"},
>         { Opt_id, "id=%d"},
> @@ -1396,6 +1407,7 @@ const struct lm_lockops gfs2_dlm_ops = {
>         .lm_first_done = gdlm_first_done,
>         .lm_recovery_result = gdlm_recovery_result,
>         .lm_unmount = gdlm_unmount,
> +       .lm_release = gdlm_release,
>         .lm_put_lock = gdlm_put_lock,
>         .lm_lock = gdlm_lock,
>         .lm_cancel = gdlm_cancel,
> diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
> index 7f8410d8fdc1..ef25ed884db2 100644
> --- a/fs/gfs2/ops_fstype.c
> +++ b/fs/gfs2/ops_fstype.c
> @@ -1075,8 +1075,12 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
>  void gfs2_lm_unmount(struct gfs2_sbd *sdp)
>  {
>         const struct lm_lockops *lm = sdp->sd_lockstruct.ls_ops;
> -       if (likely(!gfs2_withdrawn(sdp)) && lm->lm_unmount)
> +       if (likely(!gfs2_withdrawn(sdp)) && lm->lm_unmount) {
>                 lm->lm_unmount(sdp);
> +       } else {
> +               if (lm->lm_release)
> +                       lm->lm_release(sdp);
> +       }

That means we also have a memory leak for some of the fields in
"free_recover_size(ls)".

If this approach is okay, I will send a v2.

- Alex




More information about the Cluster-devel mailing list