linux/fs/xfs
Brian Foster 8d99fe92fe xfs: fix efi/efd error handling to avoid fs shutdown hangs
Freeing an extent in XFS involves logging an EFI (extent free
intention), freeing the actual extent, and logging an EFD (extent
free done). The EFI object is created with a reference count of 2:
one for the current transaction and one for the subsequently created
EFD. Under normal circumstances, the first reference is dropped when
the EFI is unpinned and the second reference is dropped when the EFD
is committed to the on-disk log.

In event of errors or filesystem shutdown, there are various
potential cleanup scenarios depending on the state of the EFI/EFD.
The cleanup scenarios are confusing and racy, as demonstrated by the
following test sequence:

	# mount $dev $mnt
	# fsstress -d $mnt -n 99999 -p 16 -z -f fallocate=1 \
		-f punch=1 -f creat=1 -f unlink=1 &
	# sleep 5
	# killall -9 fsstress; wait
	# godown -f $mnt
	# umount

... in which the final umount can hang due to the AIL being pinned
indefinitely by one or more EFI items. This can occur due to several
conditions. For example, if the shutdown occurs after the EFI is
committed to the on-disk log and the EFD committed to the CIL, but
before the EFD committed to the log, the EFD iop_committed() abort
handler does not drop its reference to the EFI. Alternatively,
manual error injection in the xfs_bmap_finish() codepath shows that
if an error occurs after the EFI transaction is committed but before
the EFD is constructed and logged, the EFI is never released from
the AIL.

Update the EFI/EFD item handling code to use a more straightforward
and reliable approach to error handling. If an error occurs after
the EFI transaction is committed and before the EFD is constructed,
release the EFI explicitly from xfs_bmap_finish(). If the EFI
transaction is cancelled, release the EFI in the unlock handler.

Once the EFD is constructed, it is responsible for releasing the EFI
under any circumstances (including whether the EFI item aborts due
to log I/O error). Update the EFD item handlers to release the EFI
if the transaction is cancelled or aborts due to log I/O error.
Finally, update xfs_bmap_finish() to log at least one EFD extent to
the transaction before xfs_free_extent() errors are handled to
ensure the transaction is dirty and EFD item error handling is
triggered.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2015-08-19 09:51:16 +10:00
..
libxfs Merge branch 'xfs-misc-fixes-for-4.2-3' into for-next 2015-06-23 08:49:01 +10:00
Kconfig xfs: require 64-bit sector_t 2014-07-30 09:12:05 +10:00
kmem.c xfs: change kmem_free to use generic kvfree() 2015-02-02 09:54:18 +11:00
kmem.h xfs: change kmem_free to use generic kvfree() 2015-02-02 09:54:18 +11:00
Makefile xfs: implement pNFS export operations 2015-02-16 11:49:23 +11:00
mrlock.h
uuid.c
uuid.h
xfs_acl.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_acl.h xfs: move acl structures to xfs_format.h 2014-11-28 14:24:37 +11:00
xfs_aops.c xfs: update for 4.2-rc1 2015-06-30 20:16:08 -07:00
xfs_aops.h xfs: add DAX file operations support 2015-06-04 09:18:53 +10:00
xfs_attr_inactive.c Merge branch 'xfs-misc-fixes-for-4.2-3' into for-next 2015-06-23 08:49:01 +10:00
xfs_attr_list.c xfs: pass attr geometry to attr leaf header conversion functions 2015-04-13 11:26:02 +10:00
xfs_attr.h
xfs_bit.c xfs: fix static and extern sparse warnings 2013-10-30 13:59:56 -05:00
xfs_bmap_util.c xfs: fix efi/efd error handling to avoid fs shutdown hangs 2015-08-19 09:51:16 +10:00
xfs_bmap_util.h xfs: Add support FALLOC_FL_INSERT_RANGE for fallocate 2015-03-25 15:08:56 +11:00
xfs_buf_item.c xfs: clarify async write failure ratelimit message 2015-02-24 10:14:04 +11:00
xfs_buf_item.h xfs: decouple inode and bmap btree header files 2013-10-23 16:28:49 -05:00
xfs_buf.c xfs: return a void pointer from xfs_buf_offset 2015-06-22 09:44:29 +10:00
xfs_buf.h xfs: return a void pointer from xfs_buf_offset 2015-06-22 09:44:29 +10:00
xfs_dir2_readdir.c Merge branch 'xfs-misc-fixes-for-3.19-2' into for-next 2014-12-04 09:46:17 +11:00
xfs_discard.c xfs: pass mp to XFS_WANT_CORRUPTED_GOTO 2015-02-23 22:39:08 +11:00
xfs_discard.h
xfs_dquot_item.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_dquot_item.h xfs: remove the quotaoff log format from the quotaoff log item 2013-12-13 11:34:08 +11:00
xfs_dquot.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_dquot.h xfs: fix implicit bool to int conversion 2015-01-09 10:48:58 +11:00
xfs_error.c xfs: remove inst_t 2015-06-22 09:44:02 +10:00
xfs_error.h xfs: remove inst_t 2015-06-22 09:44:02 +10:00
xfs_export.c VFS: normal filesystems (and lustre): d_inode() annotations 2015-04-15 15:06:57 -04:00
xfs_export.h
xfs_extent_busy.c xfs: merge xfs_ag.h into xfs_format.h 2014-11-28 14:25:04 +11:00
xfs_extent_busy.h xfs: decouple inode and bmap btree header files 2013-10-23 16:28:49 -05:00
xfs_extfree_item.c xfs: fix efi/efd error handling to avoid fs shutdown hangs 2015-08-19 09:51:16 +10:00
xfs_extfree_item.h xfs: fix efi/efd error handling to avoid fs shutdown hangs 2015-08-19 09:51:16 +10:00
xfs_file.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2015-07-04 19:36:06 -07:00
xfs_filestream.c xfs: clean up XFS_MIN_FREELIST macros 2015-06-22 10:13:30 +10:00
xfs_filestream.h xfs: add filestream allocator tracepoints 2014-04-23 07:11:52 +10:00
xfs_fsops.c Merge branch 'xfs-commit-cleanup' into for-next 2015-06-04 13:55:48 +10:00
xfs_fsops.h
xfs_globals.c xfs: export log_recovery_delay to delay mount time log recovery 2014-09-09 11:56:13 +10:00
xfs_icache.c xfs: inodes are new until the dentry cache is set up 2015-02-23 22:38:08 +11:00
xfs_icache.h xfs: merge xfs_ag.h into xfs_format.h 2014-11-28 14:25:04 +11:00
xfs_icreate_item.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_icreate_item.h
xfs_inode_item.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_inode_item.h xfs: remove the inode log format from the inode log item 2013-12-13 11:34:05 +11:00
xfs_inode.c Merge branch 'xfs-misc-fixes-for-4.2-3' into for-next 2015-06-23 08:49:01 +10:00
xfs_inode.h Merge branch 'xfs-mmap-lock' into for-next 2015-02-24 10:27:47 +11:00
xfs_ioctl32.c VFS: normal filesystems (and lustre): d_inode() annotations 2015-04-15 15:06:57 -04:00
xfs_ioctl32.h xfs: compat_xfs_bstat does not have forkoff 2014-10-02 09:17:58 +10:00
xfs_ioctl.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_ioctl.h
xfs_iomap.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_iomap.h xfs: pass a 64-bit count argument to xfs_iomap_write_unwritten 2015-01-09 10:48:12 +11:00
xfs_iops.c xfs: update for 4.2-rc1 2015-06-30 20:16:08 -07:00
xfs_iops.h xfs: inodes are new until the dentry cache is set up 2015-02-23 22:38:08 +11:00
xfs_itable.c xfs: use actual inode count for sparse records in bulkstat/inumbers 2015-05-29 09:04:19 +10:00
xfs_itable.h xfs: bulkstat chunk formatting cursor is broken 2014-11-07 08:30:30 +11:00
xfs_linux.h xfs: remove xfs_caddr_t 2015-06-22 09:45:10 +10:00
xfs_log_cil.c xfs: fix xfs_log_done interface 2015-06-04 13:48:20 +10:00
xfs_log_priv.h xfs: use void pointers in log validation helpers 2015-06-22 09:44:47 +10:00
xfs_log_recover.c xfs: disentagle EFI release from the extent count 2015-08-19 09:50:12 +10:00
xfs_log.c Merge branch 'xfs-misc-fixes-for-4.2-3' into for-next 2015-06-23 08:49:01 +10:00
xfs_log.h xfs: fix xfs_log_done interface 2015-06-04 13:48:20 +10:00
xfs_message.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_message.h
xfs_mount.c Merge branch 'xfs-sparse-inode' into for-next 2015-06-01 10:51:38 +10:00
xfs_mount.h Merge branch 'xfs-dax-support' into for-next 2015-06-04 13:01:49 +10:00
xfs_mru_cache.c xfs: xfs_mru_cache_insert() should use GFP_NOFS 2015-03-25 14:57:53 +11:00
xfs_mru_cache.h xfs: embedd mru_elem into parent structure 2014-04-23 07:11:51 +10:00
xfs_pnfs.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_pnfs.h xfs: unlock i_mutex in xfs_break_layouts 2015-04-13 11:38:29 +10:00
xfs_qm_bhv.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_qm_syscalls.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_qm.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_qm.h xfs: Convert to using ->get_state callback 2015-03-04 16:06:36 +01:00
xfs_quota.h xfs: fix quota block reservation leak when tp allocates and frees blocks 2015-06-01 07:15:37 +10:00
xfs_quotaops.c xfs: Add support for Q_SETINFO 2015-03-04 16:06:38 +01:00
xfs_rtalloc.c xfs: saner xfs_trans_commit interface 2015-06-04 13:48:08 +10:00
xfs_rtalloc.h xfs: combine xfs_rtmodify_summary and xfs_rtget_summary 2014-09-09 11:58:42 +10:00
xfs_stats.c xfs: support the XFS_BTNUM_FINOBT free inode btree type 2014-04-24 16:00:52 +10:00
xfs_stats.h xfs: support the XFS_BTNUM_FINOBT free inode btree type 2014-04-24 16:00:52 +10:00
xfs_super.c xfs: add initial DAX support 2015-06-04 09:19:18 +10:00
xfs_super.h xfs: Remove icsb infrastructure 2015-02-23 21:22:31 +11:00
xfs_symlink.c Merge branch 'xfs-misc-fixes-for-4.2-3' into for-next 2015-06-23 08:49:01 +10:00
xfs_symlink.h xfs: push down inactive transaction mgmt for remote symlinks 2013-10-08 14:53:02 -05:00
xfs_sysctl.c xfs: remove deprecated sysctls 2015-01-09 10:47:43 +11:00
xfs_sysctl.h xfs: export log_recovery_delay to delay mount time log recovery 2014-09-09 11:56:13 +10:00
xfs_sysfs.c xfs: export log_recovery_delay to delay mount time log recovery 2014-09-09 11:56:13 +10:00
xfs_sysfs.h xfs: add debug sysfs attribute set 2014-09-09 11:52:42 +10:00
xfs_trace.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_trace.h xfs: allocate sparse inode chunks on full chunk allocation failure 2015-05-29 09:18:32 +10:00
xfs_trans_ail.c xfs: remove __psint_t and __psunsigned_t 2015-06-22 09:43:32 +10:00
xfs_trans_buf.c xfs: only trace buffer items if they exist 2015-02-10 09:23:40 +11:00
xfs_trans_dquot.c xfs: Clean up xfs_trans_dup_dqinfo 2015-06-01 10:50:00 +10:00
xfs_trans_extfree.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_trans_inode.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_trans_priv.h xfs: pass a boolean flag to xfs_trans_free_items 2015-06-04 13:47:43 +10:00
xfs_trans.c xfs: return committed status from xfs_trans_roll() 2015-08-19 09:50:13 +10:00
xfs_trans.h xfs: return committed status from xfs_trans_roll() 2015-08-19 09:50:13 +10:00
xfs_xattr.c VFS: normal filesystems (and lustre): d_inode() annotations 2015-04-15 15:06:57 -04:00
xfs.h