* of the GNU General Public License version 2.
*/
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
static void meta_go_sync(struct gfs2_glock *gl)
{
+ if (gl->gl_state != LM_ST_EXCLUSIVE)
+ return;
+
if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
gfs2_log_flush(gl->gl_sbd, gl);
gfs2_meta_sync(gl);
gfs2_ail_empty_gl(gl);
}
-
}
/**
gl->gl_vn++;
}
+/**
+ * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
+ * @gl: the glock protecting the inode
+ *
+ */
+
+static void inode_go_sync(struct gfs2_glock *gl)
+{
+ struct gfs2_inode *ip = gl->gl_object;
+
+ if (ip && !S_ISREG(ip->i_inode.i_mode))
+ ip = NULL;
+
+ if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
+ gfs2_log_flush(gl->gl_sbd, gl);
+ if (ip)
+ filemap_fdatawrite(ip->i_inode.i_mapping);
+ gfs2_meta_sync(gl);
+ if (ip) {
+ struct address_space *mapping = ip->i_inode.i_mapping;
+ int error = filemap_fdatawait(mapping);
+ mapping_set_error(mapping, error);
+ }
+ clear_bit(GLF_DIRTY, &gl->gl_flags);
+ gfs2_ail_empty_gl(gl);
+ }
+}
+
/**
* inode_go_xmote_th - promote/demote a glock
* @gl: the glock
*
*/
-static void inode_go_xmote_th(struct gfs2_glock *gl, unsigned int state,
- int flags)
+static void inode_go_xmote_th(struct gfs2_glock *gl)
{
if (gl->gl_state != LM_ST_UNLOCKED)
gfs2_pte_inval(gl);
- gfs2_glock_xmote_th(gl, state, flags);
+ if (gl->gl_state == LM_ST_EXCLUSIVE)
+ inode_go_sync(gl);
}
/**
static void inode_go_drop_th(struct gfs2_glock *gl)
{
gfs2_pte_inval(gl);
- gfs2_glock_drop_th(gl);
-}
-
-/**
- * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
- * @gl: the glock protecting the inode
- *
- */
-
-static void inode_go_sync(struct gfs2_glock *gl)
-{
- struct gfs2_inode *ip = gl->gl_object;
-
- if (ip && !S_ISREG(ip->i_inode.i_mode))
- ip = NULL;
-
- if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
- gfs2_log_flush(gl->gl_sbd, gl);
- if (ip)
- filemap_fdatawrite(ip->i_inode.i_mapping);
- gfs2_meta_sync(gl);
- if (ip) {
- struct address_space *mapping = ip->i_inode.i_mapping;
- int error = filemap_fdatawait(mapping);
- if (error == -ENOSPC)
- set_bit(AS_ENOSPC, &mapping->flags);
- else if (error)
- set_bit(AS_EIO, &mapping->flags);
- }
- clear_bit(GLF_DIRTY, &gl->gl_flags);
- gfs2_ail_empty_gl(gl);
- }
+ if (gl->gl_state == LM_ST_EXCLUSIVE)
+ inode_go_sync(gl);
}
/**
if (ip && S_ISREG(ip->i_inode.i_mode)) {
truncate_inode_pages(ip->i_inode.i_mapping, 0);
- gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages);
clear_bit(GIF_PAGED, &ip->i_flags);
}
}
if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) &&
(gl->gl_state == LM_ST_EXCLUSIVE) &&
- (gh->gh_flags & GL_LOCAL_EXCL))
+ (gh->gh_state == LM_ST_EXCLUSIVE))
error = gfs2_truncatei_resume(ip);
return error;
gfs2_meta_cache_flush(ip);
}
-/**
- * inode_greedy -
- * @gl: the glock
- *
- */
-
-static void inode_greedy(struct gfs2_glock *gl)
-{
- struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_inode *ip = gl->gl_object;
- unsigned int quantum = gfs2_tune_get(sdp, gt_greedy_quantum);
- unsigned int max = gfs2_tune_get(sdp, gt_greedy_max);
- unsigned int new_time;
-
- spin_lock(&ip->i_spin);
-
- if (time_after(ip->i_last_pfault + quantum, jiffies)) {
- new_time = ip->i_greedy + quantum;
- if (new_time > max)
- new_time = max;
- } else {
- new_time = ip->i_greedy - quantum;
- if (!new_time || new_time > max)
- new_time = 1;
- }
-
- ip->i_greedy = new_time;
-
- spin_unlock(&ip->i_spin);
-
- iput(&ip->i_inode);
-}
-
/**
* rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
* @gl: the glock
*
*/
-static void trans_go_xmote_th(struct gfs2_glock *gl, unsigned int state,
- int flags)
+static void trans_go_xmote_th(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
gfs2_meta_syncfs(sdp);
gfs2_log_shutdown(sdp);
}
-
- gfs2_glock_xmote_th(gl, state, flags);
}
/**
gfs2_meta_syncfs(sdp);
gfs2_log_shutdown(sdp);
}
-
- gfs2_glock_drop_th(gl);
}
/**
}
const struct gfs2_glock_operations gfs2_meta_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
+ .go_xmote_th = meta_go_sync,
+ .go_drop_th = meta_go_sync,
.go_type = LM_TYPE_META,
};
.go_xmote_th = inode_go_xmote_th,
.go_xmote_bh = inode_go_xmote_bh,
.go_drop_th = inode_go_drop_th,
- .go_sync = inode_go_sync,
.go_inval = inode_go_inval,
.go_demote_ok = inode_go_demote_ok,
.go_lock = inode_go_lock,
.go_unlock = inode_go_unlock,
- .go_greedy = inode_greedy,
.go_type = LM_TYPE_INODE,
};
const struct gfs2_glock_operations gfs2_rgrp_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
- .go_sync = meta_go_sync,
+ .go_xmote_th = meta_go_sync,
+ .go_drop_th = meta_go_sync,
.go_inval = meta_go_inval,
.go_demote_ok = rgrp_go_demote_ok,
.go_lock = rgrp_go_lock,
};
const struct gfs2_glock_operations gfs2_iopen_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
.go_type = LM_TYPE_IOPEN,
};
const struct gfs2_glock_operations gfs2_flock_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
.go_type = LM_TYPE_FLOCK,
};
const struct gfs2_glock_operations gfs2_nondisk_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
.go_type = LM_TYPE_NONDISK,
};
const struct gfs2_glock_operations gfs2_quota_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
.go_demote_ok = quota_go_demote_ok,
.go_type = LM_TYPE_QUOTA,
};
const struct gfs2_glock_operations gfs2_journal_glops = {
- .go_xmote_th = gfs2_glock_xmote_th,
- .go_drop_th = gfs2_glock_drop_th,
.go_type = LM_TYPE_JOURNAL,
};