Commit e02003b5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-for-linus-4.10-rc3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:

 - fixes for crashes and double-cleanup errors

 - XFS maintainership handover

 - fix to prevent absurdly large block reservations

 - fix broken sysfs getter/setters

* tag 'xfs-for-linus-4.10-rc3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: fix max_retries _show and _store functions
  xfs: update MAINTAINERS
  xfs: fix crash and data corruption due to removal of busy COW extents
  xfs: use the actual AG length when reserving blocks
  xfs: fix double-cleanup when CUI recovery fails
parents 4cf18463 ff97f239
...@@ -13534,11 +13534,11 @@ F: arch/x86/xen/*swiotlb* ...@@ -13534,11 +13534,11 @@ F: arch/x86/xen/*swiotlb*
F: drivers/xen/*swiotlb* F: drivers/xen/*swiotlb*
XFS FILESYSTEM XFS FILESYSTEM
M: Dave Chinner <david@fromorbit.com> M: Darrick J. Wong <darrick.wong@oracle.com>
M: linux-xfs@vger.kernel.org M: linux-xfs@vger.kernel.org
L: linux-xfs@vger.kernel.org L: linux-xfs@vger.kernel.org
W: http://xfs.org/ W: http://xfs.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
S: Supported S: Supported
F: Documentation/filesystems/xfs.txt F: Documentation/filesystems/xfs.txt
F: fs/xfs/ F: fs/xfs/
......
...@@ -256,6 +256,9 @@ xfs_ag_resv_init( ...@@ -256,6 +256,9 @@ xfs_ag_resv_init(
goto out; goto out;
} }
ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
xfs_perag_resv(pag, XFS_AG_RESV_AGFL)->ar_reserved <=
pag->pagf_freeblks + pag->pagf_flcount);
out: out:
return error; return error;
} }
......
...@@ -409,13 +409,14 @@ xfs_refcountbt_calc_size( ...@@ -409,13 +409,14 @@ xfs_refcountbt_calc_size(
*/ */
xfs_extlen_t xfs_extlen_t
xfs_refcountbt_max_size( xfs_refcountbt_max_size(
struct xfs_mount *mp) struct xfs_mount *mp,
xfs_agblock_t agblocks)
{ {
/* Bail out if we're uninitialized, which can happen in mkfs. */ /* Bail out if we're uninitialized, which can happen in mkfs. */
if (mp->m_refc_mxr[0] == 0) if (mp->m_refc_mxr[0] == 0)
return 0; return 0;
return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); return xfs_refcountbt_calc_size(mp, agblocks);
} }
/* /*
...@@ -430,22 +431,24 @@ xfs_refcountbt_calc_reserves( ...@@ -430,22 +431,24 @@ xfs_refcountbt_calc_reserves(
{ {
struct xfs_buf *agbp; struct xfs_buf *agbp;
struct xfs_agf *agf; struct xfs_agf *agf;
xfs_agblock_t agblocks;
xfs_extlen_t tree_len; xfs_extlen_t tree_len;
int error; int error;
if (!xfs_sb_version_hasreflink(&mp->m_sb)) if (!xfs_sb_version_hasreflink(&mp->m_sb))
return 0; return 0;
*ask += xfs_refcountbt_max_size(mp);
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
if (error) if (error)
return error; return error;
agf = XFS_BUF_TO_AGF(agbp); agf = XFS_BUF_TO_AGF(agbp);
agblocks = be32_to_cpu(agf->agf_length);
tree_len = be32_to_cpu(agf->agf_refcount_blocks); tree_len = be32_to_cpu(agf->agf_refcount_blocks);
xfs_buf_relse(agbp); xfs_buf_relse(agbp);
*ask += xfs_refcountbt_max_size(mp, agblocks);
*used += tree_len; *used += tree_len;
return error; return error;
......
...@@ -66,7 +66,8 @@ extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); ...@@ -66,7 +66,8 @@ extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp);
extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp,
unsigned long long len); unsigned long long len);
extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp,
xfs_agblock_t agblocks);
extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp,
xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used);
......
...@@ -550,13 +550,14 @@ xfs_rmapbt_calc_size( ...@@ -550,13 +550,14 @@ xfs_rmapbt_calc_size(
*/ */
xfs_extlen_t xfs_extlen_t
xfs_rmapbt_max_size( xfs_rmapbt_max_size(
struct xfs_mount *mp) struct xfs_mount *mp,
xfs_agblock_t agblocks)
{ {
/* Bail out if we're uninitialized, which can happen in mkfs. */ /* Bail out if we're uninitialized, which can happen in mkfs. */
if (mp->m_rmap_mxr[0] == 0) if (mp->m_rmap_mxr[0] == 0)
return 0; return 0;
return xfs_rmapbt_calc_size(mp, mp->m_sb.sb_agblocks); return xfs_rmapbt_calc_size(mp, agblocks);
} }
/* /*
...@@ -571,25 +572,24 @@ xfs_rmapbt_calc_reserves( ...@@ -571,25 +572,24 @@ xfs_rmapbt_calc_reserves(
{ {
struct xfs_buf *agbp; struct xfs_buf *agbp;
struct xfs_agf *agf; struct xfs_agf *agf;
xfs_extlen_t pool_len; xfs_agblock_t agblocks;
xfs_extlen_t tree_len; xfs_extlen_t tree_len;
int error; int error;
if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
return 0; return 0;
/* Reserve 1% of the AG or enough for 1 block per record. */
pool_len = max(mp->m_sb.sb_agblocks / 100, xfs_rmapbt_max_size(mp));
*ask += pool_len;
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
if (error) if (error)
return error; return error;
agf = XFS_BUF_TO_AGF(agbp); agf = XFS_BUF_TO_AGF(agbp);
agblocks = be32_to_cpu(agf->agf_length);
tree_len = be32_to_cpu(agf->agf_rmap_blocks); tree_len = be32_to_cpu(agf->agf_rmap_blocks);
xfs_buf_relse(agbp); xfs_buf_relse(agbp);
/* Reserve 1% of the AG or enough for 1 block per record. */
*ask += max(agblocks / 100, xfs_rmapbt_max_size(mp, agblocks));
*used += tree_len; *used += tree_len;
return error; return error;
......
...@@ -60,7 +60,8 @@ extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); ...@@ -60,7 +60,8 @@ extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp);
extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp, extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp,
unsigned long long len); unsigned long long len);
extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp,
xfs_agblock_t agblocks);
extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp,
xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used);
......
...@@ -631,6 +631,20 @@ xfs_growfs_data_private( ...@@ -631,6 +631,20 @@ xfs_growfs_data_private(
xfs_set_low_space_thresholds(mp); xfs_set_low_space_thresholds(mp);
mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
/*
* If we expanded the last AG, free the per-AG reservation
* so we can reinitialize it with the new size.
*/
if (new) {
struct xfs_perag *pag;
pag = xfs_perag_get(mp, agno);
error = xfs_ag_resv_free(pag);
xfs_perag_put(pag);
if (error)
goto out;
}
/* Reserve AG metadata blocks. */ /* Reserve AG metadata blocks. */
error = xfs_fs_reserve_ag_blocks(mp); error = xfs_fs_reserve_ag_blocks(mp);
if (error && error != -ENOSPC) if (error && error != -ENOSPC)
......
...@@ -1597,7 +1597,8 @@ xfs_inode_free_cowblocks( ...@@ -1597,7 +1597,8 @@ xfs_inode_free_cowblocks(
* If the mapping is dirty or under writeback we cannot touch the * If the mapping is dirty or under writeback we cannot touch the
* CoW fork. Leave it alone if we're in the midst of a directio. * CoW fork. Leave it alone if we're in the midst of a directio.
*/ */
if (mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY) || if ((VFS_I(ip)->i_state & I_DIRTY_PAGES) ||
mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY) ||
mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_WRITEBACK) || mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_WRITEBACK) ||
atomic_read(&VFS_I(ip)->i_dio_count)) atomic_read(&VFS_I(ip)->i_dio_count))
return 0; return 0;
......
...@@ -526,13 +526,14 @@ xfs_cui_recover( ...@@ -526,13 +526,14 @@ xfs_cui_recover(
xfs_refcount_finish_one_cleanup(tp, rcur, error); xfs_refcount_finish_one_cleanup(tp, rcur, error);
error = xfs_defer_finish(&tp, &dfops, NULL); error = xfs_defer_finish(&tp, &dfops, NULL);
if (error) if (error)
goto abort_error; goto abort_defer;
set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags); set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
error = xfs_trans_commit(tp); error = xfs_trans_commit(tp);
return error; return error;
abort_error: abort_error:
xfs_refcount_finish_one_cleanup(tp, rcur, error); xfs_refcount_finish_one_cleanup(tp, rcur, error);
abort_defer:
xfs_defer_cancel(&dfops); xfs_defer_cancel(&dfops);
xfs_trans_cancel(tp); xfs_trans_cancel(tp);
return error; return error;
......
...@@ -396,7 +396,7 @@ max_retries_show( ...@@ -396,7 +396,7 @@ max_retries_show(
int retries; int retries;
struct xfs_error_cfg *cfg = to_error_cfg(kobject); struct xfs_error_cfg *cfg = to_error_cfg(kobject);
if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER) if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)
retries = -1; retries = -1;
else else
retries = cfg->max_retries; retries = cfg->max_retries;
...@@ -422,7 +422,7 @@ max_retries_store( ...@@ -422,7 +422,7 @@ max_retries_store(
return -EINVAL; return -EINVAL;
if (val == -1) if (val == -1)
cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; cfg->max_retries = XFS_ERR_RETRY_FOREVER;
else else
cfg->max_retries = val; cfg->max_retries = val;
return count; return count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment