Skip to content

Commit e725f44

Browse files
author
Andreas Gruenbacher
committed
gfs2: Add proper lockspace locking
JIRA: https://issues.redhat.com/browse/RHEL-116886 Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git Conflicts: RHEL-9 doesn't have commit dc52cd2 ("fs: dlm: fix F_CANCELLK to cancel pending request"). 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 4db41bf ("dlm: remove ls_local_handle from struct dlm_ls"). To fix that, add proper lockspace locking. Fixes: 3e11e53 ("GFS2: ignore unlock failures after withdraw") Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> (cherry picked from commit 6ab2655)
1 parent 5bb6a38 commit e725f44

File tree

4 files changed

+54
-18
lines changed

4 files changed

+54
-18
lines changed

fs/gfs2/file.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
14161416
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
14171417
struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
14181418
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
1419+
int ret;
14191420

14201421
if (!(fl->fl_flags & FL_POSIX))
14211422
return -ENOLCK;
@@ -1429,12 +1430,18 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
14291430
locks_lock_file_wait(file, fl);
14301431
return -EIO;
14311432
}
1432-
if (IS_GETLK(cmd))
1433-
return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
1434-
else if (fl->fl_type == F_UNLCK)
1435-
return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
1436-
else
1437-
return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
1433+
down_read(&ls->ls_sem);
1434+
ret = -ENODEV;
1435+
if (likely(ls->ls_dlm != NULL)) {
1436+
if (IS_GETLK(cmd))
1437+
ret = dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
1438+
else if (fl->fl_type == F_UNLCK)
1439+
ret = dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
1440+
else
1441+
ret = dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
1442+
}
1443+
up_read(&ls->ls_sem);
1444+
return ret;
14381445
}
14391446

14401447
static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh)

fs/gfs2/glock.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,8 @@ __acquires(&gl->gl_lockref.lock)
796796
}
797797
clear_bit(GLF_PENDING_REPLY, &gl->gl_flags);
798798

799-
if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED &&
800-
target == LM_ST_UNLOCKED &&
801-
test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
799+
if (ret == -ENODEV && gl->gl_target == LM_ST_UNLOCKED &&
800+
target == LM_ST_UNLOCKED) {
802801
/*
803802
* The lockspace has been released and the lock has
804803
* been unlocked implicitly.

fs/gfs2/incore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,8 @@ struct lm_lockstruct {
657657
struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */
658658
char *ls_lvb_bits;
659659

660+
struct rw_semaphore ls_sem;
661+
660662
spinlock_t ls_recover_spin; /* protects following fields */
661663
unsigned long ls_recover_flags; /* DFL_ */
662664
uint32_t ls_recover_mount; /* gen in first recover_done cb */

fs/gfs2/lock_dlm.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,13 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
312312
*/
313313

314314
again:
315-
error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname,
316-
GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
315+
down_read(&ls->ls_sem);
316+
error = -ENODEV;
317+
if (likely(ls->ls_dlm != NULL)) {
318+
error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname,
319+
GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
320+
}
321+
up_read(&ls->ls_sem);
317322
if (error == -EBUSY) {
318323
msleep(20);
319324
goto again;
@@ -362,8 +367,13 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
362367
flags |= DLM_LKF_VALBLK;
363368

364369
again:
365-
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, flags,
366-
NULL, gl);
370+
down_read(&ls->ls_sem);
371+
error = -ENODEV;
372+
if (likely(ls->ls_dlm != NULL)) {
373+
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, flags,
374+
NULL, gl);
375+
}
376+
up_read(&ls->ls_sem);
367377
if (error == -EBUSY) {
368378
msleep(20);
369379
goto again;
@@ -379,7 +389,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
379389
static void gdlm_cancel(struct gfs2_glock *gl)
380390
{
381391
struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
382-
dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
392+
393+
down_read(&ls->ls_sem);
394+
if (likely(ls->ls_dlm != NULL)) {
395+
dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
396+
}
397+
up_read(&ls->ls_sem);
383398
}
384399

385400
/*
@@ -560,7 +575,11 @@ static int sync_unlock(struct gfs2_sbd *sdp, struct dlm_lksb *lksb, char *name)
560575
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
561576
int error;
562577

563-
error = dlm_unlock(ls->ls_dlm, lksb->sb_lkid, 0, lksb, ls);
578+
down_read(&ls->ls_sem);
579+
error = -ENODEV;
580+
if (likely(ls->ls_dlm != NULL))
581+
error = dlm_unlock(ls->ls_dlm, lksb->sb_lkid, 0, lksb, ls);
582+
up_read(&ls->ls_sem);
564583
if (error) {
565584
fs_err(sdp, "%s lkid %x error %d\n",
566585
name, lksb->sb_lkid, error);
@@ -587,9 +606,14 @@ static int sync_lock(struct gfs2_sbd *sdp, int mode, uint32_t flags,
587606
memset(strname, 0, GDLM_STRNAME_BYTES);
588607
snprintf(strname, GDLM_STRNAME_BYTES, "%8x%16x", LM_TYPE_NONDISK, num);
589608

590-
error = dlm_lock(ls->ls_dlm, mode, lksb, flags,
591-
strname, GDLM_STRNAME_BYTES - 1,
592-
0, sync_wait_cb, ls, NULL);
609+
down_read(&ls->ls_sem);
610+
error = -ENODEV;
611+
if (likely(ls->ls_dlm != NULL)) {
612+
error = dlm_lock(ls->ls_dlm, mode, lksb, flags,
613+
strname, GDLM_STRNAME_BYTES - 1,
614+
0, sync_wait_cb, ls, NULL);
615+
}
616+
up_read(&ls->ls_sem);
593617
if (error) {
594618
fs_err(sdp, "%s lkid %x flags %x mode %d error %d\n",
595619
name, lksb->sb_lkid, flags, mode, error);
@@ -1315,6 +1339,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
13151339
*/
13161340

13171341
INIT_DELAYED_WORK(&sdp->sd_control_work, gfs2_control_func);
1342+
ls->ls_dlm = NULL;
13181343
spin_lock_init(&ls->ls_recover_spin);
13191344
ls->ls_recover_flags = 0;
13201345
ls->ls_recover_mount = 0;
@@ -1349,6 +1374,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
13491374
* create/join lockspace
13501375
*/
13511376

1377+
init_rwsem(&ls->ls_sem);
13521378
error = dlm_new_lockspace(fsname, cluster, flags, GDLM_LVB_SIZE,
13531379
&gdlm_lockspace_ops, sdp, &ops_result,
13541380
&ls->ls_dlm);
@@ -1428,10 +1454,12 @@ static void gdlm_unmount(struct gfs2_sbd *sdp)
14281454

14291455
/* mounted_lock and control_lock will be purged in dlm recovery */
14301456
release:
1457+
down_write(&ls->ls_sem);
14311458
if (ls->ls_dlm) {
14321459
dlm_release_lockspace(ls->ls_dlm, 2);
14331460
ls->ls_dlm = NULL;
14341461
}
1462+
up_write(&ls->ls_sem);
14351463

14361464
free_recover_size(ls);
14371465
}

0 commit comments

Comments
 (0)