Skip to content

Commit 6ab2655

Browse files
author
Andreas Gruenbacher
committed
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 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> Reviewed-by: Andrew Price <anprice@redhat.com>
1 parent 47faf93 commit 6ab2655

4 files changed

Lines changed: 56 additions & 20 deletions

File tree

fs/gfs2/file.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
14421442
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
14431443
struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
14441444
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
1445+
int ret;
14451446

14461447
if (!(fl->c.flc_flags & FL_POSIX))
14471448
return -ENOLCK;
@@ -1450,14 +1451,20 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
14501451
locks_lock_file_wait(file, fl);
14511452
return -EIO;
14521453
}
1453-
if (cmd == F_CANCELLK)
1454-
return dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl);
1455-
else if (IS_GETLK(cmd))
1456-
return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
1457-
else if (lock_is_unlock(fl))
1458-
return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
1459-
else
1460-
return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
1454+
down_read(&ls->ls_sem);
1455+
ret = -ENODEV;
1456+
if (likely(ls->ls_dlm != NULL)) {
1457+
if (cmd == F_CANCELLK)
1458+
ret = dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl);
1459+
else if (IS_GETLK(cmd))
1460+
ret = dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
1461+
else if (lock_is_unlock(fl))
1462+
ret = dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
1463+
else
1464+
ret = dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
1465+
}
1466+
up_read(&ls->ls_sem);
1467+
return ret;
14611468
}
14621469

14631470
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
@@ -795,9 +795,8 @@ __acquires(&gl->gl_lockref.lock)
795795
}
796796
clear_bit(GLF_PENDING_REPLY, &gl->gl_flags);
797797

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

fs/gfs2/incore.h

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

659+
struct rw_semaphore ls_sem;
660+
659661
spinlock_t ls_recover_spin; /* protects following fields */
660662
unsigned long ls_recover_flags; /* DFL_ */
661663
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);
@@ -1316,6 +1340,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
13161340
*/
13171341

13181342
INIT_DELAYED_WORK(&sdp->sd_control_work, gfs2_control_func);
1343+
ls->ls_dlm = NULL;
13191344
spin_lock_init(&ls->ls_recover_spin);
13201345
ls->ls_recover_flags = 0;
13211346
ls->ls_recover_mount = 0;
@@ -1350,6 +1375,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
13501375
* create/join lockspace
13511376
*/
13521377

1378+
init_rwsem(&ls->ls_sem);
13531379
error = dlm_new_lockspace(fsname, cluster, flags, GDLM_LVB_SIZE,
13541380
&gdlm_lockspace_ops, sdp, &ops_result,
13551381
&ls->ls_dlm);
@@ -1429,10 +1455,12 @@ static void gdlm_unmount(struct gfs2_sbd *sdp)
14291455

14301456
/* mounted_lock and control_lock will be purged in dlm recovery */
14311457
release:
1458+
down_write(&ls->ls_sem);
14321459
if (ls->ls_dlm) {
14331460
dlm_release_lockspace(ls->ls_dlm, 2);
14341461
ls->ls_dlm = NULL;
14351462
}
1463+
up_write(&ls->ls_sem);
14361464

14371465
free_recover_size(ls);
14381466
}

0 commit comments

Comments
 (0)