diff options
-rw-r--r-- | fs/gfs2/glock.c | 94 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 6 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 1 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 34 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 1 |
5 files changed, 123 insertions, 13 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 661350989e98..0290a22ebccf 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -305,6 +305,11 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) | |||
305 | clear_bit(HIF_WAIT, &gh->gh_iflags); | 305 | clear_bit(HIF_WAIT, &gh->gh_iflags); |
306 | smp_mb__after_atomic(); | 306 | smp_mb__after_atomic(); |
307 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); | 307 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); |
308 | if (gh->gh_flags & GL_ASYNC) { | ||
309 | struct gfs2_sbd *sdp = gh->gh_gl->gl_name.ln_sbd; | ||
310 | |||
311 | wake_up(&sdp->sd_async_glock_wait); | ||
312 | } | ||
308 | } | 313 | } |
309 | 314 | ||
310 | /** | 315 | /** |
@@ -959,6 +964,91 @@ int gfs2_glock_wait(struct gfs2_holder *gh) | |||
959 | return gh->gh_error; | 964 | return gh->gh_error; |
960 | } | 965 | } |
961 | 966 | ||
967 | static int glocks_pending(unsigned int num_gh, struct gfs2_holder *ghs) | ||
968 | { | ||
969 | int i; | ||
970 | |||
971 | for (i = 0; i < num_gh; i++) | ||
972 | if (test_bit(HIF_WAIT, &ghs[i].gh_iflags)) | ||
973 | return 1; | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | /** | ||
978 | * gfs2_glock_async_wait - wait on multiple asynchronous glock acquisitions | ||
979 | * @num_gh: the number of holders in the array | ||
980 | * @ghs: the glock holder array | ||
981 | * | ||
982 | * Returns: 0 on success, meaning all glocks have been granted and are held. | ||
983 | * -ESTALE if the request timed out, meaning all glocks were released, | ||
984 | * and the caller should retry the operation. | ||
985 | */ | ||
986 | |||
987 | int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs) | ||
988 | { | ||
989 | struct gfs2_sbd *sdp = ghs[0].gh_gl->gl_name.ln_sbd; | ||
990 | int i, ret = 0, timeout = 0; | ||
991 | unsigned long start_time = jiffies; | ||
992 | bool keep_waiting; | ||
993 | |||
994 | might_sleep(); | ||
995 | /* | ||
996 | * Total up the (minimum hold time * 2) of all glocks and use that to | ||
997 | * determine the max amount of time we should wait. | ||
998 | */ | ||
999 | for (i = 0; i < num_gh; i++) | ||
1000 | timeout += ghs[i].gh_gl->gl_hold_time << 1; | ||
1001 | |||
1002 | wait_for_dlm: | ||
1003 | if (!wait_event_timeout(sdp->sd_async_glock_wait, | ||
1004 | !glocks_pending(num_gh, ghs), timeout)) | ||
1005 | ret = -ESTALE; /* request timed out. */ | ||
1006 | |||
1007 | /* | ||
1008 | * If dlm granted all our requests, we need to adjust the glock | ||
1009 | * minimum hold time values according to how long we waited. | ||
1010 | * | ||
1011 | * If our request timed out, we need to repeatedly release any held | ||
1012 | * glocks we acquired thus far to allow dlm to acquire the remaining | ||
1013 | * glocks without deadlocking. We cannot currently cancel outstanding | ||
1014 | * glock acquisitions. | ||
1015 | * | ||
1016 | * The HIF_WAIT bit tells us which requests still need a response from | ||
1017 | * dlm. | ||
1018 | * | ||
1019 | * If dlm sent us any errors, we return the first error we find. | ||
1020 | */ | ||
1021 | keep_waiting = false; | ||
1022 | for (i = 0; i < num_gh; i++) { | ||
1023 | /* Skip holders we have already dequeued below. */ | ||
1024 | if (!gfs2_holder_queued(&ghs[i])) | ||
1025 | continue; | ||
1026 | /* Skip holders with a pending DLM response. */ | ||
1027 | if (test_bit(HIF_WAIT, &ghs[i].gh_iflags)) { | ||
1028 | keep_waiting = true; | ||
1029 | continue; | ||
1030 | } | ||
1031 | |||
1032 | if (test_bit(HIF_HOLDER, &ghs[i].gh_iflags)) { | ||
1033 | if (ret == -ESTALE) | ||
1034 | gfs2_glock_dq(&ghs[i]); | ||
1035 | else | ||
1036 | gfs2_glock_update_hold_time(ghs[i].gh_gl, | ||
1037 | start_time); | ||
1038 | } | ||
1039 | if (!ret) | ||
1040 | ret = ghs[i].gh_error; | ||
1041 | } | ||
1042 | |||
1043 | if (keep_waiting) | ||
1044 | goto wait_for_dlm; | ||
1045 | |||
1046 | /* | ||
1047 | * At this point, we've either acquired all locks or released them all. | ||
1048 | */ | ||
1049 | return ret; | ||
1050 | } | ||
1051 | |||
962 | /** | 1052 | /** |
963 | * handle_callback - process a demote request | 1053 | * handle_callback - process a demote request |
964 | * @gl: the glock | 1054 | * @gl: the glock |
@@ -1025,9 +1115,9 @@ __acquires(&gl->gl_lockref.lock) | |||
1025 | struct gfs2_holder *gh2; | 1115 | struct gfs2_holder *gh2; |
1026 | int try_futile = 0; | 1116 | int try_futile = 0; |
1027 | 1117 | ||
1028 | BUG_ON(gh->gh_owner_pid == NULL); | 1118 | GLOCK_BUG_ON(gl, gh->gh_owner_pid == NULL); |
1029 | if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) | 1119 | if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) |
1030 | BUG(); | 1120 | GLOCK_BUG_ON(gl, true); |
1031 | 1121 | ||
1032 | if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { | 1122 | if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { |
1033 | if (test_bit(GLF_LOCK, &gl->gl_flags)) | 1123 | if (test_bit(GLF_LOCK, &gl->gl_flags)) |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index e4e0bed5257c..b8adaf80e4c5 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -190,6 +190,7 @@ extern void gfs2_holder_uninit(struct gfs2_holder *gh); | |||
190 | extern int gfs2_glock_nq(struct gfs2_holder *gh); | 190 | extern int gfs2_glock_nq(struct gfs2_holder *gh); |
191 | extern int gfs2_glock_poll(struct gfs2_holder *gh); | 191 | extern int gfs2_glock_poll(struct gfs2_holder *gh); |
192 | extern int gfs2_glock_wait(struct gfs2_holder *gh); | 192 | extern int gfs2_glock_wait(struct gfs2_holder *gh); |
193 | extern int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs); | ||
193 | extern void gfs2_glock_dq(struct gfs2_holder *gh); | 194 | extern void gfs2_glock_dq(struct gfs2_holder *gh); |
194 | extern void gfs2_glock_dq_wait(struct gfs2_holder *gh); | 195 | extern void gfs2_glock_dq_wait(struct gfs2_holder *gh); |
195 | extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh); | 196 | extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh); |
@@ -260,6 +261,11 @@ static inline bool gfs2_holder_initialized(struct gfs2_holder *gh) | |||
260 | return gh->gh_gl; | 261 | return gh->gh_gl; |
261 | } | 262 | } |
262 | 263 | ||
264 | static inline bool gfs2_holder_queued(struct gfs2_holder *gh) | ||
265 | { | ||
266 | return !list_empty(&gh->gh_list); | ||
267 | } | ||
268 | |||
263 | /** | 269 | /** |
264 | * glock_set_object - set the gl_object field of a glock | 270 | * glock_set_object - set the gl_object field of a glock |
265 | * @gl: the glock | 271 | * @gl: the glock |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 7a993d7c022e..6b450065b9d5 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -725,6 +725,7 @@ struct gfs2_sbd { | |||
725 | struct gfs2_glock *sd_freeze_gl; | 725 | struct gfs2_glock *sd_freeze_gl; |
726 | struct work_struct sd_freeze_work; | 726 | struct work_struct sd_freeze_work; |
727 | wait_queue_head_t sd_glock_wait; | 727 | wait_queue_head_t sd_glock_wait; |
728 | wait_queue_head_t sd_async_glock_wait; | ||
728 | atomic_t sd_glock_disposal; | 729 | atomic_t sd_glock_disposal; |
729 | struct completion sd_locking_init; | 730 | struct completion sd_locking_init; |
730 | struct completion sd_wdack; | 731 | struct completion sd_wdack; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 50eeb15c6f4f..e1e18fb587eb 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -1388,16 +1388,18 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | num_gh = 1; | 1390 | num_gh = 1; |
1391 | gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 1391 | gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs); |
1392 | if (odip != ndip) { | 1392 | if (odip != ndip) { |
1393 | gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 1393 | gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE,GL_ASYNC, |
1394 | ghs + num_gh); | ||
1394 | num_gh++; | 1395 | num_gh++; |
1395 | } | 1396 | } |
1396 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 1397 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); |
1397 | num_gh++; | 1398 | num_gh++; |
1398 | 1399 | ||
1399 | if (nip) { | 1400 | if (nip) { |
1400 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 1401 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, |
1402 | ghs + num_gh); | ||
1401 | num_gh++; | 1403 | num_gh++; |
1402 | } | 1404 | } |
1403 | 1405 | ||
@@ -1406,6 +1408,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
1406 | if (error) | 1408 | if (error) |
1407 | goto out_gunlock; | 1409 | goto out_gunlock; |
1408 | } | 1410 | } |
1411 | error = gfs2_glock_async_wait(num_gh, ghs); | ||
1412 | if (error) | ||
1413 | goto out_gunlock; | ||
1409 | 1414 | ||
1410 | if (nip) { | 1415 | if (nip) { |
1411 | /* Grab the resource group glock for unlink flag twiddling. | 1416 | /* Grab the resource group glock for unlink flag twiddling. |
@@ -1555,7 +1560,8 @@ out_gunlock: | |||
1555 | gfs2_glock_dq_uninit(&rd_gh); | 1560 | gfs2_glock_dq_uninit(&rd_gh); |
1556 | 1561 | ||
1557 | while (x--) { | 1562 | while (x--) { |
1558 | gfs2_glock_dq(ghs + x); | 1563 | if (gfs2_holder_queued(ghs + x)) |
1564 | gfs2_glock_dq(ghs + x); | ||
1559 | gfs2_holder_uninit(ghs + x); | 1565 | gfs2_holder_uninit(ghs + x); |
1560 | } | 1566 | } |
1561 | out_gunlock_r: | 1567 | out_gunlock_r: |
@@ -1585,7 +1591,7 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry, | |||
1585 | struct gfs2_inode *oip = GFS2_I(odentry->d_inode); | 1591 | struct gfs2_inode *oip = GFS2_I(odentry->d_inode); |
1586 | struct gfs2_inode *nip = GFS2_I(ndentry->d_inode); | 1592 | struct gfs2_inode *nip = GFS2_I(ndentry->d_inode); |
1587 | struct gfs2_sbd *sdp = GFS2_SB(odir); | 1593 | struct gfs2_sbd *sdp = GFS2_SB(odir); |
1588 | struct gfs2_holder ghs[5], r_gh; | 1594 | struct gfs2_holder ghs[4], r_gh; |
1589 | unsigned int num_gh; | 1595 | unsigned int num_gh; |
1590 | unsigned int x; | 1596 | unsigned int x; |
1591 | umode_t old_mode = oip->i_inode.i_mode; | 1597 | umode_t old_mode = oip->i_inode.i_mode; |
@@ -1619,15 +1625,16 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry, | |||
1619 | } | 1625 | } |
1620 | 1626 | ||
1621 | num_gh = 1; | 1627 | num_gh = 1; |
1622 | gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 1628 | gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs); |
1623 | if (odip != ndip) { | 1629 | if (odip != ndip) { |
1624 | gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 1630 | gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, |
1631 | ghs + num_gh); | ||
1625 | num_gh++; | 1632 | num_gh++; |
1626 | } | 1633 | } |
1627 | gfs2_holder_init(oip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 1634 | gfs2_holder_init(oip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); |
1628 | num_gh++; | 1635 | num_gh++; |
1629 | 1636 | ||
1630 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 1637 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); |
1631 | num_gh++; | 1638 | num_gh++; |
1632 | 1639 | ||
1633 | for (x = 0; x < num_gh; x++) { | 1640 | for (x = 0; x < num_gh; x++) { |
@@ -1636,6 +1643,10 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry, | |||
1636 | goto out_gunlock; | 1643 | goto out_gunlock; |
1637 | } | 1644 | } |
1638 | 1645 | ||
1646 | error = gfs2_glock_async_wait(num_gh, ghs); | ||
1647 | if (error) | ||
1648 | goto out_gunlock; | ||
1649 | |||
1639 | error = -ENOENT; | 1650 | error = -ENOENT; |
1640 | if (oip->i_inode.i_nlink == 0 || nip->i_inode.i_nlink == 0) | 1651 | if (oip->i_inode.i_nlink == 0 || nip->i_inode.i_nlink == 0) |
1641 | goto out_gunlock; | 1652 | goto out_gunlock; |
@@ -1696,7 +1707,8 @@ out_end_trans: | |||
1696 | gfs2_trans_end(sdp); | 1707 | gfs2_trans_end(sdp); |
1697 | out_gunlock: | 1708 | out_gunlock: |
1698 | while (x--) { | 1709 | while (x--) { |
1699 | gfs2_glock_dq(ghs + x); | 1710 | if (gfs2_holder_queued(ghs + x)) |
1711 | gfs2_glock_dq(ghs + x); | ||
1700 | gfs2_holder_uninit(ghs + x); | 1712 | gfs2_holder_uninit(ghs + x); |
1701 | } | 1713 | } |
1702 | out_gunlock_r: | 1714 | out_gunlock_r: |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 4a8e5a7310f0..f3fd5cd9d43f 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -87,6 +87,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
87 | gfs2_tune_init(&sdp->sd_tune); | 87 | gfs2_tune_init(&sdp->sd_tune); |
88 | 88 | ||
89 | init_waitqueue_head(&sdp->sd_glock_wait); | 89 | init_waitqueue_head(&sdp->sd_glock_wait); |
90 | init_waitqueue_head(&sdp->sd_async_glock_wait); | ||
90 | atomic_set(&sdp->sd_glock_disposal, 0); | 91 | atomic_set(&sdp->sd_glock_disposal, 0); |
91 | init_completion(&sdp->sd_locking_init); | 92 | init_completion(&sdp->sd_locking_init); |
92 | init_completion(&sdp->sd_wdack); | 93 | init_completion(&sdp->sd_wdack); |