diff options
| author | Andreas Gruenbacher <agruenba@redhat.com> | 2025-07-07 14:31:41 +0200 |
|---|---|---|
| committer | Andreas Gruenbacher <agruenba@redhat.com> | 2025-09-12 12:02:57 +0200 |
| commit | 6ab26555c9ffef96c56ca16356e55ac5ab61ec93 (patch) | |
| tree | 38d3f524d9b59adae10c000d3d1d05640a659e4c /fs/gfs2/file.c | |
| parent | 47faf937da43df9a84e65e5a880cf813e764971e (diff) | |
gfs2: Add proper lockspace locking
GFS2 has been calling functions like dlm_lock() even after the lockspace
that these functions operate on has been released with
dlm_release_lockspace(). It has always assumed that those functions
would return -EINVAL in that case, but that was never guaranteed, and it
certainly is no longer the case since commit 4db41bf4f04f ("dlm: remove
ls_local_handle from struct dlm_ls").
To fix that, add proper lockspace locking.
Fixes: 3e11e5304150 ("GFS2: ignore unlock failures after withdraw")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Andrew Price <anprice@redhat.com>
Diffstat (limited to 'fs/gfs2/file.c')
| -rw-r--r-- | fs/gfs2/file.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 72d95185a39f..bc67fa058c84 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -1442,6 +1442,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); struct lm_lockstruct *ls = &sdp->sd_lockstruct; + int ret; if (!(fl->c.flc_flags & FL_POSIX)) return -ENOLCK; @@ -1450,14 +1451,20 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) locks_lock_file_wait(file, fl); return -EIO; } - if (cmd == F_CANCELLK) - return dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl); - else if (IS_GETLK(cmd)) - return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl); - else if (lock_is_unlock(fl)) - return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl); - else - return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl); + down_read(&ls->ls_sem); + ret = -ENODEV; + if (likely(ls->ls_dlm != NULL)) { + if (cmd == F_CANCELLK) + ret = dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl); + else if (IS_GETLK(cmd)) + ret = dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl); + else if (lock_is_unlock(fl)) + ret = dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl); + else + ret = dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl); + } + up_read(&ls->ls_sem); + return ret; } static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh) |
