You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (56 commits) [GFS2] Allow journal recovery on read-only mount [GFS2] Lockup on error [GFS2] Fix page_mkwrite truncation race path [GFS2] Fix typo [GFS2] Fix write alloc required shortcut calculation [GFS2] gfs2_alloc_required performance [GFS2] Remove unneeded i_spin [GFS2] Reduce inode size by moving i_alloc out of line [GFS2] Fix assert in log code [GFS2] Fix problems relating to execution of files on GFS2 [GFS2] Initialize extent_list earlier [GFS2] Allow page migration for writeback and ordered pages [GFS2] Remove unused variable [GFS2] Fix log block mapper [GFS2] Minor correction [GFS2] Eliminate the no longer needed sd_statfs_mutex [GFS2] Incremental patch to fix compiler warning [GFS2] Function meta_read optimization [GFS2] Only fetch the dinode once in block_map [GFS2] Reorganize function gfs2_glmutex_lock ...
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@ obj-$(CONFIG_GFS2_FS) += gfs2.o
|
||||
gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
|
||||
glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
|
||||
mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
|
||||
ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \
|
||||
ops_fstype.o ops_inode.o ops_super.o quota.o \
|
||||
recovery.o rgrp.o super.o sys.o trans.o util.o
|
||||
|
||||
obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/
|
||||
|
||||
+20
-17
@@ -59,7 +59,6 @@ struct strip_mine {
|
||||
static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
u64 block, struct page *page)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct inode *inode = &ip->i_inode;
|
||||
struct buffer_head *bh;
|
||||
int release = 0;
|
||||
@@ -95,7 +94,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
set_buffer_uptodate(bh);
|
||||
if (!gfs2_is_jdata(ip))
|
||||
mark_buffer_dirty(bh);
|
||||
if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
|
||||
if (!gfs2_is_writeback(ip))
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 0);
|
||||
|
||||
if (release) {
|
||||
@@ -453,8 +452,8 @@ static inline void bmap_unlock(struct inode *inode, int create)
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
int gfs2_block_map(struct inode *inode, u64 lblock, int create,
|
||||
struct buffer_head *bh_map)
|
||||
int gfs2_block_map(struct inode *inode, sector_t lblock,
|
||||
struct buffer_head *bh_map, int create)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
@@ -470,6 +469,7 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create,
|
||||
unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
|
||||
struct metapath mp;
|
||||
u64 size;
|
||||
struct buffer_head *dibh = NULL;
|
||||
|
||||
BUG_ON(maxlen == 0);
|
||||
|
||||
@@ -500,6 +500,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create,
|
||||
error = gfs2_meta_inode_buffer(ip, &bh);
|
||||
if (error)
|
||||
goto out_fail;
|
||||
dibh = bh;
|
||||
get_bh(dibh);
|
||||
|
||||
for (x = 0; x < end_of_metadata; x++) {
|
||||
lookup_block(ip, bh, x, &mp, create, &new, &dblock);
|
||||
@@ -518,13 +520,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create,
|
||||
if (boundary)
|
||||
set_buffer_boundary(bh_map);
|
||||
if (new) {
|
||||
struct buffer_head *dibh;
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (!error) {
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
}
|
||||
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
set_buffer_new(bh_map);
|
||||
goto out_brelse;
|
||||
}
|
||||
@@ -545,6 +542,8 @@ out_brelse:
|
||||
out_ok:
|
||||
error = 0;
|
||||
out_fail:
|
||||
if (dibh)
|
||||
brelse(dibh);
|
||||
bmap_unlock(inode, create);
|
||||
return error;
|
||||
}
|
||||
@@ -560,7 +559,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
|
||||
BUG_ON(!new);
|
||||
|
||||
bh.b_size = 1 << (inode->i_blkbits + 5);
|
||||
ret = gfs2_block_map(inode, lblock, create, &bh);
|
||||
ret = gfs2_block_map(inode, lblock, &bh, create);
|
||||
*extlen = bh.b_size >> inode->i_blkbits;
|
||||
*dblock = bh.b_blocknr;
|
||||
if (buffer_new(&bh))
|
||||
@@ -684,7 +683,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
|
||||
if (metadata)
|
||||
revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
|
||||
|
||||
error = gfs2_rindex_hold(sdp, &ip->i_alloc.al_ri_gh);
|
||||
error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -786,7 +785,7 @@ out_rg_gunlock:
|
||||
out_rlist:
|
||||
gfs2_rlist_free(&rlist);
|
||||
out:
|
||||
gfs2_glock_dq_uninit(&ip->i_alloc.al_ri_gh);
|
||||
gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -879,7 +878,6 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
loff_t from = inode->i_size;
|
||||
unsigned long index = from >> PAGE_CACHE_SHIFT;
|
||||
unsigned offset = from & (PAGE_CACHE_SIZE-1);
|
||||
@@ -911,7 +909,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
|
||||
err = 0;
|
||||
|
||||
if (!buffer_mapped(bh)) {
|
||||
gfs2_get_block(inode, iblock, bh, 0);
|
||||
gfs2_block_map(inode, iblock, bh, 0);
|
||||
/* unmapped? It's a hole - nothing to do */
|
||||
if (!buffer_mapped(bh))
|
||||
goto unlock;
|
||||
@@ -931,7 +929,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
|
||||
if (!gfs2_is_writeback(ip))
|
||||
gfs2_trans_add_bh(ip->i_gl, bh, 0);
|
||||
|
||||
zero_user_page(page, offset, length, KM_USER0);
|
||||
@@ -1224,8 +1222,13 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
do_div(lblock_stop, bsize);
|
||||
} else {
|
||||
unsigned int shift = sdp->sd_sb.sb_bsize_shift;
|
||||
u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift;
|
||||
lblock = offset >> shift;
|
||||
lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
|
||||
if (lblock_stop > end_of_file) {
|
||||
*alloc_required = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (; lblock < lblock_stop; lblock += extlen) {
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ struct gfs2_inode;
|
||||
struct page;
|
||||
|
||||
int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
|
||||
int gfs2_block_map(struct inode *inode, u64 lblock, int create, struct buffer_head *bh);
|
||||
int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create);
|
||||
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
|
||||
|
||||
int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
|
||||
|
||||
@@ -82,56 +82,6 @@ int gfs2_recoverd(void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
|
||||
* @sdp: Pointer to GFS2 superblock
|
||||
*
|
||||
* Also, periodically check to make sure that we're using the most recent
|
||||
* journal index.
|
||||
*/
|
||||
|
||||
int gfs2_logd(void *data)
|
||||
{
|
||||
struct gfs2_sbd *sdp = data;
|
||||
struct gfs2_holder ji_gh;
|
||||
unsigned long t;
|
||||
int need_flush;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
/* Advance the log tail */
|
||||
|
||||
t = sdp->sd_log_flush_time +
|
||||
gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
|
||||
|
||||
gfs2_ail1_empty(sdp, DIO_ALL);
|
||||
gfs2_log_lock(sdp);
|
||||
need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks);
|
||||
gfs2_log_unlock(sdp);
|
||||
if (need_flush || time_after_eq(jiffies, t)) {
|
||||
gfs2_log_flush(sdp, NULL);
|
||||
sdp->sd_log_flush_time = jiffies;
|
||||
}
|
||||
|
||||
/* Check for latest journal index */
|
||||
|
||||
t = sdp->sd_jindex_refresh_time +
|
||||
gfs2_tune_get(sdp, gt_jindex_refresh_secs) * HZ;
|
||||
|
||||
if (time_after_eq(jiffies, t)) {
|
||||
if (!gfs2_jindex_hold(sdp, &ji_gh))
|
||||
gfs2_glock_dq_uninit(&ji_gh);
|
||||
sdp->sd_jindex_refresh_time = jiffies;
|
||||
}
|
||||
|
||||
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
|
||||
if (freezing(current))
|
||||
refrigerator();
|
||||
schedule_timeout_interruptible(t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_quotad - Write cached quota changes into the quota file
|
||||
* @sdp: Pointer to GFS2 superblock
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
int gfs2_glockd(void *data);
|
||||
int gfs2_recoverd(void *data);
|
||||
int gfs2_logd(void *data);
|
||||
int gfs2_quotad(void *data);
|
||||
|
||||
#endif /* __DAEMON_DOT_H__ */
|
||||
|
||||
+2
-2
@@ -1876,7 +1876,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = gfs2_rindex_hold(sdp, &dip->i_alloc.al_ri_gh);
|
||||
error = gfs2_rindex_hold(sdp, &dip->i_alloc->al_ri_gh);
|
||||
if (error)
|
||||
goto out_qs;
|
||||
|
||||
@@ -1949,7 +1949,7 @@ out_rg_gunlock:
|
||||
gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
|
||||
out_rlist:
|
||||
gfs2_rlist_free(&rlist);
|
||||
gfs2_glock_dq_uninit(&dip->i_alloc.al_ri_gh);
|
||||
gfs2_glock_dq_uninit(&dip->i_alloc->al_ri_gh);
|
||||
out_qs:
|
||||
gfs2_quota_unhold(dip);
|
||||
out:
|
||||
|
||||
+6
-78
@@ -56,46 +56,6 @@ unsigned int gfs2_ea_name2type(const char *name, const char **truncated_name)
|
||||
return type;
|
||||
}
|
||||
|
||||
static int user_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
int error = permission(inode, MAY_READ, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return gfs2_ea_get_i(ip, er);
|
||||
}
|
||||
|
||||
static int user_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
|
||||
if (S_ISREG(inode->i_mode) ||
|
||||
(S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) {
|
||||
int error = permission(inode, MAY_WRITE, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
} else
|
||||
return -EPERM;
|
||||
|
||||
return gfs2_ea_set_i(ip, er);
|
||||
}
|
||||
|
||||
static int user_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
|
||||
if (S_ISREG(inode->i_mode) ||
|
||||
(S_ISDIR(inode->i_mode) && !(inode->i_mode & S_ISVTX))) {
|
||||
int error = permission(inode, MAY_WRITE, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
} else
|
||||
return -EPERM;
|
||||
|
||||
return gfs2_ea_remove_i(ip, er);
|
||||
}
|
||||
|
||||
static int system_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
if (!GFS2_ACL_IS_ACCESS(er->er_name, er->er_name_len) &&
|
||||
@@ -108,8 +68,6 @@ static int system_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
||||
|
||||
return gfs2_ea_get_i(ip, er);
|
||||
}
|
||||
|
||||
@@ -170,40 +128,10 @@ static int system_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
return gfs2_ea_remove_i(ip, er);
|
||||
}
|
||||
|
||||
static int security_eo_get(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
int error = permission(inode, MAY_READ, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return gfs2_ea_get_i(ip, er);
|
||||
}
|
||||
|
||||
static int security_eo_set(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
int error = permission(inode, MAY_WRITE, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return gfs2_ea_set_i(ip, er);
|
||||
}
|
||||
|
||||
static int security_eo_remove(struct gfs2_inode *ip, struct gfs2_ea_request *er)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
int error = permission(inode, MAY_WRITE, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return gfs2_ea_remove_i(ip, er);
|
||||
}
|
||||
|
||||
static const struct gfs2_eattr_operations gfs2_user_eaops = {
|
||||
.eo_get = user_eo_get,
|
||||
.eo_set = user_eo_set,
|
||||
.eo_remove = user_eo_remove,
|
||||
.eo_get = gfs2_ea_get_i,
|
||||
.eo_set = gfs2_ea_set_i,
|
||||
.eo_remove = gfs2_ea_remove_i,
|
||||
.eo_name = "user",
|
||||
};
|
||||
|
||||
@@ -215,9 +143,9 @@ const struct gfs2_eattr_operations gfs2_system_eaops = {
|
||||
};
|
||||
|
||||
static const struct gfs2_eattr_operations gfs2_security_eaops = {
|
||||
.eo_get = security_eo_get,
|
||||
.eo_set = security_eo_set,
|
||||
.eo_remove = security_eo_remove,
|
||||
.eo_get = gfs2_ea_get_i,
|
||||
.eo_set = gfs2_ea_set_i,
|
||||
.eo_remove = gfs2_ea_remove_i,
|
||||
.eo_name = "security",
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -1418,7 +1418,7 @@ out:
|
||||
static int ea_dealloc_block(struct gfs2_inode *ip)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct gfs2_alloc *al = &ip->i_alloc;
|
||||
struct gfs2_alloc *al = ip->i_alloc;
|
||||
struct gfs2_rgrpd *rgd;
|
||||
struct buffer_head *dibh;
|
||||
int error;
|
||||
|
||||
+31
-52
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -217,7 +217,6 @@ int gfs2_glock_put(struct gfs2_glock *gl)
|
||||
if (atomic_dec_and_test(&gl->gl_ref)) {
|
||||
hlist_del(&gl->gl_list);
|
||||
write_unlock(gl_lock_addr(gl->gl_hash));
|
||||
BUG_ON(spin_is_locked(&gl->gl_spin));
|
||||
gfs2_assert(sdp, gl->gl_state == LM_ST_UNLOCKED);
|
||||
gfs2_assert(sdp, list_empty(&gl->gl_reclaim));
|
||||
gfs2_assert(sdp, list_empty(&gl->gl_holders));
|
||||
@@ -346,7 +345,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
||||
gl->gl_object = NULL;
|
||||
gl->gl_sbd = sdp;
|
||||
gl->gl_aspace = NULL;
|
||||
lops_init_le(&gl->gl_le, &gfs2_glock_lops);
|
||||
INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
|
||||
|
||||
/* If this glock protects actual on-disk data or metadata blocks,
|
||||
@@ -461,7 +459,6 @@ static void wait_on_holder(struct gfs2_holder *gh)
|
||||
|
||||
static void gfs2_demote_wake(struct gfs2_glock *gl)
|
||||
{
|
||||
BUG_ON(!spin_is_locked(&gl->gl_spin));
|
||||
gl->gl_demote_state = LM_ST_EXCLUSIVE;
|
||||
clear_bit(GLF_DEMOTE, &gl->gl_flags);
|
||||
smp_mb__after_clear_bit();
|
||||
@@ -507,21 +504,12 @@ static int rq_mutex(struct gfs2_holder *gh)
|
||||
static int rq_promote(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
|
||||
if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
|
||||
if (list_empty(&gl->gl_holders)) {
|
||||
gl->gl_req_gh = gh;
|
||||
set_bit(GLF_LOCK, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
if (atomic_read(&sdp->sd_reclaim_count) >
|
||||
gfs2_tune_get(sdp, gt_reclaim_limit) &&
|
||||
!(gh->gh_flags & LM_FLAG_PRIORITY)) {
|
||||
gfs2_reclaim_glock(sdp);
|
||||
gfs2_reclaim_glock(sdp);
|
||||
}
|
||||
|
||||
gfs2_glock_xmote_th(gh->gh_gl, gh);
|
||||
spin_lock(&gl->gl_spin);
|
||||
}
|
||||
@@ -567,7 +555,10 @@ static int rq_demote(struct gfs2_glock *gl)
|
||||
gfs2_demote_wake(gl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_bit(GLF_LOCK, &gl->gl_flags);
|
||||
set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
|
||||
|
||||
if (gl->gl_demote_state == LM_ST_UNLOCKED ||
|
||||
gl->gl_state != LM_ST_EXCLUSIVE) {
|
||||
spin_unlock(&gl->gl_spin);
|
||||
@@ -576,7 +567,9 @@ static int rq_demote(struct gfs2_glock *gl)
|
||||
spin_unlock(&gl->gl_spin);
|
||||
gfs2_glock_xmote_th(gl, NULL);
|
||||
}
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -598,23 +591,18 @@ static void run_queue(struct gfs2_glock *gl)
|
||||
if (!list_empty(&gl->gl_waiters1)) {
|
||||
gh = list_entry(gl->gl_waiters1.next,
|
||||
struct gfs2_holder, gh_list);
|
||||
|
||||
if (test_bit(HIF_MUTEX, &gh->gh_iflags))
|
||||
blocked = rq_mutex(gh);
|
||||
else
|
||||
gfs2_assert_warn(gl->gl_sbd, 0);
|
||||
|
||||
blocked = rq_mutex(gh);
|
||||
} else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
|
||||
blocked = rq_demote(gl);
|
||||
if (gl->gl_waiters2 && !blocked) {
|
||||
set_bit(GLF_DEMOTE, &gl->gl_flags);
|
||||
gl->gl_demote_state = LM_ST_UNLOCKED;
|
||||
}
|
||||
gl->gl_waiters2 = 0;
|
||||
} else if (!list_empty(&gl->gl_waiters3)) {
|
||||
gh = list_entry(gl->gl_waiters3.next,
|
||||
struct gfs2_holder, gh_list);
|
||||
|
||||
if (test_bit(HIF_PROMOTE, &gh->gh_iflags))
|
||||
blocked = rq_promote(gh);
|
||||
else
|
||||
gfs2_assert_warn(gl->gl_sbd, 0);
|
||||
|
||||
blocked = rq_promote(gh);
|
||||
} else
|
||||
break;
|
||||
|
||||
@@ -632,27 +620,21 @@ static void run_queue(struct gfs2_glock *gl)
|
||||
|
||||
static void gfs2_glmutex_lock(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_holder gh;
|
||||
|
||||
gfs2_holder_init(gl, 0, 0, &gh);
|
||||
set_bit(HIF_MUTEX, &gh.gh_iflags);
|
||||
if (test_and_set_bit(HIF_WAIT, &gh.gh_iflags))
|
||||
BUG();
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
|
||||
struct gfs2_holder gh;
|
||||
|
||||
gfs2_holder_init(gl, 0, 0, &gh);
|
||||
set_bit(HIF_WAIT, &gh.gh_iflags);
|
||||
list_add_tail(&gh.gh_list, &gl->gl_waiters1);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
wait_on_holder(&gh);
|
||||
gfs2_holder_uninit(&gh);
|
||||
} else {
|
||||
gl->gl_owner_pid = current->pid;
|
||||
gl->gl_ip = (unsigned long)__builtin_return_address(0);
|
||||
clear_bit(HIF_WAIT, &gh.gh_iflags);
|
||||
smp_mb();
|
||||
wake_up_bit(&gh.gh_iflags, HIF_WAIT);
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
wait_on_holder(&gh);
|
||||
gfs2_holder_uninit(&gh);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,7 +673,6 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
|
||||
gl->gl_owner_pid = 0;
|
||||
gl->gl_ip = 0;
|
||||
run_queue(gl);
|
||||
BUG_ON(!spin_is_locked(&gl->gl_spin));
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
|
||||
@@ -722,7 +703,10 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
|
||||
}
|
||||
} else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
|
||||
gl->gl_demote_state != state) {
|
||||
gl->gl_demote_state = LM_ST_UNLOCKED;
|
||||
if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
|
||||
gl->gl_waiters2 = 1;
|
||||
else
|
||||
gl->gl_demote_state = LM_ST_UNLOCKED;
|
||||
}
|
||||
spin_unlock(&gl->gl_spin);
|
||||
}
|
||||
@@ -943,8 +927,8 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
|
||||
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||
unsigned int ret;
|
||||
|
||||
if (glops->go_drop_th)
|
||||
glops->go_drop_th(gl);
|
||||
if (glops->go_xmote_th)
|
||||
glops->go_xmote_th(gl);
|
||||
|
||||
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
|
||||
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
|
||||
@@ -1156,8 +1140,6 @@ restart:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
set_bit(HIF_PROMOTE, &gh->gh_iflags);
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
add_to_queue(gh);
|
||||
run_queue(gl);
|
||||
@@ -1248,12 +1230,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
|
||||
list_del_init(&gh->gh_list);
|
||||
|
||||
if (list_empty(&gl->gl_holders)) {
|
||||
spin_unlock(&gl->gl_spin);
|
||||
|
||||
if (glops->go_unlock)
|
||||
if (glops->go_unlock) {
|
||||
spin_unlock(&gl->gl_spin);
|
||||
glops->go_unlock(gh);
|
||||
|
||||
spin_lock(&gl->gl_spin);
|
||||
spin_lock(&gl->gl_spin);
|
||||
}
|
||||
gl->gl_stamp = jiffies;
|
||||
}
|
||||
|
||||
@@ -1910,8 +1891,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
|
||||
print_dbg(gi, " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
|
||||
print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
|
||||
print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no");
|
||||
print_dbg(gi, " le = %s\n",
|
||||
(list_empty(&gl->gl_le.le_list)) ? "no" : "yes");
|
||||
print_dbg(gi, " reclaim = %s\n",
|
||||
(list_empty(&gl->gl_reclaim)) ? "no" : "yes");
|
||||
if (gl->gl_aspace)
|
||||
|
||||
+18
-92
@@ -56,7 +56,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
|
||||
bd = list_entry(head->next, struct gfs2_bufdata,
|
||||
bd_ail_gl_list);
|
||||
bh = bd->bd_bh;
|
||||
gfs2_remove_from_ail(NULL, bd);
|
||||
gfs2_remove_from_ail(bd);
|
||||
bd->bd_bh = NULL;
|
||||
bh->b_private = NULL;
|
||||
bd->bd_blkno = bh->b_blocknr;
|
||||
@@ -86,15 +86,10 @@ static void gfs2_pte_inval(struct gfs2_glock *gl)
|
||||
if (!ip || !S_ISREG(inode->i_mode))
|
||||
return;
|
||||
|
||||
if (!test_bit(GIF_PAGED, &ip->i_flags))
|
||||
return;
|
||||
|
||||
unmap_shared_mapping_range(inode->i_mapping, 0, 0);
|
||||
|
||||
if (test_bit(GIF_SW_PAGED, &ip->i_flags))
|
||||
set_bit(GLF_DIRTY, &gl->gl_flags);
|
||||
|
||||
clear_bit(GIF_SW_PAGED, &ip->i_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,43 +138,33 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
|
||||
static void inode_go_sync(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_inode *ip = gl->gl_object;
|
||||
struct address_space *metamapping = gl->gl_aspace->i_mapping;
|
||||
int error;
|
||||
|
||||
if (gl->gl_state != LM_ST_UNLOCKED)
|
||||
gfs2_pte_inval(gl);
|
||||
if (gl->gl_state != LM_ST_EXCLUSIVE)
|
||||
return;
|
||||
|
||||
if (ip && !S_ISREG(ip->i_inode.i_mode))
|
||||
ip = NULL;
|
||||
|
||||
if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
|
||||
if (ip && !gfs2_is_jdata(ip))
|
||||
filemap_fdatawrite(ip->i_inode.i_mapping);
|
||||
gfs2_log_flush(gl->gl_sbd, gl);
|
||||
if (ip && gfs2_is_jdata(ip))
|
||||
filemap_fdatawrite(ip->i_inode.i_mapping);
|
||||
gfs2_meta_sync(gl);
|
||||
filemap_fdatawrite(metamapping);
|
||||
if (ip) {
|
||||
struct address_space *mapping = ip->i_inode.i_mapping;
|
||||
int error = filemap_fdatawait(mapping);
|
||||
filemap_fdatawrite(mapping);
|
||||
error = filemap_fdatawait(mapping);
|
||||
mapping_set_error(mapping, error);
|
||||
}
|
||||
error = filemap_fdatawait(metamapping);
|
||||
mapping_set_error(metamapping, error);
|
||||
clear_bit(GLF_DIRTY, &gl->gl_flags);
|
||||
gfs2_ail_empty_gl(gl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_go_xmote_th - promote/demote a glock
|
||||
* @gl: the glock
|
||||
* @state: the requested state
|
||||
* @flags:
|
||||
*
|
||||
*/
|
||||
|
||||
static void inode_go_xmote_th(struct gfs2_glock *gl)
|
||||
{
|
||||
if (gl->gl_state != LM_ST_UNLOCKED)
|
||||
gfs2_pte_inval(gl);
|
||||
if (gl->gl_state == LM_ST_EXCLUSIVE)
|
||||
inode_go_sync(gl);
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_go_xmote_bh - After promoting/demoting a glock
|
||||
* @gl: the glock
|
||||
@@ -200,22 +185,6 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_go_drop_th - unlock a glock
|
||||
* @gl: the glock
|
||||
*
|
||||
* Invoked from rq_demote().
|
||||
* Another node needs the lock in EXCLUSIVE mode, or lock (unused for too long)
|
||||
* is being purged from our node's glock cache; we're dropping lock.
|
||||
*/
|
||||
|
||||
static void inode_go_drop_th(struct gfs2_glock *gl)
|
||||
{
|
||||
gfs2_pte_inval(gl);
|
||||
if (gl->gl_state == LM_ST_EXCLUSIVE)
|
||||
inode_go_sync(gl);
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_go_inval - prepare a inode glock to be released
|
||||
* @gl: the glock
|
||||
@@ -234,10 +203,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
|
||||
set_bit(GIF_INVALID, &ip->i_flags);
|
||||
}
|
||||
|
||||
if (ip && S_ISREG(ip->i_inode.i_mode)) {
|
||||
if (ip && S_ISREG(ip->i_inode.i_mode))
|
||||
truncate_inode_pages(ip->i_inode.i_mapping, 0);
|
||||
clear_bit(GIF_PAGED, &ip->i_flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,23 +260,6 @@ static int inode_go_lock(struct gfs2_holder *gh)
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_go_unlock - operation done before an inode lock is unlocked by a
|
||||
* process
|
||||
* @gl: the glock
|
||||
* @flags:
|
||||
*
|
||||
*/
|
||||
|
||||
static void inode_go_unlock(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_inode *ip = gl->gl_object;
|
||||
|
||||
if (ip)
|
||||
gfs2_meta_cache_flush(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
|
||||
* @gl: the glock
|
||||
@@ -350,14 +300,14 @@ static void rgrp_go_unlock(struct gfs2_holder *gh)
|
||||
}
|
||||
|
||||
/**
|
||||
* trans_go_xmote_th - promote/demote the transaction glock
|
||||
* trans_go_sync - promote/demote the transaction glock
|
||||
* @gl: the glock
|
||||
* @state: the requested state
|
||||
* @flags:
|
||||
*
|
||||
*/
|
||||
|
||||
static void trans_go_xmote_th(struct gfs2_glock *gl)
|
||||
static void trans_go_sync(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
|
||||
@@ -384,7 +334,6 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl)
|
||||
|
||||
if (gl->gl_state != LM_ST_UNLOCKED &&
|
||||
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
|
||||
gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode));
|
||||
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
|
||||
|
||||
error = gfs2_find_jhead(sdp->sd_jdesc, &head);
|
||||
@@ -401,24 +350,6 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* trans_go_drop_th - unlock the transaction glock
|
||||
* @gl: the glock
|
||||
*
|
||||
* We want to sync the device even with localcaching. Remember
|
||||
* that localcaching journal replay only marks buffers dirty.
|
||||
*/
|
||||
|
||||
static void trans_go_drop_th(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_sbd *sdp = gl->gl_sbd;
|
||||
|
||||
if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
|
||||
gfs2_meta_syncfs(sdp);
|
||||
gfs2_log_shutdown(sdp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* quota_go_demote_ok - Check to see if it's ok to unlock a quota glock
|
||||
* @gl: the glock
|
||||
@@ -433,25 +364,21 @@ static int quota_go_demote_ok(struct gfs2_glock *gl)
|
||||
|
||||
const struct gfs2_glock_operations gfs2_meta_glops = {
|
||||
.go_xmote_th = meta_go_sync,
|
||||
.go_drop_th = meta_go_sync,
|
||||
.go_type = LM_TYPE_META,
|
||||
};
|
||||
|
||||
const struct gfs2_glock_operations gfs2_inode_glops = {
|
||||
.go_xmote_th = inode_go_xmote_th,
|
||||
.go_xmote_th = inode_go_sync,
|
||||
.go_xmote_bh = inode_go_xmote_bh,
|
||||
.go_drop_th = inode_go_drop_th,
|
||||
.go_inval = inode_go_inval,
|
||||
.go_demote_ok = inode_go_demote_ok,
|
||||
.go_lock = inode_go_lock,
|
||||
.go_unlock = inode_go_unlock,
|
||||
.go_type = LM_TYPE_INODE,
|
||||
.go_min_hold_time = HZ / 10,
|
||||
};
|
||||
|
||||
const struct gfs2_glock_operations gfs2_rgrp_glops = {
|
||||
.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,
|
||||
@@ -461,9 +388,8 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
|
||||
};
|
||||
|
||||
const struct gfs2_glock_operations gfs2_trans_glops = {
|
||||
.go_xmote_th = trans_go_xmote_th,
|
||||
.go_xmote_th = trans_go_sync,
|
||||
.go_xmote_bh = trans_go_xmote_bh,
|
||||
.go_drop_th = trans_go_drop_th,
|
||||
.go_type = LM_TYPE_NONDISK,
|
||||
};
|
||||
|
||||
|
||||
+16
-31
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -131,7 +131,6 @@ struct gfs2_bufdata {
|
||||
struct gfs2_glock_operations {
|
||||
void (*go_xmote_th) (struct gfs2_glock *gl);
|
||||
void (*go_xmote_bh) (struct gfs2_glock *gl);
|
||||
void (*go_drop_th) (struct gfs2_glock *gl);
|
||||
void (*go_inval) (struct gfs2_glock *gl, int flags);
|
||||
int (*go_demote_ok) (struct gfs2_glock *gl);
|
||||
int (*go_lock) (struct gfs2_holder *gh);
|
||||
@@ -141,10 +140,6 @@ struct gfs2_glock_operations {
|
||||
};
|
||||
|
||||
enum {
|
||||
/* Actions */
|
||||
HIF_MUTEX = 0,
|
||||
HIF_PROMOTE = 1,
|
||||
|
||||
/* States */
|
||||
HIF_HOLDER = 6,
|
||||
HIF_FIRST = 7,
|
||||
@@ -171,6 +166,8 @@ enum {
|
||||
GLF_DEMOTE = 3,
|
||||
GLF_PENDING_DEMOTE = 4,
|
||||
GLF_DIRTY = 5,
|
||||
GLF_DEMOTE_IN_PROGRESS = 6,
|
||||
GLF_LFLUSH = 7,
|
||||
};
|
||||
|
||||
struct gfs2_glock {
|
||||
@@ -190,6 +187,7 @@ struct gfs2_glock {
|
||||
struct list_head gl_holders;
|
||||
struct list_head gl_waiters1; /* HIF_MUTEX */
|
||||
struct list_head gl_waiters3; /* HIF_PROMOTE */
|
||||
int gl_waiters2; /* GIF_DEMOTE */
|
||||
|
||||
const struct gfs2_glock_operations *gl_ops;
|
||||
|
||||
@@ -210,7 +208,6 @@ struct gfs2_glock {
|
||||
struct gfs2_sbd *gl_sbd;
|
||||
|
||||
struct inode *gl_aspace;
|
||||
struct gfs2_log_element gl_le;
|
||||
struct list_head gl_ail_list;
|
||||
atomic_t gl_ail_count;
|
||||
struct delayed_work gl_work;
|
||||
@@ -239,7 +236,6 @@ struct gfs2_alloc {
|
||||
enum {
|
||||
GIF_INVALID = 0,
|
||||
GIF_QD_LOCKED = 1,
|
||||
GIF_PAGED = 2,
|
||||
GIF_SW_PAGED = 3,
|
||||
};
|
||||
|
||||
@@ -268,14 +264,10 @@ struct gfs2_inode {
|
||||
struct gfs2_glock *i_gl; /* Move into i_gh? */
|
||||
struct gfs2_holder i_iopen_gh;
|
||||
struct gfs2_holder i_gh; /* for prepare/commit_write only */
|
||||
struct gfs2_alloc i_alloc;
|
||||
struct gfs2_alloc *i_alloc;
|
||||
u64 i_last_rg_alloc;
|
||||
|
||||
spinlock_t i_spin;
|
||||
struct rw_semaphore i_rw_mutex;
|
||||
unsigned long i_last_pfault;
|
||||
|
||||
struct buffer_head *i_cache[GFS2_MAX_META_HEIGHT];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -287,19 +279,12 @@ static inline struct gfs2_inode *GFS2_I(struct inode *inode)
|
||||
return container_of(inode, struct gfs2_inode, i_inode);
|
||||
}
|
||||
|
||||
/* To be removed? */
|
||||
static inline struct gfs2_sbd *GFS2_SB(struct inode *inode)
|
||||
static inline struct gfs2_sbd *GFS2_SB(const struct inode *inode)
|
||||
{
|
||||
return inode->i_sb->s_fs_info;
|
||||
}
|
||||
|
||||
enum {
|
||||
GFF_DID_DIRECT_ALLOC = 0,
|
||||
GFF_EXLOCK = 1,
|
||||
};
|
||||
|
||||
struct gfs2_file {
|
||||
unsigned long f_flags; /* GFF_... */
|
||||
struct mutex f_fl_mutex;
|
||||
struct gfs2_holder f_fl_gh;
|
||||
};
|
||||
@@ -373,8 +358,17 @@ struct gfs2_ail {
|
||||
u64 ai_sync_gen;
|
||||
};
|
||||
|
||||
struct gfs2_journal_extent {
|
||||
struct list_head extent_list;
|
||||
|
||||
unsigned int lblock; /* First logical block */
|
||||
u64 dblock; /* First disk block */
|
||||
u64 blocks;
|
||||
};
|
||||
|
||||
struct gfs2_jdesc {
|
||||
struct list_head jd_list;
|
||||
struct list_head extent_list;
|
||||
|
||||
struct inode *jd_inode;
|
||||
unsigned int jd_jid;
|
||||
@@ -421,13 +415,9 @@ struct gfs2_args {
|
||||
struct gfs2_tune {
|
||||
spinlock_t gt_spin;
|
||||
|
||||
unsigned int gt_ilimit;
|
||||
unsigned int gt_ilimit_tries;
|
||||
unsigned int gt_ilimit_min;
|
||||
unsigned int gt_demote_secs; /* Cache retention for unheld glock */
|
||||
unsigned int gt_incore_log_blocks;
|
||||
unsigned int gt_log_flush_secs;
|
||||
unsigned int gt_jindex_refresh_secs; /* Check for new journal index */
|
||||
|
||||
unsigned int gt_recoverd_secs;
|
||||
unsigned int gt_logd_secs;
|
||||
@@ -443,10 +433,8 @@ struct gfs2_tune {
|
||||
unsigned int gt_new_files_jdata;
|
||||
unsigned int gt_new_files_directio;
|
||||
unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
|
||||
unsigned int gt_lockdump_size;
|
||||
unsigned int gt_stall_secs; /* Detects trouble! */
|
||||
unsigned int gt_complain_secs;
|
||||
unsigned int gt_reclaim_limit; /* Max num of glocks in reclaim list */
|
||||
unsigned int gt_statfs_quantum;
|
||||
unsigned int gt_statfs_slow;
|
||||
};
|
||||
@@ -539,7 +527,6 @@ struct gfs2_sbd {
|
||||
/* StatFS stuff */
|
||||
|
||||
spinlock_t sd_statfs_spin;
|
||||
struct mutex sd_statfs_mutex;
|
||||
struct gfs2_statfs_change_host sd_statfs_master;
|
||||
struct gfs2_statfs_change_host sd_statfs_local;
|
||||
unsigned long sd_statfs_sync_time;
|
||||
@@ -602,20 +589,18 @@ struct gfs2_sbd {
|
||||
unsigned int sd_log_commited_databuf;
|
||||
unsigned int sd_log_commited_revoke;
|
||||
|
||||
unsigned int sd_log_num_gl;
|
||||
unsigned int sd_log_num_buf;
|
||||
unsigned int sd_log_num_revoke;
|
||||
unsigned int sd_log_num_rg;
|
||||
unsigned int sd_log_num_databuf;
|
||||
|
||||
struct list_head sd_log_le_gl;
|
||||
struct list_head sd_log_le_buf;
|
||||
struct list_head sd_log_le_revoke;
|
||||
struct list_head sd_log_le_rg;
|
||||
struct list_head sd_log_le_databuf;
|
||||
struct list_head sd_log_le_ordered;
|
||||
|
||||
unsigned int sd_log_blks_free;
|
||||
atomic_t sd_log_blks_free;
|
||||
struct mutex sd_log_reserve_mutex;
|
||||
|
||||
u64 sd_log_sequence;
|
||||
|
||||
+24
-17
@@ -31,7 +31,6 @@
|
||||
#include "log.h"
|
||||
#include "meta_io.h"
|
||||
#include "ops_address.h"
|
||||
#include "ops_file.h"
|
||||
#include "ops_inode.h"
|
||||
#include "quota.h"
|
||||
#include "rgrp.h"
|
||||
@@ -132,15 +131,21 @@ static struct inode *gfs2_iget_skip(struct super_block *sb,
|
||||
|
||||
void gfs2_set_iop(struct inode *inode)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
umode_t mode = inode->i_mode;
|
||||
|
||||
if (S_ISREG(mode)) {
|
||||
inode->i_op = &gfs2_file_iops;
|
||||
inode->i_fop = &gfs2_file_fops;
|
||||
inode->i_mapping->a_ops = &gfs2_file_aops;
|
||||
if (sdp->sd_args.ar_localflocks)
|
||||
inode->i_fop = &gfs2_file_fops_nolock;
|
||||
else
|
||||
inode->i_fop = &gfs2_file_fops;
|
||||
} else if (S_ISDIR(mode)) {
|
||||
inode->i_op = &gfs2_dir_iops;
|
||||
inode->i_fop = &gfs2_dir_fops;
|
||||
if (sdp->sd_args.ar_localflocks)
|
||||
inode->i_fop = &gfs2_dir_fops_nolock;
|
||||
else
|
||||
inode->i_fop = &gfs2_dir_fops;
|
||||
} else if (S_ISLNK(mode)) {
|
||||
inode->i_op = &gfs2_symlink_iops;
|
||||
} else {
|
||||
@@ -291,12 +296,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
||||
di->di_entries = be32_to_cpu(str->di_entries);
|
||||
|
||||
di->di_eattr = be64_to_cpu(str->di_eattr);
|
||||
return 0;
|
||||
}
|
||||
if (S_ISREG(ip->i_inode.i_mode))
|
||||
gfs2_set_aops(&ip->i_inode);
|
||||
|
||||
static void gfs2_inode_bh(struct gfs2_inode *ip, struct buffer_head *bh)
|
||||
{
|
||||
ip->i_cache[0] = bh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,7 +369,8 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
|
||||
if (error)
|
||||
goto out_rg_gunlock;
|
||||
|
||||
gfs2_trans_add_gl(ip->i_gl);
|
||||
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
|
||||
set_bit(GLF_LFLUSH, &ip->i_gl->gl_flags);
|
||||
|
||||
gfs2_free_di(rgd, ip);
|
||||
|
||||
@@ -707,9 +711,10 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
|
||||
int error;
|
||||
|
||||
gfs2_alloc_get(dip);
|
||||
if (gfs2_alloc_get(dip) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dip->i_alloc.al_requested = RES_DINODE;
|
||||
dip->i_alloc->al_requested = RES_DINODE;
|
||||
error = gfs2_inplace_reserve(dip);
|
||||
if (error)
|
||||
goto out;
|
||||
@@ -855,7 +860,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
|
||||
|
||||
error = alloc_required = gfs2_diradd_alloc_required(&dip->i_inode, name);
|
||||
if (alloc_required < 0)
|
||||
goto fail;
|
||||
goto fail_quota_locks;
|
||||
if (alloc_required) {
|
||||
error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
|
||||
if (error)
|
||||
@@ -896,7 +901,7 @@ fail_end_trans:
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
fail_ipreserv:
|
||||
if (dip->i_alloc.al_rgd)
|
||||
if (dip->i_alloc->al_rgd)
|
||||
gfs2_inplace_release(dip);
|
||||
|
||||
fail_quota_locks:
|
||||
@@ -966,7 +971,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
|
||||
struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
|
||||
int error;
|
||||
u64 generation;
|
||||
struct buffer_head *bh=NULL;
|
||||
struct buffer_head *bh = NULL;
|
||||
|
||||
if (!name->len || name->len > GFS2_FNAMESIZE)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
@@ -1003,8 +1008,6 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
|
||||
if (IS_ERR(inode))
|
||||
goto fail_gunlock2;
|
||||
|
||||
gfs2_inode_bh(GFS2_I(inode), bh);
|
||||
|
||||
error = gfs2_inode_refresh(GFS2_I(inode));
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
@@ -1021,6 +1024,8 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return inode;
|
||||
@@ -1032,6 +1037,8 @@ fail_gunlock2:
|
||||
fail_gunlock:
|
||||
gfs2_glock_dq(ghs);
|
||||
fail:
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,18 @@ static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
|
||||
return ip->i_di.di_flags & GFS2_DIF_JDATA;
|
||||
}
|
||||
|
||||
static inline int gfs2_is_writeback(const struct gfs2_inode *ip)
|
||||
{
|
||||
const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
return (sdp->sd_args.ar_data == GFS2_DATA_WRITEBACK) && !gfs2_is_jdata(ip);
|
||||
}
|
||||
|
||||
static inline int gfs2_is_ordered(const struct gfs2_inode *ip)
|
||||
{
|
||||
const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
return (sdp->sd_args.ar_data == GFS2_DATA_ORDERED) && !gfs2_is_jdata(ip);
|
||||
}
|
||||
|
||||
static inline int gfs2_is_dir(const struct gfs2_inode *ip)
|
||||
{
|
||||
return S_ISDIR(ip->i_inode.i_mode);
|
||||
|
||||
@@ -67,6 +67,11 @@ static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
|
||||
memset(data, 0, 256);
|
||||
strncpy(data, data_arg, 255);
|
||||
|
||||
if (!strlen(data)) {
|
||||
log_error("no mount options, (u)mount helpers not installed");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (options = data; (x = strsep(&options, ":")); ) {
|
||||
if (!*x)
|
||||
continue;
|
||||
|
||||
@@ -89,15 +89,19 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
|
||||
op->info.number = name->ln_number;
|
||||
op->info.start = fl->fl_start;
|
||||
op->info.end = fl->fl_end;
|
||||
op->info.owner = (__u64)(long) fl->fl_owner;
|
||||
if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
|
||||
/* fl_owner is lockd which doesn't distinguish
|
||||
processes on the nfs client */
|
||||
op->info.owner = (__u64) fl->fl_pid;
|
||||
xop->callback = fl->fl_lmops->fl_grant;
|
||||
locks_init_lock(&xop->flc);
|
||||
locks_copy_lock(&xop->flc, fl);
|
||||
xop->fl = fl;
|
||||
xop->file = file;
|
||||
} else
|
||||
} else {
|
||||
op->info.owner = (__u64)(long) fl->fl_owner;
|
||||
xop->callback = NULL;
|
||||
}
|
||||
|
||||
send_op(op);
|
||||
|
||||
@@ -203,7 +207,10 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,
|
||||
op->info.number = name->ln_number;
|
||||
op->info.start = fl->fl_start;
|
||||
op->info.end = fl->fl_end;
|
||||
op->info.owner = (__u64)(long) fl->fl_owner;
|
||||
if (fl->fl_lmops && fl->fl_lmops->fl_grant)
|
||||
op->info.owner = (__u64) fl->fl_pid;
|
||||
else
|
||||
op->info.owner = (__u64)(long) fl->fl_owner;
|
||||
|
||||
send_op(op);
|
||||
wait_event(recv_wq, (op->done != 0));
|
||||
@@ -242,7 +249,10 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
|
||||
op->info.number = name->ln_number;
|
||||
op->info.start = fl->fl_start;
|
||||
op->info.end = fl->fl_end;
|
||||
op->info.owner = (__u64)(long) fl->fl_owner;
|
||||
if (fl->fl_lmops && fl->fl_lmops->fl_grant)
|
||||
op->info.owner = (__u64) fl->fl_pid;
|
||||
else
|
||||
op->info.owner = (__u64)(long) fl->fl_owner;
|
||||
|
||||
send_op(op);
|
||||
wait_event(recv_wq, (op->done != 0));
|
||||
|
||||
@@ -273,18 +273,13 @@ static int gdlm_thread(void *data, int blist)
|
||||
struct gdlm_ls *ls = (struct gdlm_ls *) data;
|
||||
struct gdlm_lock *lp = NULL;
|
||||
uint8_t complete, blocking, submit, drop;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
/* Only thread1 is allowed to do blocking callbacks since gfs
|
||||
may wait for a completion callback within a blocking cb. */
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
add_wait_queue(&ls->thread_wait, &wait);
|
||||
if (no_work(ls, blist))
|
||||
schedule();
|
||||
remove_wait_queue(&ls->thread_wait, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
wait_event_interruptible(ls->thread_wait,
|
||||
!no_work(ls, blist) || kthread_should_stop());
|
||||
|
||||
complete = blocking = submit = drop = 0;
|
||||
|
||||
|
||||
+70
-45
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/lm_interface.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
@@ -68,14 +70,12 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
|
||||
*
|
||||
*/
|
||||
|
||||
void gfs2_remove_from_ail(struct address_space *mapping, struct gfs2_bufdata *bd)
|
||||
void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
|
||||
{
|
||||
bd->bd_ail = NULL;
|
||||
list_del_init(&bd->bd_ail_st_list);
|
||||
list_del_init(&bd->bd_ail_gl_list);
|
||||
atomic_dec(&bd->bd_gl->gl_ail_count);
|
||||
if (mapping)
|
||||
gfs2_meta_cache_flush(GFS2_I(mapping->host));
|
||||
brelse(bd->bd_bh);
|
||||
}
|
||||
|
||||
@@ -92,8 +92,6 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
||||
struct buffer_head *bh;
|
||||
int retry;
|
||||
|
||||
BUG_ON(!spin_is_locked(&sdp->sd_log_lock));
|
||||
|
||||
do {
|
||||
retry = 0;
|
||||
|
||||
@@ -210,7 +208,7 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
|
||||
gfs2_log_unlock(sdp);
|
||||
}
|
||||
|
||||
int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
|
||||
static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
|
||||
{
|
||||
struct gfs2_ail *ai, *s;
|
||||
int ret;
|
||||
@@ -248,7 +246,7 @@ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
||||
bd = list_entry(head->prev, struct gfs2_bufdata,
|
||||
bd_ail_st_list);
|
||||
gfs2_assert(sdp, bd->bd_ail == ai);
|
||||
gfs2_remove_from_ail(bd->bd_bh->b_page->mapping, bd);
|
||||
gfs2_remove_from_ail(bd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +301,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
|
||||
|
||||
mutex_lock(&sdp->sd_log_reserve_mutex);
|
||||
gfs2_log_lock(sdp);
|
||||
while(sdp->sd_log_blks_free <= (blks + reserved_blks)) {
|
||||
while(atomic_read(&sdp->sd_log_blks_free) <= (blks + reserved_blks)) {
|
||||
gfs2_log_unlock(sdp);
|
||||
gfs2_ail1_empty(sdp, 0);
|
||||
gfs2_log_flush(sdp, NULL);
|
||||
@@ -312,7 +310,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
|
||||
gfs2_ail1_start(sdp, 0);
|
||||
gfs2_log_lock(sdp);
|
||||
}
|
||||
sdp->sd_log_blks_free -= blks;
|
||||
atomic_sub(blks, &sdp->sd_log_blks_free);
|
||||
gfs2_log_unlock(sdp);
|
||||
mutex_unlock(&sdp->sd_log_reserve_mutex);
|
||||
|
||||
@@ -332,27 +330,23 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
|
||||
{
|
||||
|
||||
gfs2_log_lock(sdp);
|
||||
sdp->sd_log_blks_free += blks;
|
||||
atomic_add(blks, &sdp->sd_log_blks_free);
|
||||
gfs2_assert_withdraw(sdp,
|
||||
sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
|
||||
atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
|
||||
gfs2_log_unlock(sdp);
|
||||
up_read(&sdp->sd_log_flush_lock);
|
||||
}
|
||||
|
||||
static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
|
||||
{
|
||||
struct inode *inode = sdp->sd_jdesc->jd_inode;
|
||||
int error;
|
||||
struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
|
||||
struct gfs2_journal_extent *je;
|
||||
|
||||
bh_map.b_size = 1 << inode->i_blkbits;
|
||||
error = gfs2_block_map(inode, lbn, 0, &bh_map);
|
||||
if (error || !bh_map.b_blocknr)
|
||||
printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error,
|
||||
(unsigned long long)bh_map.b_blocknr, lbn);
|
||||
gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr);
|
||||
list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
|
||||
if (lbn >= je->lblock && lbn < je->lblock + je->blocks)
|
||||
return je->dblock + lbn - je->lblock;
|
||||
}
|
||||
|
||||
return bh_map.b_blocknr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -561,8 +555,8 @@ static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
|
||||
ail2_empty(sdp, new_tail);
|
||||
|
||||
gfs2_log_lock(sdp);
|
||||
sdp->sd_log_blks_free += dist;
|
||||
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
|
||||
atomic_add(dist, &sdp->sd_log_blks_free);
|
||||
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
|
||||
gfs2_log_unlock(sdp);
|
||||
|
||||
sdp->sd_log_tail = new_tail;
|
||||
@@ -652,7 +646,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
|
||||
get_bh(bh);
|
||||
gfs2_log_unlock(sdp);
|
||||
lock_buffer(bh);
|
||||
if (test_clear_buffer_dirty(bh)) {
|
||||
if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) {
|
||||
bh->b_end_io = end_buffer_write_sync;
|
||||
submit_bh(WRITE, bh);
|
||||
} else {
|
||||
@@ -694,20 +688,16 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
|
||||
*
|
||||
*/
|
||||
|
||||
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
||||
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_ail *ai;
|
||||
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
|
||||
if (gl) {
|
||||
gfs2_log_lock(sdp);
|
||||
if (list_empty(&gl->gl_le.le_list)) {
|
||||
gfs2_log_unlock(sdp);
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
return;
|
||||
}
|
||||
gfs2_log_unlock(sdp);
|
||||
/* Log might have been flushed while we waited for the flush lock */
|
||||
if (gl && !test_bit(GLF_LFLUSH, &gl->gl_flags)) {
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
|
||||
@@ -739,7 +729,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
||||
log_flush_commit(sdp);
|
||||
else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
|
||||
gfs2_log_lock(sdp);
|
||||
sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
|
||||
atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */
|
||||
gfs2_log_unlock(sdp);
|
||||
log_write_header(sdp, 0, PULL);
|
||||
}
|
||||
@@ -767,7 +757,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
||||
static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
||||
{
|
||||
unsigned int reserved;
|
||||
unsigned int old;
|
||||
unsigned int unused;
|
||||
|
||||
gfs2_log_lock(sdp);
|
||||
|
||||
@@ -779,14 +769,11 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
||||
sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
|
||||
gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
|
||||
reserved = calc_reserved(sdp);
|
||||
old = sdp->sd_log_blks_free;
|
||||
sdp->sd_log_blks_free += tr->tr_reserved -
|
||||
(reserved - sdp->sd_log_blks_reserved);
|
||||
|
||||
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
|
||||
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
|
||||
unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
|
||||
gfs2_assert_withdraw(sdp, unused >= 0);
|
||||
atomic_add(unused, &sdp->sd_log_blks_free);
|
||||
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
|
||||
sdp->sd_jdesc->jd_blocks);
|
||||
|
||||
sdp->sd_log_blks_reserved = reserved;
|
||||
|
||||
gfs2_log_unlock(sdp);
|
||||
@@ -825,7 +812,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
|
||||
gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved);
|
||||
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_gl);
|
||||
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf);
|
||||
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
|
||||
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
|
||||
@@ -838,7 +824,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
|
||||
log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
|
||||
(sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
|
||||
|
||||
gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
|
||||
gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
|
||||
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
|
||||
gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
|
||||
|
||||
@@ -866,3 +852,42 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gfs2_logd - Update log tail as Active Items get flushed to in-place blocks
|
||||
* @sdp: Pointer to GFS2 superblock
|
||||
*
|
||||
* Also, periodically check to make sure that we're using the most recent
|
||||
* journal index.
|
||||
*/
|
||||
|
||||
int gfs2_logd(void *data)
|
||||
{
|
||||
struct gfs2_sbd *sdp = data;
|
||||
unsigned long t;
|
||||
int need_flush;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
/* Advance the log tail */
|
||||
|
||||
t = sdp->sd_log_flush_time +
|
||||
gfs2_tune_get(sdp, gt_log_flush_secs) * HZ;
|
||||
|
||||
gfs2_ail1_empty(sdp, DIO_ALL);
|
||||
gfs2_log_lock(sdp);
|
||||
need_flush = sdp->sd_log_num_buf > gfs2_tune_get(sdp, gt_incore_log_blocks);
|
||||
gfs2_log_unlock(sdp);
|
||||
if (need_flush || time_after_eq(jiffies, t)) {
|
||||
gfs2_log_flush(sdp, NULL);
|
||||
sdp->sd_log_flush_time = jiffies;
|
||||
}
|
||||
|
||||
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
|
||||
if (freezing(current))
|
||||
refrigerator();
|
||||
schedule_timeout_interruptible(t);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -48,8 +48,6 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
|
||||
unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
|
||||
unsigned int ssize);
|
||||
|
||||
int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags);
|
||||
|
||||
int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
|
||||
void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
|
||||
void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
||||
@@ -57,11 +55,19 @@ void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
||||
struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
|
||||
struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
|
||||
struct buffer_head *real);
|
||||
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
|
||||
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
|
||||
|
||||
static inline void gfs2_log_flush(struct gfs2_sbd *sbd, struct gfs2_glock *gl)
|
||||
{
|
||||
if (!gl || test_bit(GLF_LFLUSH, &gl->gl_flags))
|
||||
__gfs2_log_flush(sbd, gl);
|
||||
}
|
||||
|
||||
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
|
||||
void gfs2_remove_from_ail(struct address_space *mapping, struct gfs2_bufdata *bd);
|
||||
void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
|
||||
|
||||
void gfs2_log_shutdown(struct gfs2_sbd *sdp);
|
||||
void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
|
||||
int gfs2_logd(void *data);
|
||||
|
||||
#endif /* __LOG_DOT_H__ */
|
||||
|
||||
+13
-58
@@ -87,6 +87,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
}
|
||||
bd->bd_ail = ai;
|
||||
list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list);
|
||||
clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
|
||||
gfs2_log_unlock(sdp);
|
||||
unlock_buffer(bh);
|
||||
}
|
||||
@@ -124,49 +125,6 @@ static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type)
|
||||
return bh;
|
||||
}
|
||||
|
||||
static void __glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
|
||||
{
|
||||
struct gfs2_glock *gl;
|
||||
struct gfs2_trans *tr = current->journal_info;
|
||||
|
||||
tr->tr_touched = 1;
|
||||
|
||||
gl = container_of(le, struct gfs2_glock, gl_le);
|
||||
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl)))
|
||||
return;
|
||||
|
||||
if (!list_empty(&le->le_list))
|
||||
return;
|
||||
|
||||
gfs2_glock_hold(gl);
|
||||
set_bit(GLF_DIRTY, &gl->gl_flags);
|
||||
sdp->sd_log_num_gl++;
|
||||
list_add(&le->le_list, &sdp->sd_log_le_gl);
|
||||
}
|
||||
|
||||
static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
|
||||
{
|
||||
gfs2_log_lock(sdp);
|
||||
__glock_lo_add(sdp, le);
|
||||
gfs2_log_unlock(sdp);
|
||||
}
|
||||
|
||||
static void glock_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
||||
{
|
||||
struct list_head *head = &sdp->sd_log_le_gl;
|
||||
struct gfs2_glock *gl;
|
||||
|
||||
while (!list_empty(head)) {
|
||||
gl = list_entry(head->next, struct gfs2_glock, gl_le.le_list);
|
||||
list_del_init(&gl->gl_le.le_list);
|
||||
sdp->sd_log_num_gl--;
|
||||
|
||||
gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl));
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
gfs2_assert_warn(sdp, !sdp->sd_log_num_gl);
|
||||
}
|
||||
|
||||
static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
|
||||
{
|
||||
struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le);
|
||||
@@ -182,7 +140,8 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
|
||||
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
|
||||
if (!list_empty(&le->le_list))
|
||||
goto out;
|
||||
__glock_lo_add(sdp, &bd->bd_gl->gl_le);
|
||||
set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
|
||||
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
|
||||
gfs2_meta_check(sdp, bd->bd_bh);
|
||||
gfs2_pin(sdp, bd->bd_bh);
|
||||
sdp->sd_log_num_buf++;
|
||||
@@ -556,17 +515,20 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
|
||||
|
||||
lock_buffer(bd->bd_bh);
|
||||
gfs2_log_lock(sdp);
|
||||
if (!list_empty(&bd->bd_list_tr))
|
||||
goto out;
|
||||
tr->tr_touched = 1;
|
||||
if (gfs2_is_jdata(ip)) {
|
||||
tr->tr_num_buf++;
|
||||
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
|
||||
if (tr) {
|
||||
if (!list_empty(&bd->bd_list_tr))
|
||||
goto out;
|
||||
tr->tr_touched = 1;
|
||||
if (gfs2_is_jdata(ip)) {
|
||||
tr->tr_num_buf++;
|
||||
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
|
||||
}
|
||||
}
|
||||
if (!list_empty(&le->le_list))
|
||||
goto out;
|
||||
|
||||
__glock_lo_add(sdp, &bd->bd_gl->gl_le);
|
||||
set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
|
||||
set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
|
||||
if (gfs2_is_jdata(ip)) {
|
||||
gfs2_pin(sdp, bd->bd_bh);
|
||||
tr->tr_num_databuf_new++;
|
||||
@@ -773,12 +735,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
|
||||
}
|
||||
|
||||
|
||||
const struct gfs2_log_operations gfs2_glock_lops = {
|
||||
.lo_add = glock_lo_add,
|
||||
.lo_after_commit = glock_lo_after_commit,
|
||||
.lo_name = "glock",
|
||||
};
|
||||
|
||||
const struct gfs2_log_operations gfs2_buf_lops = {
|
||||
.lo_add = buf_lo_add,
|
||||
.lo_incore_commit = buf_lo_incore_commit,
|
||||
@@ -816,7 +772,6 @@ const struct gfs2_log_operations gfs2_databuf_lops = {
|
||||
};
|
||||
|
||||
const struct gfs2_log_operations *gfs2_log_ops[] = {
|
||||
&gfs2_glock_lops,
|
||||
&gfs2_databuf_lops,
|
||||
&gfs2_buf_lops,
|
||||
&gfs2_rg_lops,
|
||||
|
||||
+1
-2
@@ -29,9 +29,8 @@ static void gfs2_init_inode_once(struct kmem_cache *cachep, void *foo)
|
||||
struct gfs2_inode *ip = foo;
|
||||
|
||||
inode_init_once(&ip->i_inode);
|
||||
spin_lock_init(&ip->i_spin);
|
||||
init_rwsem(&ip->i_rw_mutex);
|
||||
memset(ip->i_cache, 0, sizeof(ip->i_cache));
|
||||
ip->i_alloc = NULL;
|
||||
}
|
||||
|
||||
static void gfs2_init_glock_once(struct kmem_cache *cachep, void *foo)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user