All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions
@ 2021-01-28  6:01 Darrick J. Wong
  2021-01-28  6:01 ` [PATCH 01/13] xfs: clean up quota reservation callsites Darrick J. Wong
                   ` (12 more replies)
  0 siblings, 13 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: Christoph Hellwig, Brian Foster, linux-xfs, hch, david, bfoster

Hi all,

This series reworks some of the internal quota APIs and cleans up some
of the function calls so that we have a clean(er) place to start the
space reclamation patchset.  The first five patches clean up the
existing quota transaction helpers.  The next five patches create a
common helper to allocate space, quota, and transaction to handle a file
modification.  The final three patches of the series create common
helpers to do more or less the same thing for file creation and chown
operations.  The goal of these changes is to reduce open-coded idioms,
which makes the job of the space reclamation patchset easier since we
can now (mostly) hide the retry loops within single functions.

v2: rework the xfs_quota_reserve_blkres calling conventions per hch
v3: create new xfs_trans_alloc* helpers that will take care of free
    space and quota reservation all at once for block allocations, inode
    creation, and chown operations, to simplify the subsequent patches.

If you're going to start using this mess, you probably ought to just
pull from my git trees, which are linked below.

This is an extraordinary way to destroy everything.  Enjoy!
Comments and questions are, as always, welcome.

--D

kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=quota-function-cleanups-5.12
---
 fs/xfs/libxfs/xfs_attr.c |   15 -----
 fs/xfs/libxfs/xfs_bmap.c |   23 ++-----
 fs/xfs/xfs_bmap_util.c   |   58 ++++--------------
 fs/xfs/xfs_inode.c       |   30 +++------
 fs/xfs/xfs_ioctl.c       |    4 +
 fs/xfs/xfs_iomap.c       |   51 +++++-----------
 fs/xfs/xfs_iops.c        |    5 +-
 fs/xfs/xfs_qm.c          |   93 -----------------------------
 fs/xfs/xfs_quota.h       |   59 ++++++++++++++----
 fs/xfs/xfs_reflink.c     |   87 ++++++++++++++-------------
 fs/xfs/xfs_symlink.c     |   15 +----
 fs/xfs/xfs_trans.c       |   83 ++++++++++++++++++++++++++
 fs/xfs/xfs_trans.h       |   10 +++
 fs/xfs/xfs_trans_dquot.c |  149 +++++++++++++++++++++++++++++++++++++++++++---
 14 files changed, 373 insertions(+), 309 deletions(-)


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [PATCH 01/13] xfs: clean up quota reservation callsites
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28  6:01 ` [PATCH 02/13] xfs: create convenience wrappers for incore quota block reservations Darrick J. Wong
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: Christoph Hellwig, Brian Foster, linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Convert a few xfs_trans_*reserve* callsites that are open-coding other
convenience functions.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c |    3 +--
 fs/xfs/xfs_bmap_util.c   |    4 ++--
 fs/xfs/xfs_reflink.c     |    4 ++--
 3 files changed, 5 insertions(+), 6 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index ba56554e8c05..0410627c6fcc 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -4937,8 +4937,7 @@ xfs_bmap_del_extent_delay(
 	 * sb counters as we might have to borrow some blocks for the
 	 * indirect block accounting.
 	 */
-	error = xfs_trans_reserve_quota_nblks(NULL, ip,
-			-((long)del->br_blockcount), 0,
+	error = xfs_trans_unreserve_quota_nblks(NULL, ip, del->br_blockcount, 0,
 			isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
 	if (error)
 		return error;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index f3f8c48ff5bf..792809debaaa 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -884,8 +884,8 @@ xfs_unmap_extent(
 	}
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot, ip->i_gdquot,
-			ip->i_pdquot, resblks, 0, XFS_QMOPT_RES_REGBLKS);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
+			XFS_QMOPT_RES_REGBLKS);
 	if (error)
 		goto out_trans_cancel;
 
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index e1c98dbf79e4..183142fd0961 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -508,8 +508,8 @@ xfs_reflink_cancel_cow_blocks(
 			xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
 
 			/* Remove the quota reservation */
-			error = xfs_trans_reserve_quota_nblks(NULL, ip,
-					-(long)del.br_blockcount, 0,
+			error = xfs_trans_unreserve_quota_nblks(NULL, ip,
+					del.br_blockcount, 0,
 					XFS_QMOPT_RES_REGBLKS);
 			if (error)
 				break;


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 02/13] xfs: create convenience wrappers for incore quota block reservations
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
  2021-01-28  6:01 ` [PATCH 01/13] xfs: clean up quota reservation callsites Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28 18:08   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely Darrick J. Wong
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: Christoph Hellwig, linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Create a couple of convenience wrappers for creating and deleting quota
block reservations against future changes.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_bmap.c |   10 ++++------
 fs/xfs/xfs_quota.h       |   19 +++++++++++++++++++
 fs/xfs/xfs_reflink.c     |    5 ++---
 3 files changed, 25 insertions(+), 9 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 0410627c6fcc..6edf1b5711c8 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -4097,8 +4097,7 @@ xfs_bmapi_reserve_delalloc(
 	 * blocks.  This number gets adjusted later.  We return if we haven't
 	 * allocated blocks already inside this loop.
 	 */
-	error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0,
-						XFS_QMOPT_RES_REGBLKS);
+	error = xfs_quota_reserve_blkres(ip, alen);
 	if (error)
 		return error;
 
@@ -4144,8 +4143,7 @@ xfs_bmapi_reserve_delalloc(
 	xfs_mod_fdblocks(mp, alen, false);
 out_unreserve_quota:
 	if (XFS_IS_QUOTA_ON(mp))
-		xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0,
-						XFS_QMOPT_RES_REGBLKS);
+		xfs_quota_unreserve_blkres(ip, alen);
 	return error;
 }
 
@@ -4937,8 +4935,8 @@ xfs_bmap_del_extent_delay(
 	 * sb counters as we might have to borrow some blocks for the
 	 * indirect block accounting.
 	 */
-	error = xfs_trans_unreserve_quota_nblks(NULL, ip, del->br_blockcount, 0,
-			isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+	ASSERT(!isrt);
+	error = xfs_quota_unreserve_blkres(ip, del->br_blockcount);
 	if (error)
 		return error;
 	ip->i_delayed_blks -= del->br_blockcount;
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 5a62398940d0..159d338bf161 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -108,6 +108,12 @@ extern void xfs_qm_mount_quotas(struct xfs_mount *);
 extern void xfs_qm_unmount(struct xfs_mount *);
 extern void xfs_qm_unmount_quotas(struct xfs_mount *);
 
+static inline int
+xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
+{
+	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0,
+			XFS_QMOPT_RES_REGBLKS);
+}
 #else
 static inline int
 xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
@@ -136,6 +142,13 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
 {
 	return 0;
 }
+
+static inline int
+xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
+{
+	return 0;
+}
+
 #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
 #define xfs_qm_vop_rename_dqattach(it)					(0)
 #define xfs_qm_vop_chown(tp, ip, old, new)				(NULL)
@@ -157,6 +170,12 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
 	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
 				f | XFS_QMOPT_RES_REGBLKS)
 
+static inline int
+xfs_quota_unreserve_blkres(struct xfs_inode *ip, int64_t dblocks)
+{
+	return xfs_quota_reserve_blkres(ip, -dblocks);
+}
+
 extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
 
 #endif	/* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 183142fd0961..bea64ed5a57f 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -508,9 +508,8 @@ xfs_reflink_cancel_cow_blocks(
 			xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
 
 			/* Remove the quota reservation */
-			error = xfs_trans_unreserve_quota_nblks(NULL, ip,
-					del.br_blockcount, 0,
-					XFS_QMOPT_RES_REGBLKS);
+			error = xfs_quota_unreserve_blkres(ip,
+					del.br_blockcount);
 			if (error)
 				break;
 		} else {


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
  2021-01-28  6:01 ` [PATCH 01/13] xfs: clean up quota reservation callsites Darrick J. Wong
  2021-01-28  6:01 ` [PATCH 02/13] xfs: create convenience wrappers for incore quota block reservations Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28  9:46   ` Christoph Hellwig
  2021-01-28 18:08   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 04/13] xfs: clean up icreate quota reservation calls Darrick J. Wong
                   ` (9 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

xfs_trans_cancel will release all the quota resources that were reserved
on behalf of the transaction, so get rid of the explicit unreserve step.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_bmap_util.c |    7 ++-----
 fs/xfs/xfs_iomap.c     |    6 ++----
 fs/xfs/xfs_quota.h     |    2 --
 fs/xfs/xfs_reflink.c   |    5 +----
 4 files changed, 5 insertions(+), 15 deletions(-)


diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 792809debaaa..f0a8f3377281 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -825,7 +825,7 @@ xfs_alloc_file_space(
 		error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
 				XFS_IEXT_ADD_NOSPLIT_CNT);
 		if (error)
-			goto error0;
+			goto error1;
 
 		xfs_trans_ijoin(tp, ip, 0);
 
@@ -833,7 +833,7 @@ xfs_alloc_file_space(
 					allocatesize_fsb, alloc_type, 0, imapp,
 					&nimaps);
 		if (error)
-			goto error0;
+			goto error1;
 
 		/*
 		 * Complete the transaction
@@ -856,9 +856,6 @@ xfs_alloc_file_space(
 
 	return error;
 
-error0:	/* unlock inode, unreserve quota blocks, cancel trans */
-	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
-
 error1:	/* Just cancel transaction */
 	xfs_trans_cancel(tp);
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 514e6ae010e0..de0e371ba4dd 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -253,7 +253,7 @@ xfs_iomap_write_direct(
 	error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
 			XFS_IEXT_ADD_NOSPLIT_CNT);
 	if (error)
-		goto out_res_cancel;
+		goto out_trans_cancel;
 
 	xfs_trans_ijoin(tp, ip, 0);
 
@@ -265,7 +265,7 @@ xfs_iomap_write_direct(
 	error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flags, 0,
 				imap, &nimaps);
 	if (error)
-		goto out_res_cancel;
+		goto out_trans_cancel;
 
 	/*
 	 * Complete the transaction
@@ -289,8 +289,6 @@ xfs_iomap_write_direct(
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	return error;
 
-out_res_cancel:
-	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
 out_trans_cancel:
 	xfs_trans_cancel(tp);
 	goto out_unlock;
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 159d338bf161..a395dabee033 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -164,8 +164,6 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
 #define xfs_qm_unmount_quotas(mp)
 #endif /* CONFIG_XFS_QUOTA */
 
-#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \
-	xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags)
 #define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
 	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
 				f | XFS_QMOPT_RES_REGBLKS)
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index bea64ed5a57f..15435229bc1f 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -411,7 +411,7 @@ xfs_reflink_allocate_cow(
 			XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC, 0, cmap,
 			&nimaps);
 	if (error)
-		goto out_unreserve;
+		goto out_trans_cancel;
 
 	xfs_inode_set_cowblocks_tag(ip);
 	error = xfs_trans_commit(tp);
@@ -436,9 +436,6 @@ xfs_reflink_allocate_cow(
 	trace_xfs_reflink_convert_cow(ip, cmap);
 	return xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb);
 
-out_unreserve:
-	xfs_trans_unreserve_quota_nblks(tp, ip, (long)resblks, 0,
-			XFS_QMOPT_RES_REGBLKS);
 out_trans_cancel:
 	xfs_trans_cancel(tp);
 	return error;


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 04/13] xfs: clean up icreate quota reservation calls
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (2 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28 18:09   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 05/13] xfs: fix up build warnings when quotas are disabled Darrick J. Wong
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: Christoph Hellwig, linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Create a proper helper so that inode creation calls can reserve quota
with a dedicated function.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_inode.c       |    6 ++----
 fs/xfs/xfs_quota.h       |   14 ++++++++++----
 fs/xfs/xfs_symlink.c     |    3 +--
 fs/xfs/xfs_trans_dquot.c |   18 ++++++++++++++++++
 4 files changed, 31 insertions(+), 10 deletions(-)


diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e2a1db4cee43..4bbd2fb628f7 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1037,8 +1037,7 @@ xfs_create(
 	/*
 	 * Reserve disk quota and the inode.
 	 */
-	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
-						pdqp, resblks, 1, 0);
+	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
 	if (error)
 		goto out_trans_cancel;
 
@@ -1169,8 +1168,7 @@ xfs_create_tmpfile(
 	if (error)
 		goto out_release_inode;
 
-	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
-						pdqp, resblks, 1, 0);
+	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
 	if (error)
 		goto out_trans_cancel;
 
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index a395dabee033..d1e3f94140b4 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -86,6 +86,9 @@ extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
 extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
 		struct xfs_mount *, struct xfs_dquot *,
 		struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint);
+int xfs_trans_reserve_quota_icreate(struct xfs_trans *tp,
+		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
+		struct xfs_dquot *pdqp, int64_t dblocks);
 
 extern int xfs_qm_vop_dqalloc(struct xfs_inode *, kuid_t, kgid_t,
 		prid_t, uint, struct xfs_dquot **, struct xfs_dquot **,
@@ -149,6 +152,13 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
 	return 0;
 }
 
+static inline int
+xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
+		struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, int64_t dblocks)
+{
+	return 0;
+}
+
 #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
 #define xfs_qm_vop_rename_dqattach(it)					(0)
 #define xfs_qm_vop_chown(tp, ip, old, new)				(NULL)
@@ -164,10 +174,6 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
 #define xfs_qm_unmount_quotas(mp)
 #endif /* CONFIG_XFS_QUOTA */
 
-#define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
-	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
-				f | XFS_QMOPT_RES_REGBLKS)
-
 static inline int
 xfs_quota_unreserve_blkres(struct xfs_inode *ip, int64_t dblocks)
 {
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 7f96649e918a..d5dee8f409b2 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -215,8 +215,7 @@ xfs_symlink(
 	/*
 	 * Reserve disk quota : blocks and inode.
 	 */
-	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
-						pdqp, resblks, 1, 0);
+	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
 	if (error)
 		goto out_trans_cancel;
 
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 28b8ac701919..22aa875b84f7 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -804,6 +804,24 @@ xfs_trans_reserve_quota_nblks(
 						nblks, ninos, flags);
 }
 
+/* Change the quota reservations for an inode creation activity. */
+int
+xfs_trans_reserve_quota_icreate(
+	struct xfs_trans	*tp,
+	struct xfs_dquot	*udqp,
+	struct xfs_dquot	*gdqp,
+	struct xfs_dquot	*pdqp,
+	int64_t			dblocks)
+{
+	struct xfs_mount	*mp = tp->t_mountp;
+
+	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+		return 0;
+
+	return xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp,
+			dblocks, 1, XFS_QMOPT_RES_REGBLKS);
+}
+
 /*
  * This routine is called to allocate a quotaoff log item.
  */


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 05/13] xfs: fix up build warnings when quotas are disabled
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (3 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 04/13] xfs: clean up icreate quota reservation calls Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28 18:09   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 06/13] xfs: reserve data and rt quota at the same time Darrick J. Wong
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: Christoph Hellwig, linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Fix some build warnings on gcc 10.2 when quotas are disabled.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_quota.h |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)


diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index d1e3f94140b4..72f4cfc49048 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -130,7 +130,7 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
 }
 #define xfs_trans_dup_dqinfo(tp, tp2)
 #define xfs_trans_free_dqinfo(tp)
-#define xfs_trans_mod_dquot_byino(tp, ip, fields, delta)
+#define xfs_trans_mod_dquot_byino(tp, ip, fields, delta) do { } while (0)
 #define xfs_trans_apply_dquot_deltas(tp)
 #define xfs_trans_unreserve_and_mod_dquots(tp)
 static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
@@ -166,8 +166,8 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
 #define xfs_qm_dqattach(ip)						(0)
 #define xfs_qm_dqattach_locked(ip, fl)					(0)
 #define xfs_qm_dqdetach(ip)
-#define xfs_qm_dqrele(d)
-#define xfs_qm_statvfs(ip, s)
+#define xfs_qm_dqrele(d)			do { (d) = (d); } while(0)
+#define xfs_qm_statvfs(ip, s)			do { } while(0)
 #define xfs_qm_newmount(mp, a, b)					(0)
 #define xfs_qm_mount_quotas(mp)
 #define xfs_qm_unmount(mp)


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 06/13] xfs: reserve data and rt quota at the same time
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (4 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 05/13] xfs: fix up build warnings when quotas are disabled Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28  9:49   ` Christoph Hellwig
  2021-01-28 18:10   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom Darrick J. Wong
                   ` (6 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Modify xfs_trans_reserve_quota_nblks so that we can reserve data and
realtime blocks from the dquot at the same time.  This change has the
theoretical side effect that for allocations to realtime files we will
reserve from the dquot both the number of rtblocks being allocated and
the number of bmbt blocks that might be needed to add the mapping.
However, since the mount code disables quota if it finds a realtime
device, this should not result in any behavior changes.

This also replaces the flags argument with a force? boolean since we
don't need to distinguish between data and rt quota reservations any
more, and the only other flag being passed in was FORCE_RES.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/libxfs/xfs_attr.c |    6 +-----
 fs/xfs/libxfs/xfs_bmap.c |    4 +---
 fs/xfs/xfs_bmap_util.c   |   20 +++++++++-----------
 fs/xfs/xfs_iomap.c       |   26 +++++++++++++-------------
 fs/xfs/xfs_quota.h       |   10 +++++-----
 fs/xfs/xfs_reflink.c     |    6 ++----
 fs/xfs/xfs_trans_dquot.c |   42 ++++++++++++++++++++++++++++--------------
 7 files changed, 59 insertions(+), 55 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index be51e7068dcd..e05dc0bc4a8f 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -474,12 +474,8 @@ xfs_attr_set(
 	}
 
 	if (args->value) {
-		unsigned int	quota_flags = XFS_QMOPT_RES_REGBLKS;
-
-		if (rsvd)
-			quota_flags |= XFS_QMOPT_FORCE_RES;
 		error = xfs_trans_reserve_quota_nblks(args->trans, dp,
-				args->total, 0, quota_flags);
+				args->total, 0, rsvd);
 		if (error)
 			goto out_trans_cancel;
 
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 6edf1b5711c8..043bb8c634b0 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1085,9 +1085,7 @@ xfs_bmap_add_attrfork(
 		return error;
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
-			XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
-			XFS_QMOPT_RES_REGBLKS);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd);
 	if (error)
 		goto trans_cancel;
 	if (XFS_IFORK_Q(ip))
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index f0a8f3377281..d54d9f02d3dd 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -727,7 +727,6 @@ xfs_alloc_file_space(
 	xfs_fileoff_t		startoffset_fsb;
 	xfs_fileoff_t		endoffset_fsb;
 	int			nimaps;
-	int			quota_flag;
 	int			rt;
 	xfs_trans_t		*tp;
 	xfs_bmbt_irec_t		imaps[1], *imapp;
@@ -761,6 +760,7 @@ xfs_alloc_file_space(
 	 */
 	while (allocatesize_fsb && !error) {
 		xfs_fileoff_t	s, e;
+		unsigned int	dblocks, rblocks;
 
 		/*
 		 * Determine space reservations for data/realtime.
@@ -792,18 +792,17 @@ xfs_alloc_file_space(
 		if (unlikely(rt)) {
 			resrtextents = qblocks = resblks;
 			resrtextents /= mp->m_sb.sb_rextsize;
-			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
-			quota_flag = XFS_QMOPT_RES_RTBLKS;
+			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+			rblocks = resblks;
 		} else {
-			resrtextents = 0;
-			resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
-			quota_flag = XFS_QMOPT_RES_REGBLKS;
+			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
+			rblocks = 0;
 		}
 
 		/*
 		 * Allocate and setup the transaction.
 		 */
-		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks,
+		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks,
 				resrtextents, 0, &tp);
 
 		/*
@@ -817,8 +816,8 @@ xfs_alloc_file_space(
 			break;
 		}
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks,
-						      0, quota_flag);
+		error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks,
+				false);
 		if (error)
 			goto error1;
 
@@ -881,8 +880,7 @@ xfs_unmap_extent(
 	}
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
-			XFS_QMOPT_RES_REGBLKS);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
 	if (error)
 		goto out_trans_cancel;
 
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index de0e371ba4dd..ef29d44c656a 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -194,25 +194,25 @@ xfs_iomap_write_direct(
 	struct xfs_trans	*tp;
 	xfs_filblks_t		resaligned;
 	int			nimaps;
-	int			quota_flag;
-	uint			qblocks, resblks;
+	unsigned int		dblocks, rblocks;
 	unsigned int		resrtextents = 0;
 	int			error;
 	int			bmapi_flags = XFS_BMAPI_PREALLOC;
-	uint			tflags = 0;
+	int			tflags = 0;
+	bool			force = false;
 
 	ASSERT(count_fsb > 0);
 
 	resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb,
 					   xfs_get_extsz_hint(ip));
 	if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
-		resrtextents = qblocks = resaligned;
+		resrtextents = resaligned;
 		resrtextents /= mp->m_sb.sb_rextsize;
-		resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
-		quota_flag = XFS_QMOPT_RES_RTBLKS;
+		dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+		rblocks = resaligned;
 	} else {
-		resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
-		quota_flag = XFS_QMOPT_RES_REGBLKS;
+		dblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
+		rblocks = 0;
 	}
 
 	error = xfs_qm_dqattach(ip);
@@ -235,18 +235,19 @@ xfs_iomap_write_direct(
 	if (IS_DAX(VFS_I(ip))) {
 		bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
 		if (imap->br_state == XFS_EXT_UNWRITTEN) {
+			force = true;
 			tflags |= XFS_TRANS_RESERVE;
-			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
+			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
 		}
 	}
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents,
+	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks, resrtextents,
 			tflags, &tp);
 	if (error)
 		return error;
 
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 
-	error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
 	if (error)
 		goto out_trans_cancel;
 
@@ -559,8 +560,7 @@ xfs_iomap_write_unwritten(
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
 		xfs_trans_ijoin(tp, ip, 0);
 
-		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
-				XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES);
+		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, true);
 		if (error)
 			goto error_on_bmapi_transaction;
 
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 72f4cfc49048..efd04f84d9b4 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -81,8 +81,8 @@ extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, struct xfs_inode *,
 		uint, int64_t);
 extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *);
 extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *);
-extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
-		struct xfs_inode *, int64_t, long, uint);
+int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip,
+		int64_t dblocks, int64_t rblocks, bool force);
 extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
 		struct xfs_mount *, struct xfs_dquot *,
 		struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint);
@@ -114,8 +114,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);
 static inline int
 xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
 {
-	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0,
-			XFS_QMOPT_RES_REGBLKS);
+	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0, false);
 }
 #else
 static inline int
@@ -134,7 +133,8 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
 #define xfs_trans_apply_dquot_deltas(tp)
 #define xfs_trans_unreserve_and_mod_dquots(tp)
 static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
-		struct xfs_inode *ip, int64_t nblks, long ninos, uint flags)
+		struct xfs_inode *ip, int64_t dblocks, int64_t rblocks,
+		bool force)
 {
 	return 0;
 }
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 15435229bc1f..0778b5810c26 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -398,8 +398,7 @@ xfs_reflink_allocate_cow(
 		goto convert;
 	}
 
-	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
-			XFS_QMOPT_RES_REGBLKS);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
 	if (error)
 		goto out_trans_cancel;
 
@@ -1090,8 +1089,7 @@ xfs_reflink_remap_extent(
 	if (!smap_real && dmap_written)
 		qres += dmap->br_blockcount;
 	if (qres > 0) {
-		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0,
-				XFS_QMOPT_RES_REGBLKS);
+		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, false);
 		if (error)
 			goto out_cancel;
 	}
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 22aa875b84f7..a1a72b7900c5 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -780,28 +780,42 @@ int
 xfs_trans_reserve_quota_nblks(
 	struct xfs_trans	*tp,
 	struct xfs_inode	*ip,
-	int64_t			nblks,
-	long			ninos,
-	uint			flags)
+	int64_t			dblocks,
+	int64_t			rblocks,
+	bool			force)
 {
 	struct xfs_mount	*mp = ip->i_mount;
+	unsigned int		qflags = 0;
+	int			error;
 
 	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
 		return 0;
 
 	ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
-
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-	ASSERT((flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_RTBLKS ||
-	       (flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_BLKS);
-
-	/*
-	 * Reserve nblks against these dquots, with trans as the mediator.
-	 */
-	return xfs_trans_reserve_quota_bydquots(tp, mp,
-						ip->i_udquot, ip->i_gdquot,
-						ip->i_pdquot,
-						nblks, ninos, flags);
+
+	if (force)
+		qflags |= XFS_QMOPT_FORCE_RES;
+
+	/* Reserve data device quota against the inode's dquots. */
+	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
+			ip->i_gdquot, ip->i_pdquot, dblocks, 0,
+			XFS_QMOPT_RES_REGBLKS | qflags);
+	if (error)
+		return error;
+
+	/* Do the same but for realtime blocks. */
+	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
+			ip->i_gdquot, ip->i_pdquot, rblocks, 0,
+			XFS_QMOPT_RES_RTBLKS | qflags);
+	if (error) {
+		xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
+				ip->i_gdquot, ip->i_pdquot, -dblocks, 0,
+				XFS_QMOPT_RES_REGBLKS);
+		return error;
+	}
+
+	return 0;
 }
 
 /* Change the quota reservations for an inode creation activity. */


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (5 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 06/13] xfs: reserve data and rt quota at the same time Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28  9:50   ` Christoph Hellwig
  2021-01-28 18:22   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode Darrick J. Wong
                   ` (5 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Create a new helper xfs_trans_alloc_inode that allocates a transaction,
locks and joins an inode to it, and then reserves the appropriate amount
of quota against that transction.  Then replace all the open-coded
idioms with a single call to this helper.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/libxfs/xfs_attr.c |   11 +----------
 fs/xfs/libxfs/xfs_bmap.c |   10 ++--------
 fs/xfs/xfs_bmap_util.c   |   14 +++----------
 fs/xfs/xfs_iomap.c       |   11 ++---------
 fs/xfs/xfs_trans.c       |   48 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_trans.h       |    3 +++
 6 files changed, 59 insertions(+), 38 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index e05dc0bc4a8f..cb95bc77fe59 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -458,14 +458,10 @@ xfs_attr_set(
 	 * Root fork attributes can use reserved data blocks for this
 	 * operation if necessary
 	 */
-	error = xfs_trans_alloc(mp, &tres, total, 0,
-			rsvd ? XFS_TRANS_RESERVE : 0, &args->trans);
+	error = xfs_trans_alloc_inode(dp, &tres, total, rsvd, &args->trans);
 	if (error)
 		return error;
 
-	xfs_ilock(dp, XFS_ILOCK_EXCL);
-	xfs_trans_ijoin(args->trans, dp, 0);
-
 	if (args->value || xfs_inode_hasattr(dp)) {
 		error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
 				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
@@ -474,11 +470,6 @@ xfs_attr_set(
 	}
 
 	if (args->value) {
-		error = xfs_trans_reserve_quota_nblks(args->trans, dp,
-				args->total, 0, rsvd);
-		if (error)
-			goto out_trans_cancel;
-
 		error = xfs_has_attr(args);
 		if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
 			goto out_trans_cancel;
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 043bb8c634b0..f78fa694f3c2 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1079,19 +1079,13 @@ xfs_bmap_add_attrfork(
 
 	blks = XFS_ADDAFORK_SPACE_RES(mp);
 
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0,
-			rsvd ? XFS_TRANS_RESERVE : 0, &tp);
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks,
+			rsvd, &tp);
 	if (error)
 		return error;
-
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd);
-	if (error)
-		goto trans_cancel;
 	if (XFS_IFORK_Q(ip))
 		goto trans_cancel;
 
-	xfs_trans_ijoin(tp, ip, 0);
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 	error = xfs_bmap_set_attrforkoff(ip, size, &version);
 	if (error)
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index d54d9f02d3dd..94ffdeb2dd73 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -873,18 +873,10 @@ xfs_unmap_extent(
 	uint			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
 	int			error;
 
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
-	if (error) {
-		ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp));
-		return error;
-	}
-
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
+			false, &tp);
 	if (error)
-		goto out_trans_cancel;
-
-	xfs_trans_ijoin(tp, ip, 0);
+		return error;
 
 	error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
 			XFS_IEXT_PUNCH_HOLE_CNT);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index ef29d44c656a..05de1be20426 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -552,18 +552,11 @@ xfs_iomap_write_unwritten(
 		 * here as we might be asked to write out the same inode that we
 		 * complete here and might deadlock on the iolock.
 		 */
-		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
-				XFS_TRANS_RESERVE, &tp);
+		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
+				true, &tp);
 		if (error)
 			return error;
 
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		xfs_trans_ijoin(tp, ip, 0);
-
-		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, true);
-		if (error)
-			goto error_on_bmapi_transaction;
-
 		error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
 				XFS_IEXT_WRITE_UNWRITTEN_CNT);
 		if (error)
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index e72730f85af1..156b9ed8534f 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -20,6 +20,7 @@
 #include "xfs_trace.h"
 #include "xfs_error.h"
 #include "xfs_defer.h"
+#include "xfs_inode.h"
 
 kmem_zone_t	*xfs_trans_zone;
 
@@ -1024,3 +1025,50 @@ xfs_trans_roll(
 	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
 	return xfs_trans_reserve(*tpp, &tres, 0, 0);
 }
+
+/*
+ * Allocate an transaction, lock and join the inode to it, and reserve quota.
+ *
+ * The caller must ensure that the on-disk dquots attached to this inode have
+ * already been allocated and initialized.  The caller is responsible for
+ * releasing ILOCK_EXCL if a new transaction is returned.
+ */
+int
+xfs_trans_alloc_inode(
+	struct xfs_inode	*ip,
+	struct xfs_trans_res	*resv,
+	unsigned int		dblocks,
+	bool			force,
+	struct xfs_trans	**tpp)
+{
+	struct xfs_trans	*tp;
+	struct xfs_mount	*mp = ip->i_mount;
+	int			error;
+
+	error = xfs_trans_alloc(mp, resv, dblocks, 0,
+			force ? XFS_TRANS_RESERVE : 0, &tp);
+	if (error)
+		return error;
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	xfs_trans_ijoin(tp, ip, 0);
+
+	error = xfs_qm_dqattach_locked(ip, false);
+	if (error) {
+		/* Caller should have allocated the dquots! */
+		ASSERT(error != -ENOENT);
+		goto out_cancel;
+	}
+
+	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, 0, force);
+	if (error)
+		goto out_cancel;
+
+	*tpp = tp;
+	return 0;
+
+out_cancel:
+	xfs_trans_cancel(tp);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	return error;
+}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 084658946cc8..aa50be244432 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -268,4 +268,7 @@ xfs_trans_item_relog(
 	return lip->li_ops->iop_relog(lip, tp);
 }
 
+int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
+		unsigned int dblocks, bool force, struct xfs_trans **tpp);
+
 #endif	/* __XFS_TRANS_H__ */


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (6 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28  9:51   ` Christoph Hellwig
  2021-01-28 18:22   ` Brian Foster
  2021-01-28  6:01 ` [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode Darrick J. Wong
                   ` (4 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Make it so that we can reserve rt blocks with the xfs_trans_alloc_inode
wrapper function, then convert a few more callsites.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/libxfs/xfs_attr.c |    2 +-
 fs/xfs/libxfs/xfs_bmap.c |    2 +-
 fs/xfs/xfs_bmap_util.c   |   29 +++++------------------------
 fs/xfs/xfs_iomap.c       |   22 +++++-----------------
 fs/xfs/xfs_trans.c       |    6 ++++--
 fs/xfs/xfs_trans.h       |    3 ++-
 6 files changed, 18 insertions(+), 46 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index cb95bc77fe59..472b3039eabb 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -458,7 +458,7 @@ xfs_attr_set(
 	 * Root fork attributes can use reserved data blocks for this
 	 * operation if necessary
 	 */
-	error = xfs_trans_alloc_inode(dp, &tres, total, rsvd, &args->trans);
+	error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
 	if (error)
 		return error;
 
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index f78fa694f3c2..8131bc5f4bad 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1079,7 +1079,7 @@ xfs_bmap_add_attrfork(
 
 	blks = XFS_ADDAFORK_SPACE_RES(mp);
 
-	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks,
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks, 0,
 			rsvd, &tp);
 	if (error)
 		return error;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 94ffdeb2dd73..c3b7dff21887 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -730,7 +730,6 @@ xfs_alloc_file_space(
 	int			rt;
 	xfs_trans_t		*tp;
 	xfs_bmbt_irec_t		imaps[1], *imapp;
-	uint			qblocks, resblks, resrtextents;
 	int			error;
 
 	trace_xfs_alloc_file_space(ip);
@@ -760,7 +759,7 @@ xfs_alloc_file_space(
 	 */
 	while (allocatesize_fsb && !error) {
 		xfs_fileoff_t	s, e;
-		unsigned int	dblocks, rblocks;
+		unsigned int	dblocks, rblocks, resblks;
 
 		/*
 		 * Determine space reservations for data/realtime.
@@ -790,8 +789,6 @@ xfs_alloc_file_space(
 		 */
 		resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
 		if (unlikely(rt)) {
-			resrtextents = qblocks = resblks;
-			resrtextents /= mp->m_sb.sb_rextsize;
 			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
 			rblocks = resblks;
 		} else {
@@ -802,32 +799,16 @@ xfs_alloc_file_space(
 		/*
 		 * Allocate and setup the transaction.
 		 */
-		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks,
-				resrtextents, 0, &tp);
-
-		/*
-		 * Check for running out of space
-		 */
-		if (error) {
-			/*
-			 * Free the transaction structure.
-			 */
-			ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp));
-			break;
-		}
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks,
-				false);
+		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
+				dblocks, rblocks, false, &tp);
 		if (error)
-			goto error1;
+			break;
 
 		error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
 				XFS_IEXT_ADD_NOSPLIT_CNT);
 		if (error)
 			goto error1;
 
-		xfs_trans_ijoin(tp, ip, 0);
-
 		error = xfs_bmapi_write(tp, ip, startoffset_fsb,
 					allocatesize_fsb, alloc_type, 0, imapp,
 					&nimaps);
@@ -873,7 +854,7 @@ xfs_unmap_extent(
 	uint			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
 	int			error;
 
-	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
 			false, &tp);
 	if (error)
 		return error;
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 05de1be20426..f34a76529602 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -195,19 +195,15 @@ xfs_iomap_write_direct(
 	xfs_filblks_t		resaligned;
 	int			nimaps;
 	unsigned int		dblocks, rblocks;
-	unsigned int		resrtextents = 0;
+	bool			force = false;
 	int			error;
 	int			bmapi_flags = XFS_BMAPI_PREALLOC;
-	int			tflags = 0;
-	bool			force = false;
 
 	ASSERT(count_fsb > 0);
 
 	resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb,
 					   xfs_get_extsz_hint(ip));
 	if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
-		resrtextents = resaligned;
-		resrtextents /= mp->m_sb.sb_rextsize;
 		dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
 		rblocks = resaligned;
 	} else {
@@ -236,28 +232,20 @@ xfs_iomap_write_direct(
 		bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
 		if (imap->br_state == XFS_EXT_UNWRITTEN) {
 			force = true;
-			tflags |= XFS_TRANS_RESERVE;
 			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
 		}
 	}
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks, resrtextents,
-			tflags, &tp);
+
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, dblocks,
+			rblocks, force, &tp);
 	if (error)
 		return error;
 
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
-	if (error)
-		goto out_trans_cancel;
-
 	error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
 			XFS_IEXT_ADD_NOSPLIT_CNT);
 	if (error)
 		goto out_trans_cancel;
 
-	xfs_trans_ijoin(tp, ip, 0);
-
 	/*
 	 * From this point onwards we overwrite the imap pointer that the
 	 * caller gave to us.
@@ -553,7 +541,7 @@ xfs_iomap_write_unwritten(
 		 * complete here and might deadlock on the iolock.
 		 */
 		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
-				true, &tp);
+				0, true, &tp);
 		if (error)
 			return error;
 
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 156b9ed8534f..151f274eee43 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1038,6 +1038,7 @@ xfs_trans_alloc_inode(
 	struct xfs_inode	*ip,
 	struct xfs_trans_res	*resv,
 	unsigned int		dblocks,
+	unsigned int		rblocks,
 	bool			force,
 	struct xfs_trans	**tpp)
 {
@@ -1045,7 +1046,8 @@ xfs_trans_alloc_inode(
 	struct xfs_mount	*mp = ip->i_mount;
 	int			error;
 
-	error = xfs_trans_alloc(mp, resv, dblocks, 0,
+	error = xfs_trans_alloc(mp, resv, dblocks,
+			rblocks / mp->m_sb.sb_rextsize,
 			force ? XFS_TRANS_RESERVE : 0, &tp);
 	if (error)
 		return error;
@@ -1060,7 +1062,7 @@ xfs_trans_alloc_inode(
 		goto out_cancel;
 	}
 
-	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, 0, force);
+	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
 	if (error)
 		goto out_cancel;
 
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index aa50be244432..52bbd7e6a552 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -269,6 +269,7 @@ xfs_trans_item_relog(
 }
 
 int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
-		unsigned int dblocks, bool force, struct xfs_trans **tpp);
+		unsigned int dblocks, unsigned int rblocks, bool force,
+		struct xfs_trans **tpp);
 
 #endif	/* __XFS_TRANS_H__ */


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (7 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode Darrick J. Wong
@ 2021-01-28  6:01 ` Darrick J. Wong
  2021-01-28  9:53   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  2021-01-28  6:02 ` [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent Darrick J. Wong
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:01 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

The two remaining callers of xfs_trans_reserve_quota_nblks are in the
reflink code.  These conversions aren't as uniform as the previous
conversions, so call that out in a separate patch.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_reflink.c |   58 +++++++++++++++++++++-----------------------------
 1 file changed, 24 insertions(+), 34 deletions(-)


diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 0778b5810c26..ded86cc4764c 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -376,16 +376,15 @@ xfs_reflink_allocate_cow(
 	resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
 
 	xfs_iunlock(ip, *lockmode);
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
-	*lockmode = XFS_ILOCK_EXCL;
-	xfs_ilock(ip, *lockmode);
 
-	if (error)
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
+			false, &tp);
+	if (error) {
+		/* This function must return with ILOCK_EXCL held. */
+		*lockmode = XFS_ILOCK_EXCL;
+		xfs_ilock(ip, *lockmode);
 		return error;
-
-	error = xfs_qm_dqattach_locked(ip, false);
-	if (error)
-		goto out_trans_cancel;
+	}
 
 	/*
 	 * Check for an overlapping extent again now that we dropped the ilock.
@@ -398,12 +397,6 @@ xfs_reflink_allocate_cow(
 		goto convert;
 	}
 
-	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
-	if (error)
-		goto out_trans_cancel;
-
-	xfs_trans_ijoin(tp, ip, 0);
-
 	/* Allocate the entire reservation as unwritten blocks. */
 	nimaps = 1;
 	error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount,
@@ -997,7 +990,7 @@ xfs_reflink_remap_extent(
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_trans	*tp;
 	xfs_off_t		newlen;
-	int64_t			qres, qdelta;
+	int64_t			qdelta = 0;
 	unsigned int		resblks;
 	bool			smap_real;
 	bool			dmap_written = xfs_bmap_is_written_extent(dmap);
@@ -1005,15 +998,22 @@ xfs_reflink_remap_extent(
 	int			nimaps;
 	int			error;
 
-	/* Start a rolling transaction to switch the mappings */
+	/*
+	 * Start a rolling transaction to switch the mappings.
+	 *
+	 * Adding a written extent to the extent map can cause a bmbt split,
+	 * and removing a mapped extent from the extent can cause a bmbt split.
+	 * The two operations cannot both cause a split since they operate on
+	 * the same index in the bmap btree, so we only need a reservation for
+	 * one bmbt split if either thing is happening.  However, we haven't
+	 * locked the inode yet, so we reserve assuming this is the case.
+	 */
 	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
+			false, &tp);
 	if (error)
 		goto out;
 
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	xfs_trans_ijoin(tp, ip, 0);
-
 	/*
 	 * Read what's currently mapped in the destination file into smap.
 	 * If smap isn't a hole, we will have to remove it before we can add
@@ -1061,15 +1061,9 @@ xfs_reflink_remap_extent(
 	}
 
 	/*
-	 * Compute quota reservation if we think the quota block counter for
+	 * Increase quota reservation if we think the quota block counter for
 	 * this file could increase.
 	 *
-	 * Adding a written extent to the extent map can cause a bmbt split,
-	 * and removing a mapped extent from the extent can cause a bmbt split.
-	 * The two operations cannot both cause a split since they operate on
-	 * the same index in the bmap btree, so we only need a reservation for
-	 * one bmbt split if either thing is happening.
-	 *
 	 * If we are mapping a written extent into the file, we need to have
 	 * enough quota block count reservation to handle the blocks in that
 	 * extent.  We log only the delta to the quota block counts, so if the
@@ -1083,13 +1077,9 @@ xfs_reflink_remap_extent(
 	 * before we started.  That should have removed all the delalloc
 	 * reservations, but we code defensively.
 	 */
-	qres = qdelta = 0;
-	if (smap_real || dmap_written)
-		qres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
-	if (!smap_real && dmap_written)
-		qres += dmap->br_blockcount;
-	if (qres > 0) {
-		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, false);
+	if (!smap_real && dmap_written) {
+		error = xfs_trans_reserve_quota_nblks(tp, ip,
+				dmap->br_blockcount, 0, false);
 		if (error)
 			goto out_cancel;
 	}


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (8 preceding siblings ...)
  2021-01-28  6:01 ` [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode Darrick J. Wong
@ 2021-01-28  6:02 ` Darrick J. Wong
  2021-01-28  9:55   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  2021-01-28  6:02 ` [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom Darrick J. Wong
                   ` (2 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:02 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Now that we've converted xfs_reflink_remap_extent to use the new
xfs_trans_alloc_inode API, we can focus on its slightly unusual behavior
with regard to quota reservations.

Since it's valid to remap written blocks into a hole, we must be able to
increase the quota count by the number of blocks in the mapping.
However, the incore space reservation process requires us to supply an
asymptotic guess before we can gain exclusive access to resources.  We'd
like to reserve all the quota we need up front, but we also don't want
to fail a written -> allocated remap operation unnecessarily.

The solution is to make the remap_extents function call the transaction
allocation function twice.  The first time we ask to reserve enough
space and quota to handle the absolute worst case situation, but if that
fails, we can fall back to the old strategy: ask for the bare minimum
space reservation upfront and increase the quota reservation later if we
need to.

This isn't a problem now, but in the next patchset we change the
transaction and quota code to try to reclaim space if we cannot reserve
free space or quota.  Restructuring the remap_extent function in this
manner means that if the fallback increase fails, we can pass that back
to the caller knowing that the transaction allocation already tried
freeing space.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_reflink.c |   23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)


diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index ded86cc4764c..c6296fd1512f 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -992,6 +992,7 @@ xfs_reflink_remap_extent(
 	xfs_off_t		newlen;
 	int64_t			qdelta = 0;
 	unsigned int		resblks;
+	bool			quota_reserved = true;
 	bool			smap_real;
 	bool			dmap_written = xfs_bmap_is_written_extent(dmap);
 	int			iext_delta = 0;
@@ -1007,10 +1008,26 @@ xfs_reflink_remap_extent(
 	 * the same index in the bmap btree, so we only need a reservation for
 	 * one bmbt split if either thing is happening.  However, we haven't
 	 * locked the inode yet, so we reserve assuming this is the case.
+	 *
+	 * The first allocation call tries to reserve enough space to handle
+	 * mapping dmap into a sparse part of the file plus the bmbt split.  We
+	 * haven't locked the inode or read the existing mapping yet, so we do
+	 * not know for sure that we need the space.  This should succeed most
+	 * of the time.
+	 *
+	 * If the first attempt fails, try again but reserving only enough
+	 * space to handle a bmbt split.  This is the hard minimum requirement,
+	 * and we revisit quota reservations later when we know more about what
+	 * we're remapping.
 	 */
 	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
-	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
-			false, &tp);
+	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
+			resblks + dmap->br_blockcount, 0, false, &tp);
+	if (error == -EDQUOT || error == -ENOSPC) {
+		quota_reserved = false;
+		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
+				resblks, 0, false, &tp);
+	}
 	if (error)
 		goto out;
 
@@ -1077,7 +1094,7 @@ xfs_reflink_remap_extent(
 	 * before we started.  That should have removed all the delalloc
 	 * reservations, but we code defensively.
 	 */
-	if (!smap_real && dmap_written) {
+	if (!quota_reserved && !smap_real && dmap_written) {
 		error = xfs_trans_reserve_quota_nblks(tp, ip,
 				dmap->br_blockcount, 0, false);
 		if (error)


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (9 preceding siblings ...)
  2021-01-28  6:02 ` [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent Darrick J. Wong
@ 2021-01-28  6:02 ` Darrick J. Wong
  2021-01-28  9:57   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  2021-01-28  6:02 ` [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c Darrick J. Wong
  2021-01-28  6:02 ` [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit Darrick J. Wong
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:02 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

For file creation, create a new helper xfs_trans_alloc_icreate that
allocates a transaction and reserves the appropriate amount of quota
against that transction.  Replace all the open-coded idioms with a
single call to this helper so that we can contain the retry loops in the
next patchset.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_inode.c   |   28 ++++++++++------------------
 fs/xfs/xfs_symlink.c |   14 ++++----------
 fs/xfs/xfs_trans.c   |   33 +++++++++++++++++++++++++++++++++
 fs/xfs/xfs_trans.h   |    6 ++++++
 4 files changed, 53 insertions(+), 28 deletions(-)


diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 4bbd2fb628f7..636ac13b1df2 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1022,25 +1022,20 @@ xfs_create(
 	 * the case we'll drop the one we have and get a more
 	 * appropriate transaction later.
 	 */
-	error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
+	error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
+			&tp);
 	if (error == -ENOSPC) {
 		/* flush outstanding delalloc blocks and retry */
 		xfs_flush_inodes(mp);
-		error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
+		error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp,
+				resblks, &tp);
 	}
 	if (error)
-		goto out_release_inode;
+		goto out_release_dquots;
 
 	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 	unlock_dp_on_error = true;
 
-	/*
-	 * Reserve disk quota and the inode.
-	 */
-	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
-	if (error)
-		goto out_trans_cancel;
-
 	error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
 			XFS_IEXT_DIR_MANIP_CNT(mp));
 	if (error)
@@ -1120,7 +1115,7 @@ xfs_create(
 		xfs_finish_inode_setup(ip);
 		xfs_irele(ip);
 	}
-
+ out_release_dquots:
 	xfs_qm_dqrele(udqp);
 	xfs_qm_dqrele(gdqp);
 	xfs_qm_dqrele(pdqp);
@@ -1164,13 +1159,10 @@ xfs_create_tmpfile(
 	resblks = XFS_IALLOC_SPACE_RES(mp);
 	tres = &M_RES(mp)->tr_create_tmpfile;
 
-	error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
+	error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
+			&tp);
 	if (error)
-		goto out_release_inode;
-
-	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
-	if (error)
-		goto out_trans_cancel;
+		goto out_release_dquots;
 
 	error = xfs_dir_ialloc(&tp, dp, mode, 0, 0, prid, &ip);
 	if (error)
@@ -1213,7 +1205,7 @@ xfs_create_tmpfile(
 		xfs_finish_inode_setup(ip);
 		xfs_irele(ip);
 	}
-
+ out_release_dquots:
 	xfs_qm_dqrele(udqp);
 	xfs_qm_dqrele(gdqp);
 	xfs_qm_dqrele(pdqp);
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index d5dee8f409b2..8565663b16cd 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -197,9 +197,10 @@ xfs_symlink(
 		fs_blocks = xfs_symlink_blocks(mp, pathlen);
 	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
 
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_symlink, resblks, 0, 0, &tp);
+	error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
+			pdqp, resblks, &tp);
 	if (error)
-		goto out_release_inode;
+		goto out_release_dquots;
 
 	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 	unlock_dp_on_error = true;
@@ -212,13 +213,6 @@ xfs_symlink(
 		goto out_trans_cancel;
 	}
 
-	/*
-	 * Reserve disk quota : blocks and inode.
-	 */
-	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
-	if (error)
-		goto out_trans_cancel;
-
 	error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
 			XFS_IEXT_DIR_MANIP_CNT(mp));
 	if (error)
@@ -347,7 +341,7 @@ xfs_symlink(
 		xfs_finish_inode_setup(ip);
 		xfs_irele(ip);
 	}
-
+out_release_dquots:
 	xfs_qm_dqrele(udqp);
 	xfs_qm_dqrele(gdqp);
 	xfs_qm_dqrele(pdqp);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 151f274eee43..bfb8b2a1594f 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -21,6 +21,8 @@
 #include "xfs_error.h"
 #include "xfs_defer.h"
 #include "xfs_inode.h"
+#include "xfs_dquot_item.h"
+#include "xfs_dquot.h"
 
 kmem_zone_t	*xfs_trans_zone;
 
@@ -1074,3 +1076,34 @@ xfs_trans_alloc_inode(
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	return error;
 }
+
+/*
+ * Allocate an transaction in preparation for inode creation by reserving quota
+ * against the given dquots.
+ */
+int
+xfs_trans_alloc_icreate(
+	struct xfs_mount	*mp,
+	struct xfs_trans_res	*resv,
+	struct xfs_dquot	*udqp,
+	struct xfs_dquot	*gdqp,
+	struct xfs_dquot	*pdqp,
+	unsigned int		dblocks,
+	struct xfs_trans	**tpp)
+{
+	struct xfs_trans	*tp;
+	int			error;
+
+	error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp);
+	if (error)
+		return error;
+
+	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks);
+	if (error) {
+		xfs_trans_cancel(tp);
+		return error;
+	}
+
+	*tpp = tp;
+	return 0;
+}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 52bbd7e6a552..04c132c55e9b 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -268,8 +268,14 @@ xfs_trans_item_relog(
 	return lip->li_ops->iop_relog(lip, tp);
 }
 
+struct xfs_dquot;
+
 int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
 		unsigned int dblocks, unsigned int rblocks, bool force,
 		struct xfs_trans **tpp);
+int xfs_trans_alloc_icreate(struct xfs_mount *mp, struct xfs_trans_res *resv,
+		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
+		struct xfs_dquot *pdqp, unsigned int dblocks,
+		struct xfs_trans **tpp);
 
 #endif	/* __XFS_TRANS_H__ */


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (10 preceding siblings ...)
  2021-01-28  6:02 ` [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom Darrick J. Wong
@ 2021-01-28  6:02 ` Darrick J. Wong
  2021-01-28  9:58   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  2021-01-28  6:02 ` [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit Darrick J. Wong
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:02 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c and rename it
xfs_trans_reserve_quota_chown.  This will enable us to share code with
the other quota reservation helpers, which will be very useful in the
next patchset when we implement retry loops.  No functional changes
here, we're just moving code.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_ioctl.c       |    2 -
 fs/xfs/xfs_iops.c        |    6 +--
 fs/xfs/xfs_qm.c          |   93 ----------------------------------------------
 fs/xfs/xfs_quota.h       |   14 +++++--
 fs/xfs/xfs_trans_dquot.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 107 insertions(+), 101 deletions(-)


diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 3fbd98f61ea5..e299fbd9ef13 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1470,7 +1470,7 @@ xfs_ioctl_setattr(
 
 	if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
 	    ip->i_d.di_projid != fa->fsx_projid) {
-		code = xfs_qm_vop_chown_reserve(tp, ip, NULL, NULL, pdqp,
+		code = xfs_trans_reserve_quota_chown(tp, ip, NULL, NULL, pdqp,
 				capable(CAP_FOWNER) ?  XFS_QMOPT_FORCE_RES : 0);
 		if (code)	/* out of quota */
 			goto error_trans_cancel;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index f1e21b6cfa48..cb68be87e0a4 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -730,9 +730,9 @@ xfs_setattr_nonsize(
 		    ((XFS_IS_UQUOTA_ON(mp) && !uid_eq(iuid, uid)) ||
 		     (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) {
 			ASSERT(tp);
-			error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
-						NULL, capable(CAP_FOWNER) ?
-						XFS_QMOPT_FORCE_RES : 0);
+			error = xfs_trans_reserve_quota_chown(tp, ip, udqp,
+					gdqp, NULL, capable(CAP_FOWNER) ?
+					XFS_QMOPT_FORCE_RES : 0);
 			if (error)	/* out of quota */
 				goto out_cancel;
 		}
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index c134eb4aeaa8..6c2a9fa78e7c 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1794,99 +1794,6 @@ xfs_qm_vop_chown(
 	return prevdq;
 }
 
-/*
- * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
- */
-int
-xfs_qm_vop_chown_reserve(
-	struct xfs_trans	*tp,
-	struct xfs_inode	*ip,
-	struct xfs_dquot	*udqp,
-	struct xfs_dquot	*gdqp,
-	struct xfs_dquot	*pdqp,
-	uint			flags)
-{
-	struct xfs_mount	*mp = ip->i_mount;
-	uint64_t		delblks;
-	unsigned int		blkflags;
-	struct xfs_dquot	*udq_unres = NULL;
-	struct xfs_dquot	*gdq_unres = NULL;
-	struct xfs_dquot	*pdq_unres = NULL;
-	struct xfs_dquot	*udq_delblks = NULL;
-	struct xfs_dquot	*gdq_delblks = NULL;
-	struct xfs_dquot	*pdq_delblks = NULL;
-	int			error;
-
-
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
-
-	delblks = ip->i_delayed_blks;
-	blkflags = XFS_IS_REALTIME_INODE(ip) ?
-			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
-
-	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
-	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
-		udq_delblks = udqp;
-		/*
-		 * If there are delayed allocation blocks, then we have to
-		 * unreserve those from the old dquot, and add them to the
-		 * new dquot.
-		 */
-		if (delblks) {
-			ASSERT(ip->i_udquot);
-			udq_unres = ip->i_udquot;
-		}
-	}
-	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
-	    i_gid_read(VFS_I(ip)) != gdqp->q_id) {
-		gdq_delblks = gdqp;
-		if (delblks) {
-			ASSERT(ip->i_gdquot);
-			gdq_unres = ip->i_gdquot;
-		}
-	}
-
-	if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
-	    ip->i_d.di_projid != pdqp->q_id) {
-		pdq_delblks = pdqp;
-		if (delblks) {
-			ASSERT(ip->i_pdquot);
-			pdq_unres = ip->i_pdquot;
-		}
-	}
-
-	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
-				udq_delblks, gdq_delblks, pdq_delblks,
-				ip->i_d.di_nblocks, 1, flags | blkflags);
-	if (error)
-		return error;
-
-	/*
-	 * Do the delayed blks reservations/unreservations now. Since, these
-	 * are done without the help of a transaction, if a reservation fails
-	 * its previous reservations won't be automatically undone by trans
-	 * code. So, we have to do it manually here.
-	 */
-	if (delblks) {
-		/*
-		 * Do the reservations first. Unreservation can't fail.
-		 */
-		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
-		ASSERT(udq_unres || gdq_unres || pdq_unres);
-		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
-			    udq_delblks, gdq_delblks, pdq_delblks,
-			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
-		if (error)
-			return error;
-		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
-				udq_unres, gdq_unres, pdq_unres,
-				-((xfs_qcnt_t)delblks), 0, blkflags);
-	}
-
-	return 0;
-}
-
 int
 xfs_qm_vop_rename_dqattach(
 	struct xfs_inode	**i_tab)
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index efd04f84d9b4..d3876c71be8f 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -98,9 +98,9 @@ extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
 extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **);
 extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
 		struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
-extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *,
-		struct xfs_dquot *, struct xfs_dquot *,
-		struct xfs_dquot *, uint);
+int xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
+		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
+		struct xfs_dquot *pdqp, unsigned int flags);
 extern int xfs_qm_dqattach(struct xfs_inode *);
 extern int xfs_qm_dqattach_locked(struct xfs_inode *ip, bool doalloc);
 extern void xfs_qm_dqdetach(struct xfs_inode *);
@@ -162,7 +162,13 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
 #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
 #define xfs_qm_vop_rename_dqattach(it)					(0)
 #define xfs_qm_vop_chown(tp, ip, old, new)				(NULL)
-#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl)			(0)
+static inline int
+xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
+		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
+		struct xfs_dquot *pdqp, unsigned int flags)
+{
+	return 0;
+}
 #define xfs_qm_dqattach(ip)						(0)
 #define xfs_qm_dqattach_locked(ip, fl)					(0)
 #define xfs_qm_dqdetach(ip)
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index a1a72b7900c5..88146280a177 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -836,6 +836,99 @@ xfs_trans_reserve_quota_icreate(
 			dblocks, 1, XFS_QMOPT_RES_REGBLKS);
 }
 
+/*
+ * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
+ */
+int
+xfs_trans_reserve_quota_chown(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip,
+	struct xfs_dquot	*udqp,
+	struct xfs_dquot	*gdqp,
+	struct xfs_dquot	*pdqp,
+	unsigned int		flags)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	uint64_t		delblks;
+	unsigned int		blkflags;
+	struct xfs_dquot	*udq_unres = NULL;
+	struct xfs_dquot	*gdq_unres = NULL;
+	struct xfs_dquot	*pdq_unres = NULL;
+	struct xfs_dquot	*udq_delblks = NULL;
+	struct xfs_dquot	*gdq_delblks = NULL;
+	struct xfs_dquot	*pdq_delblks = NULL;
+	int			error;
+
+
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
+
+	delblks = ip->i_delayed_blks;
+	blkflags = XFS_IS_REALTIME_INODE(ip) ?
+			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
+
+	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
+	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
+		udq_delblks = udqp;
+		/*
+		 * If there are delayed allocation blocks, then we have to
+		 * unreserve those from the old dquot, and add them to the
+		 * new dquot.
+		 */
+		if (delblks) {
+			ASSERT(ip->i_udquot);
+			udq_unres = ip->i_udquot;
+		}
+	}
+	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
+	    i_gid_read(VFS_I(ip)) != gdqp->q_id) {
+		gdq_delblks = gdqp;
+		if (delblks) {
+			ASSERT(ip->i_gdquot);
+			gdq_unres = ip->i_gdquot;
+		}
+	}
+
+	if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
+	    ip->i_d.di_projid != pdqp->q_id) {
+		pdq_delblks = pdqp;
+		if (delblks) {
+			ASSERT(ip->i_pdquot);
+			pdq_unres = ip->i_pdquot;
+		}
+	}
+
+	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
+				udq_delblks, gdq_delblks, pdq_delblks,
+				ip->i_d.di_nblocks, 1, flags | blkflags);
+	if (error)
+		return error;
+
+	/*
+	 * Do the delayed blks reservations/unreservations now. Since, these
+	 * are done without the help of a transaction, if a reservation fails
+	 * its previous reservations won't be automatically undone by trans
+	 * code. So, we have to do it manually here.
+	 */
+	if (delblks) {
+		/*
+		 * Do the reservations first. Unreservation can't fail.
+		 */
+		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
+		ASSERT(udq_unres || gdq_unres || pdq_unres);
+		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
+			    udq_delblks, gdq_delblks, pdq_delblks,
+			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
+		if (error)
+			return error;
+		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
+				udq_unres, gdq_unres, pdq_unres,
+				-((xfs_qcnt_t)delblks), 0, blkflags);
+	}
+
+	return 0;
+}
+
 /*
  * This routine is called to allocate a quotaoff log item.
  */


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit
  2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
                   ` (11 preceding siblings ...)
  2021-01-28  6:02 ` [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c Darrick J. Wong
@ 2021-01-28  6:02 ` Darrick J. Wong
  2021-01-28 10:00   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  12 siblings, 2 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28  6:02 UTC (permalink / raw)
  To: djwong; +Cc: linux-xfs, hch, david, bfoster

From: Darrick J. Wong <djwong@kernel.org>

Clean up the calling conventions of xfs_trans_reserve_quota_chown a
littel bit -- we can pass in a boolean force parameter since that's the
only qmopt that caller care about, and make the obvious deficiencies
more obvious for anyone who someday wants to clean up rt quota.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/xfs_ioctl.c       |    2 +-
 fs/xfs/xfs_iops.c        |    3 +--
 fs/xfs/xfs_quota.h       |    4 ++--
 fs/xfs/xfs_trans_dquot.c |   38 +++++++++++++++++++++-----------------
 4 files changed, 25 insertions(+), 22 deletions(-)


diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index e299fbd9ef13..73cfee8007a8 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1471,7 +1471,7 @@ xfs_ioctl_setattr(
 	if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
 	    ip->i_d.di_projid != fa->fsx_projid) {
 		code = xfs_trans_reserve_quota_chown(tp, ip, NULL, NULL, pdqp,
-				capable(CAP_FOWNER) ?  XFS_QMOPT_FORCE_RES : 0);
+				capable(CAP_FOWNER));
 		if (code)	/* out of quota */
 			goto error_trans_cancel;
 	}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index cb68be87e0a4..51c877ce90bc 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -731,8 +731,7 @@ xfs_setattr_nonsize(
 		     (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) {
 			ASSERT(tp);
 			error = xfs_trans_reserve_quota_chown(tp, ip, udqp,
-					gdqp, NULL, capable(CAP_FOWNER) ?
-					XFS_QMOPT_FORCE_RES : 0);
+					gdqp, NULL, capable(CAP_FOWNER));
 			if (error)	/* out of quota */
 				goto out_cancel;
 		}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index d3876c71be8f..c3a5b48f5860 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -100,7 +100,7 @@ extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
 		struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
 int xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
 		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
-		struct xfs_dquot *pdqp, unsigned int flags);
+		struct xfs_dquot *pdqp, bool force);
 extern int xfs_qm_dqattach(struct xfs_inode *);
 extern int xfs_qm_dqattach_locked(struct xfs_inode *ip, bool doalloc);
 extern void xfs_qm_dqdetach(struct xfs_inode *);
@@ -165,7 +165,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
 static inline int
 xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
 		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
-		struct xfs_dquot *pdqp, unsigned int flags)
+		struct xfs_dquot *pdqp, bool force)
 {
 	return 0;
 }
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 88146280a177..73ef5994d09d 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -846,26 +846,30 @@ xfs_trans_reserve_quota_chown(
 	struct xfs_dquot	*udqp,
 	struct xfs_dquot	*gdqp,
 	struct xfs_dquot	*pdqp,
-	unsigned int		flags)
+	bool			force)
 {
 	struct xfs_mount	*mp = ip->i_mount;
-	uint64_t		delblks;
-	unsigned int		blkflags;
-	struct xfs_dquot	*udq_unres = NULL;
+	struct xfs_dquot	*udq_unres = NULL;	/* old dquots */
 	struct xfs_dquot	*gdq_unres = NULL;
 	struct xfs_dquot	*pdq_unres = NULL;
-	struct xfs_dquot	*udq_delblks = NULL;
+	struct xfs_dquot	*udq_delblks = NULL;	/* new dquots */
 	struct xfs_dquot	*gdq_delblks = NULL;
 	struct xfs_dquot	*pdq_delblks = NULL;
+	uint64_t		delblks;
+	unsigned int		qflags = XFS_QMOPT_RES_REGBLKS;
 	int			error;
 
-
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
+	/*
+	 * XXX: This function doesn't handle rt quota counts correctly.  We
+	 * don't support mounting with rt+quota so leave this breadcrumb.
+	 */
+	ASSERT(!XFS_IS_REALTIME_INODE(ip));
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
 	delblks = ip->i_delayed_blks;
-	blkflags = XFS_IS_REALTIME_INODE(ip) ?
-			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
+	if (force)
+		qflags |= XFS_QMOPT_FORCE_RES;
 
 	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
 	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
@@ -898,9 +902,9 @@ xfs_trans_reserve_quota_chown(
 		}
 	}
 
-	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
-				udq_delblks, gdq_delblks, pdq_delblks,
-				ip->i_d.di_nblocks, 1, flags | blkflags);
+	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, udq_delblks,
+			gdq_delblks, pdq_delblks, ip->i_d.di_nblocks, 1,
+			qflags);
 	if (error)
 		return error;
 
@@ -917,13 +921,13 @@ xfs_trans_reserve_quota_chown(
 		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
 		ASSERT(udq_unres || gdq_unres || pdq_unres);
 		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
-			    udq_delblks, gdq_delblks, pdq_delblks,
-			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
+				udq_delblks, gdq_delblks, pdq_delblks,
+				(xfs_qcnt_t)delblks, 0, qflags);
 		if (error)
 			return error;
-		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
-				udq_unres, gdq_unres, pdq_unres,
-				-((xfs_qcnt_t)delblks), 0, blkflags);
+		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, udq_unres,
+				gdq_unres, pdq_unres, -((xfs_qcnt_t)delblks),
+				0, qflags);
 	}
 
 	return 0;


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely
  2021-01-28  6:01 ` [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely Darrick J. Wong
@ 2021-01-28  9:46   ` Christoph Hellwig
  2021-01-28 18:08   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:46 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:01:21PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> xfs_trans_cancel will release all the quota resources that were reserved
> on behalf of the transaction, so get rid of the explicit unreserve step.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 06/13] xfs: reserve data and rt quota at the same time
  2021-01-28  6:01 ` [PATCH 06/13] xfs: reserve data and rt quota at the same time Darrick J. Wong
@ 2021-01-28  9:49   ` Christoph Hellwig
  2021-01-28 18:01     ` Darrick J. Wong
  2021-01-28 18:10   ` Brian Foster
  1 sibling, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:49 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:01:38PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Modify xfs_trans_reserve_quota_nblks so that we can reserve data and
> realtime blocks from the dquot at the same time.  This change has the
> theoretical side effect that for allocations to realtime files we will
> reserve from the dquot both the number of rtblocks being allocated and
> the number of bmbt blocks that might be needed to add the mapping.
> However, since the mount code disables quota if it finds a realtime
> device, this should not result in any behavior changes.
> 
> This also replaces the flags argument with a force? boolean since we
> don't need to distinguish between data and rt quota reservations any
> more, and the only other flag being passed in was FORCE_RES.

It a removes the entirely unused nino flag, which caused quite some
confusion to me when reading this patch, so please document that.

Otherwise this looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom
  2021-01-28  6:01 ` [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom Darrick J. Wong
@ 2021-01-28  9:50   ` Christoph Hellwig
  2021-01-28 18:22   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:50 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode
  2021-01-28  6:01 ` [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode Darrick J. Wong
@ 2021-01-28  9:51   ` Christoph Hellwig
  2021-01-28 18:22   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:51 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:01:49PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Make it so that we can reserve rt blocks with the xfs_trans_alloc_inode
> wrapper function, then convert a few more callsites.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode
  2021-01-28  6:01 ` [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode Darrick J. Wong
@ 2021-01-28  9:53   ` Christoph Hellwig
  2021-01-28 18:06     ` Darrick J. Wong
  2021-01-28 18:23   ` Brian Foster
  1 sibling, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:53 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:01:55PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> The two remaining callers of xfs_trans_reserve_quota_nblks are in the
> reflink code.  These conversions aren't as uniform as the previous
> conversions, so call that out in a separate patch.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
>  fs/xfs/xfs_reflink.c |   58 +++++++++++++++++++++-----------------------------
>  1 file changed, 24 insertions(+), 34 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 0778b5810c26..ded86cc4764c 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -376,16 +376,15 @@ xfs_reflink_allocate_cow(
>  	resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
>  
>  	xfs_iunlock(ip, *lockmode);
>  
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
> +			false, &tp);
> +	if (error) {
> +		/* This function must return with ILOCK_EXCL held. */
> +		*lockmode = XFS_ILOCK_EXCL;
> +		xfs_ilock(ip, *lockmode);
>  		return error;
> +	}

The only thing that the only caller of xfs_reflink_allocate_cow does
on error is to immediately release the lock.  So I think we are better
off changing the calling convention instead of relocking here.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent
  2021-01-28  6:02 ` [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent Darrick J. Wong
@ 2021-01-28  9:55   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:55 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:02:01PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Now that we've converted xfs_reflink_remap_extent to use the new
> xfs_trans_alloc_inode API, we can focus on its slightly unusual behavior
> with regard to quota reservations.
> 
> Since it's valid to remap written blocks into a hole, we must be able to
> increase the quota count by the number of blocks in the mapping.
> However, the incore space reservation process requires us to supply an
> asymptotic guess before we can gain exclusive access to resources.  We'd
> like to reserve all the quota we need up front, but we also don't want
> to fail a written -> allocated remap operation unnecessarily.
> 
> The solution is to make the remap_extents function call the transaction
> allocation function twice.  The first time we ask to reserve enough
> space and quota to handle the absolute worst case situation, but if that
> fails, we can fall back to the old strategy: ask for the bare minimum
> space reservation upfront and increase the quota reservation later if we
> need to.
> 
> This isn't a problem now, but in the next patchset we change the
> transaction and quota code to try to reclaim space if we cannot reserve
> free space or quota.  Restructuring the remap_extent function in this
> manner means that if the fallback increase fails, we can pass that back
> to the caller knowing that the transaction allocation already tried
> freeing space.

The patch itself looks good, but I don't see what problem it solves.

Maybe I'll find out when reading the remaining patches..

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom
  2021-01-28  6:02 ` [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom Darrick J. Wong
@ 2021-01-28  9:57   ` Christoph Hellwig
  2021-01-28 18:18     ` Darrick J. Wong
  2021-01-28 18:23   ` Brian Foster
  1 sibling, 1 reply; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:57 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:02:06PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> For file creation, create a new helper xfs_trans_alloc_icreate that
> allocates a transaction and reserves the appropriate amount of quota
> against that transction.  Replace all the open-coded idioms with a
> single call to this helper so that we can contain the retry loops in the
> next patchset.

For most callers this moves the call to xfs_trans_reserve_quota_icreate
out of the ilock criticial section.  Which seems fine and actually
mildly desirable.  But please document it.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c
  2021-01-28  6:02 ` [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c Darrick J. Wong
@ 2021-01-28  9:58   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28  9:58 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit
  2021-01-28  6:02 ` [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit Darrick J. Wong
@ 2021-01-28 10:00   ` Christoph Hellwig
  2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28 10:00 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david, bfoster

On Wed, Jan 27, 2021 at 10:02:18PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Clean up the calling conventions of xfs_trans_reserve_quota_chown a
> littel bit -- we can pass in a boolean force parameter since that's the

s/littel/little/

Otherwise looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 06/13] xfs: reserve data and rt quota at the same time
  2021-01-28  9:49   ` Christoph Hellwig
@ 2021-01-28 18:01     ` Darrick J. Wong
  0 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28 18:01 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs, david, bfoster

On Thu, Jan 28, 2021 at 09:49:54AM +0000, Christoph Hellwig wrote:
> On Wed, Jan 27, 2021 at 10:01:38PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > Modify xfs_trans_reserve_quota_nblks so that we can reserve data and
> > realtime blocks from the dquot at the same time.  This change has the
> > theoretical side effect that for allocations to realtime files we will
> > reserve from the dquot both the number of rtblocks being allocated and
> > the number of bmbt blocks that might be needed to add the mapping.
> > However, since the mount code disables quota if it finds a realtime
> > device, this should not result in any behavior changes.
> > 
> > This also replaces the flags argument with a force? boolean since we
> > don't need to distinguish between data and rt quota reservations any
> > more, and the only other flag being passed in was FORCE_RES.
> 
> It a removes the entirely unused nino flag, which caused quite some
> confusion to me when reading this patch, so please document that.

D'oh, sorry.  I think I accidentally removed a sentence from the second
paragraph somehow. :(

It /should/ read:

"Now that we've moved the inode creation code away from using the _nblks
function, we can repurpose the (now unused) ninos argument for realtime
blocks, so make that change.  This also replaces the flags argument...

> Otherwise this looks good:
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>

Thanks!

--D

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode
  2021-01-28  9:53   ` Christoph Hellwig
@ 2021-01-28 18:06     ` Darrick J. Wong
  0 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28 18:06 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs, david, bfoster

On Thu, Jan 28, 2021 at 09:53:45AM +0000, Christoph Hellwig wrote:
> On Wed, Jan 27, 2021 at 10:01:55PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > The two remaining callers of xfs_trans_reserve_quota_nblks are in the
> > reflink code.  These conversions aren't as uniform as the previous
> > conversions, so call that out in a separate patch.
> > 
> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> > ---
> >  fs/xfs/xfs_reflink.c |   58 +++++++++++++++++++++-----------------------------
> >  1 file changed, 24 insertions(+), 34 deletions(-)
> > 
> > 
> > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> > index 0778b5810c26..ded86cc4764c 100644
> > --- a/fs/xfs/xfs_reflink.c
> > +++ b/fs/xfs/xfs_reflink.c
> > @@ -376,16 +376,15 @@ xfs_reflink_allocate_cow(
> >  	resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
> >  
> >  	xfs_iunlock(ip, *lockmode);
> >  
> > +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
> > +			false, &tp);
> > +	if (error) {
> > +		/* This function must return with ILOCK_EXCL held. */
> > +		*lockmode = XFS_ILOCK_EXCL;
> > +		xfs_ilock(ip, *lockmode);
> >  		return error;
> > +	}
> 
> The only thing that the only caller of xfs_reflink_allocate_cow does
> on error is to immediately release the lock.  So I think we are better
> off changing the calling convention instead of relocking here.

Ok, will do.

--D

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 02/13] xfs: create convenience wrappers for incore quota block reservations
  2021-01-28  6:01 ` [PATCH 02/13] xfs: create convenience wrappers for incore quota block reservations Darrick J. Wong
@ 2021-01-28 18:08   ` Brian Foster
  0 siblings, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:08 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:15PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Create a couple of convenience wrappers for creating and deleting quota
> block reservations against future changes.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_bmap.c |   10 ++++------
>  fs/xfs/xfs_quota.h       |   19 +++++++++++++++++++
>  fs/xfs/xfs_reflink.c     |    5 ++---
>  3 files changed, 25 insertions(+), 9 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 0410627c6fcc..6edf1b5711c8 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -4097,8 +4097,7 @@ xfs_bmapi_reserve_delalloc(
>  	 * blocks.  This number gets adjusted later.  We return if we haven't
>  	 * allocated blocks already inside this loop.
>  	 */
> -	error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0,
> -						XFS_QMOPT_RES_REGBLKS);
> +	error = xfs_quota_reserve_blkres(ip, alen);
>  	if (error)
>  		return error;
>  
> @@ -4144,8 +4143,7 @@ xfs_bmapi_reserve_delalloc(
>  	xfs_mod_fdblocks(mp, alen, false);
>  out_unreserve_quota:
>  	if (XFS_IS_QUOTA_ON(mp))
> -		xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0,
> -						XFS_QMOPT_RES_REGBLKS);
> +		xfs_quota_unreserve_blkres(ip, alen);
>  	return error;
>  }
>  
> @@ -4937,8 +4935,8 @@ xfs_bmap_del_extent_delay(
>  	 * sb counters as we might have to borrow some blocks for the
>  	 * indirect block accounting.
>  	 */
> -	error = xfs_trans_unreserve_quota_nblks(NULL, ip, del->br_blockcount, 0,
> -			isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
> +	ASSERT(!isrt);
> +	error = xfs_quota_unreserve_blkres(ip, del->br_blockcount);
>  	if (error)
>  		return error;
>  	ip->i_delayed_blks -= del->br_blockcount;
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index 5a62398940d0..159d338bf161 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -108,6 +108,12 @@ extern void xfs_qm_mount_quotas(struct xfs_mount *);
>  extern void xfs_qm_unmount(struct xfs_mount *);
>  extern void xfs_qm_unmount_quotas(struct xfs_mount *);
>  
> +static inline int
> +xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
> +{
> +	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0,
> +			XFS_QMOPT_RES_REGBLKS);
> +}
>  #else
>  static inline int
>  xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
> @@ -136,6 +142,13 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
>  {
>  	return 0;
>  }
> +
> +static inline int
> +xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
> +{
> +	return 0;
> +}
> +
>  #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
>  #define xfs_qm_vop_rename_dqattach(it)					(0)
>  #define xfs_qm_vop_chown(tp, ip, old, new)				(NULL)
> @@ -157,6 +170,12 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
>  	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
>  				f | XFS_QMOPT_RES_REGBLKS)
>  
> +static inline int
> +xfs_quota_unreserve_blkres(struct xfs_inode *ip, int64_t dblocks)
> +{
> +	return xfs_quota_reserve_blkres(ip, -dblocks);
> +}
> +
>  extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
>  
>  #endif	/* __XFS_QUOTA_H__ */
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 183142fd0961..bea64ed5a57f 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -508,9 +508,8 @@ xfs_reflink_cancel_cow_blocks(
>  			xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
>  
>  			/* Remove the quota reservation */
> -			error = xfs_trans_unreserve_quota_nblks(NULL, ip,
> -					del.br_blockcount, 0,
> -					XFS_QMOPT_RES_REGBLKS);
> +			error = xfs_quota_unreserve_blkres(ip,
> +					del.br_blockcount);
>  			if (error)
>  				break;
>  		} else {
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely
  2021-01-28  6:01 ` [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely Darrick J. Wong
  2021-01-28  9:46   ` Christoph Hellwig
@ 2021-01-28 18:08   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:08 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:21PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> xfs_trans_cancel will release all the quota resources that were reserved
> on behalf of the transaction, so get rid of the explicit unreserve step.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
>  fs/xfs/xfs_bmap_util.c |    7 ++-----
>  fs/xfs/xfs_iomap.c     |    6 ++----
>  fs/xfs/xfs_quota.h     |    2 --
>  fs/xfs/xfs_reflink.c   |    5 +----
>  4 files changed, 5 insertions(+), 15 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 792809debaaa..f0a8f3377281 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
...
> @@ -856,9 +856,6 @@ xfs_alloc_file_space(
>  
>  	return error;
>  
> -error0:	/* unlock inode, unreserve quota blocks, cancel trans */
> -	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
> -
>  error1:	/* Just cancel transaction */

Maybe just use 'error' here now..? Otherwise LGTM:

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  	xfs_trans_cancel(tp);
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 514e6ae010e0..de0e371ba4dd 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -253,7 +253,7 @@ xfs_iomap_write_direct(
>  	error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
>  			XFS_IEXT_ADD_NOSPLIT_CNT);
>  	if (error)
> -		goto out_res_cancel;
> +		goto out_trans_cancel;
>  
>  	xfs_trans_ijoin(tp, ip, 0);
>  
> @@ -265,7 +265,7 @@ xfs_iomap_write_direct(
>  	error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flags, 0,
>  				imap, &nimaps);
>  	if (error)
> -		goto out_res_cancel;
> +		goto out_trans_cancel;
>  
>  	/*
>  	 * Complete the transaction
> @@ -289,8 +289,6 @@ xfs_iomap_write_direct(
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  	return error;
>  
> -out_res_cancel:
> -	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
>  out_trans_cancel:
>  	xfs_trans_cancel(tp);
>  	goto out_unlock;
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index 159d338bf161..a395dabee033 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -164,8 +164,6 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
>  #define xfs_qm_unmount_quotas(mp)
>  #endif /* CONFIG_XFS_QUOTA */
>  
> -#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \
> -	xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags)
>  #define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
>  	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
>  				f | XFS_QMOPT_RES_REGBLKS)
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index bea64ed5a57f..15435229bc1f 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -411,7 +411,7 @@ xfs_reflink_allocate_cow(
>  			XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC, 0, cmap,
>  			&nimaps);
>  	if (error)
> -		goto out_unreserve;
> +		goto out_trans_cancel;
>  
>  	xfs_inode_set_cowblocks_tag(ip);
>  	error = xfs_trans_commit(tp);
> @@ -436,9 +436,6 @@ xfs_reflink_allocate_cow(
>  	trace_xfs_reflink_convert_cow(ip, cmap);
>  	return xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb);
>  
> -out_unreserve:
> -	xfs_trans_unreserve_quota_nblks(tp, ip, (long)resblks, 0,
> -			XFS_QMOPT_RES_REGBLKS);
>  out_trans_cancel:
>  	xfs_trans_cancel(tp);
>  	return error;
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 04/13] xfs: clean up icreate quota reservation calls
  2021-01-28  6:01 ` [PATCH 04/13] xfs: clean up icreate quota reservation calls Darrick J. Wong
@ 2021-01-28 18:09   ` Brian Foster
  0 siblings, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:09 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:27PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Create a proper helper so that inode creation calls can reserve quota
> with a dedicated function.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_inode.c       |    6 ++----
>  fs/xfs/xfs_quota.h       |   14 ++++++++++----
>  fs/xfs/xfs_symlink.c     |    3 +--
>  fs/xfs/xfs_trans_dquot.c |   18 ++++++++++++++++++
>  4 files changed, 31 insertions(+), 10 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index e2a1db4cee43..4bbd2fb628f7 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1037,8 +1037,7 @@ xfs_create(
>  	/*
>  	 * Reserve disk quota and the inode.
>  	 */
> -	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
> -						pdqp, resblks, 1, 0);
> +	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
>  	if (error)
>  		goto out_trans_cancel;
>  
> @@ -1169,8 +1168,7 @@ xfs_create_tmpfile(
>  	if (error)
>  		goto out_release_inode;
>  
> -	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
> -						pdqp, resblks, 1, 0);
> +	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
>  	if (error)
>  		goto out_trans_cancel;
>  
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index a395dabee033..d1e3f94140b4 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -86,6 +86,9 @@ extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
>  extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
>  		struct xfs_mount *, struct xfs_dquot *,
>  		struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint);
> +int xfs_trans_reserve_quota_icreate(struct xfs_trans *tp,
> +		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> +		struct xfs_dquot *pdqp, int64_t dblocks);
>  
>  extern int xfs_qm_vop_dqalloc(struct xfs_inode *, kuid_t, kgid_t,
>  		prid_t, uint, struct xfs_dquot **, struct xfs_dquot **,
> @@ -149,6 +152,13 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
>  	return 0;
>  }
>  
> +static inline int
> +xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
> +		struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, int64_t dblocks)
> +{
> +	return 0;
> +}
> +
>  #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
>  #define xfs_qm_vop_rename_dqattach(it)					(0)
>  #define xfs_qm_vop_chown(tp, ip, old, new)				(NULL)
> @@ -164,10 +174,6 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
>  #define xfs_qm_unmount_quotas(mp)
>  #endif /* CONFIG_XFS_QUOTA */
>  
> -#define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
> -	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
> -				f | XFS_QMOPT_RES_REGBLKS)
> -
>  static inline int
>  xfs_quota_unreserve_blkres(struct xfs_inode *ip, int64_t dblocks)
>  {
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 7f96649e918a..d5dee8f409b2 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -215,8 +215,7 @@ xfs_symlink(
>  	/*
>  	 * Reserve disk quota : blocks and inode.
>  	 */
> -	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
> -						pdqp, resblks, 1, 0);
> +	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
>  	if (error)
>  		goto out_trans_cancel;
>  
> diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> index 28b8ac701919..22aa875b84f7 100644
> --- a/fs/xfs/xfs_trans_dquot.c
> +++ b/fs/xfs/xfs_trans_dquot.c
> @@ -804,6 +804,24 @@ xfs_trans_reserve_quota_nblks(
>  						nblks, ninos, flags);
>  }
>  
> +/* Change the quota reservations for an inode creation activity. */
> +int
> +xfs_trans_reserve_quota_icreate(
> +	struct xfs_trans	*tp,
> +	struct xfs_dquot	*udqp,
> +	struct xfs_dquot	*gdqp,
> +	struct xfs_dquot	*pdqp,
> +	int64_t			dblocks)
> +{
> +	struct xfs_mount	*mp = tp->t_mountp;
> +
> +	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
> +		return 0;
> +
> +	return xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp,
> +			dblocks, 1, XFS_QMOPT_RES_REGBLKS);
> +}
> +
>  /*
>   * This routine is called to allocate a quotaoff log item.
>   */
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 05/13] xfs: fix up build warnings when quotas are disabled
  2021-01-28  6:01 ` [PATCH 05/13] xfs: fix up build warnings when quotas are disabled Darrick J. Wong
@ 2021-01-28 18:09   ` Brian Foster
  2021-01-28 18:22     ` Darrick J. Wong
  0 siblings, 1 reply; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:09 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Christoph Hellwig, linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:32PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Fix some build warnings on gcc 10.2 when quotas are disabled.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> ---
>  fs/xfs/xfs_quota.h |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index d1e3f94140b4..72f4cfc49048 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
...
> @@ -166,8 +166,8 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
>  #define xfs_qm_dqattach(ip)						(0)
>  #define xfs_qm_dqattach_locked(ip, fl)					(0)
>  #define xfs_qm_dqdetach(ip)
> -#define xfs_qm_dqrele(d)
> -#define xfs_qm_statvfs(ip, s)
> +#define xfs_qm_dqrele(d)			do { (d) = (d); } while(0)

What's the need for the assignment, out of curiosity?

Regardless, LGTM:

Reviewed-by: Brian Foster <bfoster@redhat.com>

> +#define xfs_qm_statvfs(ip, s)			do { } while(0)
>  #define xfs_qm_newmount(mp, a, b)					(0)
>  #define xfs_qm_mount_quotas(mp)
>  #define xfs_qm_unmount(mp)
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 06/13] xfs: reserve data and rt quota at the same time
  2021-01-28  6:01 ` [PATCH 06/13] xfs: reserve data and rt quota at the same time Darrick J. Wong
  2021-01-28  9:49   ` Christoph Hellwig
@ 2021-01-28 18:10   ` Brian Foster
  2021-01-28 18:52     ` Darrick J. Wong
  1 sibling, 1 reply; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:10 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:38PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Modify xfs_trans_reserve_quota_nblks so that we can reserve data and
> realtime blocks from the dquot at the same time.  This change has the
> theoretical side effect that for allocations to realtime files we will
> reserve from the dquot both the number of rtblocks being allocated and
> the number of bmbt blocks that might be needed to add the mapping.
> However, since the mount code disables quota if it finds a realtime
> device, this should not result in any behavior changes.
> 
> This also replaces the flags argument with a force? boolean since we

s/?//

> don't need to distinguish between data and rt quota reservations any
> more, and the only other flag being passed in was FORCE_RES.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
>  fs/xfs/libxfs/xfs_attr.c |    6 +-----
>  fs/xfs/libxfs/xfs_bmap.c |    4 +---
>  fs/xfs/xfs_bmap_util.c   |   20 +++++++++-----------
>  fs/xfs/xfs_iomap.c       |   26 +++++++++++++-------------
>  fs/xfs/xfs_quota.h       |   10 +++++-----
>  fs/xfs/xfs_reflink.c     |    6 ++----
>  fs/xfs/xfs_trans_dquot.c |   42 ++++++++++++++++++++++++++++--------------
>  7 files changed, 59 insertions(+), 55 deletions(-)
> 
> 
...
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index f0a8f3377281..d54d9f02d3dd 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
...
> @@ -792,18 +792,17 @@ xfs_alloc_file_space(
>  		if (unlikely(rt)) {
>  			resrtextents = qblocks = resblks;

This looks like the last usage of qblocks in the function.

>  			resrtextents /= mp->m_sb.sb_rextsize;
> -			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
> -			quota_flag = XFS_QMOPT_RES_RTBLKS;
> +			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
> +			rblocks = resblks;
>  		} else {
> -			resrtextents = 0;
> -			resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
> -			quota_flag = XFS_QMOPT_RES_REGBLKS;
> +			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
> +			rblocks = 0;
>  		}
>  
>  		/*
>  		 * Allocate and setup the transaction.
>  		 */
> -		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks,
> +		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks,
>  				resrtextents, 0, &tp);
>  
>  		/*
...
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index de0e371ba4dd..ef29d44c656a 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
...
> @@ -235,18 +235,19 @@ xfs_iomap_write_direct(
>  	if (IS_DAX(VFS_I(ip))) {
>  		bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
>  		if (imap->br_state == XFS_EXT_UNWRITTEN) {
> +			force = true;
>  			tflags |= XFS_TRANS_RESERVE;
> -			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
> +			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;

I'm a little confused what this hunk of logic is for in the first place,
but doesn't this also adjust down the quota where it previously only
affected the transaction reservation? Is that intentional?

Brian

>  		}
>  	}
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents,
> +	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks, resrtextents,
>  			tflags, &tp);
>  	if (error)
>  		return error;
>  
>  	xfs_ilock(ip, XFS_ILOCK_EXCL);
>  
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
> +	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
>  	if (error)
>  		goto out_trans_cancel;
>  
> @@ -559,8 +560,7 @@ xfs_iomap_write_unwritten(
>  		xfs_ilock(ip, XFS_ILOCK_EXCL);
>  		xfs_trans_ijoin(tp, ip, 0);
>  
> -		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
> -				XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES);
> +		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, true);
>  		if (error)
>  			goto error_on_bmapi_transaction;
>  
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index 72f4cfc49048..efd04f84d9b4 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -81,8 +81,8 @@ extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, struct xfs_inode *,
>  		uint, int64_t);
>  extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *);
>  extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *);
> -extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
> -		struct xfs_inode *, int64_t, long, uint);
> +int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip,
> +		int64_t dblocks, int64_t rblocks, bool force);
>  extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
>  		struct xfs_mount *, struct xfs_dquot *,
>  		struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint);
> @@ -114,8 +114,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);
>  static inline int
>  xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
>  {
> -	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0,
> -			XFS_QMOPT_RES_REGBLKS);
> +	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0, false);
>  }
>  #else
>  static inline int
> @@ -134,7 +133,8 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
>  #define xfs_trans_apply_dquot_deltas(tp)
>  #define xfs_trans_unreserve_and_mod_dquots(tp)
>  static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
> -		struct xfs_inode *ip, int64_t nblks, long ninos, uint flags)
> +		struct xfs_inode *ip, int64_t dblocks, int64_t rblocks,
> +		bool force)
>  {
>  	return 0;
>  }
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 15435229bc1f..0778b5810c26 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -398,8 +398,7 @@ xfs_reflink_allocate_cow(
>  		goto convert;
>  	}
>  
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
> -			XFS_QMOPT_RES_REGBLKS);
> +	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
>  	if (error)
>  		goto out_trans_cancel;
>  
> @@ -1090,8 +1089,7 @@ xfs_reflink_remap_extent(
>  	if (!smap_real && dmap_written)
>  		qres += dmap->br_blockcount;
>  	if (qres > 0) {
> -		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0,
> -				XFS_QMOPT_RES_REGBLKS);
> +		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, false);
>  		if (error)
>  			goto out_cancel;
>  	}
> diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> index 22aa875b84f7..a1a72b7900c5 100644
> --- a/fs/xfs/xfs_trans_dquot.c
> +++ b/fs/xfs/xfs_trans_dquot.c
> @@ -780,28 +780,42 @@ int
>  xfs_trans_reserve_quota_nblks(
>  	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
> -	int64_t			nblks,
> -	long			ninos,
> -	uint			flags)
> +	int64_t			dblocks,
> +	int64_t			rblocks,
> +	bool			force)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
> +	unsigned int		qflags = 0;
> +	int			error;
>  
>  	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
>  		return 0;
>  
>  	ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
> -
>  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
> -	ASSERT((flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_RTBLKS ||
> -	       (flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_BLKS);
> -
> -	/*
> -	 * Reserve nblks against these dquots, with trans as the mediator.
> -	 */
> -	return xfs_trans_reserve_quota_bydquots(tp, mp,
> -						ip->i_udquot, ip->i_gdquot,
> -						ip->i_pdquot,
> -						nblks, ninos, flags);
> +
> +	if (force)
> +		qflags |= XFS_QMOPT_FORCE_RES;
> +
> +	/* Reserve data device quota against the inode's dquots. */
> +	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> +			ip->i_gdquot, ip->i_pdquot, dblocks, 0,
> +			XFS_QMOPT_RES_REGBLKS | qflags);
> +	if (error)
> +		return error;
> +
> +	/* Do the same but for realtime blocks. */
> +	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> +			ip->i_gdquot, ip->i_pdquot, rblocks, 0,
> +			XFS_QMOPT_RES_RTBLKS | qflags);
> +	if (error) {
> +		xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> +				ip->i_gdquot, ip->i_pdquot, -dblocks, 0,
> +				XFS_QMOPT_RES_REGBLKS);
> +		return error;
> +	}
> +
> +	return 0;
>  }
>  
>  /* Change the quota reservations for an inode creation activity. */
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom
  2021-01-28  9:57   ` Christoph Hellwig
@ 2021-01-28 18:18     ` Darrick J. Wong
  0 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28 18:18 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-xfs, david, bfoster

On Thu, Jan 28, 2021 at 09:57:37AM +0000, Christoph Hellwig wrote:
> On Wed, Jan 27, 2021 at 10:02:06PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > For file creation, create a new helper xfs_trans_alloc_icreate that
> > allocates a transaction and reserves the appropriate amount of quota
> > against that transction.  Replace all the open-coded idioms with a
> > single call to this helper so that we can contain the retry loops in the
> > next patchset.
> 
> For most callers this moves the call to xfs_trans_reserve_quota_icreate
> out of the ilock criticial section.  Which seems fine and actually
> mildly desirable.  But please document it.

Ok, done.  Add this as a second paragraph:

"This changes the locking behavior for non-tempfile creation slightly,
in that we now make the quota reservation without holding the directory
ILOCK.  While the dquots chosen for inode creation are based on the
directory state at a given point in time, the directory ILOCK was
released as soon as the dquot references are picked up.  Hence it was
never necessary to hold the directory ILOCK for the quota reservation."

--D

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 05/13] xfs: fix up build warnings when quotas are disabled
  2021-01-28 18:09   ` Brian Foster
@ 2021-01-28 18:22     ` Darrick J. Wong
  2021-01-28 18:23       ` Christoph Hellwig
  0 siblings, 1 reply; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28 18:22 UTC (permalink / raw)
  To: Brian Foster; +Cc: Christoph Hellwig, linux-xfs, hch, david

On Thu, Jan 28, 2021 at 01:09:22PM -0500, Brian Foster wrote:
> On Wed, Jan 27, 2021 at 10:01:32PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > Fix some build warnings on gcc 10.2 when quotas are disabled.
> > 
> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > ---
> >  fs/xfs/xfs_quota.h |    6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > 
> > diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> > index d1e3f94140b4..72f4cfc49048 100644
> > --- a/fs/xfs/xfs_quota.h
> > +++ b/fs/xfs/xfs_quota.h
> ...
> > @@ -166,8 +166,8 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
> >  #define xfs_qm_dqattach(ip)						(0)
> >  #define xfs_qm_dqattach_locked(ip, fl)					(0)
> >  #define xfs_qm_dqdetach(ip)
> > -#define xfs_qm_dqrele(d)
> > -#define xfs_qm_statvfs(ip, s)
> > +#define xfs_qm_dqrele(d)			do { (d) = (d); } while(0)
> 
> What's the need for the assignment, out of curiosity?

It shuts up a gcc warning about how the dquot pointer is set but never
used.  One hopes the same gcc is smart enough not to generate any code
for this.

--D

> Regardless, LGTM:
> 
> Reviewed-by: Brian Foster <bfoster@redhat.com>
> 
> > +#define xfs_qm_statvfs(ip, s)			do { } while(0)
> >  #define xfs_qm_newmount(mp, a, b)					(0)
> >  #define xfs_qm_mount_quotas(mp)
> >  #define xfs_qm_unmount(mp)
> > 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom
  2021-01-28  6:01 ` [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom Darrick J. Wong
  2021-01-28  9:50   ` Christoph Hellwig
@ 2021-01-28 18:22   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:22 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:44PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Create a new helper xfs_trans_alloc_inode that allocates a transaction,
> locks and joins an inode to it, and then reserves the appropriate amount
> of quota against that transction.  Then replace all the open-coded
> idioms with a single call to this helper.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_attr.c |   11 +----------
>  fs/xfs/libxfs/xfs_bmap.c |   10 ++--------
>  fs/xfs/xfs_bmap_util.c   |   14 +++----------
>  fs/xfs/xfs_iomap.c       |   11 ++---------
>  fs/xfs/xfs_trans.c       |   48 ++++++++++++++++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_trans.h       |    3 +++
>  6 files changed, 59 insertions(+), 38 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index e05dc0bc4a8f..cb95bc77fe59 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -458,14 +458,10 @@ xfs_attr_set(
>  	 * Root fork attributes can use reserved data blocks for this
>  	 * operation if necessary
>  	 */
> -	error = xfs_trans_alloc(mp, &tres, total, 0,
> -			rsvd ? XFS_TRANS_RESERVE : 0, &args->trans);
> +	error = xfs_trans_alloc_inode(dp, &tres, total, rsvd, &args->trans);
>  	if (error)
>  		return error;
>  
> -	xfs_ilock(dp, XFS_ILOCK_EXCL);
> -	xfs_trans_ijoin(args->trans, dp, 0);
> -
>  	if (args->value || xfs_inode_hasattr(dp)) {
>  		error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
>  				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
> @@ -474,11 +470,6 @@ xfs_attr_set(
>  	}
>  
>  	if (args->value) {
> -		error = xfs_trans_reserve_quota_nblks(args->trans, dp,
> -				args->total, 0, rsvd);
> -		if (error)
> -			goto out_trans_cancel;
> -
>  		error = xfs_has_attr(args);
>  		if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
>  			goto out_trans_cancel;
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 043bb8c634b0..f78fa694f3c2 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1079,19 +1079,13 @@ xfs_bmap_add_attrfork(
>  
>  	blks = XFS_ADDAFORK_SPACE_RES(mp);
>  
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0,
> -			rsvd ? XFS_TRANS_RESERVE : 0, &tp);
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks,
> +			rsvd, &tp);
>  	if (error)
>  		return error;
> -
> -	xfs_ilock(ip, XFS_ILOCK_EXCL);
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd);
> -	if (error)
> -		goto trans_cancel;
>  	if (XFS_IFORK_Q(ip))
>  		goto trans_cancel;
>  
> -	xfs_trans_ijoin(tp, ip, 0);
>  	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  	error = xfs_bmap_set_attrforkoff(ip, size, &version);
>  	if (error)
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index d54d9f02d3dd..94ffdeb2dd73 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -873,18 +873,10 @@ xfs_unmap_extent(
>  	uint			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
>  	int			error;
>  
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> -	if (error) {
> -		ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp));
> -		return error;
> -	}
> -
> -	xfs_ilock(ip, XFS_ILOCK_EXCL);
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
> +			false, &tp);
>  	if (error)
> -		goto out_trans_cancel;
> -
> -	xfs_trans_ijoin(tp, ip, 0);
> +		return error;
>  
>  	error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
>  			XFS_IEXT_PUNCH_HOLE_CNT);
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index ef29d44c656a..05de1be20426 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -552,18 +552,11 @@ xfs_iomap_write_unwritten(
>  		 * here as we might be asked to write out the same inode that we
>  		 * complete here and might deadlock on the iolock.
>  		 */
> -		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
> -				XFS_TRANS_RESERVE, &tp);
> +		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
> +				true, &tp);
>  		if (error)
>  			return error;
>  
> -		xfs_ilock(ip, XFS_ILOCK_EXCL);
> -		xfs_trans_ijoin(tp, ip, 0);
> -
> -		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, true);
> -		if (error)
> -			goto error_on_bmapi_transaction;
> -
>  		error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
>  				XFS_IEXT_WRITE_UNWRITTEN_CNT);
>  		if (error)
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index e72730f85af1..156b9ed8534f 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -20,6 +20,7 @@
>  #include "xfs_trace.h"
>  #include "xfs_error.h"
>  #include "xfs_defer.h"
> +#include "xfs_inode.h"
>  
>  kmem_zone_t	*xfs_trans_zone;
>  
> @@ -1024,3 +1025,50 @@ xfs_trans_roll(
>  	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
>  	return xfs_trans_reserve(*tpp, &tres, 0, 0);
>  }
> +
> +/*
> + * Allocate an transaction, lock and join the inode to it, and reserve quota.
> + *
> + * The caller must ensure that the on-disk dquots attached to this inode have
> + * already been allocated and initialized.  The caller is responsible for
> + * releasing ILOCK_EXCL if a new transaction is returned.
> + */
> +int
> +xfs_trans_alloc_inode(
> +	struct xfs_inode	*ip,
> +	struct xfs_trans_res	*resv,
> +	unsigned int		dblocks,
> +	bool			force,
> +	struct xfs_trans	**tpp)
> +{
> +	struct xfs_trans	*tp;
> +	struct xfs_mount	*mp = ip->i_mount;
> +	int			error;
> +
> +	error = xfs_trans_alloc(mp, resv, dblocks, 0,
> +			force ? XFS_TRANS_RESERVE : 0, &tp);
> +	if (error)
> +		return error;
> +
> +	xfs_ilock(ip, XFS_ILOCK_EXCL);
> +	xfs_trans_ijoin(tp, ip, 0);
> +
> +	error = xfs_qm_dqattach_locked(ip, false);
> +	if (error) {
> +		/* Caller should have allocated the dquots! */
> +		ASSERT(error != -ENOENT);
> +		goto out_cancel;
> +	}
> +
> +	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, 0, force);
> +	if (error)
> +		goto out_cancel;
> +
> +	*tpp = tp;
> +	return 0;
> +
> +out_cancel:
> +	xfs_trans_cancel(tp);
> +	xfs_iunlock(ip, XFS_ILOCK_EXCL);
> +	return error;
> +}
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 084658946cc8..aa50be244432 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -268,4 +268,7 @@ xfs_trans_item_relog(
>  	return lip->li_ops->iop_relog(lip, tp);
>  }
>  
> +int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
> +		unsigned int dblocks, bool force, struct xfs_trans **tpp);
> +
>  #endif	/* __XFS_TRANS_H__ */
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode
  2021-01-28  6:01 ` [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode Darrick J. Wong
  2021-01-28  9:51   ` Christoph Hellwig
@ 2021-01-28 18:22   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:22 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:49PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Make it so that we can reserve rt blocks with the xfs_trans_alloc_inode
> wrapper function, then convert a few more callsites.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_attr.c |    2 +-
>  fs/xfs/libxfs/xfs_bmap.c |    2 +-
>  fs/xfs/xfs_bmap_util.c   |   29 +++++------------------------
>  fs/xfs/xfs_iomap.c       |   22 +++++-----------------
>  fs/xfs/xfs_trans.c       |    6 ++++--
>  fs/xfs/xfs_trans.h       |    3 ++-
>  6 files changed, 18 insertions(+), 46 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index cb95bc77fe59..472b3039eabb 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -458,7 +458,7 @@ xfs_attr_set(
>  	 * Root fork attributes can use reserved data blocks for this
>  	 * operation if necessary
>  	 */
> -	error = xfs_trans_alloc_inode(dp, &tres, total, rsvd, &args->trans);
> +	error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
>  	if (error)
>  		return error;
>  
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index f78fa694f3c2..8131bc5f4bad 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1079,7 +1079,7 @@ xfs_bmap_add_attrfork(
>  
>  	blks = XFS_ADDAFORK_SPACE_RES(mp);
>  
> -	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks,
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks, 0,
>  			rsvd, &tp);
>  	if (error)
>  		return error;
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 94ffdeb2dd73..c3b7dff21887 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -730,7 +730,6 @@ xfs_alloc_file_space(
>  	int			rt;
>  	xfs_trans_t		*tp;
>  	xfs_bmbt_irec_t		imaps[1], *imapp;
> -	uint			qblocks, resblks, resrtextents;
>  	int			error;
>  
>  	trace_xfs_alloc_file_space(ip);
> @@ -760,7 +759,7 @@ xfs_alloc_file_space(
>  	 */
>  	while (allocatesize_fsb && !error) {
>  		xfs_fileoff_t	s, e;
> -		unsigned int	dblocks, rblocks;
> +		unsigned int	dblocks, rblocks, resblks;
>  
>  		/*
>  		 * Determine space reservations for data/realtime.
> @@ -790,8 +789,6 @@ xfs_alloc_file_space(
>  		 */
>  		resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
>  		if (unlikely(rt)) {
> -			resrtextents = qblocks = resblks;
> -			resrtextents /= mp->m_sb.sb_rextsize;
>  			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
>  			rblocks = resblks;
>  		} else {
> @@ -802,32 +799,16 @@ xfs_alloc_file_space(
>  		/*
>  		 * Allocate and setup the transaction.
>  		 */
> -		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks,
> -				resrtextents, 0, &tp);
> -
> -		/*
> -		 * Check for running out of space
> -		 */
> -		if (error) {
> -			/*
> -			 * Free the transaction structure.
> -			 */
> -			ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp));
> -			break;
> -		}
> -		xfs_ilock(ip, XFS_ILOCK_EXCL);
> -		error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks,
> -				false);
> +		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
> +				dblocks, rblocks, false, &tp);
>  		if (error)
> -			goto error1;
> +			break;
>  
>  		error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
>  				XFS_IEXT_ADD_NOSPLIT_CNT);
>  		if (error)
>  			goto error1;
>  
> -		xfs_trans_ijoin(tp, ip, 0);
> -
>  		error = xfs_bmapi_write(tp, ip, startoffset_fsb,
>  					allocatesize_fsb, alloc_type, 0, imapp,
>  					&nimaps);
> @@ -873,7 +854,7 @@ xfs_unmap_extent(
>  	uint			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
>  	int			error;
>  
> -	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
>  			false, &tp);
>  	if (error)
>  		return error;
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 05de1be20426..f34a76529602 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -195,19 +195,15 @@ xfs_iomap_write_direct(
>  	xfs_filblks_t		resaligned;
>  	int			nimaps;
>  	unsigned int		dblocks, rblocks;
> -	unsigned int		resrtextents = 0;
> +	bool			force = false;
>  	int			error;
>  	int			bmapi_flags = XFS_BMAPI_PREALLOC;
> -	int			tflags = 0;
> -	bool			force = false;
>  
>  	ASSERT(count_fsb > 0);
>  
>  	resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb,
>  					   xfs_get_extsz_hint(ip));
>  	if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
> -		resrtextents = resaligned;
> -		resrtextents /= mp->m_sb.sb_rextsize;
>  		dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
>  		rblocks = resaligned;
>  	} else {
> @@ -236,28 +232,20 @@ xfs_iomap_write_direct(
>  		bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
>  		if (imap->br_state == XFS_EXT_UNWRITTEN) {
>  			force = true;
> -			tflags |= XFS_TRANS_RESERVE;
>  			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
>  		}
>  	}
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks, resrtextents,
> -			tflags, &tp);
> +
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, dblocks,
> +			rblocks, force, &tp);
>  	if (error)
>  		return error;
>  
> -	xfs_ilock(ip, XFS_ILOCK_EXCL);
> -
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
> -	if (error)
> -		goto out_trans_cancel;
> -
>  	error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
>  			XFS_IEXT_ADD_NOSPLIT_CNT);
>  	if (error)
>  		goto out_trans_cancel;
>  
> -	xfs_trans_ijoin(tp, ip, 0);
> -
>  	/*
>  	 * From this point onwards we overwrite the imap pointer that the
>  	 * caller gave to us.
> @@ -553,7 +541,7 @@ xfs_iomap_write_unwritten(
>  		 * complete here and might deadlock on the iolock.
>  		 */
>  		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks,
> -				true, &tp);
> +				0, true, &tp);
>  		if (error)
>  			return error;
>  
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 156b9ed8534f..151f274eee43 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -1038,6 +1038,7 @@ xfs_trans_alloc_inode(
>  	struct xfs_inode	*ip,
>  	struct xfs_trans_res	*resv,
>  	unsigned int		dblocks,
> +	unsigned int		rblocks,
>  	bool			force,
>  	struct xfs_trans	**tpp)
>  {
> @@ -1045,7 +1046,8 @@ xfs_trans_alloc_inode(
>  	struct xfs_mount	*mp = ip->i_mount;
>  	int			error;
>  
> -	error = xfs_trans_alloc(mp, resv, dblocks, 0,
> +	error = xfs_trans_alloc(mp, resv, dblocks,
> +			rblocks / mp->m_sb.sb_rextsize,
>  			force ? XFS_TRANS_RESERVE : 0, &tp);
>  	if (error)
>  		return error;
> @@ -1060,7 +1062,7 @@ xfs_trans_alloc_inode(
>  		goto out_cancel;
>  	}
>  
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, 0, force);
> +	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
>  	if (error)
>  		goto out_cancel;
>  
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index aa50be244432..52bbd7e6a552 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -269,6 +269,7 @@ xfs_trans_item_relog(
>  }
>  
>  int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
> -		unsigned int dblocks, bool force, struct xfs_trans **tpp);
> +		unsigned int dblocks, unsigned int rblocks, bool force,
> +		struct xfs_trans **tpp);
>  
>  #endif	/* __XFS_TRANS_H__ */
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode
  2021-01-28  6:01 ` [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode Darrick J. Wong
  2021-01-28  9:53   ` Christoph Hellwig
@ 2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:01:55PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> The two remaining callers of xfs_trans_reserve_quota_nblks are in the
> reflink code.  These conversions aren't as uniform as the previous
> conversions, so call that out in a separate patch.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---

Modulo Christoph's feedback on the locking:

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_reflink.c |   58 +++++++++++++++++++++-----------------------------
>  1 file changed, 24 insertions(+), 34 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 0778b5810c26..ded86cc4764c 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -376,16 +376,15 @@ xfs_reflink_allocate_cow(
>  	resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
>  
>  	xfs_iunlock(ip, *lockmode);
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> -	*lockmode = XFS_ILOCK_EXCL;
> -	xfs_ilock(ip, *lockmode);
>  
> -	if (error)
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
> +			false, &tp);
> +	if (error) {
> +		/* This function must return with ILOCK_EXCL held. */
> +		*lockmode = XFS_ILOCK_EXCL;
> +		xfs_ilock(ip, *lockmode);
>  		return error;
> -
> -	error = xfs_qm_dqattach_locked(ip, false);
> -	if (error)
> -		goto out_trans_cancel;
> +	}
>  
>  	/*
>  	 * Check for an overlapping extent again now that we dropped the ilock.
> @@ -398,12 +397,6 @@ xfs_reflink_allocate_cow(
>  		goto convert;
>  	}
>  
> -	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
> -	if (error)
> -		goto out_trans_cancel;
> -
> -	xfs_trans_ijoin(tp, ip, 0);
> -
>  	/* Allocate the entire reservation as unwritten blocks. */
>  	nimaps = 1;
>  	error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount,
> @@ -997,7 +990,7 @@ xfs_reflink_remap_extent(
>  	struct xfs_mount	*mp = ip->i_mount;
>  	struct xfs_trans	*tp;
>  	xfs_off_t		newlen;
> -	int64_t			qres, qdelta;
> +	int64_t			qdelta = 0;
>  	unsigned int		resblks;
>  	bool			smap_real;
>  	bool			dmap_written = xfs_bmap_is_written_extent(dmap);
> @@ -1005,15 +998,22 @@ xfs_reflink_remap_extent(
>  	int			nimaps;
>  	int			error;
>  
> -	/* Start a rolling transaction to switch the mappings */
> +	/*
> +	 * Start a rolling transaction to switch the mappings.
> +	 *
> +	 * Adding a written extent to the extent map can cause a bmbt split,
> +	 * and removing a mapped extent from the extent can cause a bmbt split.
> +	 * The two operations cannot both cause a split since they operate on
> +	 * the same index in the bmap btree, so we only need a reservation for
> +	 * one bmbt split if either thing is happening.  However, we haven't
> +	 * locked the inode yet, so we reserve assuming this is the case.
> +	 */
>  	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
> +			false, &tp);
>  	if (error)
>  		goto out;
>  
> -	xfs_ilock(ip, XFS_ILOCK_EXCL);
> -	xfs_trans_ijoin(tp, ip, 0);
> -
>  	/*
>  	 * Read what's currently mapped in the destination file into smap.
>  	 * If smap isn't a hole, we will have to remove it before we can add
> @@ -1061,15 +1061,9 @@ xfs_reflink_remap_extent(
>  	}
>  
>  	/*
> -	 * Compute quota reservation if we think the quota block counter for
> +	 * Increase quota reservation if we think the quota block counter for
>  	 * this file could increase.
>  	 *
> -	 * Adding a written extent to the extent map can cause a bmbt split,
> -	 * and removing a mapped extent from the extent can cause a bmbt split.
> -	 * The two operations cannot both cause a split since they operate on
> -	 * the same index in the bmap btree, so we only need a reservation for
> -	 * one bmbt split if either thing is happening.
> -	 *
>  	 * If we are mapping a written extent into the file, we need to have
>  	 * enough quota block count reservation to handle the blocks in that
>  	 * extent.  We log only the delta to the quota block counts, so if the
> @@ -1083,13 +1077,9 @@ xfs_reflink_remap_extent(
>  	 * before we started.  That should have removed all the delalloc
>  	 * reservations, but we code defensively.
>  	 */
> -	qres = qdelta = 0;
> -	if (smap_real || dmap_written)
> -		qres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
> -	if (!smap_real && dmap_written)
> -		qres += dmap->br_blockcount;
> -	if (qres > 0) {
> -		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, false);
> +	if (!smap_real && dmap_written) {
> +		error = xfs_trans_reserve_quota_nblks(tp, ip,
> +				dmap->br_blockcount, 0, false);
>  		if (error)
>  			goto out_cancel;
>  	}
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent
  2021-01-28  6:02 ` [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent Darrick J. Wong
  2021-01-28  9:55   ` Christoph Hellwig
@ 2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:02:01PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Now that we've converted xfs_reflink_remap_extent to use the new
> xfs_trans_alloc_inode API, we can focus on its slightly unusual behavior
> with regard to quota reservations.
> 
> Since it's valid to remap written blocks into a hole, we must be able to
> increase the quota count by the number of blocks in the mapping.
> However, the incore space reservation process requires us to supply an
> asymptotic guess before we can gain exclusive access to resources.  We'd
> like to reserve all the quota we need up front, but we also don't want
> to fail a written -> allocated remap operation unnecessarily.
> 
> The solution is to make the remap_extents function call the transaction
> allocation function twice.  The first time we ask to reserve enough
> space and quota to handle the absolute worst case situation, but if that
> fails, we can fall back to the old strategy: ask for the bare minimum
> space reservation upfront and increase the quota reservation later if we
> need to.
> 
> This isn't a problem now, but in the next patchset we change the
> transaction and quota code to try to reclaim space if we cannot reserve
> free space or quota.  Restructuring the remap_extent function in this
> manner means that if the fallback increase fails, we can pass that back
> to the caller knowing that the transaction allocation already tried
> freeing space.
> 

This looks pretty good to me, but I'd probably move this patch closer to
the patch that depends on it..

Brian

> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
>  fs/xfs/xfs_reflink.c |   23 ++++++++++++++++++++---
>  1 file changed, 20 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index ded86cc4764c..c6296fd1512f 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -992,6 +992,7 @@ xfs_reflink_remap_extent(
>  	xfs_off_t		newlen;
>  	int64_t			qdelta = 0;
>  	unsigned int		resblks;
> +	bool			quota_reserved = true;
>  	bool			smap_real;
>  	bool			dmap_written = xfs_bmap_is_written_extent(dmap);
>  	int			iext_delta = 0;
> @@ -1007,10 +1008,26 @@ xfs_reflink_remap_extent(
>  	 * the same index in the bmap btree, so we only need a reservation for
>  	 * one bmbt split if either thing is happening.  However, we haven't
>  	 * locked the inode yet, so we reserve assuming this is the case.
> +	 *
> +	 * The first allocation call tries to reserve enough space to handle
> +	 * mapping dmap into a sparse part of the file plus the bmbt split.  We
> +	 * haven't locked the inode or read the existing mapping yet, so we do
> +	 * not know for sure that we need the space.  This should succeed most
> +	 * of the time.
> +	 *
> +	 * If the first attempt fails, try again but reserving only enough
> +	 * space to handle a bmbt split.  This is the hard minimum requirement,
> +	 * and we revisit quota reservations later when we know more about what
> +	 * we're remapping.
>  	 */
>  	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
> -	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0,
> -			false, &tp);
> +	error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
> +			resblks + dmap->br_blockcount, 0, false, &tp);
> +	if (error == -EDQUOT || error == -ENOSPC) {
> +		quota_reserved = false;
> +		error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
> +				resblks, 0, false, &tp);
> +	}
>  	if (error)
>  		goto out;
>  
> @@ -1077,7 +1094,7 @@ xfs_reflink_remap_extent(
>  	 * before we started.  That should have removed all the delalloc
>  	 * reservations, but we code defensively.
>  	 */
> -	if (!smap_real && dmap_written) {
> +	if (!quota_reserved && !smap_real && dmap_written) {
>  		error = xfs_trans_reserve_quota_nblks(tp, ip,
>  				dmap->br_blockcount, 0, false);
>  		if (error)
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom
  2021-01-28  6:02 ` [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom Darrick J. Wong
  2021-01-28  9:57   ` Christoph Hellwig
@ 2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:02:06PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> For file creation, create a new helper xfs_trans_alloc_icreate that
> allocates a transaction and reserves the appropriate amount of quota
> against that transction.  Replace all the open-coded idioms with a
> single call to this helper so that we can contain the retry loops in the
> next patchset.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_inode.c   |   28 ++++++++++------------------
>  fs/xfs/xfs_symlink.c |   14 ++++----------
>  fs/xfs/xfs_trans.c   |   33 +++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_trans.h   |    6 ++++++
>  4 files changed, 53 insertions(+), 28 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> index 4bbd2fb628f7..636ac13b1df2 100644
> --- a/fs/xfs/xfs_inode.c
> +++ b/fs/xfs/xfs_inode.c
> @@ -1022,25 +1022,20 @@ xfs_create(
>  	 * the case we'll drop the one we have and get a more
>  	 * appropriate transaction later.
>  	 */
> -	error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
> +	error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
> +			&tp);
>  	if (error == -ENOSPC) {
>  		/* flush outstanding delalloc blocks and retry */
>  		xfs_flush_inodes(mp);
> -		error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
> +		error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp,
> +				resblks, &tp);
>  	}
>  	if (error)
> -		goto out_release_inode;
> +		goto out_release_dquots;
>  
>  	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
>  	unlock_dp_on_error = true;
>  
> -	/*
> -	 * Reserve disk quota and the inode.
> -	 */
> -	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
> -	if (error)
> -		goto out_trans_cancel;
> -
>  	error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
>  			XFS_IEXT_DIR_MANIP_CNT(mp));
>  	if (error)
> @@ -1120,7 +1115,7 @@ xfs_create(
>  		xfs_finish_inode_setup(ip);
>  		xfs_irele(ip);
>  	}
> -
> + out_release_dquots:
>  	xfs_qm_dqrele(udqp);
>  	xfs_qm_dqrele(gdqp);
>  	xfs_qm_dqrele(pdqp);
> @@ -1164,13 +1159,10 @@ xfs_create_tmpfile(
>  	resblks = XFS_IALLOC_SPACE_RES(mp);
>  	tres = &M_RES(mp)->tr_create_tmpfile;
>  
> -	error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
> +	error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
> +			&tp);
>  	if (error)
> -		goto out_release_inode;
> -
> -	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
> -	if (error)
> -		goto out_trans_cancel;
> +		goto out_release_dquots;
>  
>  	error = xfs_dir_ialloc(&tp, dp, mode, 0, 0, prid, &ip);
>  	if (error)
> @@ -1213,7 +1205,7 @@ xfs_create_tmpfile(
>  		xfs_finish_inode_setup(ip);
>  		xfs_irele(ip);
>  	}
> -
> + out_release_dquots:
>  	xfs_qm_dqrele(udqp);
>  	xfs_qm_dqrele(gdqp);
>  	xfs_qm_dqrele(pdqp);
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index d5dee8f409b2..8565663b16cd 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -197,9 +197,10 @@ xfs_symlink(
>  		fs_blocks = xfs_symlink_blocks(mp, pathlen);
>  	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
>  
> -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_symlink, resblks, 0, 0, &tp);
> +	error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
> +			pdqp, resblks, &tp);
>  	if (error)
> -		goto out_release_inode;
> +		goto out_release_dquots;
>  
>  	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
>  	unlock_dp_on_error = true;
> @@ -212,13 +213,6 @@ xfs_symlink(
>  		goto out_trans_cancel;
>  	}
>  
> -	/*
> -	 * Reserve disk quota : blocks and inode.
> -	 */
> -	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
> -	if (error)
> -		goto out_trans_cancel;
> -
>  	error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
>  			XFS_IEXT_DIR_MANIP_CNT(mp));
>  	if (error)
> @@ -347,7 +341,7 @@ xfs_symlink(
>  		xfs_finish_inode_setup(ip);
>  		xfs_irele(ip);
>  	}
> -
> +out_release_dquots:
>  	xfs_qm_dqrele(udqp);
>  	xfs_qm_dqrele(gdqp);
>  	xfs_qm_dqrele(pdqp);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 151f274eee43..bfb8b2a1594f 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -21,6 +21,8 @@
>  #include "xfs_error.h"
>  #include "xfs_defer.h"
>  #include "xfs_inode.h"
> +#include "xfs_dquot_item.h"
> +#include "xfs_dquot.h"
>  
>  kmem_zone_t	*xfs_trans_zone;
>  
> @@ -1074,3 +1076,34 @@ xfs_trans_alloc_inode(
>  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
>  	return error;
>  }
> +
> +/*
> + * Allocate an transaction in preparation for inode creation by reserving quota
> + * against the given dquots.
> + */
> +int
> +xfs_trans_alloc_icreate(
> +	struct xfs_mount	*mp,
> +	struct xfs_trans_res	*resv,
> +	struct xfs_dquot	*udqp,
> +	struct xfs_dquot	*gdqp,
> +	struct xfs_dquot	*pdqp,
> +	unsigned int		dblocks,
> +	struct xfs_trans	**tpp)
> +{
> +	struct xfs_trans	*tp;
> +	int			error;
> +
> +	error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp);
> +	if (error)
> +		return error;
> +
> +	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks);
> +	if (error) {
> +		xfs_trans_cancel(tp);
> +		return error;
> +	}
> +
> +	*tpp = tp;
> +	return 0;
> +}
> diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
> index 52bbd7e6a552..04c132c55e9b 100644
> --- a/fs/xfs/xfs_trans.h
> +++ b/fs/xfs/xfs_trans.h
> @@ -268,8 +268,14 @@ xfs_trans_item_relog(
>  	return lip->li_ops->iop_relog(lip, tp);
>  }
>  
> +struct xfs_dquot;
> +
>  int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
>  		unsigned int dblocks, unsigned int rblocks, bool force,
>  		struct xfs_trans **tpp);
> +int xfs_trans_alloc_icreate(struct xfs_mount *mp, struct xfs_trans_res *resv,
> +		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> +		struct xfs_dquot *pdqp, unsigned int dblocks,
> +		struct xfs_trans **tpp);
>  
>  #endif	/* __XFS_TRANS_H__ */
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c
  2021-01-28  6:02 ` [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c Darrick J. Wong
  2021-01-28  9:58   ` Christoph Hellwig
@ 2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:02:12PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c and rename it
> xfs_trans_reserve_quota_chown.  This will enable us to share code with
> the other quota reservation helpers, which will be very useful in the
> next patchset when we implement retry loops.  No functional changes
> here, we're just moving code.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_ioctl.c       |    2 -
>  fs/xfs/xfs_iops.c        |    6 +--
>  fs/xfs/xfs_qm.c          |   93 ----------------------------------------------
>  fs/xfs/xfs_quota.h       |   14 +++++--
>  fs/xfs/xfs_trans_dquot.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 107 insertions(+), 101 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 3fbd98f61ea5..e299fbd9ef13 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -1470,7 +1470,7 @@ xfs_ioctl_setattr(
>  
>  	if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
>  	    ip->i_d.di_projid != fa->fsx_projid) {
> -		code = xfs_qm_vop_chown_reserve(tp, ip, NULL, NULL, pdqp,
> +		code = xfs_trans_reserve_quota_chown(tp, ip, NULL, NULL, pdqp,
>  				capable(CAP_FOWNER) ?  XFS_QMOPT_FORCE_RES : 0);
>  		if (code)	/* out of quota */
>  			goto error_trans_cancel;
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index f1e21b6cfa48..cb68be87e0a4 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -730,9 +730,9 @@ xfs_setattr_nonsize(
>  		    ((XFS_IS_UQUOTA_ON(mp) && !uid_eq(iuid, uid)) ||
>  		     (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) {
>  			ASSERT(tp);
> -			error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
> -						NULL, capable(CAP_FOWNER) ?
> -						XFS_QMOPT_FORCE_RES : 0);
> +			error = xfs_trans_reserve_quota_chown(tp, ip, udqp,
> +					gdqp, NULL, capable(CAP_FOWNER) ?
> +					XFS_QMOPT_FORCE_RES : 0);
>  			if (error)	/* out of quota */
>  				goto out_cancel;
>  		}
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index c134eb4aeaa8..6c2a9fa78e7c 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
> @@ -1794,99 +1794,6 @@ xfs_qm_vop_chown(
>  	return prevdq;
>  }
>  
> -/*
> - * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
> - */
> -int
> -xfs_qm_vop_chown_reserve(
> -	struct xfs_trans	*tp,
> -	struct xfs_inode	*ip,
> -	struct xfs_dquot	*udqp,
> -	struct xfs_dquot	*gdqp,
> -	struct xfs_dquot	*pdqp,
> -	uint			flags)
> -{
> -	struct xfs_mount	*mp = ip->i_mount;
> -	uint64_t		delblks;
> -	unsigned int		blkflags;
> -	struct xfs_dquot	*udq_unres = NULL;
> -	struct xfs_dquot	*gdq_unres = NULL;
> -	struct xfs_dquot	*pdq_unres = NULL;
> -	struct xfs_dquot	*udq_delblks = NULL;
> -	struct xfs_dquot	*gdq_delblks = NULL;
> -	struct xfs_dquot	*pdq_delblks = NULL;
> -	int			error;
> -
> -
> -	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
> -	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
> -
> -	delblks = ip->i_delayed_blks;
> -	blkflags = XFS_IS_REALTIME_INODE(ip) ?
> -			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
> -
> -	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
> -	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
> -		udq_delblks = udqp;
> -		/*
> -		 * If there are delayed allocation blocks, then we have to
> -		 * unreserve those from the old dquot, and add them to the
> -		 * new dquot.
> -		 */
> -		if (delblks) {
> -			ASSERT(ip->i_udquot);
> -			udq_unres = ip->i_udquot;
> -		}
> -	}
> -	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
> -	    i_gid_read(VFS_I(ip)) != gdqp->q_id) {
> -		gdq_delblks = gdqp;
> -		if (delblks) {
> -			ASSERT(ip->i_gdquot);
> -			gdq_unres = ip->i_gdquot;
> -		}
> -	}
> -
> -	if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
> -	    ip->i_d.di_projid != pdqp->q_id) {
> -		pdq_delblks = pdqp;
> -		if (delblks) {
> -			ASSERT(ip->i_pdquot);
> -			pdq_unres = ip->i_pdquot;
> -		}
> -	}
> -
> -	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
> -				udq_delblks, gdq_delblks, pdq_delblks,
> -				ip->i_d.di_nblocks, 1, flags | blkflags);
> -	if (error)
> -		return error;
> -
> -	/*
> -	 * Do the delayed blks reservations/unreservations now. Since, these
> -	 * are done without the help of a transaction, if a reservation fails
> -	 * its previous reservations won't be automatically undone by trans
> -	 * code. So, we have to do it manually here.
> -	 */
> -	if (delblks) {
> -		/*
> -		 * Do the reservations first. Unreservation can't fail.
> -		 */
> -		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
> -		ASSERT(udq_unres || gdq_unres || pdq_unres);
> -		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> -			    udq_delblks, gdq_delblks, pdq_delblks,
> -			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
> -		if (error)
> -			return error;
> -		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> -				udq_unres, gdq_unres, pdq_unres,
> -				-((xfs_qcnt_t)delblks), 0, blkflags);
> -	}
> -
> -	return 0;
> -}
> -
>  int
>  xfs_qm_vop_rename_dqattach(
>  	struct xfs_inode	**i_tab)
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index efd04f84d9b4..d3876c71be8f 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -98,9 +98,9 @@ extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
>  extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **);
>  extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
>  		struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
> -extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *,
> -		struct xfs_dquot *, struct xfs_dquot *,
> -		struct xfs_dquot *, uint);
> +int xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
> +		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> +		struct xfs_dquot *pdqp, unsigned int flags);
>  extern int xfs_qm_dqattach(struct xfs_inode *);
>  extern int xfs_qm_dqattach_locked(struct xfs_inode *ip, bool doalloc);
>  extern void xfs_qm_dqdetach(struct xfs_inode *);
> @@ -162,7 +162,13 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
>  #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
>  #define xfs_qm_vop_rename_dqattach(it)					(0)
>  #define xfs_qm_vop_chown(tp, ip, old, new)				(NULL)
> -#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl)			(0)
> +static inline int
> +xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
> +		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> +		struct xfs_dquot *pdqp, unsigned int flags)
> +{
> +	return 0;
> +}
>  #define xfs_qm_dqattach(ip)						(0)
>  #define xfs_qm_dqattach_locked(ip, fl)					(0)
>  #define xfs_qm_dqdetach(ip)
> diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> index a1a72b7900c5..88146280a177 100644
> --- a/fs/xfs/xfs_trans_dquot.c
> +++ b/fs/xfs/xfs_trans_dquot.c
> @@ -836,6 +836,99 @@ xfs_trans_reserve_quota_icreate(
>  			dblocks, 1, XFS_QMOPT_RES_REGBLKS);
>  }
>  
> +/*
> + * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
> + */
> +int
> +xfs_trans_reserve_quota_chown(
> +	struct xfs_trans	*tp,
> +	struct xfs_inode	*ip,
> +	struct xfs_dquot	*udqp,
> +	struct xfs_dquot	*gdqp,
> +	struct xfs_dquot	*pdqp,
> +	unsigned int		flags)
> +{
> +	struct xfs_mount	*mp = ip->i_mount;
> +	uint64_t		delblks;
> +	unsigned int		blkflags;
> +	struct xfs_dquot	*udq_unres = NULL;
> +	struct xfs_dquot	*gdq_unres = NULL;
> +	struct xfs_dquot	*pdq_unres = NULL;
> +	struct xfs_dquot	*udq_delblks = NULL;
> +	struct xfs_dquot	*gdq_delblks = NULL;
> +	struct xfs_dquot	*pdq_delblks = NULL;
> +	int			error;
> +
> +
> +	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
> +	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
> +
> +	delblks = ip->i_delayed_blks;
> +	blkflags = XFS_IS_REALTIME_INODE(ip) ?
> +			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
> +
> +	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
> +	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
> +		udq_delblks = udqp;
> +		/*
> +		 * If there are delayed allocation blocks, then we have to
> +		 * unreserve those from the old dquot, and add them to the
> +		 * new dquot.
> +		 */
> +		if (delblks) {
> +			ASSERT(ip->i_udquot);
> +			udq_unres = ip->i_udquot;
> +		}
> +	}
> +	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
> +	    i_gid_read(VFS_I(ip)) != gdqp->q_id) {
> +		gdq_delblks = gdqp;
> +		if (delblks) {
> +			ASSERT(ip->i_gdquot);
> +			gdq_unres = ip->i_gdquot;
> +		}
> +	}
> +
> +	if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
> +	    ip->i_d.di_projid != pdqp->q_id) {
> +		pdq_delblks = pdqp;
> +		if (delblks) {
> +			ASSERT(ip->i_pdquot);
> +			pdq_unres = ip->i_pdquot;
> +		}
> +	}
> +
> +	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
> +				udq_delblks, gdq_delblks, pdq_delblks,
> +				ip->i_d.di_nblocks, 1, flags | blkflags);
> +	if (error)
> +		return error;
> +
> +	/*
> +	 * Do the delayed blks reservations/unreservations now. Since, these
> +	 * are done without the help of a transaction, if a reservation fails
> +	 * its previous reservations won't be automatically undone by trans
> +	 * code. So, we have to do it manually here.
> +	 */
> +	if (delblks) {
> +		/*
> +		 * Do the reservations first. Unreservation can't fail.
> +		 */
> +		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
> +		ASSERT(udq_unres || gdq_unres || pdq_unres);
> +		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> +			    udq_delblks, gdq_delblks, pdq_delblks,
> +			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
> +		if (error)
> +			return error;
> +		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> +				udq_unres, gdq_unres, pdq_unres,
> +				-((xfs_qcnt_t)delblks), 0, blkflags);
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * This routine is called to allocate a quotaoff log item.
>   */
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit
  2021-01-28  6:02 ` [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit Darrick J. Wong
  2021-01-28 10:00   ` Christoph Hellwig
@ 2021-01-28 18:23   ` Brian Foster
  1 sibling, 0 replies; 41+ messages in thread
From: Brian Foster @ 2021-01-28 18:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, hch, david

On Wed, Jan 27, 2021 at 10:02:18PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Clean up the calling conventions of xfs_trans_reserve_quota_chown a
> littel bit -- we can pass in a boolean force parameter since that's the
> only qmopt that caller care about, and make the obvious deficiencies
> more obvious for anyone who someday wants to clean up rt quota.
> 
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_ioctl.c       |    2 +-
>  fs/xfs/xfs_iops.c        |    3 +--
>  fs/xfs/xfs_quota.h       |    4 ++--
>  fs/xfs/xfs_trans_dquot.c |   38 +++++++++++++++++++++-----------------
>  4 files changed, 25 insertions(+), 22 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index e299fbd9ef13..73cfee8007a8 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -1471,7 +1471,7 @@ xfs_ioctl_setattr(
>  	if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
>  	    ip->i_d.di_projid != fa->fsx_projid) {
>  		code = xfs_trans_reserve_quota_chown(tp, ip, NULL, NULL, pdqp,
> -				capable(CAP_FOWNER) ?  XFS_QMOPT_FORCE_RES : 0);
> +				capable(CAP_FOWNER));
>  		if (code)	/* out of quota */
>  			goto error_trans_cancel;
>  	}
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index cb68be87e0a4..51c877ce90bc 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -731,8 +731,7 @@ xfs_setattr_nonsize(
>  		     (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) {
>  			ASSERT(tp);
>  			error = xfs_trans_reserve_quota_chown(tp, ip, udqp,
> -					gdqp, NULL, capable(CAP_FOWNER) ?
> -					XFS_QMOPT_FORCE_RES : 0);
> +					gdqp, NULL, capable(CAP_FOWNER));
>  			if (error)	/* out of quota */
>  				goto out_cancel;
>  		}
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index d3876c71be8f..c3a5b48f5860 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -100,7 +100,7 @@ extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
>  		struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
>  int xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
>  		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> -		struct xfs_dquot *pdqp, unsigned int flags);
> +		struct xfs_dquot *pdqp, bool force);
>  extern int xfs_qm_dqattach(struct xfs_inode *);
>  extern int xfs_qm_dqattach_locked(struct xfs_inode *ip, bool doalloc);
>  extern void xfs_qm_dqdetach(struct xfs_inode *);
> @@ -165,7 +165,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp,
>  static inline int
>  xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip,
>  		struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> -		struct xfs_dquot *pdqp, unsigned int flags)
> +		struct xfs_dquot *pdqp, bool force)
>  {
>  	return 0;
>  }
> diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> index 88146280a177..73ef5994d09d 100644
> --- a/fs/xfs/xfs_trans_dquot.c
> +++ b/fs/xfs/xfs_trans_dquot.c
> @@ -846,26 +846,30 @@ xfs_trans_reserve_quota_chown(
>  	struct xfs_dquot	*udqp,
>  	struct xfs_dquot	*gdqp,
>  	struct xfs_dquot	*pdqp,
> -	unsigned int		flags)
> +	bool			force)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
> -	uint64_t		delblks;
> -	unsigned int		blkflags;
> -	struct xfs_dquot	*udq_unres = NULL;
> +	struct xfs_dquot	*udq_unres = NULL;	/* old dquots */
>  	struct xfs_dquot	*gdq_unres = NULL;
>  	struct xfs_dquot	*pdq_unres = NULL;
> -	struct xfs_dquot	*udq_delblks = NULL;
> +	struct xfs_dquot	*udq_delblks = NULL;	/* new dquots */
>  	struct xfs_dquot	*gdq_delblks = NULL;
>  	struct xfs_dquot	*pdq_delblks = NULL;
> +	uint64_t		delblks;
> +	unsigned int		qflags = XFS_QMOPT_RES_REGBLKS;
>  	int			error;
>  
> -
> -	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
> +	/*
> +	 * XXX: This function doesn't handle rt quota counts correctly.  We
> +	 * don't support mounting with rt+quota so leave this breadcrumb.
> +	 */
> +	ASSERT(!XFS_IS_REALTIME_INODE(ip));
> +	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
>  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
>  
>  	delblks = ip->i_delayed_blks;
> -	blkflags = XFS_IS_REALTIME_INODE(ip) ?
> -			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
> +	if (force)
> +		qflags |= XFS_QMOPT_FORCE_RES;
>  
>  	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
>  	    i_uid_read(VFS_I(ip)) != udqp->q_id) {
> @@ -898,9 +902,9 @@ xfs_trans_reserve_quota_chown(
>  		}
>  	}
>  
> -	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
> -				udq_delblks, gdq_delblks, pdq_delblks,
> -				ip->i_d.di_nblocks, 1, flags | blkflags);
> +	error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, udq_delblks,
> +			gdq_delblks, pdq_delblks, ip->i_d.di_nblocks, 1,
> +			qflags);
>  	if (error)
>  		return error;
>  
> @@ -917,13 +921,13 @@ xfs_trans_reserve_quota_chown(
>  		ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
>  		ASSERT(udq_unres || gdq_unres || pdq_unres);
>  		error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> -			    udq_delblks, gdq_delblks, pdq_delblks,
> -			    (xfs_qcnt_t)delblks, 0, flags | blkflags);
> +				udq_delblks, gdq_delblks, pdq_delblks,
> +				(xfs_qcnt_t)delblks, 0, qflags);
>  		if (error)
>  			return error;
> -		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> -				udq_unres, gdq_unres, pdq_unres,
> -				-((xfs_qcnt_t)delblks), 0, blkflags);
> +		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, udq_unres,
> +				gdq_unres, pdq_unres, -((xfs_qcnt_t)delblks),
> +				0, qflags);
>  	}
>  
>  	return 0;
> 


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 05/13] xfs: fix up build warnings when quotas are disabled
  2021-01-28 18:22     ` Darrick J. Wong
@ 2021-01-28 18:23       ` Christoph Hellwig
  0 siblings, 0 replies; 41+ messages in thread
From: Christoph Hellwig @ 2021-01-28 18:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: Brian Foster, Christoph Hellwig, linux-xfs, hch, david

On Thu, Jan 28, 2021 at 10:22:49AM -0800, Darrick J. Wong wrote:
> > > -#define xfs_qm_dqrele(d)
> > > -#define xfs_qm_statvfs(ip, s)
> > > +#define xfs_qm_dqrele(d)			do { (d) = (d); } while(0)
> > 
> > What's the need for the assignment, out of curiosity?
> 
> It shuts up a gcc warning about how the dquot pointer is set but never
> used.  One hopes the same gcc is smart enough not to generate any code
> for this.

The alternative would be to turn these stubs into inline functions,
which would also kill the warning.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [PATCH 06/13] xfs: reserve data and rt quota at the same time
  2021-01-28 18:10   ` Brian Foster
@ 2021-01-28 18:52     ` Darrick J. Wong
  0 siblings, 0 replies; 41+ messages in thread
From: Darrick J. Wong @ 2021-01-28 18:52 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs, hch, david

On Thu, Jan 28, 2021 at 01:10:21PM -0500, Brian Foster wrote:
> On Wed, Jan 27, 2021 at 10:01:38PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > Modify xfs_trans_reserve_quota_nblks so that we can reserve data and
> > realtime blocks from the dquot at the same time.  This change has the
> > theoretical side effect that for allocations to realtime files we will
> > reserve from the dquot both the number of rtblocks being allocated and
> > the number of bmbt blocks that might be needed to add the mapping.
> > However, since the mount code disables quota if it finds a realtime
> > device, this should not result in any behavior changes.
> > 
> > This also replaces the flags argument with a force? boolean since we
> 
> s/?//
> 
> > don't need to distinguish between data and rt quota reservations any
> > more, and the only other flag being passed in was FORCE_RES.
> > 
> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> > ---
> >  fs/xfs/libxfs/xfs_attr.c |    6 +-----
> >  fs/xfs/libxfs/xfs_bmap.c |    4 +---
> >  fs/xfs/xfs_bmap_util.c   |   20 +++++++++-----------
> >  fs/xfs/xfs_iomap.c       |   26 +++++++++++++-------------
> >  fs/xfs/xfs_quota.h       |   10 +++++-----
> >  fs/xfs/xfs_reflink.c     |    6 ++----
> >  fs/xfs/xfs_trans_dquot.c |   42 ++++++++++++++++++++++++++++--------------
> >  7 files changed, 59 insertions(+), 55 deletions(-)
> > 
> > 
> ...
> > diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> > index f0a8f3377281..d54d9f02d3dd 100644
> > --- a/fs/xfs/xfs_bmap_util.c
> > +++ b/fs/xfs/xfs_bmap_util.c
> ...
> > @@ -792,18 +792,17 @@ xfs_alloc_file_space(
> >  		if (unlikely(rt)) {
> >  			resrtextents = qblocks = resblks;
> 
> This looks like the last usage of qblocks in the function.

Oops, yes, that can go away.  Fixed.

> >  			resrtextents /= mp->m_sb.sb_rextsize;
> > -			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
> > -			quota_flag = XFS_QMOPT_RES_RTBLKS;
> > +			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
> > +			rblocks = resblks;
> >  		} else {
> > -			resrtextents = 0;
> > -			resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
> > -			quota_flag = XFS_QMOPT_RES_REGBLKS;
> > +			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
> > +			rblocks = 0;
> >  		}
> >  
> >  		/*
> >  		 * Allocate and setup the transaction.
> >  		 */
> > -		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks,
> > +		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks,
> >  				resrtextents, 0, &tp);
> >  
> >  		/*
> ...
> > diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> > index de0e371ba4dd..ef29d44c656a 100644
> > --- a/fs/xfs/xfs_iomap.c
> > +++ b/fs/xfs/xfs_iomap.c
> ...
> > @@ -235,18 +235,19 @@ xfs_iomap_write_direct(
> >  	if (IS_DAX(VFS_I(ip))) {
> >  		bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
> >  		if (imap->br_state == XFS_EXT_UNWRITTEN) {
> > +			force = true;
> >  			tflags |= XFS_TRANS_RESERVE;
> > -			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
> > +			dblocks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
> 
> I'm a little confused what this hunk of logic is for in the first place,

I think this was to prevent racing write faults to an unwritten extent
in an S_DAX file from clobbering each other.  Looking at the dax write
fault path (__xfs_filemap_fault), we only take MMAPLOCK_SHARED, so the
only way we can serialize the storage zeroing that must be done with
unwritten extent conversion is when we take the ILOCK to do the
conversion, aka BMAPI_ZERO.

xfs_direct_write_iomap_begin accomplishes this by (ab|re)using the
"allocation" path to do the extent conversion.  The space is already
allocated, so we only have to reserve enough free space/quota to handle
the bmbt split.

> but doesn't this also adjust down the quota where it previously only
> affected the transaction reservation? Is that intentional?

So yes, it does adjust down the quota reservation for this one case, but
I don't think we needed it in the first place.  Still, I'll cut out this
part and make it a separate fix patch so that the conversion is more
straightforward.  Thanks for pointing that out.

--D

> Brian
> 
> >  		}
> >  	}
> > -	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents,
> > +	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, dblocks, resrtextents,
> >  			tflags, &tp);
> >  	if (error)
> >  		return error;
> >  
> >  	xfs_ilock(ip, XFS_ILOCK_EXCL);
> >  
> > -	error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
> > +	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
> >  	if (error)
> >  		goto out_trans_cancel;
> >  
> > @@ -559,8 +560,7 @@ xfs_iomap_write_unwritten(
> >  		xfs_ilock(ip, XFS_ILOCK_EXCL);
> >  		xfs_trans_ijoin(tp, ip, 0);
> >  
> > -		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
> > -				XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES);
> > +		error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, true);
> >  		if (error)
> >  			goto error_on_bmapi_transaction;
> >  
> > diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> > index 72f4cfc49048..efd04f84d9b4 100644
> > --- a/fs/xfs/xfs_quota.h
> > +++ b/fs/xfs/xfs_quota.h
> > @@ -81,8 +81,8 @@ extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, struct xfs_inode *,
> >  		uint, int64_t);
> >  extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *);
> >  extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *);
> > -extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
> > -		struct xfs_inode *, int64_t, long, uint);
> > +int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip,
> > +		int64_t dblocks, int64_t rblocks, bool force);
> >  extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
> >  		struct xfs_mount *, struct xfs_dquot *,
> >  		struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint);
> > @@ -114,8 +114,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);
> >  static inline int
> >  xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t dblocks)
> >  {
> > -	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0,
> > -			XFS_QMOPT_RES_REGBLKS);
> > +	return xfs_trans_reserve_quota_nblks(NULL, ip, dblocks, 0, false);
> >  }
> >  #else
> >  static inline int
> > @@ -134,7 +133,8 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid,
> >  #define xfs_trans_apply_dquot_deltas(tp)
> >  #define xfs_trans_unreserve_and_mod_dquots(tp)
> >  static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
> > -		struct xfs_inode *ip, int64_t nblks, long ninos, uint flags)
> > +		struct xfs_inode *ip, int64_t dblocks, int64_t rblocks,
> > +		bool force)
> >  {
> >  	return 0;
> >  }
> > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> > index 15435229bc1f..0778b5810c26 100644
> > --- a/fs/xfs/xfs_reflink.c
> > +++ b/fs/xfs/xfs_reflink.c
> > @@ -398,8 +398,7 @@ xfs_reflink_allocate_cow(
> >  		goto convert;
> >  	}
> >  
> > -	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
> > -			XFS_QMOPT_RES_REGBLKS);
> > +	error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, false);
> >  	if (error)
> >  		goto out_trans_cancel;
> >  
> > @@ -1090,8 +1089,7 @@ xfs_reflink_remap_extent(
> >  	if (!smap_real && dmap_written)
> >  		qres += dmap->br_blockcount;
> >  	if (qres > 0) {
> > -		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0,
> > -				XFS_QMOPT_RES_REGBLKS);
> > +		error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, false);
> >  		if (error)
> >  			goto out_cancel;
> >  	}
> > diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> > index 22aa875b84f7..a1a72b7900c5 100644
> > --- a/fs/xfs/xfs_trans_dquot.c
> > +++ b/fs/xfs/xfs_trans_dquot.c
> > @@ -780,28 +780,42 @@ int
> >  xfs_trans_reserve_quota_nblks(
> >  	struct xfs_trans	*tp,
> >  	struct xfs_inode	*ip,
> > -	int64_t			nblks,
> > -	long			ninos,
> > -	uint			flags)
> > +	int64_t			dblocks,
> > +	int64_t			rblocks,
> > +	bool			force)
> >  {
> >  	struct xfs_mount	*mp = ip->i_mount;
> > +	unsigned int		qflags = 0;
> > +	int			error;
> >  
> >  	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
> >  		return 0;
> >  
> >  	ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
> > -
> >  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
> > -	ASSERT((flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_RTBLKS ||
> > -	       (flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_BLKS);
> > -
> > -	/*
> > -	 * Reserve nblks against these dquots, with trans as the mediator.
> > -	 */
> > -	return xfs_trans_reserve_quota_bydquots(tp, mp,
> > -						ip->i_udquot, ip->i_gdquot,
> > -						ip->i_pdquot,
> > -						nblks, ninos, flags);
> > +
> > +	if (force)
> > +		qflags |= XFS_QMOPT_FORCE_RES;
> > +
> > +	/* Reserve data device quota against the inode's dquots. */
> > +	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> > +			ip->i_gdquot, ip->i_pdquot, dblocks, 0,
> > +			XFS_QMOPT_RES_REGBLKS | qflags);
> > +	if (error)
> > +		return error;
> > +
> > +	/* Do the same but for realtime blocks. */
> > +	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> > +			ip->i_gdquot, ip->i_pdquot, rblocks, 0,
> > +			XFS_QMOPT_RES_RTBLKS | qflags);
> > +	if (error) {
> > +		xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> > +				ip->i_gdquot, ip->i_pdquot, -dblocks, 0,
> > +				XFS_QMOPT_RES_REGBLKS);
> > +		return error;
> > +	}
> > +
> > +	return 0;
> >  }
> >  
> >  /* Change the quota reservations for an inode creation activity. */
> > 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2021-01-28 18:55 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-28  6:01 [PATCHSET v3 00/13] xfs: minor cleanups of the quota functions Darrick J. Wong
2021-01-28  6:01 ` [PATCH 01/13] xfs: clean up quota reservation callsites Darrick J. Wong
2021-01-28  6:01 ` [PATCH 02/13] xfs: create convenience wrappers for incore quota block reservations Darrick J. Wong
2021-01-28 18:08   ` Brian Foster
2021-01-28  6:01 ` [PATCH 03/13] xfs: remove xfs_trans_unreserve_quota_nblks completely Darrick J. Wong
2021-01-28  9:46   ` Christoph Hellwig
2021-01-28 18:08   ` Brian Foster
2021-01-28  6:01 ` [PATCH 04/13] xfs: clean up icreate quota reservation calls Darrick J. Wong
2021-01-28 18:09   ` Brian Foster
2021-01-28  6:01 ` [PATCH 05/13] xfs: fix up build warnings when quotas are disabled Darrick J. Wong
2021-01-28 18:09   ` Brian Foster
2021-01-28 18:22     ` Darrick J. Wong
2021-01-28 18:23       ` Christoph Hellwig
2021-01-28  6:01 ` [PATCH 06/13] xfs: reserve data and rt quota at the same time Darrick J. Wong
2021-01-28  9:49   ` Christoph Hellwig
2021-01-28 18:01     ` Darrick J. Wong
2021-01-28 18:10   ` Brian Foster
2021-01-28 18:52     ` Darrick J. Wong
2021-01-28  6:01 ` [PATCH 07/13] xfs: refactor common transaction/inode/quota allocation idiom Darrick J. Wong
2021-01-28  9:50   ` Christoph Hellwig
2021-01-28 18:22   ` Brian Foster
2021-01-28  6:01 ` [PATCH 08/13] xfs: allow reservation of rtblocks with xfs_trans_alloc_inode Darrick J. Wong
2021-01-28  9:51   ` Christoph Hellwig
2021-01-28 18:22   ` Brian Foster
2021-01-28  6:01 ` [PATCH 09/13] xfs: refactor reflink functions to use xfs_trans_alloc_inode Darrick J. Wong
2021-01-28  9:53   ` Christoph Hellwig
2021-01-28 18:06     ` Darrick J. Wong
2021-01-28 18:23   ` Brian Foster
2021-01-28  6:02 ` [PATCH 10/13] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent Darrick J. Wong
2021-01-28  9:55   ` Christoph Hellwig
2021-01-28 18:23   ` Brian Foster
2021-01-28  6:02 ` [PATCH 11/13] xfs: refactor inode creation transaction/inode/quota allocation idiom Darrick J. Wong
2021-01-28  9:57   ` Christoph Hellwig
2021-01-28 18:18     ` Darrick J. Wong
2021-01-28 18:23   ` Brian Foster
2021-01-28  6:02 ` [PATCH 12/13] xfs: move xfs_qm_vop_chown_reserve to xfs_trans_dquot.c Darrick J. Wong
2021-01-28  9:58   ` Christoph Hellwig
2021-01-28 18:23   ` Brian Foster
2021-01-28  6:02 ` [PATCH 13/13] xfs: clean up xfs_trans_reserve_quota_chown a bit Darrick J. Wong
2021-01-28 10:00   ` Christoph Hellwig
2021-01-28 18:23   ` Brian Foster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.