linux-hardened/fs/xfs
Dave Chinner 3b19034d4f xfs: fix shutdown hang on invalid inode during create
When the new inode verify in xfs_iread() fails, the create
transaction is aborted and a shutdown occurs. The subsequent unmount
then hangs in xfs_wait_buftarg() on a buffer that has an elevated
hold count. Debug showed that it was an AGI buffer getting stuck:

[   22.576147] XFS (vdb): buffer 0x2/0x1, hold 0x2 stuck
[   22.976213] XFS (vdb): buffer 0x2/0x1, hold 0x2 stuck
[   23.376206] XFS (vdb): buffer 0x2/0x1, hold 0x2 stuck
[   23.776325] XFS (vdb): buffer 0x2/0x1, hold 0x2 stuck

The trace of this buffer leading up to the shutdown (trimmed for
brevity) looks like:

xfs_buf_init:        bno 0x2 nblks 0x1 hold 1 caller xfs_buf_get_map
xfs_buf_get:         bno 0x2 len 0x200 hold 1 caller xfs_buf_read_map
xfs_buf_read:        bno 0x2 len 0x200 hold 1 caller xfs_trans_read_buf_map
xfs_buf_iorequest:   bno 0x2 nblks 0x1 hold 1 caller _xfs_buf_read
xfs_buf_hold:        bno 0x2 nblks 0x1 hold 1 caller xfs_buf_iorequest
xfs_buf_rele:        bno 0x2 nblks 0x1 hold 2 caller xfs_buf_iorequest
xfs_buf_iowait:      bno 0x2 nblks 0x1 hold 1 caller _xfs_buf_read
xfs_buf_ioerror:     bno 0x2 len 0x200 hold 1 caller xfs_buf_bio_end_io
xfs_buf_iodone:      bno 0x2 nblks 0x1 hold 1 caller _xfs_buf_ioend
xfs_buf_iowait_done: bno 0x2 nblks 0x1 hold 1 caller _xfs_buf_read
xfs_buf_hold:        bno 0x2 nblks 0x1 hold 1 caller xfs_buf_item_init
xfs_trans_read_buf:  bno 0x2 len 0x200 hold 2 recur 0 refcount 1
xfs_trans_brelse:    bno 0x2 len 0x200 hold 2 recur 0 refcount 1
xfs_buf_item_relse:  bno 0x2 nblks 0x1 hold 2 caller xfs_trans_brelse
xfs_buf_rele:        bno 0x2 nblks 0x1 hold 2 caller xfs_buf_item_relse
xfs_buf_unlock:      bno 0x2 nblks 0x1 hold 1 caller xfs_trans_brelse
xfs_buf_rele:        bno 0x2 nblks 0x1 hold 1 caller xfs_trans_brelse
xfs_buf_trylock:     bno 0x2 nblks 0x1 hold 2 caller _xfs_buf_find
xfs_buf_find:        bno 0x2 len 0x200 hold 2 caller xfs_buf_get_map
xfs_buf_get:         bno 0x2 len 0x200 hold 2 caller xfs_buf_read_map
xfs_buf_read:        bno 0x2 len 0x200 hold 2 caller xfs_trans_read_buf_map
xfs_buf_hold:        bno 0x2 nblks 0x1 hold 2 caller xfs_buf_item_init
xfs_trans_read_buf:  bno 0x2 len 0x200 hold 3 recur 0 refcount 1
xfs_trans_log_buf:   bno 0x2 len 0x200 hold 3 recur 0 refcount 1
xfs_buf_item_unlock: bno 0x2 len 0x200 hold 3 flags DIRTY liflags ABORTED
xfs_buf_unlock:      bno 0x2 nblks 0x1 hold 3 caller xfs_buf_item_unlock
xfs_buf_rele:        bno 0x2 nblks 0x1 hold 3 caller xfs_buf_item_unlock

And that is the AGI buffer from cold cache read into memory to
transaction abort. You can see at transaction abort the bli is dirty
and only has a single reference. The item is not pinned, and it's
not in the AIL. Hence the only reference to it is this transaction.

The problem is that the xfs_buf_item_unlock() call is dropping the
last reference to the xfs_buf_log_item attached to the buffer (which
holds a reference to the buffer), but it is not freeing the
xfs_buf_log_item. Hence nothing will ever release the buffer, and
the unmount hangs waiting for this reference to go away.

The fix is simple - xfs_buf_item_unlock needs to detect the last
reference going away in this case and free the xfs_buf_log_item to
release the reference it holds on the buffer.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
2013-01-26 09:34:38 -06:00
..
Kconfig xfs: add CRC infrastructure 2012-11-19 20:11:24 -06:00
kmem.c xfs: switch to proper __bitwise type for KM_... flags 2012-05-29 23:28:32 -04:00
kmem.h xfs: switch to proper __bitwise type for KM_... flags 2012-05-29 23:28:32 -04:00
Makefile xfs: remove xfs_flushinval_pages 2012-11-14 15:15:08 -06:00
mrlock.h
time.h
uuid.c
uuid.h xfs: add CRC infrastructure 2012-11-19 20:11:24 -06:00
xfs.h
xfs_acl.c userns: Pass a userns parameter into posix_acl_to_xattr and posix_acl_from_xattr 2012-09-18 01:01:35 -07:00
xfs_acl.h
xfs_ag.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_alloc.c xfs: don't zero structure members after a memset(0) 2013-01-03 16:00:07 -06:00
xfs_alloc.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_alloc_btree.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_alloc_btree.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_aops.c xfs: fix direct IO nested transaction deadlock. 2012-11-29 14:22:56 -06:00
xfs_aops.h Prefix IO_XX flags with XFS_IO_XX to avoid namespace colision. 2012-07-22 11:00:55 -05:00
xfs_attr.c xfs: add xfs_da_node verification 2012-11-15 21:34:55 -06:00
xfs_attr.h
xfs_attr_leaf.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_attr_leaf.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_attr_sf.h
xfs_bit.c
xfs_bit.h
xfs_bmap.c xfs: pull up stack_switch check into xfs_bmapi_write 2013-01-17 17:53:37 -06:00
xfs_bmap.h xfs: move allocation stack switch up to xfs_bmapi_allocate 2012-10-18 17:42:48 -05:00
xfs_bmap_btree.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_bmap_btree.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_btree.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_btree.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_buf.c xfs: fix shutdown hang on invalid inode during create 2013-01-26 09:34:38 -06:00
xfs_buf.h xfs: use b_maps[] for discontiguous buffers 2012-12-17 16:19:56 -06:00
xfs_buf_item.c xfs: fix shutdown hang on invalid inode during create 2013-01-26 09:34:38 -06:00
xfs_buf_item.h xfs remove the XFS_TRANS_DEBUG routines 2012-12-17 16:29:00 -06:00
xfs_cksum.h xfs: add CRC infrastructure 2012-11-19 20:11:24 -06:00
xfs_da_btree.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_da_btree.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dfrag.c xfs: remove xfs_flushinval_pages 2012-11-14 15:15:08 -06:00
xfs_dfrag.h
xfs_dinode.h xfs: fix typo in comment of xfs_dinode_t. 2012-06-14 12:28:26 -05:00
xfs_dir2.c xfs: remove struct xfs_dabuf and infrastructure 2012-07-01 14:50:07 -05:00
xfs_dir2.h
xfs_dir2_block.c xfs: recalculate leaf entry pointer after compacting a dir2 block 2013-01-13 14:36:17 -06:00
xfs_dir2_data.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dir2_format.h
xfs_dir2_leaf.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dir2_node.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dir2_priv.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dir2_sf.c xfs: remove struct xfs_dabuf and infrastructure 2012-07-01 14:50:07 -05:00
xfs_discard.c xfs: check for possible overflow in xfs_ioc_trim 2012-08-23 14:48:44 -05:00
xfs_discard.h
xfs_dquot.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dquot.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_dquot_item.c xfs: clean up xfs_bit.h includes 2012-05-14 16:21:00 -05:00
xfs_dquot_item.h
xfs_error.c xfs: move xfsagino_t to xfs_types.h 2012-05-14 16:20:54 -05:00
xfs_error.h
xfs_export.c xfs: remove xfs_iget.c 2012-10-17 13:42:25 -05:00
xfs_export.h
xfs_extent_busy.c xfs: make xfs_extent_busy_trim not static 2012-05-14 16:21:04 -05:00
xfs_extent_busy.h xfs: make xfs_extent_busy_trim not static 2012-05-14 16:21:04 -05:00
xfs_extfree_item.c xfs: move xfsagino_t to xfs_types.h 2012-05-14 16:20:54 -05:00
xfs_extfree_item.h
xfs_file.c xfs: byte range granularity for XFS_IOC_ZERO_RANGE 2012-11-29 14:21:46 -06:00
xfs_filestream.c xfs: rename allocation range fields in struct xfs_bmalloca 2011-10-11 21:15:06 -05:00
xfs_filestream.h
xfs_fs.h xfs: add minimum file size filtering to eofblocks scan 2012-11-08 15:32:29 -06:00
xfs_fsops.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_fsops.h
xfs_globals.c xfs: add background scanning to clear eofblocks inodes 2012-11-08 15:34:59 -06:00
xfs_ialloc.c xfs: don't zero structure members after a memset(0) 2013-01-03 16:00:07 -06:00
xfs_ialloc.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_ialloc_btree.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_ialloc_btree.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_icache.c xfs: add background scanning to clear eofblocks inodes 2012-11-08 15:34:59 -06:00
xfs_icache.h xfs: add background scanning to clear eofblocks inodes 2012-11-08 15:34:59 -06:00
xfs_inode.c xfs remove the XFS_TRANS_DEBUG routines 2012-12-17 16:29:00 -06:00
xfs_inode.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_inode_item.c xfs remove the XFS_TRANS_DEBUG routines 2012-12-17 16:29:00 -06:00
xfs_inode_item.h xfs remove the XFS_TRANS_DEBUG routines 2012-12-17 16:29:00 -06:00
xfs_inum.h xfs: move xfsagino_t to xfs_types.h 2012-05-14 16:20:54 -05:00
xfs_ioctl.c xfs: add inode id filtering to eofblocks scan 2012-11-08 15:29:14 -06:00
xfs_ioctl.h
xfs_ioctl32.c xfs: Convert to new freezing code 2012-07-31 09:45:48 +04:00
xfs_ioctl32.h
xfs_iomap.c xfs: limit speculative prealloc near ENOSPC thresholds 2013-01-24 11:08:55 -06:00
xfs_iomap.h
xfs_iops.c xfs: remove xfs_flush_pages 2012-11-14 15:12:45 -06:00
xfs_iops.h
xfs_itable.c xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_itable.h
xfs_linux.h xfs: add CRC infrastructure 2012-11-19 20:11:24 -06:00
xfs_log.c xfs: fix fs/xfs/xfs_log.c:1740:39: error: 'B_TRUE' undeclared 2013-01-18 15:11:57 -06:00
xfs_log.h xfs: xfs_quiesce_attr() should quiesce the log like unmount 2012-10-17 13:39:14 -05:00
xfs_log_cil.c xfs: rename log structure to xlog 2012-06-21 14:21:11 -05:00
xfs_log_priv.h xfs: fix sparse reported log CRC endian issue 2012-12-03 12:10:59 -06:00
xfs_log_recover.c xfs: fix sparse reported log CRC endian issue 2012-12-03 12:10:59 -06:00
xfs_log_recover.h
xfs_message.c xfs: move xfsagino_t to xfs_types.h 2012-05-14 16:20:54 -05:00
xfs_message.h treewide: use __printf not __attribute__((format(printf,...))) 2011-10-31 17:30:54 -07:00
xfs_mount.c xfs: Do not return EFSCORRUPTED when filesystem probe finds no XFS magic 2013-01-16 17:33:53 -06:00
xfs_mount.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_mru_cache.c
xfs_mru_cache.h
xfs_qm.c xfs: fix stray dquot unlock when reclaiming dquots 2012-11-29 14:24:03 -06:00
xfs_qm.h xfs: remove the global xfs_Gqm structure 2012-03-14 12:06:32 -05:00
xfs_qm_bhv.c xfs: Remove boolean_t typedef completely. 2013-01-17 17:32:57 -06:00
xfs_qm_syscalls.c xfs: Remove boolean_t typedef completely. 2013-01-17 17:32:57 -06:00
xfs_quota.h Define new macro XFS_ALL_QUOTA_ACTIVE and simply some usage 2012-02-03 11:32:20 -06:00
xfs_quota_priv.h xfs: use per-filesystem radix trees for dquot lookup 2012-03-14 11:09:06 -05:00
xfs_quotaops.c userns: Convert qutoactl 2012-09-18 01:01:39 -07:00
xfs_rename.c xfs: move xfsagino_t to xfs_types.h 2012-05-14 16:20:54 -05:00
xfs_rtalloc.c xfs: uncached buffer reads need to return an error 2012-11-15 21:34:05 -06:00
xfs_rtalloc.h
xfs_sb.h xfs: add CRC infrastructure 2012-11-19 20:11:24 -06:00
xfs_stats.c xfs: use common code for quota statistics 2012-03-14 11:09:06 -05:00
xfs_stats.h xfs: use common code for quota statistics 2012-03-14 11:09:06 -05:00
xfs_super.c fs/xfs remove obsolete simple_strto<foo> 2013-01-13 14:42:07 -06:00
xfs_super.h xfs: xfs_sync_data is redundant. 2012-10-17 12:01:25 -05:00
xfs_sysctl.c xfs: add background scanning to clear eofblocks inodes 2012-11-08 15:34:59 -06:00
xfs_sysctl.h xfs: add background scanning to clear eofblocks inodes 2012-11-08 15:34:59 -06:00
xfs_trace.c xfs: clean up xfs_bit.h includes 2012-05-14 16:21:00 -05:00
xfs_trace.h xfs: fix shutdown hang on invalid inode during create 2013-01-26 09:34:38 -06:00
xfs_trans.c xfs: Convert to new freezing code 2012-07-31 09:45:48 +04:00
xfs_trans.h xfs: convert buffer verifiers to an ops structure. 2012-11-15 21:35:12 -06:00
xfs_trans_ail.c xfs remove the XFS_TRANS_DEBUG routines 2012-12-17 16:29:00 -06:00
xfs_trans_buf.c xfs: fix the multi-segment log buffer format 2012-12-17 16:28:14 -06:00
xfs_trans_dquot.c xfs: Remove boolean_t typedef completely. 2013-01-17 17:32:57 -06:00
xfs_trans_extfree.c xfs: move xfsagino_t to xfs_types.h 2012-05-14 16:20:54 -05:00
xfs_trans_inode.c xfs remove the XFS_TRANS_DEBUG routines 2012-12-17 16:29:00 -06:00
xfs_trans_priv.h xfs: re-enable xfsaild idle mode and fix associated races 2012-07-29 16:27:57 -05:00
xfs_trans_space.h
xfs_types.h xfs: Remove boolean_t typedef completely. 2013-01-17 17:32:57 -06:00
xfs_utils.c xfs: remove the alloc_done argument to xfs_dialloc 2012-07-29 16:00:31 -05:00
xfs_utils.h xfs: propagate umode_t 2012-01-03 22:55:00 -05:00
xfs_vnode.h xfs: remove remaining scraps of struct xfs_iomap 2012-03-15 13:40:16 -05:00
xfs_vnodeops.c xfs: Remove boolean_t typedef completely. 2013-01-17 17:32:57 -06:00
xfs_vnodeops.h xfs: byte range granularity for XFS_IOC_ZERO_RANGE 2012-11-29 14:21:46 -06:00
xfs_xattr.c