|
@@ -40,6 +40,7 @@
|
|
#include "quota.h"
|
|
#include "quota.h"
|
|
#include "super.h"
|
|
#include "super.h"
|
|
#include "util.h"
|
|
#include "util.h"
|
|
|
|
+#include "bmap.h"
|
|
|
|
|
|
struct gfs2_gl_hash_bucket {
|
|
struct gfs2_gl_hash_bucket {
|
|
struct hlist_head hb_list;
|
|
struct hlist_head hb_list;
|
|
@@ -289,7 +290,8 @@ static void gfs2_holder_wake(struct gfs2_holder *gh)
|
|
* do_promote - promote as many requests as possible on the current queue
|
|
* do_promote - promote as many requests as possible on the current queue
|
|
* @gl: The glock
|
|
* @gl: The glock
|
|
*
|
|
*
|
|
- * Returns: true if there is a blocked holder at the head of the list
|
|
|
|
|
|
+ * Returns: 1 if there is a blocked holder at the head of the list, or 2
|
|
|
|
+ * if a type specific operation is underway.
|
|
*/
|
|
*/
|
|
|
|
|
|
static int do_promote(struct gfs2_glock *gl)
|
|
static int do_promote(struct gfs2_glock *gl)
|
|
@@ -312,6 +314,8 @@ restart:
|
|
ret = glops->go_lock(gh);
|
|
ret = glops->go_lock(gh);
|
|
spin_lock(&gl->gl_spin);
|
|
spin_lock(&gl->gl_spin);
|
|
if (ret) {
|
|
if (ret) {
|
|
|
|
+ if (ret == 1)
|
|
|
|
+ return 2;
|
|
gh->gh_error = ret;
|
|
gh->gh_error = ret;
|
|
list_del_init(&gh->gh_list);
|
|
list_del_init(&gh->gh_list);
|
|
gfs2_holder_wake(gh);
|
|
gfs2_holder_wake(gh);
|
|
@@ -416,6 +420,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
|
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
|
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
|
struct gfs2_holder *gh;
|
|
struct gfs2_holder *gh;
|
|
unsigned state = ret & LM_OUT_ST_MASK;
|
|
unsigned state = ret & LM_OUT_ST_MASK;
|
|
|
|
+ int rv;
|
|
|
|
|
|
spin_lock(&gl->gl_spin);
|
|
spin_lock(&gl->gl_spin);
|
|
state_change(gl, state);
|
|
state_change(gl, state);
|
|
@@ -470,7 +475,6 @@ retry:
|
|
gfs2_demote_wake(gl);
|
|
gfs2_demote_wake(gl);
|
|
if (state != LM_ST_UNLOCKED) {
|
|
if (state != LM_ST_UNLOCKED) {
|
|
if (glops->go_xmote_bh) {
|
|
if (glops->go_xmote_bh) {
|
|
- int rv;
|
|
|
|
spin_unlock(&gl->gl_spin);
|
|
spin_unlock(&gl->gl_spin);
|
|
rv = glops->go_xmote_bh(gl, gh);
|
|
rv = glops->go_xmote_bh(gl, gh);
|
|
if (rv == -EAGAIN)
|
|
if (rv == -EAGAIN)
|
|
@@ -481,10 +485,13 @@ retry:
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- do_promote(gl);
|
|
|
|
|
|
+ rv = do_promote(gl);
|
|
|
|
+ if (rv == 2)
|
|
|
|
+ goto out_locked;
|
|
}
|
|
}
|
|
out:
|
|
out:
|
|
clear_bit(GLF_LOCK, &gl->gl_flags);
|
|
clear_bit(GLF_LOCK, &gl->gl_flags);
|
|
|
|
+out_locked:
|
|
spin_unlock(&gl->gl_spin);
|
|
spin_unlock(&gl->gl_spin);
|
|
gfs2_glock_put(gl);
|
|
gfs2_glock_put(gl);
|
|
}
|
|
}
|
|
@@ -584,6 +591,7 @@ __releases(&gl->gl_spin)
|
|
__acquires(&gl->gl_spin)
|
|
__acquires(&gl->gl_spin)
|
|
{
|
|
{
|
|
struct gfs2_holder *gh = NULL;
|
|
struct gfs2_holder *gh = NULL;
|
|
|
|
+ int ret;
|
|
|
|
|
|
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags))
|
|
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags))
|
|
return;
|
|
return;
|
|
@@ -602,8 +610,11 @@ __acquires(&gl->gl_spin)
|
|
} else {
|
|
} else {
|
|
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
|
|
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
|
|
gfs2_demote_wake(gl);
|
|
gfs2_demote_wake(gl);
|
|
- if (do_promote(gl) == 0)
|
|
|
|
|
|
+ ret = do_promote(gl);
|
|
|
|
+ if (ret == 0)
|
|
goto out;
|
|
goto out;
|
|
|
|
+ if (ret == 2)
|
|
|
|
+ return;
|
|
gh = find_first_waiter(gl);
|
|
gh = find_first_waiter(gl);
|
|
gl->gl_target = gh->gh_state;
|
|
gl->gl_target = gh->gh_state;
|
|
if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
|
|
if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
|
|
@@ -1556,6 +1567,20 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
|
|
|
|
+{
|
|
|
|
+ struct gfs2_glock *gl = ip->i_gl;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = gfs2_truncatei_resume(ip);
|
|
|
|
+ gfs2_assert_withdraw(gl->gl_sbd, ret == 0);
|
|
|
|
+
|
|
|
|
+ spin_lock(&gl->gl_spin);
|
|
|
|
+ clear_bit(GLF_LOCK, &gl->gl_flags);
|
|
|
|
+ run_queue(gl, 1);
|
|
|
|
+ spin_unlock(&gl->gl_spin);
|
|
|
|
+}
|
|
|
|
+
|
|
static const char *state2str(unsigned state)
|
|
static const char *state2str(unsigned state)
|
|
{
|
|
{
|
|
switch(state) {
|
|
switch(state) {
|