Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 67679
b: refs/heads/master
c: d7b616e
h: refs/heads/master
i:
  67677: 8a4bae2
  67675: b45b245
  67671: 9b647d8
  67663: 1bb7e87
  67647: ae00b6a
v: v3
  • Loading branch information
Steven Whitehouse committed Oct 10, 2007
1 parent 9ef6a6a commit 2671dd3
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 128 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9b9107a5a8b190e6cf09bbdf893869c6a9c482cc
refs/heads/master: d7b616e252b125f12b007c392f7644053bb6f140
2 changes: 1 addition & 1 deletion trunk/fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -612,13 +612,13 @@ struct gfs2_sbd {
unsigned int sd_log_num_revoke;
unsigned int sd_log_num_rg;
unsigned int sd_log_num_databuf;
unsigned int sd_log_num_jdata;

struct list_head sd_log_le_gl;
struct list_head sd_log_le_buf;
struct list_head sd_log_le_revoke;
struct list_head sd_log_le_rg;
struct list_head sd_log_le_databuf;
struct list_head sd_log_le_ordered;

unsigned int sd_log_blks_free;
struct mutex sd_log_reserve_mutex;
Expand Down
57 changes: 55 additions & 2 deletions trunk/fs/gfs2/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,57 @@ static void log_flush_commit(struct gfs2_sbd *sdp)
}
}

static void gfs2_ordered_write(struct gfs2_sbd *sdp)
{
struct gfs2_bufdata *bd;
struct buffer_head *bh;
LIST_HEAD(written);

gfs2_log_lock(sdp);
while (!list_empty(&sdp->sd_log_le_ordered)) {
bd = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_bufdata, bd_le.le_list);
list_move(&bd->bd_le.le_list, &written);
bh = bd->bd_bh;
if (!buffer_dirty(bh))
continue;
get_bh(bh);
gfs2_log_unlock(sdp);
lock_buffer(bh);
if (test_clear_buffer_dirty(bh)) {
bh->b_end_io = end_buffer_write_sync;
submit_bh(WRITE, bh);
} else {
unlock_buffer(bh);
brelse(bh);
}
gfs2_log_lock(sdp);
}
list_splice(&written, &sdp->sd_log_le_ordered);
gfs2_log_unlock(sdp);
}

static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
{
struct gfs2_bufdata *bd;
struct buffer_head *bh;

gfs2_log_lock(sdp);
while (!list_empty(&sdp->sd_log_le_ordered)) {
bd = list_entry(sdp->sd_log_le_ordered.prev, struct gfs2_bufdata, bd_le.le_list);
bh = bd->bd_bh;
if (buffer_locked(bh)) {
get_bh(bh);
gfs2_log_unlock(sdp);
wait_on_buffer(bh);
brelse(bh);
gfs2_log_lock(sdp);
continue;
}
list_del_init(&bd->bd_le.le_list);
}
gfs2_log_unlock(sdp);
}

/**
* gfs2_log_flush - flush incore transaction(s)
* @sdp: the filesystem
Expand Down Expand Up @@ -648,7 +699,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
INIT_LIST_HEAD(&ai->ai_ail2_list);

gfs2_assert_withdraw(sdp,
sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
sdp->sd_log_num_buf + sdp->sd_log_num_databuf ==
sdp->sd_log_commited_buf +
sdp->sd_log_commited_databuf);
gfs2_assert_withdraw(sdp,
Expand All @@ -658,7 +709,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
sdp->sd_log_flush_wrapped = 0;
ai->ai_first = sdp->sd_log_flush_head;

gfs2_ordered_write(sdp);
lops_before_commit(sdp);
gfs2_ordered_wait(sdp);

if (!list_empty(&sdp->sd_log_flush_list))
log_flush_commit(sdp);
else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
Expand Down Expand Up @@ -751,7 +805,6 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
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_jdata);
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_databuf);
Expand Down
160 changes: 40 additions & 120 deletions trunk/fs/gfs2/lops.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,10 +555,11 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
if (gfs2_is_jdata(ip)) {
gfs2_pin(sdp, bd->bd_bh);
tr->tr_num_databuf_new++;
sdp->sd_log_num_jdata++;
sdp->sd_log_num_databuf++;
list_add(&le->le_list, &sdp->sd_log_le_databuf);
} else {
list_add(&le->le_list, &sdp->sd_log_le_ordered);
}
sdp->sd_log_num_databuf++;
list_add(&le->le_list, &sdp->sd_log_le_databuf);
out:
gfs2_log_unlock(sdp);
unlock_buffer(bd->bd_bh);
Expand All @@ -583,114 +584,59 @@ static int gfs2_check_magic(struct buffer_head *bh)
/**
* databuf_lo_before_commit - Scan the data buffers, writing as we go
*
* Here we scan through the lists of buffers and make the assumption
* that any buffer thats been pinned is being journaled, and that
* any unpinned buffer is an ordered write data buffer and therefore
* will be written back rather than journaled.
*/

static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
{
LIST_HEAD(started);
struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
struct gfs2_bufdata *bd1 = NULL, *bd2;
struct buffer_head *bh = NULL,*bh1 = NULL;
struct gfs2_log_descriptor *ld;
unsigned int limit;
unsigned int total_dbuf;
unsigned int total_jdata;
unsigned int total;
unsigned int num, n;
__be64 *ptr = NULL;
int magic;


limit = databuf_limit(sdp);

/*
* Start writing ordered buffers, write journaled buffers
* into the log along with a header
*/
gfs2_log_lock(sdp);
total_dbuf = sdp->sd_log_num_databuf;
total_jdata = sdp->sd_log_num_jdata;
total = sdp->sd_log_num_databuf;
bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf,
bd_le.le_list);
while(total_dbuf) {
num = total_jdata;
while(total) {
num = total;
if (num > limit)
num = limit;

gfs2_log_unlock(sdp);
bh = gfs2_log_get_buf(sdp);
gfs2_log_lock(sdp);

ld = (struct gfs2_log_descriptor *)bh->b_data;
ptr = (__be64 *)(bh->b_data + DATABUF_OFFSET);
ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD);
ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD);
ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_JDATA);
ld->ld_length = cpu_to_be32(num + 1);
ld->ld_data1 = cpu_to_be32(num);
ld->ld_data2 = cpu_to_be32(0);
memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));

n = 0;
list_for_each_entry_safe_continue(bd1, bdt,
&sdp->sd_log_le_databuf,
bd_le.le_list) {
/* store off the buffer head in a local ptr since
* gfs2_bufdata might change when we drop the log lock
*/
list_for_each_entry_continue(bd1, &sdp->sd_log_le_databuf,
bd_le.le_list) {
bh1 = bd1->bd_bh;

/* An ordered write buffer */
if (bh1 && !buffer_pinned(bh1)) {
list_move(&bd1->bd_le.le_list, &started);
if (bd1 == bd2) {
bd2 = NULL;
bd2 = list_prepare_entry(bd2,
&sdp->sd_log_le_databuf,
bd_le.le_list);
}
total_dbuf--;
if (bh1) {
if (buffer_dirty(bh1)) {
get_bh(bh1);

gfs2_log_unlock(sdp);

ll_rw_block(SWRITE, 1, &bh1);
brelse(bh1);

gfs2_log_lock(sdp);
}
continue;
}
continue;
} else if (bh1) { /* A journaled buffer */
int magic;
gfs2_log_unlock(sdp);
if (!bh) {
bh = gfs2_log_get_buf(sdp);
ld = (struct gfs2_log_descriptor *)
bh->b_data;
ptr = (__be64 *)(bh->b_data +
DATABUF_OFFSET);
ld->ld_header.mh_magic =
cpu_to_be32(GFS2_MAGIC);
ld->ld_header.mh_type =
cpu_to_be32(GFS2_METATYPE_LD);
ld->ld_header.mh_format =
cpu_to_be32(GFS2_FORMAT_LD);
ld->ld_type =
cpu_to_be32(GFS2_LOG_DESC_JDATA);
ld->ld_length = cpu_to_be32(num + 1);
ld->ld_data1 = cpu_to_be32(num);
ld->ld_data2 = cpu_to_be32(0);
memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved));
}
magic = gfs2_check_magic(bh1);
*ptr++ = cpu_to_be64(bh1->b_blocknr);
*ptr++ = cpu_to_be64((__u64)magic);
clear_buffer_escaped(bh1);
if (unlikely(magic != 0))
set_buffer_escaped(bh1);
gfs2_log_lock(sdp);
if (++n >= num)
break;
} else if (!bh1) {
total_dbuf--;
sdp->sd_log_num_databuf--;
list_del_init(&bd1->bd_le.le_list);
if (bd1 == bd2) {
bd2 = NULL;
bd2 = list_prepare_entry(bd2,
&sdp->sd_log_le_databuf,
bd_le.le_list);
}
kmem_cache_free(gfs2_bufdata_cachep, bd1);
}
magic = gfs2_check_magic(bh1);
*ptr++ = cpu_to_be64(bh1->b_blocknr);
*ptr++ = cpu_to_be64((__u64)magic);
clear_buffer_escaped(bh1);
if (unlikely(magic != 0))
set_buffer_escaped(bh1);
if (++n >= num)
break;
}
gfs2_log_unlock(sdp);
if (bh) {
Expand Down Expand Up @@ -727,34 +673,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
break;
}
bh = NULL;
BUG_ON(total_dbuf < num);
total_dbuf -= num;
total_jdata -= num;
BUG_ON(total < num);
total -= num;
}
gfs2_log_unlock(sdp);

/* Wait on all ordered buffers */
while (!list_empty(&started)) {
gfs2_log_lock(sdp);
bd1 = list_entry(started.next, struct gfs2_bufdata,
bd_le.le_list);
list_del_init(&bd1->bd_le.le_list);
sdp->sd_log_num_databuf--;
bh = bd1->bd_bh;
if (bh) {
bh->b_private = NULL;
get_bh(bh);
gfs2_log_unlock(sdp);
wait_on_buffer(bh);
brelse(bh);
} else
gfs2_log_unlock(sdp);

kmem_cache_free(gfs2_bufdata_cachep, bd1);
}

/* We've removed all the ordered write bufs here, so only jdata left */
gfs2_assert_warn(sdp, sdp->sd_log_num_databuf == sdp->sd_log_num_jdata);
}

static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
Expand Down Expand Up @@ -838,11 +760,9 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list);
list_del_init(&bd->bd_le.le_list);
sdp->sd_log_num_databuf--;
sdp->sd_log_num_jdata--;
gfs2_unpin(sdp, bd->bd_bh, ai);
}
gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf);
gfs2_assert_warn(sdp, !sdp->sd_log_num_jdata);
}


Expand Down
50 changes: 46 additions & 4 deletions trunk/fs/gfs2/ops_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,13 +616,50 @@ static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock)
return dblock;
}

static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
{
struct gfs2_bufdata *bd;

lock_buffer(bh);
gfs2_log_lock(sdp);
clear_buffer_dirty(bh);
bd = bh->b_private;
if (bd) {
if (!list_empty(&bd->bd_le.le_list)) {
if (!buffer_pinned(bh))
list_del_init(&bd->bd_le.le_list);
}
}
bh->b_bdev = NULL;
clear_buffer_mapped(bh);
clear_buffer_req(bh);
clear_buffer_new(bh);
gfs2_log_unlock(sdp);
unlock_buffer(bh);
}

static void gfs2_invalidatepage(struct page *page, unsigned long offset)
{
struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
struct buffer_head *bh, *head;
unsigned long pos = 0;

BUG_ON(!PageLocked(page));
if (offset == 0)
ClearPageChecked(page);
if (!page_has_buffers(page))
goto out;

block_invalidatepage(page, offset);
bh = head = page_buffers(page);
do {
if (offset <= pos)
gfs2_discard(sdp, bh);
pos += bh->b_size;
bh = bh->b_this_page;
} while (bh != head);
out:
if (offset == 0)
try_to_release_page(page, 0);
}

/**
Expand Down Expand Up @@ -732,9 +769,14 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
if (bd) {
gfs2_assert_warn(sdp, bd->bd_bh == bh);
gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
bd->bd_bh = NULL;
if (!list_empty(&bd->bd_le.le_list))
bd = NULL;
if (!list_empty(&bd->bd_le.le_list)) {
if (!buffer_pinned(bh))
list_del_init(&bd->bd_le.le_list);
else
bd = NULL;
}
if (bd)
bd->bd_bh = NULL;
bh->b_private = NULL;
}
gfs2_log_unlock(sdp);
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/gfs2/ops_fstype.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
INIT_LIST_HEAD(&sdp->sd_log_le_revoke);
INIT_LIST_HEAD(&sdp->sd_log_le_rg);
INIT_LIST_HEAD(&sdp->sd_log_le_databuf);
INIT_LIST_HEAD(&sdp->sd_log_le_ordered);

mutex_init(&sdp->sd_log_reserve_mutex);
INIT_LIST_HEAD(&sdp->sd_ail1_list);
Expand Down

0 comments on commit 2671dd3

Please sign in to comment.