Commit ba3afcc7 authored by Timothy Shimmin's avatar Timothy Shimmin Committed by Linus Torvalds

[XFS] xfs reservation issues with xlog_sync roundoff

SGI-PV: 922265
SGI-Modid: xfs-linux:xfs-kern:20222a
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent e31d2d1f
...@@ -902,20 +902,15 @@ xlog_space_left(xlog_t *log, int cycle, int bytes) ...@@ -902,20 +902,15 @@ xlog_space_left(xlog_t *log, int cycle, int bytes)
} else { } else {
/* /*
* The reservation head is behind the tail. * The reservation head is behind the tail.
* This can only happen when the AIL is empty so the tail
* is equal to the head and the l_roundoff value in the
* log structure is taking up the difference between the
* reservation head and the tail. The bytes accounted for
* by the l_roundoff field are temporarily 'lost' to the
* reservation mechanism, but they are cleaned up when the
* log buffers that created them are reused. These lost
* bytes are what allow the reservation head to fall behind
* the tail in the case that the log is 'empty'.
* In this case we just want to return the size of the * In this case we just want to return the size of the
* log as the amount of space left. * log as the amount of space left.
*/ */
ASSERT((tail_cycle == (cycle + 1)) || xfs_fs_cmn_err(CE_ALERT, log->l_mp,
((bytes + log->l_roundoff) >= tail_bytes)); "xlog_space_left: head behind tail\n"
" tail_cycle = %d, tail_bytes = %d\n"
" GH cycle = %d, GH bytes = %d",
tail_cycle, tail_bytes, cycle, bytes);
ASSERT(0);
free_bytes = log->l_logsize; free_bytes = log->l_logsize;
} }
return free_bytes; return free_bytes;
...@@ -1355,8 +1350,8 @@ xlog_grant_push_ail(xfs_mount_t *mp, ...@@ -1355,8 +1350,8 @@ xlog_grant_push_ail(xfs_mount_t *mp,
/* /*
* Flush out the in-core log (iclog) to the on-disk log in a synchronous or * Flush out the in-core log (iclog) to the on-disk log in an asynchronous
* asynchronous fashion. Previously, we should have moved the current iclog * fashion. Previously, we should have moved the current iclog
* ptr in the log to point to the next available iclog. This allows further * ptr in the log to point to the next available iclog. This allows further
* write to continue while this code syncs out an iclog ready to go. * write to continue while this code syncs out an iclog ready to go.
* Before an in-core log can be written out, the data section must be scanned * Before an in-core log can be written out, the data section must be scanned
...@@ -1388,8 +1383,11 @@ xlog_sync(xlog_t *log, ...@@ -1388,8 +1383,11 @@ xlog_sync(xlog_t *log,
int i, ops; int i, ops;
uint count; /* byte count of bwrite */ uint count; /* byte count of bwrite */
uint count_init; /* initial count before roundup */ uint count_init; /* initial count before roundup */
int roundoff; /* roundoff to BB or stripe */
int split = 0; /* split write into two regions */ int split = 0; /* split write into two regions */
int error; int error;
SPLDECL(s);
int v2 = XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb);
XFS_STATS_INC(xs_log_writes); XFS_STATS_INC(xs_log_writes);
ASSERT(iclog->ic_refcnt == 0); ASSERT(iclog->ic_refcnt == 0);
...@@ -1398,23 +1396,34 @@ xlog_sync(xlog_t *log, ...@@ -1398,23 +1396,34 @@ xlog_sync(xlog_t *log,
count_init = log->l_iclog_hsize + iclog->ic_offset; count_init = log->l_iclog_hsize + iclog->ic_offset;
/* Round out the log write size */ /* Round out the log write size */
if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) && if (v2 && log->l_mp->m_sb.sb_logsunit > 1) {
log->l_mp->m_sb.sb_logsunit > 1) {
/* we have a v2 stripe unit to use */ /* we have a v2 stripe unit to use */
count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init)); count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init));
} else { } else {
count = BBTOB(BTOBB(count_init)); count = BBTOB(BTOBB(count_init));
} }
iclog->ic_roundoff = count - count_init; roundoff = count - count_init;
log->l_roundoff += iclog->ic_roundoff; ASSERT(roundoff >= 0);
ASSERT((v2 && log->l_mp->m_sb.sb_logsunit > 1 &&
roundoff < log->l_mp->m_sb.sb_logsunit)
||
(log->l_mp->m_sb.sb_logsunit <= 1 &&
roundoff < BBTOB(1)));
xlog_pack_data(log, iclog); /* put cycle number in every block */ /* move grant heads by roundoff in sync */
s = GRANT_LOCK(log);
XLOG_GRANT_ADD_SPACE(log, roundoff, 'w');
XLOG_GRANT_ADD_SPACE(log, roundoff, 'r');
GRANT_UNLOCK(log, s);
/* put cycle number in every block */
xlog_pack_data(log, iclog, roundoff);
/* real byte length */ /* real byte length */
if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { if (v2) {
INT_SET(iclog->ic_header.h_len, INT_SET(iclog->ic_header.h_len,
ARCH_CONVERT, ARCH_CONVERT,
iclog->ic_offset + iclog->ic_roundoff); iclog->ic_offset + roundoff);
} else { } else {
INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset); INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
} }
...@@ -2278,11 +2287,6 @@ xlog_state_get_iclog_space(xlog_t *log, ...@@ -2278,11 +2287,6 @@ xlog_state_get_iclog_space(xlog_t *log,
INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle); INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
ASSIGN_LSN(head->h_lsn, log, ARCH_CONVERT); ASSIGN_LSN(head->h_lsn, log, ARCH_CONVERT);
ASSERT(log->l_curr_block >= 0); ASSERT(log->l_curr_block >= 0);
/* round off error from last write with this iclog */
ticket->t_curr_res -= iclog->ic_roundoff;
log->l_roundoff -= iclog->ic_roundoff;
iclog->ic_roundoff = 0;
} }
/* If there is enough room to write everything, then do it. Otherwise, /* If there is enough room to write everything, then do it. Otherwise,
...@@ -2853,7 +2857,6 @@ xlog_state_sync_all(xlog_t *log, uint flags) ...@@ -2853,7 +2857,6 @@ xlog_state_sync_all(xlog_t *log, uint flags)
* has already taken care of the roundoff from * has already taken care of the roundoff from
* the previous sync. * the previous sync.
*/ */
ASSERT(iclog->ic_roundoff == 0);
iclog->ic_refcnt++; iclog->ic_refcnt++;
lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT); lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
xlog_state_switch_iclogs(log, iclog, 0); xlog_state_switch_iclogs(log, iclog, 0);
......
...@@ -430,7 +430,6 @@ typedef struct xlog_iclog_fields { ...@@ -430,7 +430,6 @@ typedef struct xlog_iclog_fields {
int ic_size; int ic_size;
int ic_offset; int ic_offset;
int ic_refcnt; int ic_refcnt;
int ic_roundoff;
int ic_bwritecnt; int ic_bwritecnt;
ushort_t ic_state; ushort_t ic_state;
char *ic_datap; /* pointer to iclog data */ char *ic_datap; /* pointer to iclog data */
...@@ -462,7 +461,6 @@ typedef struct xlog_in_core { ...@@ -462,7 +461,6 @@ typedef struct xlog_in_core {
#define ic_size hic_fields.ic_size #define ic_size hic_fields.ic_size
#define ic_offset hic_fields.ic_offset #define ic_offset hic_fields.ic_offset
#define ic_refcnt hic_fields.ic_refcnt #define ic_refcnt hic_fields.ic_refcnt
#define ic_roundoff hic_fields.ic_roundoff
#define ic_bwritecnt hic_fields.ic_bwritecnt #define ic_bwritecnt hic_fields.ic_bwritecnt
#define ic_state hic_fields.ic_state #define ic_state hic_fields.ic_state
#define ic_datap hic_fields.ic_datap #define ic_datap hic_fields.ic_datap
...@@ -498,7 +496,6 @@ typedef struct log { ...@@ -498,7 +496,6 @@ typedef struct log {
xfs_daddr_t l_logBBstart; /* start block of log */ xfs_daddr_t l_logBBstart; /* start block of log */
int l_logsize; /* size of log in bytes */ int l_logsize; /* size of log in bytes */
int l_logBBsize; /* size of log in BB chunks */ int l_logBBsize; /* size of log in BB chunks */
int l_roundoff; /* round off error of iclogs */
int l_curr_cycle; /* Cycle number of log writes */ int l_curr_cycle; /* Cycle number of log writes */
int l_prev_cycle; /* Cycle number before last int l_prev_cycle; /* Cycle number before last
* block increment */ * block increment */
...@@ -545,7 +542,7 @@ extern int xlog_find_tail(xlog_t *log, ...@@ -545,7 +542,7 @@ extern int xlog_find_tail(xlog_t *log,
int readonly); int readonly);
extern int xlog_recover(xlog_t *log, int readonly); extern int xlog_recover(xlog_t *log, int readonly);
extern int xlog_recover_finish(xlog_t *log, int mfsi_flags); extern int xlog_recover_finish(xlog_t *log, int mfsi_flags);
extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog); extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
extern void xlog_recover_process_iunlinks(xlog_t *log); extern void xlog_recover_process_iunlinks(xlog_t *log);
extern struct xfs_buf *xlog_get_bp(xlog_t *, int); extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
......
...@@ -3384,10 +3384,11 @@ xlog_pack_data_checksum( ...@@ -3384,10 +3384,11 @@ xlog_pack_data_checksum(
void void
xlog_pack_data( xlog_pack_data(
xlog_t *log, xlog_t *log,
xlog_in_core_t *iclog) xlog_in_core_t *iclog,
int roundoff)
{ {
int i, j, k; int i, j, k;
int size = iclog->ic_offset + iclog->ic_roundoff; int size = iclog->ic_offset + roundoff;
uint cycle_lsn; uint cycle_lsn;
xfs_caddr_t dp; xfs_caddr_t dp;
xlog_in_core_2_t *xhdr; xlog_in_core_2_t *xhdr;
......
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