Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
Browse files Browse the repository at this point in the history
Pull GFS2 updates from Steven Whitehouse:
 "The main feature this time is the new Orlov allocator and the patches
  leading up to it which allow us to allocate new inodes from their own
  allocation context, rather than borrowing that of their parent
  directory.  It is this change which then allows us to choose a
  different location for subdirectories when required.  This works
  exactly as per the ext3 implementation from the users point of view.

  In addition to that, we've got a speed up in gfs2_rbm_from_block()
  from Bob Peterson, three locking related improvements from Dave
  Teigland plus a selection of smaller bug fixes and clean ups."

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: Set gl_object during inode create
  GFS2: add error check while allocating new inodes
  GFS2: don't reference inode's glock during block allocation trace
  GFS2: remove redundant lvb pointer
  GFS2: only use lvb on glocks that need it
  GFS2: skip dlm_unlock calls in unmount
  GFS2: Fix one RG corner case
  GFS2: Eliminate redundant buffer_head manipulation in gfs2_unlink_inode
  GFS2: Use dirty_inode in gfs2_dir_add
  GFS2: Fix truncation of journaled data files
  GFS2: Add Orlov allocator
  GFS2: Use proper allocation context for new inodes
  GFS2: Add test for resource group congestion status
  GFS2: Rename glops go_xmote_th to go_sync
  GFS2: Speed up gfs2_rbm_from_block
  GFS2: Review bug traps in glops.c
  • Loading branch information
Linus Torvalds committed Dec 15, 2012
2 parents be354f4 + 1e2d9d4 commit 08242bc
Show file tree
Hide file tree
Showing 16 changed files with 380 additions and 194 deletions.
2 changes: 1 addition & 1 deletion fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
goto out_unlock;

requested = data_blocks + ind_blocks;
error = gfs2_inplace_reserve(ip, requested);
error = gfs2_inplace_reserve(ip, requested, 0);
if (error)
goto out_qunlock;
}
Expand Down
54 changes: 50 additions & 4 deletions fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,41 @@ static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
return err;
}

/**
* gfs2_journaled_truncate - Wrapper for truncate_pagecache for jdata files
* @inode: The inode being truncated
* @oldsize: The original (larger) size
* @newsize: The new smaller size
*
* With jdata files, we have to journal a revoke for each block which is
* truncated. As a result, we need to split this into separate transactions
* if the number of pages being truncated gets too large.
*/

#define GFS2_JTRUNC_REVOKES 8192

static int gfs2_journaled_truncate(struct inode *inode, u64 oldsize, u64 newsize)
{
struct gfs2_sbd *sdp = GFS2_SB(inode);
u64 max_chunk = GFS2_JTRUNC_REVOKES * sdp->sd_vfs->s_blocksize;
u64 chunk;
int error;

while (oldsize != newsize) {
chunk = oldsize - newsize;
if (chunk > max_chunk)
chunk = max_chunk;
truncate_pagecache(inode, oldsize, oldsize - chunk);
oldsize -= chunk;
gfs2_trans_end(sdp);
error = gfs2_trans_begin(sdp, RES_DINODE, GFS2_JTRUNC_REVOKES);
if (error)
return error;
}

return 0;
}

static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
{
struct gfs2_inode *ip = GFS2_I(inode);
Expand All @@ -1000,8 +1035,10 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
int journaled = gfs2_is_jdata(ip);
int error;

error = gfs2_trans_begin(sdp,
RES_DINODE + (journaled ? RES_JDATA : 0), 0);
if (journaled)
error = gfs2_trans_begin(sdp, RES_DINODE + RES_JDATA, GFS2_JTRUNC_REVOKES);
else
error = gfs2_trans_begin(sdp, RES_DINODE, 0);
if (error)
return error;

Expand All @@ -1026,7 +1063,16 @@ static int trunc_start(struct inode *inode, u64 oldsize, u64 newsize)
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data);

truncate_pagecache(inode, oldsize, newsize);
if (journaled)
error = gfs2_journaled_truncate(inode, oldsize, newsize);
else
truncate_pagecache(inode, oldsize, newsize);

if (error) {
brelse(dibh);
return error;
}

out_brelse:
brelse(dibh);
out:
Expand Down Expand Up @@ -1178,7 +1224,7 @@ static int do_grow(struct inode *inode, u64 size)
if (error)
return error;

error = gfs2_inplace_reserve(ip, 1);
error = gfs2_inplace_reserve(ip, 1, 0);
if (error)
goto do_grow_qunlock;
unstuff = 1;
Expand Down
7 changes: 1 addition & 6 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1676,16 +1676,11 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
be16_add_cpu(&leaf->lf_entries, 1);
}
brelse(bh);
error = gfs2_meta_inode_buffer(ip, &bh);
if (error)
break;
gfs2_trans_add_bh(ip->i_gl, bh, 1);
ip->i_entries++;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
if (S_ISDIR(nip->i_inode.i_mode))
inc_nlink(&ip->i_inode);
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
mark_inode_dirty(inode);
error = 0;
break;
}
Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
if (ret)
goto out_unlock;
gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
if (ret)
goto out_quota_unlock;

Expand Down Expand Up @@ -825,7 +825,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
retry:
gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);

error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks);
error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
if (error) {
if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
bytes >>= 1;
Expand Down
40 changes: 26 additions & 14 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ struct gfs2_glock_iter {

typedef void (*glock_examiner) (struct gfs2_glock * gl);

static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0)
static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);

static struct dentry *gfs2_root;
Expand Down Expand Up @@ -107,10 +105,12 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
{
struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);

if (gl->gl_ops->go_flags & GLOF_ASPACE)
if (gl->gl_ops->go_flags & GLOF_ASPACE) {
kmem_cache_free(gfs2_glock_aspace_cachep, gl);
else
} else {
kfree(gl->gl_lksb.sb_lvbptr);
kmem_cache_free(gfs2_glock_cachep, gl);
}
}

void gfs2_glock_free(struct gfs2_glock *gl)
Expand Down Expand Up @@ -537,8 +537,8 @@ __acquires(&gl->gl_spin)
(lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
clear_bit(GLF_BLOCKING, &gl->gl_flags);
spin_unlock(&gl->gl_spin);
if (glops->go_xmote_th)
glops->go_xmote_th(gl);
if (glops->go_sync)
glops->go_sync(gl);
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
Expand All @@ -547,7 +547,10 @@ __acquires(&gl->gl_spin)
if (sdp->sd_lockstruct.ls_ops->lm_lock) {
/* lock_dlm */
ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
GLOCK_BUG_ON(gl, ret);
if (ret) {
printk(KERN_ERR "GFS2: lm_lock ret %d\n", ret);
GLOCK_BUG_ON(gl, 1);
}
} else { /* lock_nolock */
finish_xmote(gl, target);
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
Expand Down Expand Up @@ -736,6 +739,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
if (!gl)
return -ENOMEM;

memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));

if (glops->go_flags & GLOF_LVB) {
gl->gl_lksb.sb_lvbptr = kzalloc(GFS2_MIN_LVB_SIZE, GFP_KERNEL);
if (!gl->gl_lksb.sb_lvbptr) {
kmem_cache_free(cachep, gl);
return -ENOMEM;
}
}

atomic_inc(&sdp->sd_glock_disposal);
gl->gl_sbd = sdp;
gl->gl_flags = 0;
Expand All @@ -753,9 +766,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
preempt_enable();
gl->gl_stats.stats[GFS2_LKS_DCOUNT] = 0;
gl->gl_stats.stats[GFS2_LKS_QCOUNT] = 0;
memset(&gl->gl_lksb, 0, sizeof(struct dlm_lksb));
memset(gl->gl_lvb, 0, 32 * sizeof(char));
gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
gl->gl_tchange = jiffies;
gl->gl_object = NULL;
gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
Expand All @@ -777,6 +787,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
tmp = search_bucket(hash, sdp, &name);
if (tmp) {
spin_unlock_bucket(hash);
kfree(gl->gl_lksb.sb_lvbptr);
kmem_cache_free(cachep, gl);
atomic_dec(&sdp->sd_glock_disposal);
gl = tmp;
Expand Down Expand Up @@ -1013,7 +1024,7 @@ __acquires(&gl->gl_spin)
printk(KERN_ERR "pid: %d\n", pid_nr(gh->gh_owner_pid));
printk(KERN_ERR "lock type: %d req lock state : %d\n",
gh->gh_gl->gl_name.ln_type, gh->gh_state);
__dump_glock(NULL, gl);
gfs2_dump_glock(NULL, gl);
BUG();
}

Expand Down Expand Up @@ -1508,7 +1519,7 @@ static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
{
int ret;
spin_lock(&gl->gl_spin);
ret = __dump_glock(seq, gl);
ret = gfs2_dump_glock(seq, gl);
spin_unlock(&gl->gl_spin);
return ret;
}
Expand All @@ -1528,6 +1539,7 @@ static void dump_glock_func(struct gfs2_glock *gl)

void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
{
set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
glock_hash_walk(clear_glock, sdp);
flush_workqueue(glock_workqueue);
wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
Expand Down Expand Up @@ -1655,7 +1667,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
}

/**
* __dump_glock - print information about a glock
* gfs2_dump_glock - print information about a glock
* @seq: The seq_file struct
* @gl: the glock
*
Expand All @@ -1672,7 +1684,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
* Returns: 0 on success, -ENOBUFS when we run out of space
*/

static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
{
const struct gfs2_glock_operations *glops = gl->gl_ops;
unsigned long long dtime;
Expand Down
54 changes: 27 additions & 27 deletions fs/gfs2/glock.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,33 +178,33 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
return NULL;
}

int gfs2_glock_get(struct gfs2_sbd *sdp,
u64 number, const struct gfs2_glock_operations *glops,
int create, struct gfs2_glock **glp);
void gfs2_glock_hold(struct gfs2_glock *gl);
void gfs2_glock_put_nolock(struct gfs2_glock *gl);
void gfs2_glock_put(struct gfs2_glock *gl);
void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
struct gfs2_holder *gh);
void gfs2_holder_reinit(unsigned int state, unsigned flags,
struct gfs2_holder *gh);
void gfs2_holder_uninit(struct gfs2_holder *gh);
int gfs2_glock_nq(struct gfs2_holder *gh);
int gfs2_glock_poll(struct gfs2_holder *gh);
int gfs2_glock_wait(struct gfs2_holder *gh);
void gfs2_glock_dq(struct gfs2_holder *gh);
void gfs2_glock_dq_wait(struct gfs2_holder *gh);

void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
u64 number, const struct gfs2_glock_operations *glops,
unsigned int state, int flags, struct gfs2_holder *gh);

int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);

__printf(2, 3)
extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
const struct gfs2_glock_operations *glops,
int create, struct gfs2_glock **glp);
extern void gfs2_glock_hold(struct gfs2_glock *gl);
extern void gfs2_glock_put_nolock(struct gfs2_glock *gl);
extern void gfs2_glock_put(struct gfs2_glock *gl);
extern void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
unsigned flags, struct gfs2_holder *gh);
extern void gfs2_holder_reinit(unsigned int state, unsigned flags,
struct gfs2_holder *gh);
extern void gfs2_holder_uninit(struct gfs2_holder *gh);
extern int gfs2_glock_nq(struct gfs2_holder *gh);
extern int gfs2_glock_poll(struct gfs2_holder *gh);
extern int gfs2_glock_wait(struct gfs2_holder *gh);
extern void gfs2_glock_dq(struct gfs2_holder *gh);
extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
extern int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
const struct gfs2_glock_operations *glops,
unsigned int state, int flags,
struct gfs2_holder *gh);
extern int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
extern void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
extern void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
extern int gfs2_dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { gfs2_dump_glock(NULL, gl); BUG(); } } while(0)
extern __printf(2, 3)
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);

/**
Expand Down
19 changes: 10 additions & 9 deletions fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)

gfs2_trans_add_revoke(sdp, bd);
}
BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
spin_unlock(&sdp->sd_ail_lock);
gfs2_log_unlock(sdp);
}
Expand All @@ -96,7 +96,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
tr.tr_ip = (unsigned long)__builtin_return_address(0);
sb_start_intwrite(sdp->sd_vfs);
gfs2_log_reserve(sdp, tr.tr_reserved);
BUG_ON(current->journal_info);
WARN_ON_ONCE(current->journal_info);
current->journal_info = &tr;

__gfs2_ail_flush(gl, 0);
Expand Down Expand Up @@ -139,7 +139,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)

if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
return;
BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);

gfs2_log_flush(gl->gl_sbd, gl);
filemap_fdatawrite(metamapping);
Expand Down Expand Up @@ -168,7 +168,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
{
struct address_space *mapping = gfs2_glock2aspace(gl);

BUG_ON(!(flags & DIO_METADATA));
WARN_ON_ONCE(!(flags & DIO_METADATA));
gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
truncate_inode_pages(mapping, 0);

Expand Down Expand Up @@ -197,7 +197,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
return;

BUG_ON(gl->gl_state != LM_ST_EXCLUSIVE);
GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);

gfs2_log_flush(gl->gl_sbd, gl);
filemap_fdatawrite(metamapping);
Expand Down Expand Up @@ -536,7 +536,7 @@ const struct gfs2_glock_operations gfs2_meta_glops = {
};

const struct gfs2_glock_operations gfs2_inode_glops = {
.go_xmote_th = inode_go_sync,
.go_sync = inode_go_sync,
.go_inval = inode_go_inval,
.go_demote_ok = inode_go_demote_ok,
.go_lock = inode_go_lock,
Expand All @@ -546,17 +546,17 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
};

const struct gfs2_glock_operations gfs2_rgrp_glops = {
.go_xmote_th = rgrp_go_sync,
.go_sync = rgrp_go_sync,
.go_inval = rgrp_go_inval,
.go_lock = gfs2_rgrp_go_lock,
.go_unlock = gfs2_rgrp_go_unlock,
.go_dump = gfs2_rgrp_dump,
.go_type = LM_TYPE_RGRP,
.go_flags = GLOF_ASPACE,
.go_flags = GLOF_ASPACE | GLOF_LVB,
};

const struct gfs2_glock_operations gfs2_trans_glops = {
.go_xmote_th = trans_go_sync,
.go_sync = trans_go_sync,
.go_xmote_bh = trans_go_xmote_bh,
.go_demote_ok = trans_go_demote_ok,
.go_type = LM_TYPE_NONDISK,
Expand All @@ -577,6 +577,7 @@ const struct gfs2_glock_operations gfs2_nondisk_glops = {

const struct gfs2_glock_operations gfs2_quota_glops = {
.go_type = LM_TYPE_QUOTA,
.go_flags = GLOF_LVB,
};

const struct gfs2_glock_operations gfs2_journal_glops = {
Expand Down
Loading

0 comments on commit 08242bc

Please sign in to comment.