Commit c73891c9 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-5.12-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
 "A couple of minor corrections for the new idmapping functionality, and
  a fix for a theoretical hang that could occur if we decide to abort a
  mount after dirtying the quota inodes.

  Summary:

   - Fix quota accounting on creat() when id mapping is enabled

   - Actually reclaim dirty quota inodes when mount fails

   - Typo fixes for documentation

   - Restrict both bulkstat calls on idmapped/namespaced mounts"

* tag 'xfs-5.12-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: also reject BULKSTAT_SINGLE in a mount user namespace
  docs: ABI: Fix the spelling oustanding to outstanding in the file sysfs-fs-xfs
  xfs: force log and push AIL to clear pinned inodes when aborting mount
  xfs: fix quota accounting when a mount is idmapped
parents bf152b0b 8723d5ba
...@@ -33,7 +33,7 @@ Contact: xfs@oss.sgi.com ...@@ -33,7 +33,7 @@ Contact: xfs@oss.sgi.com
Description: Description:
The current state of the log write grant head. It The current state of the log write grant head. It
represents the total log reservation of all currently represents the total log reservation of all currently
oustanding transactions, including regrants due to outstanding transactions, including regrants due to
rolling transactions. The grant head is exported in rolling transactions. The grant head is exported in
"cycle:bytes" format. "cycle:bytes" format.
Users: xfstests Users: xfstests
...@@ -1007,7 +1007,8 @@ xfs_create( ...@@ -1007,7 +1007,8 @@ xfs_create(
/* /*
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, error = xfs_qm_vop_dqalloc(dp, fsuid_into_mnt(mnt_userns),
fsgid_into_mnt(mnt_userns), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
&udqp, &gdqp, &pdqp); &udqp, &gdqp, &pdqp);
if (error) if (error)
...@@ -1157,7 +1158,8 @@ xfs_create_tmpfile( ...@@ -1157,7 +1158,8 @@ xfs_create_tmpfile(
/* /*
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, error = xfs_qm_vop_dqalloc(dp, fsuid_into_mnt(mnt_userns),
fsgid_into_mnt(mnt_userns), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
&udqp, &gdqp, &pdqp); &udqp, &gdqp, &pdqp);
if (error) if (error)
......
...@@ -168,6 +168,12 @@ xfs_bulkstat_one( ...@@ -168,6 +168,12 @@ xfs_bulkstat_one(
}; };
int error; int error;
if (breq->mnt_userns != &init_user_ns) {
xfs_warn_ratelimited(breq->mp,
"bulkstat not supported inside of idmapped mounts.");
return -EINVAL;
}
ASSERT(breq->icount == 1); ASSERT(breq->icount == 1);
bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat), bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
......
...@@ -634,6 +634,47 @@ xfs_check_summary_counts( ...@@ -634,6 +634,47 @@ xfs_check_summary_counts(
return xfs_initialize_perag_data(mp, mp->m_sb.sb_agcount); return xfs_initialize_perag_data(mp, mp->m_sb.sb_agcount);
} }
/*
* Flush and reclaim dirty inodes in preparation for unmount. Inodes and
* internal inode structures can be sitting in the CIL and AIL at this point,
* so we need to unpin them, write them back and/or reclaim them before unmount
* can proceed.
*
* An inode cluster that has been freed can have its buffer still pinned in
* memory because the transaction is still sitting in a iclog. The stale inodes
* on that buffer will be pinned to the buffer until the transaction hits the
* disk and the callbacks run. Pushing the AIL will skip the stale inodes and
* may never see the pinned buffer, so nothing will push out the iclog and
* unpin the buffer.
*
* Hence we need to force the log to unpin everything first. However, log
* forces don't wait for the discards they issue to complete, so we have to
* explicitly wait for them to complete here as well.
*
* Then we can tell the world we are unmounting so that error handling knows
* that the filesystem is going away and we should error out anything that we
* have been retrying in the background. This will prevent never-ending
* retries in AIL pushing from hanging the unmount.
*
* Finally, we can push the AIL to clean all the remaining dirty objects, then
* reclaim the remaining inodes that are still in memory at this point in time.
*/
static void
xfs_unmount_flush_inodes(
struct xfs_mount *mp)
{
xfs_log_force(mp, XFS_LOG_SYNC);
xfs_extent_busy_wait_all(mp);
flush_workqueue(xfs_discard_wq);
mp->m_flags |= XFS_MOUNT_UNMOUNTING;
xfs_ail_push_all_sync(mp->m_ail);
cancel_delayed_work_sync(&mp->m_reclaim_work);
xfs_reclaim_inodes(mp);
xfs_health_unmount(mp);
}
/* /*
* This function does the following on an initial mount of a file system: * This function does the following on an initial mount of a file system:
* - reads the superblock from disk and init the mount struct * - reads the superblock from disk and init the mount struct
...@@ -1008,7 +1049,7 @@ xfs_mountfs( ...@@ -1008,7 +1049,7 @@ xfs_mountfs(
/* Clean out dquots that might be in memory after quotacheck. */ /* Clean out dquots that might be in memory after quotacheck. */
xfs_qm_unmount(mp); xfs_qm_unmount(mp);
/* /*
* Cancel all delayed reclaim work and reclaim the inodes directly. * Flush all inode reclamation work and flush the log.
* We have to do this /after/ rtunmount and qm_unmount because those * We have to do this /after/ rtunmount and qm_unmount because those
* two will have scheduled delayed reclaim for the rt/quota inodes. * two will have scheduled delayed reclaim for the rt/quota inodes.
* *
...@@ -1018,11 +1059,8 @@ xfs_mountfs( ...@@ -1018,11 +1059,8 @@ xfs_mountfs(
* qm_unmount_quotas and therefore rely on qm_unmount to release the * qm_unmount_quotas and therefore rely on qm_unmount to release the
* quota inodes. * quota inodes.
*/ */
cancel_delayed_work_sync(&mp->m_reclaim_work); xfs_unmount_flush_inodes(mp);
xfs_reclaim_inodes(mp);
xfs_health_unmount(mp);
out_log_dealloc: out_log_dealloc:
mp->m_flags |= XFS_MOUNT_UNMOUNTING;
xfs_log_mount_cancel(mp); xfs_log_mount_cancel(mp);
out_fail_wait: out_fail_wait:
if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
...@@ -1063,47 +1101,7 @@ xfs_unmountfs( ...@@ -1063,47 +1101,7 @@ xfs_unmountfs(
xfs_rtunmount_inodes(mp); xfs_rtunmount_inodes(mp);
xfs_irele(mp->m_rootip); xfs_irele(mp->m_rootip);
/* xfs_unmount_flush_inodes(mp);
* We can potentially deadlock here if we have an inode cluster
* that has been freed has its buffer still pinned in memory because
* the transaction is still sitting in a iclog. The stale inodes
* on that buffer will be pinned to the buffer until the
* transaction hits the disk and the callbacks run. Pushing the AIL will
* skip the stale inodes and may never see the pinned buffer, so
* nothing will push out the iclog and unpin the buffer. Hence we
* need to force the log here to ensure all items are flushed into the
* AIL before we go any further.
*/
xfs_log_force(mp, XFS_LOG_SYNC);
/*
* Wait for all busy extents to be freed, including completion of
* any discard operation.
*/
xfs_extent_busy_wait_all(mp);
flush_workqueue(xfs_discard_wq);
/*
* We now need to tell the world we are unmounting. This will allow
* us to detect that the filesystem is going away and we should error
* out anything that we have been retrying in the background. This will
* prevent neverending retries in AIL pushing from hanging the unmount.
*/
mp->m_flags |= XFS_MOUNT_UNMOUNTING;
/*
* Flush all pending changes from the AIL.
*/
xfs_ail_push_all_sync(mp->m_ail);
/*
* Reclaim all inodes. At this point there should be no dirty inodes and
* none should be pinned or locked. Stop background inode reclaim here
* if it is still running.
*/
cancel_delayed_work_sync(&mp->m_reclaim_work);
xfs_reclaim_inodes(mp);
xfs_health_unmount(mp);
xfs_qm_unmount(mp); xfs_qm_unmount(mp);
......
...@@ -182,7 +182,8 @@ xfs_symlink( ...@@ -182,7 +182,8 @@ xfs_symlink(
/* /*
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, error = xfs_qm_vop_dqalloc(dp, fsuid_into_mnt(mnt_userns),
fsgid_into_mnt(mnt_userns), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
&udqp, &gdqp, &pdqp); &udqp, &gdqp, &pdqp);
if (error) if (error)
......
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