Commit e07dd2ad authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents eba0e319 7bc5c414
...@@ -2,7 +2,7 @@ obj-$(CONFIG_GFS2_FS) += gfs2.o ...@@ -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 \ 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 \ 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 \ 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 recovery.o rgrp.o super.o sys.o trans.o util.o
obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/ obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/
......
...@@ -59,7 +59,6 @@ struct strip_mine { ...@@ -59,7 +59,6 @@ struct strip_mine {
static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
u64 block, struct page *page) u64 block, struct page *page)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode; struct inode *inode = &ip->i_inode;
struct buffer_head *bh; struct buffer_head *bh;
int release = 0; int release = 0;
...@@ -95,7 +94,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh, ...@@ -95,7 +94,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
if (!gfs2_is_jdata(ip)) if (!gfs2_is_jdata(ip))
mark_buffer_dirty(bh); 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); gfs2_trans_add_bh(ip->i_gl, bh, 0);
if (release) { if (release) {
...@@ -453,8 +452,8 @@ static inline void bmap_unlock(struct inode *inode, int create) ...@@ -453,8 +452,8 @@ static inline void bmap_unlock(struct inode *inode, int create)
* Returns: errno * Returns: errno
*/ */
int gfs2_block_map(struct inode *inode, u64 lblock, int create, int gfs2_block_map(struct inode *inode, sector_t lblock,
struct buffer_head *bh_map) struct buffer_head *bh_map, int create)
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
...@@ -470,6 +469,7 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create, ...@@ -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; unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
struct metapath mp; struct metapath mp;
u64 size; u64 size;
struct buffer_head *dibh = NULL;
BUG_ON(maxlen == 0); BUG_ON(maxlen == 0);
...@@ -500,6 +500,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create, ...@@ -500,6 +500,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create,
error = gfs2_meta_inode_buffer(ip, &bh); error = gfs2_meta_inode_buffer(ip, &bh);
if (error) if (error)
goto out_fail; goto out_fail;
dibh = bh;
get_bh(dibh);
for (x = 0; x < end_of_metadata; x++) { for (x = 0; x < end_of_metadata; x++) {
lookup_block(ip, bh, x, &mp, create, &new, &dblock); lookup_block(ip, bh, x, &mp, create, &new, &dblock);
...@@ -518,13 +520,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create, ...@@ -518,13 +520,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create,
if (boundary) if (boundary)
set_buffer_boundary(bh_map); set_buffer_boundary(bh_map);
if (new) { 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_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data); gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
}
set_buffer_new(bh_map); set_buffer_new(bh_map);
goto out_brelse; goto out_brelse;
} }
...@@ -545,6 +542,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create, ...@@ -545,6 +542,8 @@ int gfs2_block_map(struct inode *inode, u64 lblock, int create,
out_ok: out_ok:
error = 0; error = 0;
out_fail: out_fail:
if (dibh)
brelse(dibh);
bmap_unlock(inode, create); bmap_unlock(inode, create);
return error; return error;
} }
...@@ -560,7 +559,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi ...@@ -560,7 +559,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
BUG_ON(!new); BUG_ON(!new);
bh.b_size = 1 << (inode->i_blkbits + 5); 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; *extlen = bh.b_size >> inode->i_blkbits;
*dblock = bh.b_blocknr; *dblock = bh.b_blocknr;
if (buffer_new(&bh)) if (buffer_new(&bh))
...@@ -684,7 +683,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, ...@@ -684,7 +683,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
if (metadata) if (metadata)
revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; 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) if (error)
return error; return error;
...@@ -786,7 +785,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, ...@@ -786,7 +785,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
out_rlist: out_rlist:
gfs2_rlist_free(&rlist); gfs2_rlist_free(&rlist);
out: out:
gfs2_glock_dq_uninit(&ip->i_alloc.al_ri_gh); gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
return error; return error;
} }
...@@ -879,7 +878,6 @@ static int gfs2_block_truncate_page(struct address_space *mapping) ...@@ -879,7 +878,6 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
{ {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
loff_t from = inode->i_size; loff_t from = inode->i_size;
unsigned long index = from >> PAGE_CACHE_SHIFT; unsigned long index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1); unsigned offset = from & (PAGE_CACHE_SIZE-1);
...@@ -911,7 +909,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping) ...@@ -911,7 +909,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
err = 0; err = 0;
if (!buffer_mapped(bh)) { 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 */ /* unmapped? It's a hole - nothing to do */
if (!buffer_mapped(bh)) if (!buffer_mapped(bh))
goto unlock; goto unlock;
...@@ -931,7 +929,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping) ...@@ -931,7 +929,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
err = 0; 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); gfs2_trans_add_bh(ip->i_gl, bh, 0);
zero_user_page(page, offset, length, KM_USER0); zero_user_page(page, offset, length, KM_USER0);
...@@ -1224,8 +1222,13 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, ...@@ -1224,8 +1222,13 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
do_div(lblock_stop, bsize); do_div(lblock_stop, bsize);
} else { } else {
unsigned int shift = sdp->sd_sb.sb_bsize_shift; 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 = offset >> shift;
lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> 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) { for (; lblock < lblock_stop; lblock += extlen) {
......
...@@ -15,7 +15,7 @@ struct gfs2_inode; ...@@ -15,7 +15,7 @@ struct gfs2_inode;
struct page; struct page;
int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *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_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
int gfs2_truncatei(struct gfs2_inode *ip, u64 size); int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
......
...@@ -82,56 +82,6 @@ int gfs2_recoverd(void *data) ...@@ -82,56 +82,6 @@ int gfs2_recoverd(void *data)
return 0; 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 * gfs2_quotad - Write cached quota changes into the quota file
* @sdp: Pointer to GFS2 superblock * @sdp: Pointer to GFS2 superblock
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
int gfs2_glockd(void *data); int gfs2_glockd(void *data);
int gfs2_recoverd(void *data); int gfs2_recoverd(void *data);
int gfs2_logd(void *data);
int gfs2_quotad(void *data); int gfs2_quotad(void *data);
#endif /* __DAEMON_DOT_H__ */ #endif /* __DAEMON_DOT_H__ */
...@@ -1876,7 +1876,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, ...@@ -1876,7 +1876,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
if (error) if (error)
goto out; 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) if (error)
goto out_qs; goto out_qs;
...@@ -1949,7 +1949,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, ...@@ -1949,7 +1949,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs); gfs2_glock_dq_m(rlist.rl_rgrps, rlist.rl_ghs);
out_rlist: out_rlist:
gfs2_rlist_free(&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: out_qs:
gfs2_quota_unhold(dip); gfs2_quota_unhold(dip);
out: out:
......
...@@ -56,46 +56,6 @@ unsigned int gfs2_ea_name2type(const char *name, const char **truncated_name) ...@@ -56,46 +56,6 @@ unsigned int gfs2_ea_name2type(const char *name, const char **truncated_name)
return type; 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) 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) && 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) ...@@ -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))) GFS2_ACL_IS_DEFAULT(er->er_name, er->er_name_len)))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return gfs2_ea_get_i(ip, er); 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) ...@@ -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); 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 = { static const struct gfs2_eattr_operations gfs2_user_eaops = {
.eo_get = user_eo_get, .eo_get = gfs2_ea_get_i,
.eo_set = user_eo_set, .eo_set = gfs2_ea_set_i,
.eo_remove = user_eo_remove, .eo_remove = gfs2_ea_remove_i,
.eo_name = "user", .eo_name = "user",
}; };
...@@ -215,9 +143,9 @@ const struct gfs2_eattr_operations gfs2_system_eaops = { ...@@ -215,9 +143,9 @@ const struct gfs2_eattr_operations gfs2_system_eaops = {
}; };
static const struct gfs2_eattr_operations gfs2_security_eaops = { static const struct gfs2_eattr_operations gfs2_security_eaops = {
.eo_get = security_eo_get, .eo_get = gfs2_ea_get_i,
.eo_set = security_eo_set, .eo_set = gfs2_ea_set_i,
.eo_remove = security_eo_remove, .eo_remove = gfs2_ea_remove_i,
.eo_name = "security", .eo_name = "security",
}; };
......
...@@ -1418,7 +1418,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) ...@@ -1418,7 +1418,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
static int ea_dealloc_block(struct gfs2_inode *ip) static int ea_dealloc_block(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 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 gfs2_rgrpd *rgd;
struct buffer_head *dibh; struct buffer_head *dibh;
int error; int error;
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * 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, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -217,7 +217,6 @@ int gfs2_glock_put(struct gfs2_glock *gl) ...@@ -217,7 +217,6 @@ int gfs2_glock_put(struct gfs2_glock *gl)
if (atomic_dec_and_test(&gl->gl_ref)) { if (atomic_dec_and_test(&gl->gl_ref)) {
hlist_del(&gl->gl_list); hlist_del(&gl->gl_list);
write_unlock(gl_lock_addr(gl->gl_hash)); 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, gl->gl_state == LM_ST_UNLOCKED);
gfs2_assert(sdp, list_empty(&gl->gl_reclaim)); gfs2_assert(sdp, list_empty(&gl->gl_reclaim));
gfs2_assert(sdp, list_empty(&gl->gl_holders)); gfs2_assert(sdp, list_empty(&gl->gl_holders));
...@@ -346,7 +345,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, ...@@ -346,7 +345,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
gl->gl_object = NULL; gl->gl_object = NULL;
gl->gl_sbd = sdp; gl->gl_sbd = sdp;
gl->gl_aspace = NULL; gl->gl_aspace = NULL;
lops_init_le(&gl->gl_le, &gfs2_glock_lops);
INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
/* If this glock protects actual on-disk data or metadata blocks, /* If this glock protects actual on-disk data or metadata blocks,
...@@ -461,7 +459,6 @@ static void wait_on_holder(struct gfs2_holder *gh) ...@@ -461,7 +459,6 @@ static void wait_on_holder(struct gfs2_holder *gh)
static void gfs2_demote_wake(struct gfs2_glock *gl) static void gfs2_demote_wake(struct gfs2_glock *gl)
{ {
BUG_ON(!spin_is_locked(&gl->gl_spin));
gl->gl_demote_state = LM_ST_EXCLUSIVE; gl->gl_demote_state = LM_ST_EXCLUSIVE;
clear_bit(GLF_DEMOTE, &gl->gl_flags); clear_bit(GLF_DEMOTE, &gl->gl_flags);
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
...@@ -507,21 +504,12 @@ static int rq_mutex(struct gfs2_holder *gh) ...@@ -507,21 +504,12 @@ static int rq_mutex(struct gfs2_holder *gh)
static int rq_promote(struct gfs2_holder *gh) static int rq_promote(struct gfs2_holder *gh)
{ {
struct gfs2_glock *gl = gh->gh_gl; 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 (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
if (list_empty(&gl->gl_holders)) { if (list_empty(&gl->gl_holders)) {
gl->gl_req_gh = gh; gl->gl_req_gh = gh;
set_bit(GLF_LOCK, &gl->gl_flags); set_bit(GLF_LOCK, &gl->gl_flags);
spin_unlock(&gl->gl_spin); 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); gfs2_glock_xmote_th(gh->gh_gl, gh);
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
} }
...@@ -567,7 +555,10 @@ static int rq_demote(struct gfs2_glock *gl) ...@@ -567,7 +555,10 @@ static int rq_demote(struct gfs2_glock *gl)
gfs2_demote_wake(gl); gfs2_demote_wake(gl);
return 0; return 0;
} }
set_bit(GLF_LOCK, &gl->gl_flags); set_bit(GLF_LOCK, &gl->gl_flags);
set_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
if (gl->gl_demote_state == LM_ST_UNLOCKED || if (gl->gl_demote_state == LM_ST_UNLOCKED ||
gl->gl_state != LM_ST_EXCLUSIVE) { gl->gl_state != LM_ST_EXCLUSIVE) {
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
...@@ -576,7 +567,9 @@ static int rq_demote(struct gfs2_glock *gl) ...@@ -576,7 +567,9 @@ static int rq_demote(struct gfs2_glock *gl)
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
gfs2_glock_xmote_th(gl, NULL); gfs2_glock_xmote_th(gl, NULL);
} }
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
return 0; return 0;
} }
...@@ -598,23 +591,18 @@ static void run_queue(struct gfs2_glock *gl) ...@@ -598,23 +591,18 @@ static void run_queue(struct gfs2_glock *gl)
if (!list_empty(&gl->gl_waiters1)) { if (!list_empty(&gl->gl_waiters1)) {
gh = list_entry(gl->gl_waiters1.next, gh = list_entry(gl->gl_waiters1.next,
struct gfs2_holder, gh_list); struct gfs2_holder, gh_list);
if (test_bit(HIF_MUTEX, &gh->gh_iflags))
blocked = rq_mutex(gh); blocked = rq_mutex(gh);
else
gfs2_assert_warn(gl->gl_sbd, 0);
} else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
blocked = rq_demote(gl); 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)) { } else if (!list_empty(&gl->gl_waiters3)) {
gh = list_entry(gl->gl_waiters3.next, gh = list_entry(gl->gl_waiters3.next,
struct gfs2_holder, gh_list); struct gfs2_holder, gh_list);
if (test_bit(HIF_PROMOTE, &gh->gh_iflags))
blocked = rq_promote(gh); blocked = rq_promote(gh);
else
gfs2_assert_warn(gl->gl_sbd, 0);
} else } else
break; break;
...@@ -632,27 +620,21 @@ static void run_queue(struct gfs2_glock *gl) ...@@ -632,27 +620,21 @@ static void run_queue(struct gfs2_glock *gl)
static void gfs2_glmutex_lock(struct gfs2_glock *gl) static void gfs2_glmutex_lock(struct gfs2_glock *gl)
{ {
spin_lock(&gl->gl_spin);
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
struct gfs2_holder gh; struct gfs2_holder gh;
gfs2_holder_init(gl, 0, 0, &gh); gfs2_holder_init(gl, 0, 0, &gh);
set_bit(HIF_MUTEX, &gh.gh_iflags); set_bit(HIF_WAIT, &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)) {
list_add_tail(&gh.gh_list, &gl->gl_waiters1); list_add_tail(&gh.gh_list, &gl->gl_waiters1);
spin_unlock(&gl->gl_spin);
wait_on_holder(&gh);
gfs2_holder_uninit(&gh);
} else { } else {
gl->gl_owner_pid = current->pid; gl->gl_owner_pid = current->pid;
gl->gl_ip = (unsigned long)__builtin_return_address(0); 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) ...@@ -691,7 +673,6 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
gl->gl_owner_pid = 0; gl->gl_owner_pid = 0;
gl->gl_ip = 0; gl->gl_ip = 0;
run_queue(gl); run_queue(gl);
BUG_ON(!spin_is_locked(&gl->gl_spin));
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
} }
...@@ -722,6 +703,9 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state, ...@@ -722,6 +703,9 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
} }
} else if (gl->gl_demote_state != LM_ST_UNLOCKED && } else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
gl->gl_demote_state != state) { gl->gl_demote_state != state) {
if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
gl->gl_waiters2 = 1;
else
gl->gl_demote_state = LM_ST_UNLOCKED; gl->gl_demote_state = LM_ST_UNLOCKED;
} }
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
...@@ -943,8 +927,8 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl) ...@@ -943,8 +927,8 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
const struct gfs2_glock_operations *glops = gl->gl_ops; const struct gfs2_glock_operations *glops = gl->gl_ops;
unsigned int ret; unsigned int ret;
if (glops->go_drop_th) if (glops->go_xmote_th)
glops->go_drop_th(gl); glops->go_xmote_th(gl);
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
...@@ -1156,8 +1140,6 @@ int gfs2_glock_nq(struct gfs2_holder *gh) ...@@ -1156,8 +1140,6 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
return -EIO; return -EIO;
} }
set_bit(HIF_PROMOTE, &gh->gh_iflags);
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
add_to_queue(gh); add_to_queue(gh);
run_queue(gl); run_queue(gl);
...@@ -1248,12 +1230,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh) ...@@ -1248,12 +1230,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
list_del_init(&gh->gh_list); list_del_init(&gh->gh_list);
if (list_empty(&gl->gl_holders)) { if (list_empty(&gl->gl_holders)) {
if (glops->go_unlock) {
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
if (glops->go_unlock)
glops->go_unlock(gh); glops->go_unlock(gh);
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
}
gl->gl_stamp = jiffies; gl->gl_stamp = jiffies;
} }
...@@ -1910,8 +1891,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl) ...@@ -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, " 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, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no"); 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", print_dbg(gi, " reclaim = %s\n",
(list_empty(&gl->gl_reclaim)) ? "no" : "yes"); (list_empty(&gl->gl_reclaim)) ? "no" : "yes");
if (gl->gl_aspace) if (gl->gl_aspace)
......
...@@ -56,7 +56,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) ...@@ -56,7 +56,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
bd = list_entry(head->next, struct gfs2_bufdata, bd = list_entry(head->next, struct gfs2_bufdata,
bd_ail_gl_list); bd_ail_gl_list);
bh = bd->bd_bh; bh = bd->bd_bh;
gfs2_remove_from_ail(NULL, bd); gfs2_remove_from_ail(bd);
bd->bd_bh = NULL; bd->bd_bh = NULL;
bh->b_private = NULL; bh->b_private = NULL;
bd->bd_blkno = bh->b_blocknr; bd->bd_blkno = bh->b_blocknr;
...@@ -86,15 +86,10 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) ...@@ -86,15 +86,10 @@ static void gfs2_pte_inval(struct gfs2_glock *gl)
if (!ip || !S_ISREG(inode->i_mode)) if (!ip || !S_ISREG(inode->i_mode))
return; return;
if (!test_bit(GIF_PAGED, &ip->i_flags))
return;
unmap_shared_mapping_range(inode->i_mapping, 0, 0); unmap_shared_mapping_range(inode->i_mapping, 0, 0);
if (test_bit(GIF_SW_PAGED, &ip->i_flags)) if (test_bit(GIF_SW_PAGED, &ip->i_flags))
set_bit(GLF_DIRTY, &gl->gl_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) ...@@ -143,43 +138,33 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
static void inode_go_sync(struct gfs2_glock *gl) static void inode_go_sync(struct gfs2_glock *gl)
{ {
struct gfs2_inode *ip = gl->gl_object; 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)) if (ip && !S_ISREG(ip->i_inode.i_mode))
ip = NULL; ip = NULL;
if (test_bit(GLF_DIRTY, &gl->gl_flags)) { 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); gfs2_log_flush(gl->gl_sbd, gl);
if (ip && gfs2_is_jdata(ip)) filemap_fdatawrite(metamapping);
filemap_fdatawrite(ip->i_inode.i_mapping);
gfs2_meta_sync(gl);
if (ip) { if (ip) {
struct address_space *mapping = ip->i_inode.i_mapping; 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); mapping_set_error(mapping, error);
} }
error = filemap_fdatawait(metamapping);
mapping_set_error(metamapping, error);
clear_bit(GLF_DIRTY, &gl->gl_flags); clear_bit(GLF_DIRTY, &gl->gl_flags);
gfs2_ail_empty_gl(gl); 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 * inode_go_xmote_bh - After promoting/demoting a glock
* @gl: the glock * @gl: the glock
...@@ -200,22 +185,6 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl) ...@@ -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 * inode_go_inval - prepare a inode glock to be released
* @gl: the glock * @gl: the glock
...@@ -234,10 +203,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) ...@@ -234,10 +203,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
set_bit(GIF_INVALID, &ip->i_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); 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) ...@@ -293,23 +260,6 @@ static int inode_go_lock(struct gfs2_holder *gh)
return error; 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 * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
* @gl: the glock * @gl: the glock
...@@ -350,14 +300,14 @@ static void rgrp_go_unlock(struct gfs2_holder *gh) ...@@ -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 * @gl: the glock
* @state: the requested state * @state: the requested state
* @flags: * @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; struct gfs2_sbd *sdp = gl->gl_sbd;
...@@ -384,7 +334,6 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl) ...@@ -384,7 +334,6 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl)
if (gl->gl_state != LM_ST_UNLOCKED && if (gl->gl_state != LM_ST_UNLOCKED &&
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { 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); j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
error = gfs2_find_jhead(sdp->sd_jdesc, &head); error = gfs2_find_jhead(sdp->sd_jdesc, &head);
...@@ -401,24 +350,6 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl) ...@@ -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 * quota_go_demote_ok - Check to see if it's ok to unlock a quota glock
* @gl: the glock * @gl: the glock
...@@ -433,25 +364,21 @@ static int quota_go_demote_ok(struct gfs2_glock *gl) ...@@ -433,25 +364,21 @@ static int quota_go_demote_ok(struct gfs2_glock *gl)
const struct gfs2_glock_operations gfs2_meta_glops = { const struct gfs2_glock_operations gfs2_meta_glops = {
.go_xmote_th = meta_go_sync, .go_xmote_th = meta_go_sync,
.go_drop_th = meta_go_sync,
.go_type = LM_TYPE_META, .go_type = LM_TYPE_META,
}; };
const struct gfs2_glock_operations gfs2_inode_glops = { 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_xmote_bh = inode_go_xmote_bh,
.go_drop_th = inode_go_drop_th,
.go_inval = inode_go_inval, .go_inval = inode_go_inval,
.go_demote_ok = inode_go_demote_ok, .go_demote_ok = inode_go_demote_ok,
.go_lock = inode_go_lock, .go_lock = inode_go_lock,
.go_unlock = inode_go_unlock,
.go_type = LM_TYPE_INODE, .go_type = LM_TYPE_INODE,
.go_min_hold_time = HZ / 10, .go_min_hold_time = HZ / 10,
}; };
const struct gfs2_glock_operations gfs2_rgrp_glops = { const struct gfs2_glock_operations gfs2_rgrp_glops = {
.go_xmote_th = meta_go_sync, .go_xmote_th = meta_go_sync,
.go_drop_th = meta_go_sync,
.go_inval = meta_go_inval, .go_inval = meta_go_inval,
.go_demote_ok = rgrp_go_demote_ok, .go_demote_ok = rgrp_go_demote_ok,
.go_lock = rgrp_go_lock, .go_lock = rgrp_go_lock,
...@@ -461,9 +388,8 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { ...@@ -461,9 +388,8 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
}; };
const struct gfs2_glock_operations gfs2_trans_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_xmote_bh = trans_go_xmote_bh,
.go_drop_th = trans_go_drop_th,
.go_type = LM_TYPE_NONDISK, .go_type = LM_TYPE_NONDISK,
}; };
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * 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, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -131,7 +131,6 @@ struct gfs2_bufdata { ...@@ -131,7 +131,6 @@ struct gfs2_bufdata {
struct gfs2_glock_operations { struct gfs2_glock_operations {
void (*go_xmote_th) (struct gfs2_glock *gl); void (*go_xmote_th) (struct gfs2_glock *gl);
void (*go_xmote_bh) (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); void (*go_inval) (struct gfs2_glock *gl, int flags);
int (*go_demote_ok) (struct gfs2_glock *gl); int (*go_demote_ok) (struct gfs2_glock *gl);
int (*go_lock) (struct gfs2_holder *gh); int (*go_lock) (struct gfs2_holder *gh);
...@@ -141,10 +140,6 @@ struct gfs2_glock_operations { ...@@ -141,10 +140,6 @@ struct gfs2_glock_operations {
}; };
enum { enum {
/* Actions */
HIF_MUTEX = 0,
HIF_PROMOTE = 1,
/* States */ /* States */
HIF_HOLDER = 6, HIF_HOLDER = 6,
HIF_FIRST = 7, HIF_FIRST = 7,
...@@ -171,6 +166,8 @@ enum { ...@@ -171,6 +166,8 @@ enum {
GLF_DEMOTE = 3, GLF_DEMOTE = 3,
GLF_PENDING_DEMOTE = 4, GLF_PENDING_DEMOTE = 4,
GLF_DIRTY = 5, GLF_DIRTY = 5,
GLF_DEMOTE_IN_PROGRESS = 6,
GLF_LFLUSH = 7,
}; };
struct gfs2_glock { struct gfs2_glock {
...@@ -190,6 +187,7 @@ struct gfs2_glock { ...@@ -190,6 +187,7 @@ struct gfs2_glock {
struct list_head gl_holders; struct list_head gl_holders;
struct list_head gl_waiters1; /* HIF_MUTEX */ struct list_head gl_waiters1; /* HIF_MUTEX */
struct list_head gl_waiters3; /* HIF_PROMOTE */ struct list_head gl_waiters3; /* HIF_PROMOTE */
int gl_waiters2; /* GIF_DEMOTE */
const struct gfs2_glock_operations *gl_ops; const struct gfs2_glock_operations *gl_ops;
...@@ -210,7 +208,6 @@ struct gfs2_glock { ...@@ -210,7 +208,6 @@ struct gfs2_glock {
struct gfs2_sbd *gl_sbd; struct gfs2_sbd *gl_sbd;
struct inode *gl_aspace; struct inode *gl_aspace;
struct gfs2_log_element gl_le;
struct list_head gl_ail_list; struct list_head gl_ail_list;
atomic_t gl_ail_count; atomic_t gl_ail_count;
struct delayed_work gl_work; struct delayed_work gl_work;
...@@ -239,7 +236,6 @@ struct gfs2_alloc { ...@@ -239,7 +236,6 @@ struct gfs2_alloc {
enum { enum {
GIF_INVALID = 0, GIF_INVALID = 0,
GIF_QD_LOCKED = 1, GIF_QD_LOCKED = 1,
GIF_PAGED = 2,
GIF_SW_PAGED = 3, GIF_SW_PAGED = 3,
}; };
...@@ -268,14 +264,10 @@ struct gfs2_inode { ...@@ -268,14 +264,10 @@ struct gfs2_inode {
struct gfs2_glock *i_gl; /* Move into i_gh? */ struct gfs2_glock *i_gl; /* Move into i_gh? */
struct gfs2_holder i_iopen_gh; struct gfs2_holder i_iopen_gh;
struct gfs2_holder i_gh; /* for prepare/commit_write only */ 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; u64 i_last_rg_alloc;
spinlock_t i_spin;
struct rw_semaphore i_rw_mutex; 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) ...@@ -287,19 +279,12 @@ static inline struct gfs2_inode *GFS2_I(struct inode *inode)
return container_of(inode, struct gfs2_inode, i_inode); return container_of(inode, struct gfs2_inode, i_inode);
} }
/* To be removed? */ static inline struct gfs2_sbd *GFS2_SB(const struct inode *inode)
static inline struct gfs2_sbd *GFS2_SB(struct inode *inode)
{ {
return inode->i_sb->s_fs_info; return inode->i_sb->s_fs_info;
} }
enum {
GFF_DID_DIRECT_ALLOC = 0,
GFF_EXLOCK = 1,
};
struct gfs2_file { struct gfs2_file {
unsigned long f_flags; /* GFF_... */
struct mutex f_fl_mutex; struct mutex f_fl_mutex;
struct gfs2_holder f_fl_gh; struct gfs2_holder f_fl_gh;
}; };
...@@ -373,8 +358,17 @@ struct gfs2_ail { ...@@ -373,8 +358,17 @@ struct gfs2_ail {
u64 ai_sync_gen; 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 gfs2_jdesc {
struct list_head jd_list; struct list_head jd_list;
struct list_head extent_list;
struct inode *jd_inode; struct inode *jd_inode;
unsigned int jd_jid; unsigned int jd_jid;
...@@ -421,13 +415,9 @@ struct gfs2_args { ...@@ -421,13 +415,9 @@ struct gfs2_args {
struct gfs2_tune { struct gfs2_tune {
spinlock_t gt_spin; 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_demote_secs; /* Cache retention for unheld glock */
unsigned int gt_incore_log_blocks; unsigned int gt_incore_log_blocks;
unsigned int gt_log_flush_secs; 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_recoverd_secs;
unsigned int gt_logd_secs; unsigned int gt_logd_secs;
...@@ -443,10 +433,8 @@ struct gfs2_tune { ...@@ -443,10 +433,8 @@ struct gfs2_tune {
unsigned int gt_new_files_jdata; unsigned int gt_new_files_jdata;
unsigned int gt_new_files_directio; unsigned int gt_new_files_directio;
unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ 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_stall_secs; /* Detects trouble! */
unsigned int gt_complain_secs; 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_quantum;
unsigned int gt_statfs_slow; unsigned int gt_statfs_slow;
}; };
...@@ -539,7 +527,6 @@ struct gfs2_sbd { ...@@ -539,7 +527,6 @@ struct gfs2_sbd {
/* StatFS stuff */ /* StatFS stuff */
spinlock_t sd_statfs_spin; 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_master;
struct gfs2_statfs_change_host sd_statfs_local; struct gfs2_statfs_change_host sd_statfs_local;
unsigned long sd_statfs_sync_time; unsigned long sd_statfs_sync_time;
...@@ -602,20 +589,18 @@ struct gfs2_sbd { ...@@ -602,20 +589,18 @@ struct gfs2_sbd {
unsigned int sd_log_commited_databuf; unsigned int sd_log_commited_databuf;
unsigned int sd_log_commited_revoke; unsigned int sd_log_commited_revoke;
unsigned int sd_log_num_gl;
unsigned int sd_log_num_buf; unsigned int sd_log_num_buf;
unsigned int sd_log_num_revoke; unsigned int sd_log_num_revoke;
unsigned int sd_log_num_rg; unsigned int sd_log_num_rg;
unsigned int sd_log_num_databuf; 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_buf;
struct list_head sd_log_le_revoke; struct list_head sd_log_le_revoke;
struct list_head sd_log_le_rg; struct list_head sd_log_le_rg;
struct list_head sd_log_le_databuf; struct list_head sd_log_le_databuf;
struct list_head sd_log_le_ordered; 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; struct mutex sd_log_reserve_mutex;
u64 sd_log_sequence; u64 sd_log_sequence;
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "log.h" #include "log.h"
#include "meta_io.h" #include "meta_io.h"
#include "ops_address.h" #include "ops_address.h"
#include "ops_file.h"
#include "ops_inode.h" #include "ops_inode.h"
#include "quota.h" #include "quota.h"
#include "rgrp.h" #include "rgrp.h"
...@@ -132,14 +131,20 @@ static struct inode *gfs2_iget_skip(struct super_block *sb, ...@@ -132,14 +131,20 @@ static struct inode *gfs2_iget_skip(struct super_block *sb,
void gfs2_set_iop(struct inode *inode) void gfs2_set_iop(struct inode *inode)
{ {
struct gfs2_sbd *sdp = GFS2_SB(inode);
umode_t mode = inode->i_mode; umode_t mode = inode->i_mode;
if (S_ISREG(mode)) { if (S_ISREG(mode)) {
inode->i_op = &gfs2_file_iops; inode->i_op = &gfs2_file_iops;
if (sdp->sd_args.ar_localflocks)
inode->i_fop = &gfs2_file_fops_nolock;
else
inode->i_fop = &gfs2_file_fops; inode->i_fop = &gfs2_file_fops;
inode->i_mapping->a_ops = &gfs2_file_aops;
} else if (S_ISDIR(mode)) { } else if (S_ISDIR(mode)) {
inode->i_op = &gfs2_dir_iops; inode->i_op = &gfs2_dir_iops;
if (sdp->sd_args.ar_localflocks)
inode->i_fop = &gfs2_dir_fops_nolock;
else
inode->i_fop = &gfs2_dir_fops; inode->i_fop = &gfs2_dir_fops;
} else if (S_ISLNK(mode)) { } else if (S_ISLNK(mode)) {
inode->i_op = &gfs2_symlink_iops; inode->i_op = &gfs2_symlink_iops;
...@@ -291,12 +296,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -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_entries = be32_to_cpu(str->di_entries);
di->di_eattr = be64_to_cpu(str->di_eattr); 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) return 0;
{
ip->i_cache[0] = bh;
} }
/** /**
...@@ -366,7 +369,8 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) ...@@ -366,7 +369,8 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
if (error) if (error)
goto out_rg_gunlock; 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); gfs2_free_di(rgd, ip);
...@@ -707,9 +711,10 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) ...@@ -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); struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
int error; 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); error = gfs2_inplace_reserve(dip);
if (error) if (error)
goto out; goto out;
...@@ -855,7 +860,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, ...@@ -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); error = alloc_required = gfs2_diradd_alloc_required(&dip->i_inode, name);
if (alloc_required < 0) if (alloc_required < 0)
goto fail; goto fail_quota_locks;
if (alloc_required) { if (alloc_required) {
error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid); error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
if (error) if (error)
...@@ -896,7 +901,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, ...@@ -896,7 +901,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
fail_ipreserv: fail_ipreserv:
if (dip->i_alloc.al_rgd) if (dip->i_alloc->al_rgd)
gfs2_inplace_release(dip); gfs2_inplace_release(dip);
fail_quota_locks: fail_quota_locks:
...@@ -966,7 +971,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, ...@@ -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 }; struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
int error; int error;
u64 generation; u64 generation;
struct buffer_head *bh=NULL; struct buffer_head *bh = NULL;
if (!name->len || name->len > GFS2_FNAMESIZE) if (!name->len || name->len > GFS2_FNAMESIZE)
return ERR_PTR(-ENAMETOOLONG); return ERR_PTR(-ENAMETOOLONG);
...@@ -1003,8 +1008,6 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, ...@@ -1003,8 +1008,6 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (IS_ERR(inode)) if (IS_ERR(inode))
goto fail_gunlock2; goto fail_gunlock2;
gfs2_inode_bh(GFS2_I(inode), bh);
error = gfs2_inode_refresh(GFS2_I(inode)); error = gfs2_inode_refresh(GFS2_I(inode));
if (error) if (error)
goto fail_gunlock2; goto fail_gunlock2;
...@@ -1021,6 +1024,8 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, ...@@ -1021,6 +1024,8 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error) if (error)
goto fail_gunlock2; goto fail_gunlock2;
if (bh)
brelse(bh);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
return inode; return inode;
...@@ -1032,6 +1037,8 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, ...@@ -1032,6 +1037,8 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
fail_gunlock: fail_gunlock:
gfs2_glock_dq(ghs); gfs2_glock_dq(ghs);
fail: fail:
if (bh)
brelse(bh);
return ERR_PTR(error); return ERR_PTR(error);
} }
......
...@@ -20,6 +20,18 @@ static inline int gfs2_is_jdata(const struct gfs2_inode *ip) ...@@ -20,6 +20,18 @@ static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
return ip->i_di.di_flags & GFS2_DIF_JDATA; 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) static inline int gfs2_is_dir(const struct gfs2_inode *ip)
{ {
return S_ISDIR(ip->i_inode.i_mode); 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) ...@@ -67,6 +67,11 @@ static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
memset(data, 0, 256); memset(data, 0, 256);
strncpy(data, data_arg, 255); 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, ":")); ) { for (options = data; (x = strsep(&options, ":")); ) {
if (!*x) if (!*x)
continue; continue;
......
...@@ -89,15 +89,19 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name, ...@@ -89,15 +89,19 @@ int gdlm_plock(void *lockspace, struct lm_lockname *name,
op->info.number = name->ln_number; op->info.number = name->ln_number;
op->info.start = fl->fl_start; op->info.start = fl->fl_start;
op->info.end = fl->fl_end; op->info.end = fl->fl_end;
op->info.owner = (__u64)(long) fl->fl_owner;
if (fl->fl_lmops && fl->fl_lmops->fl_grant) { 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; xop->callback = fl->fl_lmops->fl_grant;
locks_init_lock(&xop->flc); locks_init_lock(&xop->flc);
locks_copy_lock(&xop->flc, fl); locks_copy_lock(&xop->flc, fl);
xop->fl = fl; xop->fl = fl;
xop->file = file; xop->file = file;
} else } else {
op->info.owner = (__u64)(long) fl->fl_owner;
xop->callback = NULL; xop->callback = NULL;
}
send_op(op); send_op(op);
...@@ -203,6 +207,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name, ...@@ -203,6 +207,9 @@ int gdlm_punlock(void *lockspace, struct lm_lockname *name,
op->info.number = name->ln_number; op->info.number = name->ln_number;
op->info.start = fl->fl_start; op->info.start = fl->fl_start;
op->info.end = fl->fl_end; op->info.end = fl->fl_end;
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; op->info.owner = (__u64)(long) fl->fl_owner;
send_op(op); send_op(op);
...@@ -242,6 +249,9 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name, ...@@ -242,6 +249,9 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
op->info.number = name->ln_number; op->info.number = name->ln_number;
op->info.start = fl->fl_start; op->info.start = fl->fl_start;
op->info.end = fl->fl_end; op->info.end = fl->fl_end;
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; op->info.owner = (__u64)(long) fl->fl_owner;
send_op(op); send_op(op);
......
...@@ -273,18 +273,13 @@ static int gdlm_thread(void *data, int blist) ...@@ -273,18 +273,13 @@ static int gdlm_thread(void *data, int blist)
struct gdlm_ls *ls = (struct gdlm_ls *) data; struct gdlm_ls *ls = (struct gdlm_ls *) data;
struct gdlm_lock *lp = NULL; struct gdlm_lock *lp = NULL;
uint8_t complete, blocking, submit, drop; uint8_t complete, blocking, submit, drop;
DECLARE_WAITQUEUE(wait, current);
/* Only thread1 is allowed to do blocking callbacks since gfs /* Only thread1 is allowed to do blocking callbacks since gfs
may wait for a completion callback within a blocking cb. */ may wait for a completion callback within a blocking cb. */
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE); wait_event_interruptible(ls->thread_wait,
add_wait_queue(&ls->thread_wait, &wait); !no_work(ls, blist) || kthread_should_stop());
if (no_work(ls, blist))
schedule();
remove_wait_queue(&ls->thread_wait, &wait);
set_current_state(TASK_RUNNING);
complete = blocking = submit = drop = 0; complete = blocking = submit = drop = 0;
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * 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, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/lm_interface.h> #include <linux/lm_interface.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
...@@ -68,14 +70,12 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct, ...@@ -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; bd->bd_ail = NULL;
list_del_init(&bd->bd_ail_st_list); list_del_init(&bd->bd_ail_st_list);
list_del_init(&bd->bd_ail_gl_list); list_del_init(&bd->bd_ail_gl_list);
atomic_dec(&bd->bd_gl->gl_ail_count); atomic_dec(&bd->bd_gl->gl_ail_count);
if (mapping)
gfs2_meta_cache_flush(GFS2_I(mapping->host));
brelse(bd->bd_bh); brelse(bd->bd_bh);
} }
...@@ -92,8 +92,6 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) ...@@ -92,8 +92,6 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
struct buffer_head *bh; struct buffer_head *bh;
int retry; int retry;
BUG_ON(!spin_is_locked(&sdp->sd_log_lock));
do { do {
retry = 0; retry = 0;
...@@ -210,7 +208,7 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags) ...@@ -210,7 +208,7 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp, int flags)
gfs2_log_unlock(sdp); 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; struct gfs2_ail *ai, *s;
int ret; int ret;
...@@ -248,7 +246,7 @@ static void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) ...@@ -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 = list_entry(head->prev, struct gfs2_bufdata,
bd_ail_st_list); bd_ail_st_list);
gfs2_assert(sdp, bd->bd_ail == ai); 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) ...@@ -303,7 +301,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
mutex_lock(&sdp->sd_log_reserve_mutex); mutex_lock(&sdp->sd_log_reserve_mutex);
gfs2_log_lock(sdp); 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_log_unlock(sdp);
gfs2_ail1_empty(sdp, 0); gfs2_ail1_empty(sdp, 0);
gfs2_log_flush(sdp, NULL); gfs2_log_flush(sdp, NULL);
...@@ -312,7 +310,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) ...@@ -312,7 +310,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
gfs2_ail1_start(sdp, 0); gfs2_ail1_start(sdp, 0);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
} }
sdp->sd_log_blks_free -= blks; atomic_sub(blks, &sdp->sd_log_blks_free);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
mutex_unlock(&sdp->sd_log_reserve_mutex); mutex_unlock(&sdp->sd_log_reserve_mutex);
...@@ -332,27 +330,23 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) ...@@ -332,27 +330,23 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks)
{ {
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
sdp->sd_log_blks_free += blks; atomic_add(blks, &sdp->sd_log_blks_free);
gfs2_assert_withdraw(sdp, 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); gfs2_log_unlock(sdp);
up_read(&sdp->sd_log_flush_lock); up_read(&sdp->sd_log_flush_lock);
} }
static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn)
{ {
struct inode *inode = sdp->sd_jdesc->jd_inode; struct gfs2_journal_extent *je;
int error;
struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) {
if (lbn >= je->lblock && lbn < je->lblock + je->blocks)
bh_map.b_size = 1 << inode->i_blkbits; return je->dblock + lbn - je->lblock;
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, return -1;
(unsigned long long)bh_map.b_blocknr, lbn);
gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr);
return bh_map.b_blocknr;
} }
/** /**
...@@ -561,8 +555,8 @@ static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail) ...@@ -561,8 +555,8 @@ static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
ail2_empty(sdp, new_tail); ail2_empty(sdp, new_tail);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
sdp->sd_log_blks_free += dist; atomic_add(dist, &sdp->sd_log_blks_free);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= sdp->sd_jdesc->jd_blocks);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
sdp->sd_log_tail = new_tail; sdp->sd_log_tail = new_tail;
...@@ -652,7 +646,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp) ...@@ -652,7 +646,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
get_bh(bh); get_bh(bh);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
lock_buffer(bh); 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; bh->b_end_io = end_buffer_write_sync;
submit_bh(WRITE, bh); submit_bh(WRITE, bh);
} else { } else {
...@@ -694,21 +688,17 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp) ...@@ -694,21 +688,17 @@ 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; struct gfs2_ail *ai;
down_write(&sdp->sd_log_flush_lock); down_write(&sdp->sd_log_flush_lock);
if (gl) { /* Log might have been flushed while we waited for the flush lock */
gfs2_log_lock(sdp); if (gl && !test_bit(GLF_LFLUSH, &gl->gl_flags)) {
if (list_empty(&gl->gl_le.le_list)) {
gfs2_log_unlock(sdp);
up_write(&sdp->sd_log_flush_lock); up_write(&sdp->sd_log_flush_lock);
return; return;
} }
gfs2_log_unlock(sdp);
}
ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL); ai = kzalloc(sizeof(struct gfs2_ail), GFP_NOFS | __GFP_NOFAIL);
INIT_LIST_HEAD(&ai->ai_ail1_list); INIT_LIST_HEAD(&ai->ai_ail1_list);
...@@ -739,7 +729,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) ...@@ -739,7 +729,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
log_flush_commit(sdp); log_flush_commit(sdp);
else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){ else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
gfs2_log_lock(sdp); 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); gfs2_log_unlock(sdp);
log_write_header(sdp, 0, PULL); log_write_header(sdp, 0, PULL);
} }
...@@ -767,7 +757,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) ...@@ -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) static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{ {
unsigned int reserved; unsigned int reserved;
unsigned int old; unsigned int unused;
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
...@@ -779,14 +769,11 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) ...@@ -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; 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); gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
reserved = calc_reserved(sdp); reserved = calc_reserved(sdp);
old = sdp->sd_log_blks_free; unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
sdp->sd_log_blks_free += tr->tr_reserved - gfs2_assert_withdraw(sdp, unused >= 0);
(reserved - sdp->sd_log_blks_reserved); atomic_add(unused, &sdp->sd_log_blks_free);
gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
sdp->sd_jdesc->jd_blocks); sdp->sd_jdesc->jd_blocks);
sdp->sd_log_blks_reserved = reserved; sdp->sd_log_blks_reserved = reserved;
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
...@@ -825,7 +812,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) ...@@ -825,7 +812,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
down_write(&sdp->sd_log_flush_lock); down_write(&sdp->sd_log_flush_lock);
gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); 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_buf);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg); gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
...@@ -838,7 +824,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp) ...@@ -838,7 +824,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
(sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL); (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, sdp->sd_log_head == sdp->sd_log_tail);
gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list)); gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
...@@ -866,3 +852,42 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp) ...@@ -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;
}
...@@ -48,8 +48,6 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp, ...@@ -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 gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
unsigned int ssize); unsigned int ssize);
int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags);
int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); 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_release(struct gfs2_sbd *sdp, unsigned int blks);
void gfs2_log_incr_head(struct gfs2_sbd *sdp); void gfs2_log_incr_head(struct gfs2_sbd *sdp);
...@@ -57,11 +55,19 @@ 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_get_buf(struct gfs2_sbd *sdp);
struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
struct buffer_head *real); 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_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_log_shutdown(struct gfs2_sbd *sdp);
void gfs2_meta_syncfs(struct gfs2_sbd *sdp); void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
int gfs2_logd(void *data);
#endif /* __LOG_DOT_H__ */ #endif /* __LOG_DOT_H__ */
...@@ -87,6 +87,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, ...@@ -87,6 +87,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
} }
bd->bd_ail = ai; bd->bd_ail = ai;
list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list);
clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
unlock_buffer(bh); unlock_buffer(bh);
} }
...@@ -124,49 +125,6 @@ static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type) ...@@ -124,49 +125,6 @@ static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type)
return bh; 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) 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); 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) ...@@ -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); list_add(&bd->bd_list_tr, &tr->tr_list_buf);
if (!list_empty(&le->le_list)) if (!list_empty(&le->le_list))
goto out; 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_meta_check(sdp, bd->bd_bh);
gfs2_pin(sdp, bd->bd_bh); gfs2_pin(sdp, bd->bd_bh);
sdp->sd_log_num_buf++; sdp->sd_log_num_buf++;
...@@ -556,6 +515,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) ...@@ -556,6 +515,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
lock_buffer(bd->bd_bh); lock_buffer(bd->bd_bh);
gfs2_log_lock(sdp); gfs2_log_lock(sdp);
if (tr) {
if (!list_empty(&bd->bd_list_tr)) if (!list_empty(&bd->bd_list_tr))
goto out; goto out;
tr->tr_touched = 1; tr->tr_touched = 1;
...@@ -563,10 +523,12 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) ...@@ -563,10 +523,12 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
tr->tr_num_buf++; tr->tr_num_buf++;
list_add(&bd->bd_list_tr, &tr->tr_list_buf); list_add(&bd->bd_list_tr, &tr->tr_list_buf);
} }
}
if (!list_empty(&le->le_list)) if (!list_empty(&le->le_list))
goto out; 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)) { if (gfs2_is_jdata(ip)) {
gfs2_pin(sdp, bd->bd_bh); gfs2_pin(sdp, bd->bd_bh);
tr->tr_num_databuf_new++; tr->tr_num_databuf_new++;
...@@ -773,12 +735,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) ...@@ -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 = { const struct gfs2_log_operations gfs2_buf_lops = {
.lo_add = buf_lo_add, .lo_add = buf_lo_add,
.lo_incore_commit = buf_lo_incore_commit, .lo_incore_commit = buf_lo_incore_commit,
...@@ -816,7 +772,6 @@ const struct gfs2_log_operations gfs2_databuf_lops = { ...@@ -816,7 +772,6 @@ const struct gfs2_log_operations gfs2_databuf_lops = {
}; };
const struct gfs2_log_operations *gfs2_log_ops[] = { const struct gfs2_log_operations *gfs2_log_ops[] = {
&gfs2_glock_lops,
&gfs2_databuf_lops, &gfs2_databuf_lops,
&gfs2_buf_lops, &gfs2_buf_lops,
&gfs2_rg_lops, &gfs2_rg_lops,
......
...@@ -29,9 +29,8 @@ static void gfs2_init_inode_once(struct kmem_cache *cachep, void *foo) ...@@ -29,9 +29,8 @@ static void gfs2_init_inode_once(struct kmem_cache *cachep, void *foo)
struct gfs2_inode *ip = foo; struct gfs2_inode *ip = foo;
inode_init_once(&ip->i_inode); inode_init_once(&ip->i_inode);
spin_lock_init(&ip->i_spin);
init_rwsem(&ip->i_rw_mutex); 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) static void gfs2_init_glock_once(struct kmem_cache *cachep, void *foo)
......
...@@ -50,6 +50,7 @@ static int gfs2_aspace_writepage(struct page *page, ...@@ -50,6 +50,7 @@ static int gfs2_aspace_writepage(struct page *page,
static const struct address_space_operations aspace_aops = { static const struct address_space_operations aspace_aops = {
.writepage = gfs2_aspace_writepage, .writepage = gfs2_aspace_writepage,
.releasepage = gfs2_releasepage, .releasepage = gfs2_releasepage,
.sync_page = block_sync_page,
}; };
/** /**
...@@ -221,7 +222,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, ...@@ -221,7 +222,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
struct buffer_head **bhp) struct buffer_head **bhp)
{ {
*bhp = getbuf(gl, blkno, CREATE); *bhp = getbuf(gl, blkno, CREATE);
if (!buffer_uptodate(*bhp)) if (!buffer_uptodate(*bhp)) {
ll_rw_block(READ_META, 1, bhp); ll_rw_block(READ_META, 1, bhp);
if (flags & DIO_WAIT) { if (flags & DIO_WAIT) {
int error = gfs2_meta_wait(gl->gl_sbd, *bhp); int error = gfs2_meta_wait(gl->gl_sbd, *bhp);
...@@ -230,6 +231,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, ...@@ -230,6 +231,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
return error; return error;
} }
} }
}
return 0; return 0;
} }
...@@ -282,7 +284,7 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, ...@@ -282,7 +284,7 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
return; return;
} }
bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL), bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL);
bd->bd_bh = bh; bd->bd_bh = bh;
bd->bd_gl = gl; bd->bd_gl = gl;
...@@ -317,7 +319,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int ...@@ -317,7 +319,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
} }
if (bd) { if (bd) {
if (bd->bd_ail) { if (bd->bd_ail) {
gfs2_remove_from_ail(NULL, bd); gfs2_remove_from_ail(bd);
bh->b_private = NULL; bh->b_private = NULL;
bd->bd_bh = NULL; bd->bd_bh = NULL;
bd->bd_blkno = bh->b_blocknr; bd->bd_blkno = bh->b_blocknr;
...@@ -357,32 +359,6 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) ...@@ -357,32 +359,6 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
} }
} }
/**
* gfs2_meta_cache_flush - get rid of any references on buffers for this inode
* @ip: The GFS2 inode
*
* This releases buffers that are in the most-recently-used array of
* blocks used for indirect block addressing for this inode.
*/
void gfs2_meta_cache_flush(struct gfs2_inode *ip)
{
struct buffer_head **bh_slot;
unsigned int x;
spin_lock(&ip->i_spin);
for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) {
bh_slot = &ip->i_cache[x];
if (*bh_slot) {
brelse(*bh_slot);
*bh_slot = NULL;
}
}
spin_unlock(&ip->i_spin);
}
/** /**
* gfs2_meta_indirect_buffer - Get a metadata buffer * gfs2_meta_indirect_buffer - Get a metadata buffer
* @ip: The GFS2 inode * @ip: The GFS2 inode
...@@ -391,8 +367,6 @@ void gfs2_meta_cache_flush(struct gfs2_inode *ip) ...@@ -391,8 +367,6 @@ void gfs2_meta_cache_flush(struct gfs2_inode *ip)
* @new: Non-zero if we may create a new buffer * @new: Non-zero if we may create a new buffer
* @bhp: the buffer is returned here * @bhp: the buffer is returned here
* *
* Try to use the gfs2_inode's MRU metadata tree cache.
*
* Returns: errno * Returns: errno
*/ */
...@@ -401,58 +375,25 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, ...@@ -401,58 +375,25 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_glock *gl = ip->i_gl; struct gfs2_glock *gl = ip->i_gl;
struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height; struct buffer_head *bh;
int in_cache = 0; int ret = 0;
BUG_ON(!gl);
BUG_ON(!sdp);
spin_lock(&ip->i_spin);
if (*bh_slot && (*bh_slot)->b_blocknr == num) {
bh = *bh_slot;
get_bh(bh);
in_cache = 1;
}
spin_unlock(&ip->i_spin);
if (!bh)
bh = getbuf(gl, num, CREATE);
if (!bh)
return -ENOBUFS;
if (new) { if (new) {
if (gfs2_assert_warn(sdp, height)) BUG_ON(height == 0);
goto err; bh = gfs2_meta_new(gl, num);
meta_prep_new(bh);
gfs2_trans_add_bh(ip->i_gl, bh, 1); gfs2_trans_add_bh(ip->i_gl, bh, 1);
gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
} else { } else {
u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI; u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI;
if (!buffer_uptodate(bh)) { ret = gfs2_meta_read(gl, num, DIO_WAIT, &bh);
ll_rw_block(READ_META, 1, &bh); if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) {
if (gfs2_meta_wait(sdp, bh)) brelse(bh);
goto err; ret = -EIO;
}
if (gfs2_metatype_check(sdp, bh, mtype))
goto err;
} }
if (!in_cache) {
spin_lock(&ip->i_spin);
if (*bh_slot)
brelse(*bh_slot);
*bh_slot = bh;
get_bh(bh);
spin_unlock(&ip->i_spin);
} }
*bhp = bh; *bhp = bh;
return 0; return ret;
err:
brelse(bh);
return -EIO;
} }
/** /**
......
...@@ -56,7 +56,6 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, ...@@ -56,7 +56,6 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr,
void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
void gfs2_meta_cache_flush(struct gfs2_inode *ip);
int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
int new, struct buffer_head **bhp); int new, struct buffer_head **bhp);
......
This diff is collapsed.
...@@ -14,9 +14,10 @@ ...@@ -14,9 +14,10 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/mm.h> #include <linux/mm.h>
extern const struct address_space_operations gfs2_file_aops;
extern int gfs2_get_block(struct inode *inode, sector_t lblock,
struct buffer_head *bh_result, int create);
extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask);
extern int gfs2_internal_read(struct gfs2_inode *ip,
struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size);
extern void gfs2_set_aops(struct inode *inode);
#endif /* __OPS_ADDRESS_DOT_H__ */ #endif /* __OPS_ADDRESS_DOT_H__ */
...@@ -33,57 +33,12 @@ ...@@ -33,57 +33,12 @@
#include "lm.h" #include "lm.h"
#include "log.h" #include "log.h"
#include "meta_io.h" #include "meta_io.h"
#include "ops_file.h"
#include "ops_vm.h"
#include "quota.h" #include "quota.h"
#include "rgrp.h" #include "rgrp.h"
#include "trans.h" #include "trans.h"
#include "util.h" #include "util.h"
#include "eaops.h" #include "eaops.h"
#include "ops_address.h"
/*
* Most fields left uninitialised to catch anybody who tries to
* use them. f_flags set to prevent file_accessed() from touching
* any other part of this. Its use is purely as a flag so that we
* know (in readpage()) whether or not do to locking.
*/
struct file gfs2_internal_file_sentinel = {
.f_flags = O_NOATIME|O_RDONLY,
};
static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
unsigned long offset, unsigned long size)
{
char *kaddr;
unsigned long count = desc->count;
if (size > count)
size = count;
kaddr = kmap(page);
memcpy(desc->arg.data, kaddr + offset, size);
kunmap(page);
desc->count = count - size;
desc->written += size;
desc->arg.buf += size;
return size;
}
int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size)
{
struct inode *inode = &ip->i_inode;
read_descriptor_t desc;
desc.written = 0;
desc.arg.data = buf;
desc.count = size;
desc.error = 0;
do_generic_mapping_read(inode->i_mapping, ra_state,
&gfs2_internal_file_sentinel, pos, &desc,
gfs2_read_actor);
return desc.written ? desc.written : desc.error;
}
/** /**
* gfs2_llseek - seek to a location in a file * gfs2_llseek - seek to a location in a file
...@@ -214,7 +169,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) ...@@ -214,7 +169,7 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
if (put_user(fsflags, ptr)) if (put_user(fsflags, ptr))
error = -EFAULT; error = -EFAULT;
gfs2_glock_dq_m(1, &gh); gfs2_glock_dq(&gh);
gfs2_holder_uninit(&gh); gfs2_holder_uninit(&gh);
return error; return error;
} }
...@@ -291,7 +246,16 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) ...@@ -291,7 +246,16 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
if (error) if (error)
goto out; goto out;
} }
if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
if (flags & GFS2_DIF_JDATA)
gfs2_log_flush(sdp, ip->i_gl);
error = filemap_fdatawrite(inode->i_mapping);
if (error)
goto out;
error = filemap_fdatawait(inode->i_mapping);
if (error)
goto out;
}
error = gfs2_trans_begin(sdp, RES_DINODE, 0); error = gfs2_trans_begin(sdp, RES_DINODE, 0);
if (error) if (error)
goto out; goto out;
...@@ -303,6 +267,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) ...@@ -303,6 +267,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
gfs2_dinode_out(ip, bh->b_data); gfs2_dinode_out(ip, bh->b_data);
brelse(bh); brelse(bh);
gfs2_set_inode_flags(inode); gfs2_set_inode_flags(inode);
gfs2_set_aops(inode);
out_trans_end: out_trans_end:
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out: out:
...@@ -338,6 +303,128 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -338,6 +303,128 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -ENOTTY; return -ENOTTY;
} }
/**
* gfs2_allocate_page_backing - Use bmap to allocate blocks
* @page: The (locked) page to allocate backing for
*
* We try to allocate all the blocks required for the page in
* one go. This might fail for various reasons, so we keep
* trying until all the blocks to back this page are allocated.
* If some of the blocks are already allocated, thats ok too.
*/
static int gfs2_allocate_page_backing(struct page *page)
{
struct inode *inode = page->mapping->host;
struct buffer_head bh;
unsigned long size = PAGE_CACHE_SIZE;
u64 lblock = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
do {
bh.b_state = 0;
bh.b_size = size;
gfs2_block_map(inode, lblock, &bh, 1);
if (!buffer_mapped(&bh))
return -EIO;
size -= bh.b_size;
lblock += (bh.b_size >> inode->i_blkbits);
} while(size > 0);
return 0;
}
/**
* gfs2_page_mkwrite - Make a shared, mmap()ed, page writable
* @vma: The virtual memory area
* @page: The page which is about to become writable
*
* When the page becomes writable, we need to ensure that we have
* blocks allocated on disk to back that page.
*/
static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
{
struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
unsigned long last_index;
u64 pos = page->index << (PAGE_CACHE_SIZE - inode->i_blkbits);
unsigned int data_blocks, ind_blocks, rblocks;
int alloc_required = 0;
struct gfs2_holder gh;
struct gfs2_alloc *al;
int ret;
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &gh);
ret = gfs2_glock_nq_atime(&gh);
if (ret)
goto out;
set_bit(GIF_SW_PAGED, &ip->i_flags);
gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required);
if (ret || !alloc_required)
goto out_unlock;
ret = -ENOMEM;
al = gfs2_alloc_get(ip);
if (al == NULL)
goto out_unlock;
ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (ret)
goto out_alloc_put;
ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
if (ret)
goto out_quota_unlock;
al->al_requested = data_blocks + ind_blocks;
ret = gfs2_inplace_reserve(ip);
if (ret)
goto out_quota_unlock;
rblocks = RES_DINODE + ind_blocks;
if (gfs2_is_jdata(ip))
rblocks += data_blocks ? data_blocks : 1;
if (ind_blocks || data_blocks)
rblocks += RES_STATFS + RES_QUOTA;
ret = gfs2_trans_begin(sdp, rblocks, 0);
if (ret)
goto out_trans_fail;
lock_page(page);
ret = -EINVAL;
last_index = ip->i_inode.i_size >> PAGE_CACHE_SHIFT;
if (page->index > last_index)
goto out_unlock_page;
ret = 0;
if (!PageUptodate(page) || page->mapping != ip->i_inode.i_mapping)
goto out_unlock_page;
if (gfs2_is_stuffed(ip)) {
ret = gfs2_unstuff_dinode(ip, page);
if (ret)
goto out_unlock_page;
}
ret = gfs2_allocate_page_backing(page);
out_unlock_page:
unlock_page(page);
gfs2_trans_end(sdp);
out_trans_fail:
gfs2_inplace_release(ip);
out_quota_unlock:
gfs2_quota_unlock(ip);
out_alloc_put:
gfs2_alloc_put(ip);
out_unlock:
gfs2_glock_dq(&gh);
out:
gfs2_holder_uninit(&gh);
return ret;
}
static struct vm_operations_struct gfs2_vm_ops = {
.fault = filemap_fault,
.page_mkwrite = gfs2_page_mkwrite,
};
/** /**
* gfs2_mmap - * gfs2_mmap -
...@@ -360,14 +447,7 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -360,14 +447,7 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
return error; return error;
} }
/* This is VM_MAYWRITE instead of VM_WRITE because a call vma->vm_ops = &gfs2_vm_ops;
to mprotect() can turn on VM_WRITE later. */
if ((vma->vm_flags & (VM_MAYSHARE | VM_MAYWRITE)) ==
(VM_MAYSHARE | VM_MAYWRITE))
vma->vm_ops = &gfs2_vm_ops_sharewrite;
else
vma->vm_ops = &gfs2_vm_ops_private;
gfs2_glock_dq_uninit(&i_gh); gfs2_glock_dq_uninit(&i_gh);
...@@ -538,15 +618,6 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) ...@@ -538,15 +618,6 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
if (__mandatory_lock(&ip->i_inode)) if (__mandatory_lock(&ip->i_inode))
return -ENOLCK; return -ENOLCK;
if (sdp->sd_args.ar_localflocks) {
if (IS_GETLK(cmd)) {
posix_test_lock(file, fl);
return 0;
} else {
return posix_lock_file_wait(file, fl);
}
}
if (cmd == F_CANCELLK) { if (cmd == F_CANCELLK) {
/* Hack: */ /* Hack: */
cmd = F_SETLK; cmd = F_SETLK;
...@@ -632,16 +703,12 @@ static void do_unflock(struct file *file, struct file_lock *fl) ...@@ -632,16 +703,12 @@ static void do_unflock(struct file *file, struct file_lock *fl)
static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
{ {
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
if (!(fl->fl_flags & FL_FLOCK)) if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK; return -ENOLCK;
if (__mandatory_lock(&ip->i_inode)) if (__mandatory_lock(&ip->i_inode))
return -ENOLCK; return -ENOLCK;
if (sdp->sd_args.ar_localflocks)
return flock_lock_file_wait(file, fl);
if (fl->fl_type == F_UNLCK) { if (fl->fl_type == F_UNLCK) {
do_unflock(file, fl); do_unflock(file, fl);
return 0; return 0;
...@@ -678,3 +745,27 @@ const struct file_operations gfs2_dir_fops = { ...@@ -678,3 +745,27 @@ const struct file_operations gfs2_dir_fops = {
.flock = gfs2_flock, .flock = gfs2_flock,
}; };
const struct file_operations gfs2_file_fops_nolock = {
.llseek = gfs2_llseek,
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.unlocked_ioctl = gfs2_ioctl,
.mmap = gfs2_mmap,
.open = gfs2_open,
.release = gfs2_close,
.fsync = gfs2_fsync,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
.setlease = gfs2_setlease,
};
const struct file_operations gfs2_dir_fops_nolock = {
.readdir = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open,
.release = gfs2_close,
.fsync = gfs2_fsync,
};
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 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
* of the GNU General Public License version 2.
*/
#ifndef __OPS_FILE_DOT_H__
#define __OPS_FILE_DOT_H__
#include <linux/fs.h>
struct gfs2_inode;
extern struct file gfs2_internal_file_sentinel;
extern int gfs2_internal_read(struct gfs2_inode *ip,
struct file_ra_state *ra_state,
char *buf, loff_t *pos, unsigned size);
extern void gfs2_set_inode_flags(struct inode *inode);
extern const struct file_operations gfs2_file_fops;
extern const struct file_operations gfs2_dir_fops;
#endif /* __OPS_FILE_DOT_H__ */
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * 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, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
#include "bmap.h"
#include "daemon.h" #include "daemon.h"
#include "glock.h" #include "glock.h"
#include "glops.h" #include "glops.h"
...@@ -59,7 +60,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -59,7 +60,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
mutex_init(&sdp->sd_inum_mutex); mutex_init(&sdp->sd_inum_mutex);
spin_lock_init(&sdp->sd_statfs_spin); spin_lock_init(&sdp->sd_statfs_spin);
mutex_init(&sdp->sd_statfs_mutex);
spin_lock_init(&sdp->sd_rindex_spin); spin_lock_init(&sdp->sd_rindex_spin);
mutex_init(&sdp->sd_rindex_mutex); mutex_init(&sdp->sd_rindex_mutex);
...@@ -77,7 +77,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -77,7 +77,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
spin_lock_init(&sdp->sd_log_lock); spin_lock_init(&sdp->sd_log_lock);
INIT_LIST_HEAD(&sdp->sd_log_le_gl);
INIT_LIST_HEAD(&sdp->sd_log_le_buf); INIT_LIST_HEAD(&sdp->sd_log_le_buf);
INIT_LIST_HEAD(&sdp->sd_log_le_revoke); INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
INIT_LIST_HEAD(&sdp->sd_log_le_rg); INIT_LIST_HEAD(&sdp->sd_log_le_rg);
...@@ -303,6 +302,67 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) ...@@ -303,6 +302,67 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
return error; return error;
} }
/**
* map_journal_extents - create a reusable "extent" mapping from all logical
* blocks to all physical blocks for the given journal. This will save
* us time when writing journal blocks. Most journals will have only one
* extent that maps all their logical blocks. That's because gfs2.mkfs
* arranges the journal blocks sequentially to maximize performance.
* So the extent would map the first block for the entire file length.
* However, gfs2_jadd can happen while file activity is happening, so
* those journals may not be sequential. Less likely is the case where
* the users created their own journals by mounting the metafs and
* laying it out. But it's still possible. These journals might have
* several extents.
*
* TODO: This should be done in bigger chunks rather than one block at a time,
* but since it's only done at mount time, I'm not worried about the
* time it takes.
*/
static int map_journal_extents(struct gfs2_sbd *sdp)
{
struct gfs2_jdesc *jd = sdp->sd_jdesc;
unsigned int lb;
u64 db, prev_db; /* logical block, disk block, prev disk block */
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_journal_extent *jext = NULL;
struct buffer_head bh;
int rc = 0;
prev_db = 0;
for (lb = 0; lb < ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift; lb++) {
bh.b_state = 0;
bh.b_blocknr = 0;
bh.b_size = 1 << ip->i_inode.i_blkbits;
rc = gfs2_block_map(jd->jd_inode, lb, &bh, 0);
db = bh.b_blocknr;
if (rc || !db) {
printk(KERN_INFO "GFS2 journal mapping error %d: lb="
"%u db=%llu\n", rc, lb, (unsigned long long)db);
break;
}
if (!prev_db || db != prev_db + 1) {
jext = kzalloc(sizeof(struct gfs2_journal_extent),
GFP_KERNEL);
if (!jext) {
printk(KERN_INFO "GFS2 error: out of memory "
"mapping journal extents.\n");
rc = -ENOMEM;
break;
}
jext->dblock = db;
jext->lblock = lb;
jext->blocks = 1;
list_add_tail(&jext->extent_list, &jd->extent_list);
} else {
jext->blocks++;
}
prev_db = db;
}
return rc;
}
static int init_journal(struct gfs2_sbd *sdp, int undo) static int init_journal(struct gfs2_sbd *sdp, int undo)
{ {
struct gfs2_holder ji_gh; struct gfs2_holder ji_gh;
...@@ -340,7 +400,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -340,7 +400,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
if (sdp->sd_args.ar_spectator) { if (sdp->sd_args.ar_spectator) {
sdp->sd_jdesc = gfs2_jdesc_find(sdp, 0); sdp->sd_jdesc = gfs2_jdesc_find(sdp, 0);
sdp->sd_log_blks_free = sdp->sd_jdesc->jd_blocks; atomic_set(&sdp->sd_log_blks_free, sdp->sd_jdesc->jd_blocks);
} else { } else {
if (sdp->sd_lockstruct.ls_jid >= gfs2_jindex_size(sdp)) { if (sdp->sd_lockstruct.ls_jid >= gfs2_jindex_size(sdp)) {
fs_err(sdp, "can't mount journal #%u\n", fs_err(sdp, "can't mount journal #%u\n",
...@@ -377,7 +437,10 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) ...@@ -377,7 +437,10 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
sdp->sd_jdesc->jd_jid, error); sdp->sd_jdesc->jd_jid, error);
goto fail_jinode_gh; goto fail_jinode_gh;
} }
sdp->sd_log_blks_free = sdp->sd_jdesc->jd_blocks; atomic_set(&sdp->sd_log_blks_free, sdp->sd_jdesc->jd_blocks);
/* Map the extents for this journal's blocks */
map_journal_extents(sdp);
} }
if (sdp->sd_lockstruct.ls_first) { if (sdp->sd_lockstruct.ls_first) {
......
...@@ -61,7 +61,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry, ...@@ -61,7 +61,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0); inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0);
if (!IS_ERR(inode)) { if (!IS_ERR(inode)) {
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
if (dip->i_alloc.al_rgd) if (dip->i_alloc->al_rgd)
gfs2_inplace_release(dip); gfs2_inplace_release(dip);
gfs2_quota_unlock(dip); gfs2_quota_unlock(dip);
gfs2_alloc_put(dip); gfs2_alloc_put(dip);
...@@ -113,8 +113,18 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, ...@@ -113,8 +113,18 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
if (inode && IS_ERR(inode)) if (inode && IS_ERR(inode))
return ERR_PTR(PTR_ERR(inode)); return ERR_PTR(PTR_ERR(inode));
if (inode) if (inode) {
struct gfs2_glock *gl = GFS2_I(inode)->i_gl;
struct gfs2_holder gh;
int error;
error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
if (error) {
iput(inode);
return ERR_PTR(error);
}
gfs2_glock_dq_uninit(&gh);
return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry);
}
d_add(dentry, inode); d_add(dentry, inode);
return NULL; return NULL;
...@@ -366,7 +376,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry, ...@@ -366,7 +376,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
} }
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
if (dip->i_alloc.al_rgd) if (dip->i_alloc->al_rgd)
gfs2_inplace_release(dip); gfs2_inplace_release(dip);
gfs2_quota_unlock(dip); gfs2_quota_unlock(dip);
gfs2_alloc_put(dip); gfs2_alloc_put(dip);
...@@ -442,7 +452,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -442,7 +452,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
gfs2_assert_withdraw(sdp, !error); /* dip already pinned */ gfs2_assert_withdraw(sdp, !error); /* dip already pinned */
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
if (dip->i_alloc.al_rgd) if (dip->i_alloc->al_rgd)
gfs2_inplace_release(dip); gfs2_inplace_release(dip);
gfs2_quota_unlock(dip); gfs2_quota_unlock(dip);
gfs2_alloc_put(dip); gfs2_alloc_put(dip);
...@@ -548,7 +558,7 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode, ...@@ -548,7 +558,7 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode,
} }
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
if (dip->i_alloc.al_rgd) if (dip->i_alloc->al_rgd)
gfs2_inplace_release(dip); gfs2_inplace_release(dip);
gfs2_quota_unlock(dip); gfs2_quota_unlock(dip);
gfs2_alloc_put(dip); gfs2_alloc_put(dip);
......
...@@ -16,5 +16,11 @@ extern const struct inode_operations gfs2_file_iops; ...@@ -16,5 +16,11 @@ extern const struct inode_operations gfs2_file_iops;
extern const struct inode_operations gfs2_dir_iops; extern const struct inode_operations gfs2_dir_iops;
extern const struct inode_operations gfs2_symlink_iops; extern const struct inode_operations gfs2_symlink_iops;
extern const struct inode_operations gfs2_dev_iops; extern const struct inode_operations gfs2_dev_iops;
extern const struct file_operations gfs2_file_fops;
extern const struct file_operations gfs2_dir_fops;
extern const struct file_operations gfs2_file_fops_nolock;
extern const struct file_operations gfs2_dir_fops_nolock;
extern void gfs2_set_inode_flags(struct inode *inode);
#endif /* __OPS_INODE_DOT_H__ */ #endif /* __OPS_INODE_DOT_H__ */
...@@ -487,7 +487,6 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb) ...@@ -487,7 +487,6 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
if (ip) { if (ip) {
ip->i_flags = 0; ip->i_flags = 0;
ip->i_gl = NULL; ip->i_gl = NULL;
ip->i_last_pfault = jiffies;
} }
return &ip->i_inode; return &ip->i_inode;
} }
......
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 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
* of the GNU General Public License version 2.
*/
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
#include "gfs2.h"
#include "incore.h"
#include "bmap.h"
#include "glock.h"
#include "inode.h"
#include "ops_vm.h"
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
#include "util.h"
static int gfs2_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
set_bit(GIF_PAGED, &ip->i_flags);
return filemap_fault(vma, vmf);
}
static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
unsigned long index = page->index;
u64 lblock = index << (PAGE_CACHE_SHIFT -
sdp->sd_sb.sb_bsize_shift);
unsigned int blocks = PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift;
struct gfs2_alloc *al;
unsigned int data_blocks, ind_blocks;
unsigned int x;
int error;
al = gfs2_alloc_get(ip);
error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
if (error)
goto out;
error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
if (error)
goto out_gunlock_q;
gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
al->al_requested = data_blocks + ind_blocks;
error = gfs2_inplace_reserve(ip);
if (error)
goto out_gunlock_q;
error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
ind_blocks + RES_DINODE +
RES_STATFS + RES_QUOTA, 0);
if (error)
goto out_ipres;
if (gfs2_is_stuffed(ip)) {
error = gfs2_unstuff_dinode(ip, NULL);
if (error)
goto out_trans;
}
for (x = 0; x < blocks; ) {
u64 dblock;
unsigned int extlen;
int new = 1;
error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
if (error)
goto out_trans;
lblock += extlen;
x += extlen;
}
gfs2_assert_warn(sdp, al->al_alloced);
out_trans:
gfs2_trans_end(sdp);
out_ipres:
gfs2_inplace_release(ip);
out_gunlock_q:
gfs2_quota_unlock(ip);
out:
gfs2_alloc_put(ip);
return error;
}
static int gfs2_sharewrite_fault(struct vm_area_struct *vma,
struct vm_fault *vmf)
{
struct file *file = vma->vm_file;
struct gfs2_file *gf = file->private_data;
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_holder i_gh;
int alloc_required;
int error;
int ret = 0;
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
if (error)
goto out;
set_bit(GIF_PAGED, &ip->i_flags);
set_bit(GIF_SW_PAGED, &ip->i_flags);
error = gfs2_write_alloc_required(ip,
(u64)vmf->pgoff << PAGE_CACHE_SHIFT,
PAGE_CACHE_SIZE, &alloc_required);
if (error) {
ret = VM_FAULT_OOM; /* XXX: are these right? */
goto out_unlock;
}
set_bit(GFF_EXLOCK, &gf->f_flags);
ret = filemap_fault(vma, vmf);
clear_bit(GFF_EXLOCK, &gf->f_flags);
if (ret & VM_FAULT_ERROR)
goto out_unlock;
if (alloc_required) {
/* XXX: do we need to drop page lock around alloc_page_backing?*/
error = alloc_page_backing(ip, vmf->page);
if (error) {
/*
* VM_FAULT_LOCKED should always be the case for
* filemap_fault, but it may not be in a future
* implementation.
*/
if (ret & VM_FAULT_LOCKED)
unlock_page(vmf->page);
page_cache_release(vmf->page);
ret = VM_FAULT_OOM;
goto out_unlock;
}
set_page_dirty(vmf->page);
}
out_unlock:
gfs2_glock_dq_uninit(&i_gh);
out:
return ret;
}
struct vm_operations_struct gfs2_vm_ops_private = {
.fault = gfs2_private_fault,
};
struct vm_operations_struct gfs2_vm_ops_sharewrite = {
.fault = gfs2_sharewrite_fault,
};
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2006 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
* of the GNU General Public License version 2.
*/
#ifndef __OPS_VM_DOT_H__
#define __OPS_VM_DOT_H__
#include <linux/mm.h>
extern struct vm_operations_struct gfs2_vm_ops_private;
extern struct vm_operations_struct gfs2_vm_ops_sharewrite;
#endif /* __OPS_VM_DOT_H__ */
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * 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, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
#include "super.h" #include "super.h"
#include "trans.h" #include "trans.h"
#include "inode.h" #include "inode.h"
#include "ops_file.h"
#include "ops_address.h" #include "ops_address.h"
#include "util.h" #include "util.h"
...@@ -274,10 +273,10 @@ static int bh_get(struct gfs2_quota_data *qd) ...@@ -274,10 +273,10 @@ static int bh_get(struct gfs2_quota_data *qd)
} }
block = qd->qd_slot / sdp->sd_qc_per_block; block = qd->qd_slot / sdp->sd_qc_per_block;
offset = qd->qd_slot % sdp->sd_qc_per_block;; offset = qd->qd_slot % sdp->sd_qc_per_block;
bh_map.b_size = 1 << ip->i_inode.i_blkbits; bh_map.b_size = 1 << ip->i_inode.i_blkbits;
error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map); error = gfs2_block_map(&ip->i_inode, block, &bh_map, 0);
if (error) if (error)
goto fail; goto fail;
error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh); error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh);
...@@ -454,7 +453,7 @@ static void qdsb_put(struct gfs2_quota_data *qd) ...@@ -454,7 +453,7 @@ static void qdsb_put(struct gfs2_quota_data *qd)
int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 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_quota_data **qd = al->al_qd; struct gfs2_quota_data **qd = al->al_qd;
int error; int error;
...@@ -502,7 +501,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) ...@@ -502,7 +501,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
void gfs2_quota_unhold(struct gfs2_inode *ip) void gfs2_quota_unhold(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
unsigned int x; unsigned int x;
gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)); gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
...@@ -646,7 +645,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, ...@@ -646,7 +645,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
} }
if (!buffer_mapped(bh)) { if (!buffer_mapped(bh)) {
gfs2_get_block(inode, iblock, bh, 1); gfs2_block_map(inode, iblock, bh, 1);
if (!buffer_mapped(bh)) if (!buffer_mapped(bh))
goto unlock; goto unlock;
} }
...@@ -793,11 +792,9 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh, ...@@ -793,11 +792,9 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
struct gfs2_holder i_gh; struct gfs2_holder i_gh;
struct gfs2_quota_host q; struct gfs2_quota_host q;
char buf[sizeof(struct gfs2_quota)]; char buf[sizeof(struct gfs2_quota)];
struct file_ra_state ra_state;
int error; int error;
struct gfs2_quota_lvb *qlvb; struct gfs2_quota_lvb *qlvb;
file_ra_state_init(&ra_state, sdp->sd_quota_inode->i_mapping);
restart: restart:
error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh); error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh);
if (error) if (error)
...@@ -820,8 +817,8 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh, ...@@ -820,8 +817,8 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
memset(buf, 0, sizeof(struct gfs2_quota)); memset(buf, 0, sizeof(struct gfs2_quota));
pos = qd2offset(qd); pos = qd2offset(qd);
error = gfs2_internal_read(ip, &ra_state, buf, error = gfs2_internal_read(ip, NULL, buf, &pos,
&pos, sizeof(struct gfs2_quota)); sizeof(struct gfs2_quota));
if (error < 0) if (error < 0)
goto fail_gunlock; goto fail_gunlock;
...@@ -856,7 +853,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh, ...@@ -856,7 +853,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid) int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
unsigned int x; unsigned int x;
int error = 0; int error = 0;
...@@ -924,7 +921,7 @@ static int need_sync(struct gfs2_quota_data *qd) ...@@ -924,7 +921,7 @@ static int need_sync(struct gfs2_quota_data *qd)
void gfs2_quota_unlock(struct gfs2_inode *ip) void gfs2_quota_unlock(struct gfs2_inode *ip)
{ {
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
struct gfs2_quota_data *qda[4]; struct gfs2_quota_data *qda[4];
unsigned int count = 0; unsigned int count = 0;
unsigned int x; unsigned int x;
...@@ -972,7 +969,7 @@ static int print_message(struct gfs2_quota_data *qd, char *type) ...@@ -972,7 +969,7 @@ static int print_message(struct gfs2_quota_data *qd, char *type)
int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 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_quota_data *qd; struct gfs2_quota_data *qd;
s64 value; s64 value;
unsigned int x; unsigned int x;
...@@ -1016,10 +1013,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) ...@@ -1016,10 +1013,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
void gfs2_quota_change(struct gfs2_inode *ip, s64 change, void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
u32 uid, u32 gid) u32 uid, u32 gid)
{ {
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
struct gfs2_quota_data *qd; struct gfs2_quota_data *qd;
unsigned int x; unsigned int x;
unsigned int found = 0;
if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change)) if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
return; return;
...@@ -1032,7 +1028,6 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change, ...@@ -1032,7 +1028,6 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) || if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
(qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) { (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) {
do_qc(qd, change); do_qc(qd, change);
found++;
} }
} }
} }
......
...@@ -391,7 +391,7 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea ...@@ -391,7 +391,7 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
lblock = head->lh_blkno; lblock = head->lh_blkno;
gfs2_replay_incr_blk(sdp, &lblock); gfs2_replay_incr_blk(sdp, &lblock);
bh_map.b_size = 1 << ip->i_inode.i_blkbits; bh_map.b_size = 1 << ip->i_inode.i_blkbits;
error = gfs2_block_map(&ip->i_inode, lblock, 0, &bh_map); error = gfs2_block_map(&ip->i_inode, lblock, &bh_map, 0);
if (error) if (error)
return error; return error;
if (!bh_map.b_blocknr) { if (!bh_map.b_blocknr) {
...@@ -504,13 +504,21 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd) ...@@ -504,13 +504,21 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
ro = 1; ro = 1;
} else { } else {
if (sdp->sd_vfs->s_flags & MS_RDONLY) if (sdp->sd_vfs->s_flags & MS_RDONLY) {
ro = 1; /* check if device itself is read-only */
ro = bdev_read_only(sdp->sd_vfs->s_bdev);
if (!ro) {
fs_info(sdp, "recovery required on "
"read-only filesystem.\n");
fs_info(sdp, "write access will be "
"enabled during recovery.\n");
}
}
} }
if (ro) { if (ro) {
fs_warn(sdp, "jid=%u: Can't replay: read-only FS\n", fs_warn(sdp, "jid=%u: Can't replay: read-only block "
jd->jd_jid); "device\n", jd->jd_jid);
error = -EROFS; error = -EROFS;
goto fail_gunlock_tr; goto fail_gunlock_tr;
} }
......
...@@ -25,10 +25,10 @@ ...@@ -25,10 +25,10 @@
#include "rgrp.h" #include "rgrp.h"
#include "super.h" #include "super.h"
#include "trans.h" #include "trans.h"
#include "ops_file.h"
#include "util.h" #include "util.h"
#include "log.h" #include "log.h"
#include "inode.h" #include "inode.h"
#include "ops_address.h"
#define BFITNOENT ((u32)~0) #define BFITNOENT ((u32)~0)
#define NO_BLOCK ((u64)~0) #define NO_BLOCK ((u64)~0)
...@@ -126,41 +126,43 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, ...@@ -126,41 +126,43 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
* Return: the block number (bitmap buffer scope) that was found * Return: the block number (bitmap buffer scope) that was found
*/ */
static u32 gfs2_bitfit(struct gfs2_rgrpd *rgd, unsigned char *buffer, static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
unsigned int buflen, u32 goal,
unsigned char old_state) unsigned char old_state)
{ {
unsigned char *byte, *end, alloc; unsigned char *byte;
u32 blk = goal; u32 blk = goal;
unsigned int bit; unsigned int bit, bitlong;
unsigned long *plong, plong55;
byte = buffer + (goal / GFS2_NBBY); byte = buffer + (goal / GFS2_NBBY);
plong = (unsigned long *)(buffer + (goal / GFS2_NBBY));
bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
end = buffer + buflen; bitlong = bit;
alloc = (old_state == GFS2_BLKST_FREE) ? 0x55 : 0; #if BITS_PER_LONG == 32
plong55 = 0x55555555;
while (byte < end) { #else
/* If we're looking for a free block we can eliminate all plong55 = 0x5555555555555555;
bitmap settings with 0x55, which represents four data #endif
blocks in a row. If we're looking for a data block, we can while (byte < buffer + buflen) {
eliminate 0x00 which corresponds to four free blocks. */
if ((*byte & 0x55) == alloc) { if (bitlong == 0 && old_state == 0 && *plong == plong55) {
blk += (8 - bit) >> 1; plong++;
byte += sizeof(unsigned long);
bit = 0; blk += sizeof(unsigned long) * GFS2_NBBY;
byte++;
continue; continue;
} }
if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) if (((*byte >> bit) & GFS2_BIT_MASK) == old_state)
return blk; return blk;
bit += GFS2_BIT_SIZE; bit += GFS2_BIT_SIZE;
if (bit >= 8) { if (bit >= 8) {
bit = 0; bit = 0;
byte++; byte++;
} }
bitlong += GFS2_BIT_SIZE;
if (bitlong >= sizeof(unsigned long) * 8) {
bitlong = 0;
plong++;
}
blk++; blk++;
} }
...@@ -817,11 +819,9 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) ...@@ -817,11 +819,9 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip)
{ {
struct gfs2_alloc *al = &ip->i_alloc; BUG_ON(ip->i_alloc != NULL);
ip->i_alloc = kzalloc(sizeof(struct gfs2_alloc), GFP_KERNEL);
/* FIXME: Should assert that the correct locks are held here... */ return ip->i_alloc;
memset(al, 0, sizeof(*al));
return al;
} }
/** /**
...@@ -1059,25 +1059,33 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) ...@@ -1059,25 +1059,33 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
struct inode *inode = NULL; struct inode *inode = NULL;
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd, *begin = NULL; struct gfs2_rgrpd *rgd, *begin = NULL;
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
int flags = LM_FLAG_TRY; int flags = LM_FLAG_TRY;
int skipped = 0; int skipped = 0;
int loops = 0; int loops = 0;
int error; int error, rg_locked;
/* Try recently successful rgrps */ /* Try recently successful rgrps */
rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc); rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc);
while (rgd) { while (rgd) {
rg_locked = 0;
if (gfs2_glock_is_locked_by_me(rgd->rd_gl)) {
rg_locked = 1;
error = 0;
} else {
error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE,
LM_FLAG_TRY, &al->al_rgd_gh); LM_FLAG_TRY, &al->al_rgd_gh);
}
switch (error) { switch (error) {
case 0: case 0:
if (try_rgrp_fit(rgd, al)) if (try_rgrp_fit(rgd, al))
goto out; goto out;
if (rgd->rd_flags & GFS2_RDF_CHECK) if (rgd->rd_flags & GFS2_RDF_CHECK)
inode = try_rgrp_unlink(rgd, last_unlinked); inode = try_rgrp_unlink(rgd, last_unlinked);
if (!rg_locked)
gfs2_glock_dq_uninit(&al->al_rgd_gh); gfs2_glock_dq_uninit(&al->al_rgd_gh);
if (inode) if (inode)
return inode; return inode;
...@@ -1098,14 +1106,22 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) ...@@ -1098,14 +1106,22 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
begin = rgd = forward_rgrp_get(sdp); begin = rgd = forward_rgrp_get(sdp);
for (;;) { for (;;) {
rg_locked = 0;
if (gfs2_glock_is_locked_by_me(rgd->rd_gl)) {
rg_locked = 1;
error = 0;
} else {
error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, flags, error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, flags,
&al->al_rgd_gh); &al->al_rgd_gh);
}
switch (error) { switch (error) {
case 0: case 0:
if (try_rgrp_fit(rgd, al)) if (try_rgrp_fit(rgd, al))
goto out; goto out;
if (rgd->rd_flags & GFS2_RDF_CHECK) if (rgd->rd_flags & GFS2_RDF_CHECK)
inode = try_rgrp_unlink(rgd, last_unlinked); inode = try_rgrp_unlink(rgd, last_unlinked);
if (!rg_locked)
gfs2_glock_dq_uninit(&al->al_rgd_gh); gfs2_glock_dq_uninit(&al->al_rgd_gh);
if (inode) if (inode)
return inode; return inode;
...@@ -1158,7 +1174,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) ...@@ -1158,7 +1174,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
struct inode *inode; struct inode *inode;
int error = 0; int error = 0;
u64 last_unlinked = NO_BLOCK; u64 last_unlinked = NO_BLOCK;
...@@ -1204,7 +1220,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) ...@@ -1204,7 +1220,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
void gfs2_inplace_release(struct gfs2_inode *ip) void gfs2_inplace_release(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc; struct gfs2_alloc *al = ip->i_alloc;
if (gfs2_assert_warn(sdp, al->al_alloced <= al->al_requested) == -1) if (gfs2_assert_warn(sdp, al->al_alloced <= al->al_requested) == -1)
fs_warn(sdp, "al_alloced = %u, al_requested = %u " fs_warn(sdp, "al_alloced = %u, al_requested = %u "
...@@ -1213,6 +1229,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) ...@@ -1213,6 +1229,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
al->al_line); al->al_line);
al->al_rgd = NULL; al->al_rgd = NULL;
if (al->al_rgd_gh.gh_gl)
gfs2_glock_dq_uninit(&al->al_rgd_gh); gfs2_glock_dq_uninit(&al->al_rgd_gh);
if (ip != GFS2_I(sdp->sd_rindex)) if (ip != GFS2_I(sdp->sd_rindex))
gfs2_glock_dq_uninit(&al->al_ri_gh); gfs2_glock_dq_uninit(&al->al_ri_gh);
...@@ -1301,11 +1318,10 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, ...@@ -1301,11 +1318,10 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
/* The GFS2_BLKST_UNLINKED state doesn't apply to the clone /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone
bitmaps, so we must search the originals for that. */ bitmaps, so we must search the originals for that. */
if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone) if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone)
blk = gfs2_bitfit(rgd, bi->bi_clone + bi->bi_offset, blk = gfs2_bitfit(bi->bi_clone + bi->bi_offset,
bi->bi_len, goal, old_state); bi->bi_len, goal, old_state);
else else
blk = gfs2_bitfit(rgd, blk = gfs2_bitfit(bi->bi_bh->b_data + bi->bi_offset,
bi->bi_bh->b_data + bi->bi_offset,
bi->bi_len, goal, old_state); bi->bi_len, goal, old_state);
if (blk != BFITNOENT) if (blk != BFITNOENT)
break; break;
...@@ -1394,7 +1410,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, ...@@ -1394,7 +1410,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
u64 gfs2_alloc_data(struct gfs2_inode *ip) u64 gfs2_alloc_data(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 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 = al->al_rgd; struct gfs2_rgrpd *rgd = al->al_rgd;
u32 goal, blk; u32 goal, blk;
u64 block; u64 block;
...@@ -1439,7 +1455,7 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip) ...@@ -1439,7 +1455,7 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
u64 gfs2_alloc_meta(struct gfs2_inode *ip) u64 gfs2_alloc_meta(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 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 = al->al_rgd; struct gfs2_rgrpd *rgd = al->al_rgd;
u32 goal, blk; u32 goal, blk;
u64 block; u64 block;
...@@ -1485,7 +1501,7 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip) ...@@ -1485,7 +1501,7 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip)
u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_alloc *al = &dip->i_alloc; struct gfs2_alloc *al = dip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd; struct gfs2_rgrpd *rgd = al->al_rgd;
u32 blk; u32 blk;
u64 block; u64 block;
......
...@@ -32,7 +32,9 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd); ...@@ -32,7 +32,9 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd);
struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip); struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
static inline void gfs2_alloc_put(struct gfs2_inode *ip) static inline void gfs2_alloc_put(struct gfs2_inode *ip)
{ {
return; /* So we can see where ip->i_alloc is used */ BUG_ON(ip->i_alloc == NULL);
kfree(ip->i_alloc);
ip->i_alloc = NULL;
} }
int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int gfs2_inplace_reserve_i(struct gfs2_inode *ip,
......
/* /*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * 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, * This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions * modify, copy, or redistribute it subject to the terms and conditions
...@@ -51,13 +51,9 @@ void gfs2_tune_init(struct gfs2_tune *gt) ...@@ -51,13 +51,9 @@ void gfs2_tune_init(struct gfs2_tune *gt)
{ {
spin_lock_init(&gt->gt_spin); spin_lock_init(&gt->gt_spin);
gt->gt_ilimit = 100;
gt->gt_ilimit_tries = 3;
gt->gt_ilimit_min = 1;
gt->gt_demote_secs = 300; gt->gt_demote_secs = 300;
gt->gt_incore_log_blocks = 1024; gt->gt_incore_log_blocks = 1024;
gt->gt_log_flush_secs = 60; gt->gt_log_flush_secs = 60;
gt->gt_jindex_refresh_secs = 60;
gt->gt_recoverd_secs = 60; gt->gt_recoverd_secs = 60;
gt->gt_logd_secs = 1; gt->gt_logd_secs = 1;
gt->gt_quotad_secs = 5; gt->gt_quotad_secs = 5;
...@@ -71,10 +67,8 @@ void gfs2_tune_init(struct gfs2_tune *gt) ...@@ -71,10 +67,8 @@ void gfs2_tune_init(struct gfs2_tune *gt)
gt->gt_new_files_jdata = 0; gt->gt_new_files_jdata = 0;
gt->gt_new_files_directio = 0; gt->gt_new_files_directio = 0;
gt->gt_max_readahead = 1 << 18; gt->gt_max_readahead = 1 << 18;
gt->gt_lockdump_size = 131072;
gt->gt_stall_secs = 600; gt->gt_stall_secs = 600;
gt->gt_complain_secs = 10; gt->gt_complain_secs = 10;
gt->gt_reclaim_limit = 5000;
gt->gt_statfs_quantum = 30; gt->gt_statfs_quantum = 30;
gt->gt_statfs_slow = 0; gt->gt_statfs_slow = 0;
} }
...@@ -393,6 +387,7 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) ...@@ -393,6 +387,7 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
if (!jd) if (!jd)
break; break;
INIT_LIST_HEAD(&jd->extent_list);
jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1, NULL); jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1, NULL);
if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
if (!jd->jd_inode) if (!jd->jd_inode)
...@@ -422,8 +417,9 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) ...@@ -422,8 +417,9 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
void gfs2_jindex_free(struct gfs2_sbd *sdp) void gfs2_jindex_free(struct gfs2_sbd *sdp)
{ {
struct list_head list; struct list_head list, *head;
struct gfs2_jdesc *jd; struct gfs2_jdesc *jd;
struct gfs2_journal_extent *jext;
spin_lock(&sdp->sd_jindex_spin); spin_lock(&sdp->sd_jindex_spin);
list_add(&list, &sdp->sd_jindex_list); list_add(&list, &sdp->sd_jindex_list);
...@@ -433,6 +429,14 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp) ...@@ -433,6 +429,14 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp)
while (!list_empty(&list)) { while (!list_empty(&list)) {
jd = list_entry(list.next, struct gfs2_jdesc, jd_list); jd = list_entry(list.next, struct gfs2_jdesc, jd_list);
head = &jd->extent_list;
while (!list_empty(head)) {
jext = list_entry(head->next,
struct gfs2_journal_extent,
extent_list);
list_del(&jext->extent_list);
kfree(jext);
}
list_del(&jd->jd_list); list_del(&jd->jd_list);
iput(jd->jd_inode); iput(jd->jd_inode);
kfree(jd); kfree(jd);
...@@ -543,7 +547,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) ...@@ -543,7 +547,6 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
if (error) if (error)
return error; return error;
gfs2_meta_cache_flush(ip);
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
error = gfs2_find_jhead(sdp->sd_jdesc, &head); error = gfs2_find_jhead(sdp->sd_jdesc, &head);
...@@ -686,9 +689,7 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, ...@@ -686,9 +689,7 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
if (error) if (error)
return; return;
mutex_lock(&sdp->sd_statfs_mutex);
gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
mutex_unlock(&sdp->sd_statfs_mutex);
spin_lock(&sdp->sd_statfs_spin); spin_lock(&sdp->sd_statfs_spin);
l_sc->sc_total += total; l_sc->sc_total += total;
...@@ -736,9 +737,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) ...@@ -736,9 +737,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp)
if (error) if (error)
goto out_bh2; goto out_bh2;
mutex_lock(&sdp->sd_statfs_mutex);
gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
mutex_unlock(&sdp->sd_statfs_mutex);
spin_lock(&sdp->sd_statfs_spin); spin_lock(&sdp->sd_statfs_spin);
m_sc->sc_total += l_sc->sc_total; m_sc->sc_total += l_sc->sc_total;
......
...@@ -32,7 +32,8 @@ spinlock_t gfs2_sys_margs_lock; ...@@ -32,7 +32,8 @@ spinlock_t gfs2_sys_margs_lock;
static ssize_t id_show(struct gfs2_sbd *sdp, char *buf) static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_vfs->s_id); return snprintf(buf, PAGE_SIZE, "%u:%u\n",
MAJOR(sdp->sd_vfs->s_dev), MINOR(sdp->sd_vfs->s_dev));
} }
static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf) static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf)
...@@ -425,13 +426,11 @@ TUNE_ATTR_2(name, name##_store) ...@@ -425,13 +426,11 @@ TUNE_ATTR_2(name, name##_store)
TUNE_ATTR(demote_secs, 0); TUNE_ATTR(demote_secs, 0);
TUNE_ATTR(incore_log_blocks, 0); TUNE_ATTR(incore_log_blocks, 0);
TUNE_ATTR(log_flush_secs, 0); TUNE_ATTR(log_flush_secs, 0);
TUNE_ATTR(jindex_refresh_secs, 0);
TUNE_ATTR(quota_warn_period, 0); TUNE_ATTR(quota_warn_period, 0);
TUNE_ATTR(quota_quantum, 0); TUNE_ATTR(quota_quantum, 0);
TUNE_ATTR(atime_quantum, 0); TUNE_ATTR(atime_quantum, 0);
TUNE_ATTR(max_readahead, 0); TUNE_ATTR(max_readahead, 0);
TUNE_ATTR(complain_secs, 0); TUNE_ATTR(complain_secs, 0);
TUNE_ATTR(reclaim_limit, 0);
TUNE_ATTR(statfs_slow, 0); TUNE_ATTR(statfs_slow, 0);
TUNE_ATTR(new_files_jdata, 0); TUNE_ATTR(new_files_jdata, 0);
TUNE_ATTR(new_files_directio, 0); TUNE_ATTR(new_files_directio, 0);
...@@ -448,13 +447,11 @@ static struct attribute *tune_attrs[] = { ...@@ -448,13 +447,11 @@ static struct attribute *tune_attrs[] = {
&tune_attr_demote_secs.attr, &tune_attr_demote_secs.attr,
&tune_attr_incore_log_blocks.attr, &tune_attr_incore_log_blocks.attr,
&tune_attr_log_flush_secs.attr, &tune_attr_log_flush_secs.attr,
&tune_attr_jindex_refresh_secs.attr,
&tune_attr_quota_warn_period.attr, &tune_attr_quota_warn_period.attr,
&tune_attr_quota_quantum.attr, &tune_attr_quota_quantum.attr,
&tune_attr_atime_quantum.attr, &tune_attr_atime_quantum.attr,
&tune_attr_max_readahead.attr, &tune_attr_max_readahead.attr,
&tune_attr_complain_secs.attr, &tune_attr_complain_secs.attr,
&tune_attr_reclaim_limit.attr,
&tune_attr_statfs_slow.attr, &tune_attr_statfs_slow.attr,
&tune_attr_quota_simul_sync.attr, &tune_attr_quota_simul_sync.attr,
&tune_attr_quota_cache_secs.attr, &tune_attr_quota_cache_secs.attr,
......
...@@ -114,11 +114,6 @@ void gfs2_trans_end(struct gfs2_sbd *sdp) ...@@ -114,11 +114,6 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
gfs2_log_flush(sdp, NULL); gfs2_log_flush(sdp, NULL);
} }
void gfs2_trans_add_gl(struct gfs2_glock *gl)
{
lops_add(gl->gl_sbd, &gl->gl_le);
}
/** /**
* gfs2_trans_add_bh - Add a to-be-modified buffer to the current transaction * gfs2_trans_add_bh - Add a to-be-modified buffer to the current transaction
* @gl: the glock the buffer belongs to * @gl: the glock the buffer belongs to
......
...@@ -30,7 +30,6 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks, ...@@ -30,7 +30,6 @@ int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
void gfs2_trans_end(struct gfs2_sbd *sdp); void gfs2_trans_end(struct gfs2_sbd *sdp);
void gfs2_trans_add_gl(struct gfs2_glock *gl);
void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta); void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta);
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno); void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment