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 changes from Steven Whitehouse.

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: Change truncate page allocation to be GFP_NOFS
  GFS2: call gfs2_write_alloc_required for each chunk
  GFS2: Clean up log flush header writing
  GFS2: Remove a __GFP_NOFAIL allocation
  GFS2: Flush pending glock work when evicting an inode
  GFS2: make sure rgrps are up to date in func gfs2_blk2rgrpd
  GFS2: Eliminate sd_rindex_mutex
  GFS2: Unlock rindex mutex on glock error
  GFS2: Make bd_cmp() static
  GFS2: Sort the ordered write list
  GFS2: FITRIM ioctl support
  GFS2: Move two functions from log.c to lops.c
  GFS2: glock statistics gathering
  • Loading branch information
Linus Torvalds committed Mar 22, 2012
2 parents 30d73f3 + 220cca2 commit ad12ab2
Show file tree
Hide file tree
Showing 20 changed files with 805 additions and 245 deletions.
4 changes: 2 additions & 2 deletions fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
int release = 0;

if (!page || page->index) {
page = grab_cache_page(inode->i_mapping, 0);
page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
if (!page)
return -ENOMEM;
release = 1;
Expand Down Expand Up @@ -930,7 +930,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from)
struct page *page;
int err;

page = grab_cache_page(mapping, index);
page = find_or_create_page(mapping, index, GFP_NOFS);
if (!page)
return 0;

Expand Down
15 changes: 10 additions & 5 deletions fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return gfs2_get_flags(filp, (u32 __user *)arg);
case FS_IOC_SETFLAGS:
return gfs2_set_flags(filp, (u32 __user *)arg);
case FITRIM:
return gfs2_fitrim(filp, (void __user *)arg);
}
return -ENOTTY;
}
Expand Down Expand Up @@ -674,6 +676,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *dibh;
int error;
loff_t size = len;
unsigned int nr_blks;
sector_t lblock = offset >> inode->i_blkbits;

Expand Down Expand Up @@ -707,8 +710,8 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
goto out;
}
}
if (offset + len > inode->i_size && !(mode & FALLOC_FL_KEEP_SIZE))
i_size_write(inode, offset + len);
if (offset + size > inode->i_size && !(mode & FALLOC_FL_KEEP_SIZE))
i_size_write(inode, offset + size);

mark_inode_dirty(inode);

Expand Down Expand Up @@ -777,12 +780,14 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
if (unlikely(error))
goto out_uninit;

if (!gfs2_write_alloc_required(ip, offset, len))
goto out_unlock;

while (len > 0) {
if (len < bytes)
bytes = len;
if (!gfs2_write_alloc_required(ip, offset, bytes)) {
len -= bytes;
offset += bytes;
continue;
}
qa = gfs2_qadata_get(ip);
if (!qa) {
error = -ENOMEM;
Expand Down
210 changes: 202 additions & 8 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/rcupdate.h>
#include <linux/rculist_bl.h>
#include <linux/bit_spinlock.h>
#include <linux/percpu.h>

#include "gfs2.h"
#include "incore.h"
Expand Down Expand Up @@ -543,6 +544,11 @@ __acquires(&gl->gl_spin)
do_error(gl, 0); /* Fail queued try locks */
}
gl->gl_req = target;
set_bit(GLF_BLOCKING, &gl->gl_flags);
if ((gl->gl_req == LM_ST_UNLOCKED) ||
(gl->gl_state == LM_ST_EXCLUSIVE) ||
(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);
Expand Down Expand Up @@ -744,6 +750,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
return -ENOMEM;

atomic_inc(&sdp->sd_glock_disposal);
gl->gl_sbd = sdp;
gl->gl_flags = 0;
gl->gl_name = name;
atomic_set(&gl->gl_ref, 1);
Expand All @@ -752,12 +759,17 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
gl->gl_demote_state = LM_ST_EXCLUSIVE;
gl->gl_hash = hash;
gl->gl_ops = glops;
snprintf(gl->gl_strname, GDLM_STRNAME_BYTES, "%8x%16llx", name.ln_type, (unsigned long long)number);
gl->gl_dstamp = ktime_set(0, 0);
preempt_disable();
/* We use the global stats to estimate the initial per-glock stats */
gl->gl_stats = this_cpu_ptr(sdp->sd_lkstats)->lkstats[glops->go_type];
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));
gl->gl_lksb.sb_lvbptr = gl->gl_lvb;
gl->gl_tchange = jiffies;
gl->gl_object = NULL;
gl->gl_sbd = sdp;
gl->gl_hold_time = GL_GLOCK_DFT_HOLD;
INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
INIT_WORK(&gl->gl_delete, delete_work_func);
Expand Down Expand Up @@ -999,6 +1011,8 @@ __acquires(&gl->gl_spin)
}
set_bit(GLF_QUEUED, &gl->gl_flags);
trace_gfs2_glock_queue(gh, 1);
gfs2_glstats_inc(gl, GFS2_LKS_QCOUNT);
gfs2_sbstats_inc(gl, GFS2_LKS_QCOUNT);
if (likely(insert_pt == NULL)) {
list_add_tail(&gh->gh_list, &gl->gl_holders);
if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
Expand Down Expand Up @@ -1658,6 +1672,8 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
*p++ = 'L';
if (gl->gl_object)
*p++ = 'o';
if (test_bit(GLF_BLOCKING, gflags))
*p++ = 'b';
*p = 0;
return buf;
}
Expand Down Expand Up @@ -1714,8 +1730,78 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl)
return error;
}

static int gfs2_glstats_seq_show(struct seq_file *seq, void *iter_ptr)
{
struct gfs2_glock *gl = iter_ptr;

seq_printf(seq, "G: n:%u/%llx rtt:%lld/%lld rttb:%lld/%lld irt:%lld/%lld dcnt: %lld qcnt: %lld\n",
gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number,
(long long)gl->gl_stats.stats[GFS2_LKS_SRTT],
(long long)gl->gl_stats.stats[GFS2_LKS_SRTTVAR],
(long long)gl->gl_stats.stats[GFS2_LKS_SRTTB],
(long long)gl->gl_stats.stats[GFS2_LKS_SRTTVARB],
(long long)gl->gl_stats.stats[GFS2_LKS_SIRT],
(long long)gl->gl_stats.stats[GFS2_LKS_SIRTVAR],
(long long)gl->gl_stats.stats[GFS2_LKS_DCOUNT],
(long long)gl->gl_stats.stats[GFS2_LKS_QCOUNT]);
return 0;
}

static const char *gfs2_gltype[] = {
"type",
"reserved",
"nondisk",
"inode",
"rgrp",
"meta",
"iopen",
"flock",
"plock",
"quota",
"journal",
};

static const char *gfs2_stype[] = {
[GFS2_LKS_SRTT] = "srtt",
[GFS2_LKS_SRTTVAR] = "srttvar",
[GFS2_LKS_SRTTB] = "srttb",
[GFS2_LKS_SRTTVARB] = "srttvarb",
[GFS2_LKS_SIRT] = "sirt",
[GFS2_LKS_SIRTVAR] = "sirtvar",
[GFS2_LKS_DCOUNT] = "dlm",
[GFS2_LKS_QCOUNT] = "queue",
};

#define GFS2_NR_SBSTATS (ARRAY_SIZE(gfs2_gltype) * ARRAY_SIZE(gfs2_stype))

static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
{
struct gfs2_glock_iter *gi = seq->private;
struct gfs2_sbd *sdp = gi->sdp;
unsigned index = gi->hash >> 3;
unsigned subindex = gi->hash & 0x07;
s64 value;
int i;

if (index == 0 && subindex != 0)
return 0;

seq_printf(seq, "%-10s %8s:", gfs2_gltype[index],
(index == 0) ? "cpu": gfs2_stype[subindex]);

for_each_possible_cpu(i) {
const struct gfs2_pcpu_lkstats *lkstats = per_cpu_ptr(sdp->sd_lkstats, i);
if (index == 0) {
value = i;
} else {
value = lkstats->lkstats[index - 1].stats[subindex];
}
seq_printf(seq, " %15lld", (long long)value);
}
seq_putc(seq, '\n');
return 0;
}

int __init gfs2_glock_init(void)
{
Expand Down Expand Up @@ -1828,14 +1914,57 @@ static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
return dump_glock(seq, iter_ptr);
}

static void *gfs2_sbstats_seq_start(struct seq_file *seq, loff_t *pos)
{
struct gfs2_glock_iter *gi = seq->private;

gi->hash = *pos;
if (*pos >= GFS2_NR_SBSTATS)
return NULL;
preempt_disable();
return SEQ_START_TOKEN;
}

static void *gfs2_sbstats_seq_next(struct seq_file *seq, void *iter_ptr,
loff_t *pos)
{
struct gfs2_glock_iter *gi = seq->private;
(*pos)++;
gi->hash++;
if (gi->hash >= GFS2_NR_SBSTATS) {
preempt_enable();
return NULL;
}
return SEQ_START_TOKEN;
}

static void gfs2_sbstats_seq_stop(struct seq_file *seq, void *iter_ptr)
{
preempt_enable();
}

static const struct seq_operations gfs2_glock_seq_ops = {
.start = gfs2_glock_seq_start,
.next = gfs2_glock_seq_next,
.stop = gfs2_glock_seq_stop,
.show = gfs2_glock_seq_show,
};

static int gfs2_debugfs_open(struct inode *inode, struct file *file)
static const struct seq_operations gfs2_glstats_seq_ops = {
.start = gfs2_glock_seq_start,
.next = gfs2_glock_seq_next,
.stop = gfs2_glock_seq_stop,
.show = gfs2_glstats_seq_show,
};

static const struct seq_operations gfs2_sbstats_seq_ops = {
.start = gfs2_sbstats_seq_start,
.next = gfs2_sbstats_seq_next,
.stop = gfs2_sbstats_seq_stop,
.show = gfs2_sbstats_seq_show,
};

static int gfs2_glocks_open(struct inode *inode, struct file *file)
{
int ret = seq_open_private(file, &gfs2_glock_seq_ops,
sizeof(struct gfs2_glock_iter));
Expand All @@ -1847,9 +1976,49 @@ static int gfs2_debugfs_open(struct inode *inode, struct file *file)
return ret;
}

static const struct file_operations gfs2_debug_fops = {
static int gfs2_glstats_open(struct inode *inode, struct file *file)
{
int ret = seq_open_private(file, &gfs2_glstats_seq_ops,
sizeof(struct gfs2_glock_iter));
if (ret == 0) {
struct seq_file *seq = file->private_data;
struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private;
}
return ret;
}

static int gfs2_sbstats_open(struct inode *inode, struct file *file)
{
int ret = seq_open_private(file, &gfs2_sbstats_seq_ops,
sizeof(struct gfs2_glock_iter));
if (ret == 0) {
struct seq_file *seq = file->private_data;
struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private;
}
return ret;
}

static const struct file_operations gfs2_glocks_fops = {
.owner = THIS_MODULE,
.open = gfs2_glocks_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_private,
};

static const struct file_operations gfs2_glstats_fops = {
.owner = THIS_MODULE,
.open = gfs2_debugfs_open,
.open = gfs2_glstats_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_private,
};

static const struct file_operations gfs2_sbstats_fops = {
.owner = THIS_MODULE,
.open = gfs2_sbstats_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_private,
Expand All @@ -1863,20 +2032,45 @@ int gfs2_create_debugfs_file(struct gfs2_sbd *sdp)
sdp->debugfs_dentry_glocks = debugfs_create_file("glocks",
S_IFREG | S_IRUGO,
sdp->debugfs_dir, sdp,
&gfs2_debug_fops);
&gfs2_glocks_fops);
if (!sdp->debugfs_dentry_glocks)
return -ENOMEM;
goto fail;

sdp->debugfs_dentry_glstats = debugfs_create_file("glstats",
S_IFREG | S_IRUGO,
sdp->debugfs_dir, sdp,
&gfs2_glstats_fops);
if (!sdp->debugfs_dentry_glstats)
goto fail;

sdp->debugfs_dentry_sbstats = debugfs_create_file("sbstats",
S_IFREG | S_IRUGO,
sdp->debugfs_dir, sdp,
&gfs2_sbstats_fops);
if (!sdp->debugfs_dentry_sbstats)
goto fail;

return 0;
fail:
gfs2_delete_debugfs_file(sdp);
return -ENOMEM;
}

void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp)
{
if (sdp && sdp->debugfs_dir) {
if (sdp->debugfs_dir) {
if (sdp->debugfs_dentry_glocks) {
debugfs_remove(sdp->debugfs_dentry_glocks);
sdp->debugfs_dentry_glocks = NULL;
}
if (sdp->debugfs_dentry_glstats) {
debugfs_remove(sdp->debugfs_dentry_glstats);
sdp->debugfs_dentry_glstats = NULL;
}
if (sdp->debugfs_dentry_sbstats) {
debugfs_remove(sdp->debugfs_dentry_sbstats);
sdp->debugfs_dentry_sbstats = NULL;
}
debugfs_remove(sdp->debugfs_dir);
sdp->debugfs_dir = NULL;
}
Expand Down
Loading

0 comments on commit ad12ab2

Please sign in to comment.