@@ -143,6 +143,28 @@ xfs_ag_resv_needed(
return len;
}
+/*
+ * xfs_ag_resv_update_space() hides the reservations from userspace by modifying
+ * the maximum usable space in the filesystem as well as the free blocks
+ * available. This means a truly empty filesystem will report that it's truly
+ * empty rather than reporting that it has some significant amount of free space
+ * used that the user cannot free.
+ */
+static int
+xfs_ag_resv_update_space(
+ struct xfs_mount *mp,
+ int64_t resv)
+{
+ int error;
+
+ error = xfs_mod_fdblocks(mp, resv, true);
+ if (error)
+ return error;
+
+ mp->m_usable_blocks += resv;
+ return 0;
+}
+
/* Clean out a reservation */
static int
__xfs_ag_resv_free(
@@ -166,7 +188,8 @@ __xfs_ag_resv_free(
oldresv = resv->ar_orig_reserved;
else
oldresv = resv->ar_reserved;
- error = xfs_mod_fdblocks(pag->pag_mount, oldresv, true);
+
+ error = xfs_ag_resv_update_space(pag->pag_mount, (int64_t)oldresv);
resv->ar_reserved = 0;
resv->ar_asked = 0;
@@ -207,7 +230,7 @@ __xfs_ag_resv_init(
ask = used;
reserved = ask - used;
- error = xfs_mod_fdblocks(mp, -(int64_t)reserved, true);
+ error = xfs_ag_resv_update_space(pag->pag_mount, -(int64_t)reserved);
if (error) {
trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno,
error, _RET_IP_);