|
| 1 | +gfs2: Add proper lockspace locking |
| 2 | + |
| 3 | +jira KERNEL-325 |
| 4 | +Rebuild_History Non-Buildable kernel-4.18.0-553.89.1.el8_10 |
| 5 | +commit-author Andreas Gruenbacher <agruenba@redhat.com> |
| 6 | +commit 6ab26555c9ffef96c56ca16356e55ac5ab61ec93 |
| 7 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 8 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 9 | +ciq/ciq_backports/kernel-4.18.0-553.89.1.el8_10/6ab26555.failed |
| 10 | + |
| 11 | +GFS2 has been calling functions like dlm_lock() even after the lockspace |
| 12 | +that these functions operate on has been released with |
| 13 | +dlm_release_lockspace(). It has always assumed that those functions |
| 14 | +would return -EINVAL in that case, but that was never guaranteed, and it |
| 15 | +certainly is no longer the case since commit 4db41bf4f04f ("dlm: remove |
| 16 | +ls_local_handle from struct dlm_ls"). |
| 17 | + |
| 18 | +To fix that, add proper lockspace locking. |
| 19 | + |
| 20 | +Fixes: 3e11e5304150 ("GFS2: ignore unlock failures after withdraw") |
| 21 | + Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> |
| 22 | + Reviewed-by: Andrew Price <anprice@redhat.com> |
| 23 | +(cherry picked from commit 6ab26555c9ffef96c56ca16356e55ac5ab61ec93) |
| 24 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 25 | + |
| 26 | +# Conflicts: |
| 27 | +# fs/gfs2/file.c |
| 28 | +# fs/gfs2/lock_dlm.c |
| 29 | +diff --cc fs/gfs2/file.c |
| 30 | +index dd07e0f60888,bc67fa058c84..000000000000 |
| 31 | +--- a/fs/gfs2/file.c |
| 32 | ++++ b/fs/gfs2/file.c |
| 33 | +@@@ -1414,28 -1442,44 +1414,46 @@@ static int gfs2_lock(struct file *file |
| 34 | + struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); |
| 35 | + struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); |
| 36 | + struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
| 37 | ++ int ret; |
| 38 | + |
| 39 | + - if (!(fl->c.flc_flags & FL_POSIX)) |
| 40 | + + if (!(fl->fl_flags & FL_POSIX)) |
| 41 | + + return -ENOLCK; |
| 42 | + + if (__mandatory_lock(&ip->i_inode) && fl->fl_type != F_UNLCK) |
| 43 | + return -ENOLCK; |
| 44 | + - if (gfs2_withdrawing_or_withdrawn(sdp)) { |
| 45 | + - if (lock_is_unlock(fl)) |
| 46 | + + |
| 47 | + + if (cmd == F_CANCELLK) { |
| 48 | + + /* Hack: */ |
| 49 | + + cmd = F_SETLK; |
| 50 | + + fl->fl_type = F_UNLCK; |
| 51 | + + } |
| 52 | + + if (unlikely(gfs2_withdrawn(sdp))) { |
| 53 | + + if (fl->fl_type == F_UNLCK) |
| 54 | + locks_lock_file_wait(file, fl); |
| 55 | + return -EIO; |
| 56 | + } |
| 57 | +++<<<<<<< HEAD |
| 58 | + + if (IS_GETLK(cmd)) |
| 59 | + + return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl); |
| 60 | + + else if (fl->fl_type == F_UNLCK) |
| 61 | + + return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl); |
| 62 | + + else |
| 63 | + + return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl); |
| 64 | +++======= |
| 65 | ++ down_read(&ls->ls_sem); |
| 66 | ++ ret = -ENODEV; |
| 67 | ++ if (likely(ls->ls_dlm != NULL)) { |
| 68 | ++ if (cmd == F_CANCELLK) |
| 69 | ++ ret = dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl); |
| 70 | ++ else if (IS_GETLK(cmd)) |
| 71 | ++ ret = dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl); |
| 72 | ++ else if (lock_is_unlock(fl)) |
| 73 | ++ ret = dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl); |
| 74 | ++ else |
| 75 | ++ ret = dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl); |
| 76 | ++ } |
| 77 | ++ up_read(&ls->ls_sem); |
| 78 | ++ return ret; |
| 79 | + -} |
| 80 | + - |
| 81 | + -static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh) |
| 82 | + -{ |
| 83 | + - struct gfs2_glock *gl = gfs2_glock_hold(fl_gh->gh_gl); |
| 84 | + - |
| 85 | + - /* |
| 86 | + - * Make sure gfs2_glock_put() won't sleep under the file->f_lock |
| 87 | + - * spinlock. |
| 88 | + - */ |
| 89 | + - |
| 90 | + - spin_lock(&file->f_lock); |
| 91 | + - gfs2_holder_uninit(fl_gh); |
| 92 | + - spin_unlock(&file->f_lock); |
| 93 | + - gfs2_glock_put(gl); |
| 94 | +++>>>>>>> 6ab26555c9ff (gfs2: Add proper lockspace locking) |
| 95 | + } |
| 96 | + |
| 97 | + static int do_flock(struct file *file, int cmd, struct file_lock *fl) |
| 98 | +diff --cc fs/gfs2/lock_dlm.c |
| 99 | +index 0579fdbc9c63,3c7db20ce564..000000000000 |
| 100 | +--- a/fs/gfs2/lock_dlm.c |
| 101 | ++++ b/fs/gfs2/lock_dlm.c |
| 102 | +@@@ -334,9 -363,17 +339,19 @@@ static void gdlm_put_lock(struct gfs2_g |
| 103 | + return; |
| 104 | + } |
| 105 | + |
| 106 | + - if (gl->gl_lksb.sb_lvbptr) |
| 107 | + - flags |= DLM_LKF_VALBLK; |
| 108 | + - |
| 109 | + again: |
| 110 | +++<<<<<<< HEAD |
| 111 | + + error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, |
| 112 | + + NULL, gl); |
| 113 | +++======= |
| 114 | ++ down_read(&ls->ls_sem); |
| 115 | ++ error = -ENODEV; |
| 116 | ++ if (likely(ls->ls_dlm != NULL)) { |
| 117 | ++ error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, flags, |
| 118 | ++ NULL, gl); |
| 119 | ++ } |
| 120 | ++ up_read(&ls->ls_sem); |
| 121 | +++>>>>>>> 6ab26555c9ff (gfs2: Add proper lockspace locking) |
| 122 | + if (error == -EBUSY) { |
| 123 | + msleep(20); |
| 124 | + goto again; |
| 125 | +* Unmerged path fs/gfs2/file.c |
| 126 | +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c |
| 127 | +index de182757764b..8581006a1023 100644 |
| 128 | +--- a/fs/gfs2/glock.c |
| 129 | ++++ b/fs/gfs2/glock.c |
| 130 | +@@ -827,9 +827,8 @@ __acquires(&gl->gl_lockref.lock) |
| 131 | + } |
| 132 | + clear_bit(GLF_PENDING_REPLY, &gl->gl_flags); |
| 133 | + |
| 134 | +- if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED && |
| 135 | +- target == LM_ST_UNLOCKED && |
| 136 | +- test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) { |
| 137 | ++ if (ret == -ENODEV && gl->gl_target == LM_ST_UNLOCKED && |
| 138 | ++ target == LM_ST_UNLOCKED) { |
| 139 | + /* |
| 140 | + * The lockspace has been released and the lock has |
| 141 | + * been unlocked implicitly. |
| 142 | +diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h |
| 143 | +index 6eca783f0691..36018c48b8f2 100644 |
| 144 | +--- a/fs/gfs2/incore.h |
| 145 | ++++ b/fs/gfs2/incore.h |
| 146 | +@@ -665,6 +665,8 @@ struct lm_lockstruct { |
| 147 | + struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */ |
| 148 | + char *ls_lvb_bits; |
| 149 | + |
| 150 | ++ struct rw_semaphore ls_sem; |
| 151 | ++ |
| 152 | + spinlock_t ls_recover_spin; /* protects following fields */ |
| 153 | + unsigned long ls_recover_flags; /* DFL_ */ |
| 154 | + uint32_t ls_recover_mount; /* gen in first recover_done cb */ |
| 155 | +* Unmerged path fs/gfs2/lock_dlm.c |
0 commit comments