Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs:
  xfs: copy li_lsn before dropping AIL lock
  XFS bug in log recover with quota (bugzilla id 855)
This commit is contained in:
Linus Torvalds 2009-11-17 09:42:35 -08:00
commit ac50e95078
2 changed files with 22 additions and 5 deletions

View File

@ -1980,7 +1980,7 @@ xlog_recover_do_reg_buffer(
"XFS: NULL dquot in %s.", __func__); "XFS: NULL dquot in %s.", __func__);
goto next; goto next;
} }
if (item->ri_buf[i].i_len < sizeof(xfs_dqblk_t)) { if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
cmn_err(CE_ALERT, cmn_err(CE_ALERT,
"XFS: dquot too small (%d) in %s.", "XFS: dquot too small (%d) in %s.",
item->ri_buf[i].i_len, __func__); item->ri_buf[i].i_len, __func__);
@ -2635,7 +2635,7 @@ xlog_recover_do_dquot_trans(
"XFS: NULL dquot in %s.", __func__); "XFS: NULL dquot in %s.", __func__);
return XFS_ERROR(EIO); return XFS_ERROR(EIO);
} }
if (item->ri_buf[1].i_len < sizeof(xfs_dqblk_t)) { if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) {
cmn_err(CE_ALERT, cmn_err(CE_ALERT,
"XFS: dquot too small (%d) in %s.", "XFS: dquot too small (%d) in %s.",
item->ri_buf[1].i_len, __func__); item->ri_buf[1].i_len, __func__);

View File

@ -467,6 +467,7 @@ xfs_trans_ail_update(
{ {
xfs_log_item_t *dlip = NULL; xfs_log_item_t *dlip = NULL;
xfs_log_item_t *mlip; /* ptr to minimum lip */ xfs_log_item_t *mlip; /* ptr to minimum lip */
xfs_lsn_t tail_lsn;
mlip = xfs_ail_min(ailp); mlip = xfs_ail_min(ailp);
@ -483,8 +484,16 @@ xfs_trans_ail_update(
if (mlip == dlip) { if (mlip == dlip) {
mlip = xfs_ail_min(ailp); mlip = xfs_ail_min(ailp);
/*
* It is not safe to access mlip after the AIL lock is
* dropped, so we must get a copy of li_lsn before we do
* so. This is especially important on 32-bit platforms
* where accessing and updating 64-bit values like li_lsn
* is not atomic.
*/
tail_lsn = mlip->li_lsn;
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
xfs_log_move_tail(ailp->xa_mount, mlip->li_lsn); xfs_log_move_tail(ailp->xa_mount, tail_lsn);
} else { } else {
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
} }
@ -514,6 +523,7 @@ xfs_trans_ail_delete(
{ {
xfs_log_item_t *dlip; xfs_log_item_t *dlip;
xfs_log_item_t *mlip; xfs_log_item_t *mlip;
xfs_lsn_t tail_lsn;
if (lip->li_flags & XFS_LI_IN_AIL) { if (lip->li_flags & XFS_LI_IN_AIL) {
mlip = xfs_ail_min(ailp); mlip = xfs_ail_min(ailp);
@ -527,9 +537,16 @@ xfs_trans_ail_delete(
if (mlip == dlip) { if (mlip == dlip) {
mlip = xfs_ail_min(ailp); mlip = xfs_ail_min(ailp);
/*
* It is not safe to access mlip after the AIL lock
* is dropped, so we must get a copy of li_lsn
* before we do so. This is especially important
* on 32-bit platforms where accessing and updating
* 64-bit values like li_lsn is not atomic.
*/
tail_lsn = mlip ? mlip->li_lsn : 0;
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
xfs_log_move_tail(ailp->xa_mount, xfs_log_move_tail(ailp->xa_mount, tail_lsn);
(mlip ? mlip->li_lsn : 0));
} else { } else {
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
} }