xfs: bugfixes for 3.12-rc3
- fix for directory node collapse regression - fix for recovery over stale on disk structures - fix for eofblocks ioctl - fix asserts in xfs_inode_free - lock the ail before removing an item from it -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJSRvPvAAoJENaLyazVq6ZOoXAP/3/AD1iuqGWBy2wIjISNJupu ST4gW5FXgBlG/sr1zGOA/L6VCdAaQMFSnlOnGpOjAyCH8VJ+XVb+4WCammzQ9CEu YJsbjlra52V3cOhGxDsuE9uEDIAqxnyiZndF/Pk1gnyGzpt5da3CxwI9UVuR8Dlt 9O/dJXuKGdKgBtQKzOfrzIDXQZ2zE5NPvueHsDU6i6Hd7YECwG5j4fRqS8jf49jY sleZo0CVkYx1IcIB//oVXa+JbyelhiS5D8Ro3dUbW8lJTToHq9RaIiE/xrz2nz2c lUcaQdecxAnN4NKtHu/QR18u5HauA7FH26cV+PUGWWmbjHTP3oybsnHJWZr+08cX +NfC9dpLl3VTapVNCxVeuToE2DhgTQuWOODiIFSi+Ljt3P6zfIKKBMqwJ6FceaJD 4afVT2GDEtvZuFbfhyvXUzP9bm0PLoZRI68bLLi772W2Zc8aiprJyKAcm/GtlxTk biluUwoGn+zD60u0GwAtlQ2g+/jTReoeAjez+LW1dWNrUwfVdnZh8xlFGEXEd/dS scx6BHSlJtwVKEWWYMO+JLHJ077yNR5RPoRFFokS1XGOSGiEuuSkAkS0eAcC5WCX egfGHzkymOOQhcXb/qPjpCVBbHEnCuYw6b24eNyceyqfE8o6iZmsUcF3kOzsa8Up fOVpOP7UovMR5teKQxAa =AUDD -----END PGP SIGNATURE----- Merge tag 'xfs-for-linus-v3.12-rc3' of git://oss.sgi.com/xfs/xfs Pull xfs bugfixes from Ben Myers: - fix for directory node collapse regression - fix for recovery over stale on disk structures - fix for eofblocks ioctl - fix asserts in xfs_inode_free - lock the ail before removing an item from it * tag 'xfs-for-linus-v3.12-rc3' of git://oss.sgi.com/xfs/xfs: xfs: fix node forward in xfs_node_toosmall xfs: log recovery lsn ordering needs uuid check xfs: fix XFS_IOC_FREE_EOFBLOCKS definition xfs: asserting lock not held during freeing not valid xfs: lock the AIL before removing the buffer item
This commit is contained in:
commit
ddd23eb182
5 changed files with 68 additions and 22 deletions
|
@ -628,6 +628,7 @@ xfs_buf_item_unlock(
|
|||
else if (aborted) {
|
||||
ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
|
||||
if (lip->li_flags & XFS_LI_IN_AIL) {
|
||||
spin_lock(&lip->li_ailp->xa_lock);
|
||||
xfs_trans_ail_delete(lip->li_ailp, lip,
|
||||
SHUTDOWN_LOG_IO_ERROR);
|
||||
}
|
||||
|
|
|
@ -1224,6 +1224,7 @@ xfs_da3_node_toosmall(
|
|||
/* start with smaller blk num */
|
||||
forward = nodehdr.forw < nodehdr.back;
|
||||
for (i = 0; i < 2; forward = !forward, i++) {
|
||||
struct xfs_da3_icnode_hdr thdr;
|
||||
if (forward)
|
||||
blkno = nodehdr.forw;
|
||||
else
|
||||
|
@ -1236,10 +1237,10 @@ xfs_da3_node_toosmall(
|
|||
return(error);
|
||||
|
||||
node = bp->b_addr;
|
||||
xfs_da3_node_hdr_from_disk(&nodehdr, node);
|
||||
xfs_da3_node_hdr_from_disk(&thdr, node);
|
||||
xfs_trans_brelse(state->args->trans, bp);
|
||||
|
||||
if (count - nodehdr.count >= 0)
|
||||
if (count - thdr.count >= 0)
|
||||
break; /* fits with at least 25% to spare */
|
||||
}
|
||||
if (i >= 2) {
|
||||
|
|
|
@ -515,7 +515,7 @@ typedef struct xfs_swapext
|
|||
/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
|
||||
#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
|
||||
#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
|
||||
#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks)
|
||||
#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
|
||||
|
||||
/*
|
||||
* ioctl commands that replace IRIX syssgi()'s
|
||||
|
|
|
@ -119,11 +119,6 @@ xfs_inode_free(
|
|||
ip->i_itemp = NULL;
|
||||
}
|
||||
|
||||
/* asserts to verify all state is correct here */
|
||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||
ASSERT(!spin_is_locked(&ip->i_flags_lock));
|
||||
ASSERT(!xfs_isiflocked(ip));
|
||||
|
||||
/*
|
||||
* Because we use RCU freeing we need to ensure the inode always
|
||||
* appears to be reclaimed with an invalid inode number when in the
|
||||
|
@ -135,6 +130,10 @@ xfs_inode_free(
|
|||
ip->i_ino = 0;
|
||||
spin_unlock(&ip->i_flags_lock);
|
||||
|
||||
/* asserts to verify all state is correct here */
|
||||
ASSERT(atomic_read(&ip->i_pincount) == 0);
|
||||
ASSERT(!xfs_isiflocked(ip));
|
||||
|
||||
call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
|
||||
}
|
||||
|
||||
|
|
|
@ -1970,6 +1970,13 @@ xlog_recover_do_inode_buffer(
|
|||
* magic number. If we don't recognise the magic number in the buffer, then
|
||||
* return a LSN of -1 so that the caller knows it was an unrecognised block and
|
||||
* so can recover the buffer.
|
||||
*
|
||||
* Note: we cannot rely solely on magic number matches to determine that the
|
||||
* buffer has a valid LSN - we also need to verify that it belongs to this
|
||||
* filesystem, so we need to extract the object's LSN and compare it to that
|
||||
* which we read from the superblock. If the UUIDs don't match, then we've got a
|
||||
* stale metadata block from an old filesystem instance that we need to recover
|
||||
* over the top of.
|
||||
*/
|
||||
static xfs_lsn_t
|
||||
xlog_recover_get_buf_lsn(
|
||||
|
@ -1980,6 +1987,8 @@ xlog_recover_get_buf_lsn(
|
|||
__uint16_t magic16;
|
||||
__uint16_t magicda;
|
||||
void *blk = bp->b_addr;
|
||||
uuid_t *uuid;
|
||||
xfs_lsn_t lsn = -1;
|
||||
|
||||
/* v4 filesystems always recover immediately */
|
||||
if (!xfs_sb_version_hascrc(&mp->m_sb))
|
||||
|
@ -1992,43 +2001,79 @@ xlog_recover_get_buf_lsn(
|
|||
case XFS_ABTB_MAGIC:
|
||||
case XFS_ABTC_MAGIC:
|
||||
case XFS_IBT_CRC_MAGIC:
|
||||
case XFS_IBT_MAGIC:
|
||||
return be64_to_cpu(
|
||||
((struct xfs_btree_block *)blk)->bb_u.s.bb_lsn);
|
||||
case XFS_IBT_MAGIC: {
|
||||
struct xfs_btree_block *btb = blk;
|
||||
|
||||
lsn = be64_to_cpu(btb->bb_u.s.bb_lsn);
|
||||
uuid = &btb->bb_u.s.bb_uuid;
|
||||
break;
|
||||
}
|
||||
case XFS_BMAP_CRC_MAGIC:
|
||||
case XFS_BMAP_MAGIC:
|
||||
return be64_to_cpu(
|
||||
((struct xfs_btree_block *)blk)->bb_u.l.bb_lsn);
|
||||
case XFS_BMAP_MAGIC: {
|
||||
struct xfs_btree_block *btb = blk;
|
||||
|
||||
lsn = be64_to_cpu(btb->bb_u.l.bb_lsn);
|
||||
uuid = &btb->bb_u.l.bb_uuid;
|
||||
break;
|
||||
}
|
||||
case XFS_AGF_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
|
||||
uuid = &((struct xfs_agf *)blk)->agf_uuid;
|
||||
break;
|
||||
case XFS_AGFL_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
|
||||
uuid = &((struct xfs_agfl *)blk)->agfl_uuid;
|
||||
break;
|
||||
case XFS_AGI_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
|
||||
uuid = &((struct xfs_agi *)blk)->agi_uuid;
|
||||
break;
|
||||
case XFS_SYMLINK_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
|
||||
uuid = &((struct xfs_dsymlink_hdr *)blk)->sl_uuid;
|
||||
break;
|
||||
case XFS_DIR3_BLOCK_MAGIC:
|
||||
case XFS_DIR3_DATA_MAGIC:
|
||||
case XFS_DIR3_FREE_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
|
||||
uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid;
|
||||
break;
|
||||
case XFS_ATTR3_RMT_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
|
||||
uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid;
|
||||
break;
|
||||
case XFS_SB_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
|
||||
uuid = &((struct xfs_dsb *)blk)->sb_uuid;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (lsn != (xfs_lsn_t)-1) {
|
||||
if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
|
||||
goto recover_immediately;
|
||||
return lsn;
|
||||
}
|
||||
|
||||
magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic);
|
||||
switch (magicda) {
|
||||
case XFS_DIR3_LEAF1_MAGIC:
|
||||
case XFS_DIR3_LEAFN_MAGIC:
|
||||
case XFS_DA3_NODE_MAGIC:
|
||||
return be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
|
||||
lsn = be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
|
||||
uuid = &((struct xfs_da3_blkinfo *)blk)->uuid;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (lsn != (xfs_lsn_t)-1) {
|
||||
if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
|
||||
goto recover_immediately;
|
||||
return lsn;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do individual object checks on dquot and inode buffers as they
|
||||
* have their own individual LSN records. Also, we could have a stale
|
||||
|
|
Loading…
Reference in a new issue