Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 58581
b: refs/heads/master
c: 2332c44
h: refs/heads/master
i:
  58579: e3bf129
v: v3
  • Loading branch information
Robert Peterson authored and Steven Whitehouse committed Jul 9, 2007
1 parent 6c72bf6 commit 5ec35e5
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 57 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: 2840501ac822c5bf712f67b4b02640e16e145a29
refs/heads/master: 2332c4435bb733b5cd4f612ee57532bd8fde4c1c
4 changes: 3 additions & 1 deletion trunk/fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,9 @@ struct gfs2_trans {

unsigned int tr_num_buf;
unsigned int tr_num_buf_new;
unsigned int tr_num_databuf_new;
unsigned int tr_num_buf_rm;
unsigned int tr_num_databuf_rm;
struct list_head tr_list_buf;

unsigned int tr_num_revoke;
Expand Down Expand Up @@ -599,6 +601,7 @@ struct gfs2_sbd {

unsigned int sd_log_blks_reserved;
unsigned int sd_log_commited_buf;
unsigned int sd_log_commited_databuf;
unsigned int sd_log_commited_revoke;

unsigned int sd_log_num_gl;
Expand All @@ -607,7 +610,6 @@ struct gfs2_sbd {
unsigned int sd_log_num_rg;
unsigned int sd_log_num_databuf;
unsigned int sd_log_num_jdata;
unsigned int sd_log_num_hdrs;

struct list_head sd_log_le_gl;
struct list_head sd_log_le_buf;
Expand Down
100 changes: 76 additions & 24 deletions trunk/fs/gfs2/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
* @blks: The number of blocks to reserve
*
* Note that we never give out the last few blocks of the journal. Thats
* due to the fact that there is are a small number of header blocks
* due to the fact that there is a small number of header blocks
* associated with each log flush. The exact number can't be known until
* flush time, so we ensure that we have just enough free blocks at all
* times to avoid running out during a log flush.
Expand Down Expand Up @@ -371,6 +371,58 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer
return dist;
}

/**
* calc_reserved - Calculate the number of blocks to reserve when
* refunding a transaction's unused buffers.
* @sdp: The GFS2 superblock
*
* This is complex. We need to reserve room for all our currently used
* metadata buffers (e.g. normal file I/O rewriting file time stamps) and
* all our journaled data buffers for journaled files (e.g. files in the
* meta_fs like rindex, or files for which chattr +j was done.)
* If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
* will count it as free space (sd_log_blks_free) and corruption will follow.
*
* We can have metadata bufs and jdata bufs in the same journal. So each
* type gets its own log header, for which we need to reserve a block.
* In fact, each type has the potential for needing more than one header
* in cases where we have more buffers than will fit on a journal page.
* Metadata journal entries take up half the space of journaled buffer entries.
* Thus, metadata entries have buf_limit (502) and journaled buffers have
* databuf_limit (251) before they cause a wrap around.
*
* Also, we need to reserve blocks for revoke journal entries and one for an
* overall header for the lot.
*
* Returns: the number of blocks reserved
*/
static unsigned int calc_reserved(struct gfs2_sbd *sdp)
{
unsigned int reserved = 0;
unsigned int mbuf_limit, metabufhdrs_needed;
unsigned int dbuf_limit, databufhdrs_needed;
unsigned int revokes = 0;

mbuf_limit = buf_limit(sdp);
metabufhdrs_needed = (sdp->sd_log_commited_buf +
(mbuf_limit - 1)) / mbuf_limit;
dbuf_limit = databuf_limit(sdp);
databufhdrs_needed = (sdp->sd_log_commited_databuf +
(dbuf_limit - 1)) / dbuf_limit;

if (sdp->sd_log_commited_revoke)
revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
sizeof(u64));

reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
sdp->sd_log_commited_databuf + databufhdrs_needed +
revokes;
/* One for the overall header */
if (reserved)
reserved++;
return reserved;
}

static unsigned int current_tail(struct gfs2_sbd *sdp)
{
struct gfs2_ail *ai;
Expand Down Expand Up @@ -461,14 +513,14 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
return bh;
}

static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull)
static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
{
unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);

ail2_empty(sdp, new_tail);

gfs2_log_lock(sdp);
sdp->sd_log_blks_free += dist - (pull ? 1 : 0);
sdp->sd_log_blks_free += dist;
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
gfs2_log_unlock(sdp);

Expand Down Expand Up @@ -518,7 +570,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
brelse(bh);

if (sdp->sd_log_tail != tail)
log_pull_tail(sdp, tail, pull);
log_pull_tail(sdp, tail);
else
gfs2_assert_withdraw(sdp, !pull);

Expand Down Expand Up @@ -579,7 +631,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
INIT_LIST_HEAD(&ai->ai_ail1_list);
INIT_LIST_HEAD(&ai->ai_ail2_list);

gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf + sdp->sd_log_num_jdata == sdp->sd_log_commited_buf);
gfs2_assert_withdraw(sdp,
sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
sdp->sd_log_commited_buf +
sdp->sd_log_commited_databuf);
gfs2_assert_withdraw(sdp,
sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);

Expand All @@ -590,16 +645,19 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
lops_before_commit(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)
else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
gfs2_log_lock(sdp);
sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
gfs2_log_unlock(sdp);
log_write_header(sdp, 0, PULL);
}
lops_after_commit(sdp, ai);

gfs2_log_lock(sdp);
sdp->sd_log_head = sdp->sd_log_flush_head;
sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
sdp->sd_log_blks_reserved = 0;
sdp->sd_log_commited_buf = 0;
sdp->sd_log_num_hdrs = 0;
sdp->sd_log_commited_databuf = 0;
sdp->sd_log_commited_revoke = 0;

if (!list_empty(&ai->ai_ail1_list)) {
Expand All @@ -616,32 +674,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)

static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
unsigned int reserved = 0;
unsigned int reserved;
unsigned int old;

gfs2_log_lock(sdp);

sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0);
sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
tr->tr_num_databuf_rm;
gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
(((int)sdp->sd_log_commited_databuf) >= 0));
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);

if (sdp->sd_log_commited_buf)
reserved += sdp->sd_log_commited_buf;
if (sdp->sd_log_commited_revoke)
reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
sizeof(u64));
if (reserved)
reserved++;

reserved = calc_reserved(sdp);
old = sdp->sd_log_blks_free;
sdp->sd_log_blks_free += tr->tr_reserved -
(reserved - sdp->sd_log_blks_reserved);

gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
gfs2_assert_withdraw(sdp,
sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks +
sdp->sd_log_num_hdrs);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
sdp->sd_jdesc->jd_blocks);

sdp->sd_log_blks_reserved = reserved;

Expand Down Expand Up @@ -687,13 +739,13 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
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);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs);
gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));

sdp->sd_log_flush_head = sdp->sd_log_head;
sdp->sd_log_flush_wrapped = 0;

log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0);
log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
(sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);

gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
Expand Down
53 changes: 23 additions & 30 deletions trunk/fs/gfs2/lops.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "gfs2.h"
#include "incore.h"
#include "inode.h"
#include "glock.h"
#include "log.h"
#include "lops.h"
Expand Down Expand Up @@ -117,15 +118,13 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
struct gfs2_log_descriptor *ld;
struct gfs2_bufdata *bd1 = NULL, *bd2;
unsigned int total = sdp->sd_log_num_buf;
unsigned int offset = sizeof(struct gfs2_log_descriptor);
unsigned int offset = BUF_OFFSET;
unsigned int limit;
unsigned int num;
unsigned n;
__be64 *ptr;

offset += sizeof(__be64) - 1;
offset &= ~(sizeof(__be64) - 1);
limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
limit = buf_limit(sdp);
/* for 4k blocks, limit = 503 */

bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
Expand All @@ -134,7 +133,6 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
if (total > limit)
num = limit;
bh = gfs2_log_get_buf(sdp);
sdp->sd_log_num_hdrs++;
ld = (struct gfs2_log_descriptor *)bh->b_data;
ptr = (__be64 *)(bh->b_data + offset);
ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
Expand Down Expand Up @@ -469,27 +467,26 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
struct gfs2_inode *ip = GFS2_I(mapping->host);

gfs2_log_lock(sdp);
tr->tr_touched = 1;
if (list_empty(&bd->bd_list_tr) &&
(ip->i_di.di_flags & GFS2_DIF_JDATA)) {
tr->tr_num_buf++;
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
gfs2_log_unlock(sdp);
if (!list_empty(&le->le_list))
return;
gfs2_pin(sdp, bd->bd_bh);
tr->tr_num_buf_new++;
} else {
if (!list_empty(&bd->bd_list_tr)) {
gfs2_log_unlock(sdp);
return;
}
tr->tr_touched = 1;
tr->tr_num_buf++;
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
gfs2_log_unlock(sdp);
if (!list_empty(&le->le_list))
return;

gfs2_trans_add_gl(bd->bd_gl);
gfs2_log_lock(sdp);
if (list_empty(&le->le_list)) {
if (ip->i_di.di_flags & GFS2_DIF_JDATA)
sdp->sd_log_num_jdata++;
sdp->sd_log_num_databuf++;
list_add(&le->le_list, &sdp->sd_log_le_databuf);
if (gfs2_is_jdata(ip)) {
sdp->sd_log_num_jdata++;
gfs2_pin(sdp, bd->bd_bh);
tr->tr_num_databuf_new++;
}
sdp->sd_log_num_databuf++;
gfs2_log_lock(sdp);
list_add(&le->le_list, &sdp->sd_log_le_databuf);
gfs2_log_unlock(sdp);
}

Expand Down Expand Up @@ -522,17 +519,14 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
LIST_HEAD(started);
struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
struct buffer_head *bh = NULL,*bh1 = NULL;
unsigned int offset = sizeof(struct gfs2_log_descriptor);
struct gfs2_log_descriptor *ld;
unsigned int limit;
unsigned int total_dbuf = sdp->sd_log_num_databuf;
unsigned int total_jdata = sdp->sd_log_num_jdata;
unsigned int num, n;
__be64 *ptr = NULL;

offset += 2*sizeof(__be64) - 1;
offset &= ~(2*sizeof(__be64) - 1);
limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
limit = databuf_limit(sdp);

/*
* Start writing ordered buffers, write journaled buffers
Expand Down Expand Up @@ -583,10 +577,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
gfs2_log_unlock(sdp);
if (!bh) {
bh = gfs2_log_get_buf(sdp);
sdp->sd_log_num_hdrs++;
ld = (struct gfs2_log_descriptor *)
bh->b_data;
ptr = (__be64 *)(bh->b_data + offset);
ptr = (__be64 *)(bh->b_data +
DATABUF_OFFSET);
ld->ld_header.mh_magic =
cpu_to_be32(GFS2_MAGIC);
ld->ld_header.mh_type =
Expand All @@ -607,8 +601,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
if (unlikely(magic != 0))
set_buffer_escaped(bh1);
gfs2_log_lock(sdp);
n += 2;
if (n >= num)
if (++n >= num)
break;
} else if (!bh1) {
total_dbuf--;
Expand Down
23 changes: 23 additions & 0 deletions trunk/fs/gfs2/lops.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
#include <linux/list.h>
#include "incore.h"

#define BUF_OFFSET \
((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \
~(sizeof(__be64) - 1))
#define DATABUF_OFFSET \
((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \
~(2 * sizeof(__be64) - 1))

extern const struct gfs2_log_operations gfs2_glock_lops;
extern const struct gfs2_log_operations gfs2_buf_lops;
extern const struct gfs2_log_operations gfs2_revoke_lops;
Expand All @@ -21,6 +28,22 @@ extern const struct gfs2_log_operations gfs2_databuf_lops;

extern const struct gfs2_log_operations *gfs2_log_ops[];

static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
{
unsigned int limit;

limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64);
return limit;
}

static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
{
unsigned int limit;

limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64));
return limit;
}

static inline void lops_init_le(struct gfs2_log_element *le,
const struct gfs2_log_operations *lops)
{
Expand Down
8 changes: 7 additions & 1 deletion trunk/fs/gfs2/meta_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,18 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)

if (test_clear_buffer_pinned(bh)) {
struct gfs2_trans *tr = current->journal_info;
struct gfs2_inode *bh_ip =
GFS2_I(bh->b_page->mapping->host);

gfs2_log_lock(sdp);
list_del_init(&bd->bd_le.le_list);
gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
sdp->sd_log_num_buf--;
gfs2_log_unlock(sdp);
tr->tr_num_buf_rm++;
if (bh_ip->i_inode.i_private != NULL)
tr->tr_num_databuf_rm++;
else
tr->tr_num_buf_rm++;
brelse(bh);
}
if (bd) {
Expand Down

0 comments on commit 5ec35e5

Please sign in to comment.