xfs: always rejoin held resources during defer roll
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 24 Jul 2019 06:34:51 +0000 (06:34 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Aug 2019 06:28:58 +0000 (08:28 +0200)
commit655bb2c4ace4ef3b34791b3ca4cc45693f2c0ecd
tree4af75f2ea659f7f3a64877ffd437d0a8445b4145
parent83a8e6b2f2e39d4b500ed67e68145751ba9140ed
xfs: always rejoin held resources during defer roll

commit 710d707d2fa9cf4c2aa9def129e71e99513466ea upstream.

During testing of xfs/141 on a V4 filesystem, I observed some
inconsistent behavior with regards to resources that are held (i.e.
remain locked) across a defer roll.  The transaction roll always gives
the defer roll function a new transaction, even if committing the old
transaction fails.  However, the defer roll function only rejoins the
held resources if the transaction commit succeedied.  This means that
callers of defer roll have to figure out whether the held resources are
attached to the transaction being passed back.

Worse yet, if the defer roll was part of a defer finish call, we have a
third possibility: the defer finish could pass back a dirty transaction
with dirty held resources and an error code.

The only sane way to handle all of these scenarios is to require that
the code that held the resource either cancel the transaction before
unlocking and releasing the resources, or use functions that detach
resources from a transaction properly (e.g.  xfs_trans_brelse) if they
need to drop the reference before committing or cancelling the
transaction.

In order to make this so, change the defer roll code to join held
resources to the new transaction unconditionally and fix all the bhold
callers to release the held buffers correctly.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
[mcgrof: fixes kz#204223 ]
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr.h
fs/xfs/libxfs/xfs_defer.c
fs/xfs/xfs_dquot.c