From: "Darrick J. Wong" <djwong@kernel.org>
To: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 06/11] xfs: flush eof/cowblocks if we can't reserve quota for file blocks
Date: Mon, 18 Jan 2021 19:56:26 -0800 [thread overview]
Message-ID: <20210119035626.GM3134581@magnolia> (raw)
In-Reply-To: <161100795124.88816.6644776235251695171.stgit@magnolia>
On Mon, Jan 18, 2021 at 02:12:31PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
>
> If a fs modification (data write, reflink, xattr set, fallocate, etc.)
> is unable to reserve enough quota to handle the modification, try
> clearing whatever space the filesystem might have been hanging onto in
> the hopes of speeding up the filesystem. The flushing behavior will
> become particularly important when we add deferred inode inactivation
> because that will increase the amount of space that isn't actively tied
> to user data.
>
> Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> ---
> fs/xfs/libxfs/xfs_attr.c | 10 +++++--
> fs/xfs/libxfs/xfs_bmap.c | 10 +++++--
> fs/xfs/xfs_bmap_util.c | 22 ++++++++++------
> fs/xfs/xfs_iomap.c | 24 ++++++++++++-----
> fs/xfs/xfs_quota.h | 15 +++++++----
> fs/xfs/xfs_reflink.c | 31 +++++++++++++++-------
> fs/xfs/xfs_trans_dquot.c | 64 ++++++++++++++++++++++++++++++++++++++--------
> 7 files changed, 129 insertions(+), 47 deletions(-)
>
>
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index fd8e6418a0d3..49da931d0d19 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -395,6 +395,7 @@ xfs_attr_set(
> struct xfs_mount *mp = dp->i_mount;
> struct xfs_trans_res tres;
> bool rsvd = (args->attr_filter & XFS_ATTR_ROOT);
> + bool quota_retry = false;
> int error, local;
> unsigned int total;
>
> @@ -453,6 +454,7 @@ xfs_attr_set(
> * Root fork attributes can use reserved data blocks for this
> * operation if necessary
> */
> +retry:
> error = xfs_trans_alloc(mp, &tres, total, 0,
> rsvd ? XFS_TRANS_RESERVE : 0, &args->trans);
> if (error)
> @@ -465,10 +467,12 @@ xfs_attr_set(
>
> if (rsvd)
> quota_flags |= XFS_QMOPT_FORCE_RES;
> - error = xfs_trans_reserve_quota_nblks(args->trans, dp,
> - args->total, 0, quota_flags);
> + error = xfs_trans_reserve_quota_nblks(&args->trans, dp,
> + args->total, 0, quota_flags, "a_retry);
> if (error)
> - goto out_trans_cancel;
> + return error;
> + if (quota_retry)
> + goto retry;
>
> error = xfs_has_attr(args);
> if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index fa6b442eb75f..1bca18a7381b 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -1070,6 +1070,7 @@ xfs_bmap_add_attrfork(
> int blks; /* space reservation */
> int version = 1; /* superblock attr version */
> int logflags; /* logging flags */
> + bool quota_retry = false;
> int error; /* error return value */
>
> ASSERT(XFS_IFORK_Q(ip) == 0);
> @@ -1079,17 +1080,20 @@ xfs_bmap_add_attrfork(
>
> blks = XFS_ADDAFORK_SPACE_RES(mp);
>
> +retry:
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0,
> rsvd ? XFS_TRANS_RESERVE : 0, &tp);
> if (error)
> return error;
>
> xfs_ilock(ip, XFS_ILOCK_EXCL);
> - error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
> + error = xfs_trans_reserve_quota_nblks(&tp, ip, blks, 0, rsvd ?
> XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
> - XFS_QMOPT_RES_REGBLKS);
> + XFS_QMOPT_RES_REGBLKS, "a_retry);
> if (error)
> - goto trans_cancel;
> + return error;
> + if (quota_retry)
> + goto retry;
> if (XFS_IFORK_Q(ip))
> goto trans_cancel;
>
> diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
> index 671cb104861e..d12c9e9e5c7b 100644
> --- a/fs/xfs/xfs_bmap_util.c
> +++ b/fs/xfs/xfs_bmap_util.c
> @@ -761,6 +761,7 @@ xfs_alloc_file_space(
> */
> while (allocatesize_fsb && !error) {
> xfs_fileoff_t s, e;
> + bool quota_retry = false;
>
> /*
> * Determine space reservations for data/realtime.
> @@ -803,6 +804,7 @@ xfs_alloc_file_space(
> /*
> * Allocate and setup the transaction.
> */
> +retry:
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks,
> resrtextents, 0, &tp);
>
> @@ -817,10 +819,12 @@ 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, qblocks, 0,
> + quota_flag, "a_retry);
> if (error)
> - goto error1;
> + return error;
> + if (quota_retry)
> + goto retry;
>
> xfs_trans_ijoin(tp, ip, 0);
>
> @@ -853,8 +857,6 @@ xfs_alloc_file_space(
>
> 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);
> return error;
> @@ -870,8 +872,10 @@ xfs_unmap_extent(
> struct xfs_mount *mp = ip->i_mount;
> struct xfs_trans *tp;
> uint resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
> + bool quota_retry = false;
> int error;
>
> +retry:
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> if (error) {
> ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp));
> @@ -879,10 +883,12 @@ 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,
> + XFS_QMOPT_RES_REGBLKS, "a_retry);
> if (error)
> - goto out_trans_cancel;
> + return error;
> + if (quota_retry)
> + goto retry;
>
> xfs_trans_ijoin(tp, ip, 0);
>
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 7b9ff824e82d..d9583f1de2fc 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -27,7 +27,7 @@
> #include "xfs_dquot_item.h"
> #include "xfs_dquot.h"
> #include "xfs_reflink.h"
> -
> +#include "xfs_icache.h"
>
> #define XFS_ALLOC_ALIGN(mp, off) \
> (((off) >> mp->m_allocsize_log) << mp->m_allocsize_log)
> @@ -197,6 +197,7 @@ xfs_iomap_write_direct(
> int quota_flag;
> uint qblocks, resblks;
> unsigned int resrtextents = 0;
> + bool quota_retry = false;
> int error;
> int bmapi_flags = XFS_BMAPI_PREALLOC;
> uint tflags = 0;
> @@ -239,6 +240,7 @@ xfs_iomap_write_direct(
> resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
> }
> }
> +retry:
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents,
> tflags, &tp);
> if (error)
> @@ -246,9 +248,12 @@ xfs_iomap_write_direct(
>
> 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, qblocks, 0, quota_flag,
> + "a_retry);
> if (error)
> - goto out_trans_cancel;
> + return error;
> + if (quota_retry)
> + goto retry;
>
> xfs_trans_ijoin(tp, ip, 0);
>
> @@ -286,7 +291,6 @@ xfs_iomap_write_direct(
>
> 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;
> }
> @@ -539,6 +543,8 @@ xfs_iomap_write_unwritten(
> return error;
>
> do {
> + bool quota_retry = false;
> +
> /*
> * Set up a transaction to convert the range of extents
> * from unwritten to real. Do allocations in a loop until
> @@ -548,6 +554,7 @@ 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.
> */
> +retry:
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
> XFS_TRANS_RESERVE, &tp);
> if (error)
> @@ -556,10 +563,13 @@ 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,
> + XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES,
> + "a_retry);
> if (error)
> - goto error_on_bmapi_transaction;
> + return error;
> + if (quota_retry)
> + goto retry;
>
> /*
> * Modify the unwritten extent state of the buffer.
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index 1c37b5be60c3..996046eb1492 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -81,8 +81,9 @@ 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 **tpp, struct xfs_inode *ip,
> + int64_t nblocks, long ninos, unsigned int flags,
> + bool *retry);
> 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);
> @@ -128,7 +129,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,
Oops, forgot to change this to 'struct xfs_trans **tpp'...
--D
> - struct xfs_inode *ip, int64_t nblks, long ninos, uint flags)
> + struct xfs_inode *ip, int64_t nblks, long ninos,
> + unsigned int flags, bool *retry)
> {
> return 0;
> }
> @@ -170,14 +172,17 @@ static inline int
> xfs_trans_unreserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip,
> int64_t nblks, long ninos, unsigned int flags)
> {
> - return xfs_trans_reserve_quota_nblks(tp, ip, -nblks, -ninos, flags);
> + return xfs_trans_reserve_quota_nblks(&tp, ip, -nblks, -ninos, flags,
> + NULL);
> }
>
> static inline int
> xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t nblks,
> unsigned int flags)
> {
> - return xfs_trans_reserve_quota_nblks(NULL, ip, nblks, 0, flags);
> + struct xfs_trans *tp = NULL;
> +
> + return xfs_trans_reserve_quota_nblks(&tp, ip, nblks, 0, flags, NULL);
> }
>
> static inline int
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 1f3270ffaea5..8d768c3c4b25 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -351,13 +351,14 @@ xfs_reflink_allocate_cow(
> bool convert_now)
> {
> struct xfs_mount *mp = ip->i_mount;
> + struct xfs_trans *tp;
> xfs_fileoff_t offset_fsb = imap->br_startoff;
> xfs_filblks_t count_fsb = imap->br_blockcount;
> - struct xfs_trans *tp;
> - int nimaps, error = 0;
> - bool found;
> xfs_filblks_t resaligned;
> xfs_extlen_t resblks = 0;
> + bool found;
> + bool quota_retry = false;
> + int nimaps, error = 0;
>
> ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
> if (!ip->i_cowfp) {
> @@ -376,6 +377,7 @@ xfs_reflink_allocate_cow(
> resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
>
> xfs_iunlock(ip, *lockmode);
> +retry:
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> *lockmode = XFS_ILOCK_EXCL;
> xfs_ilock(ip, *lockmode);
> @@ -398,10 +400,15 @@ xfs_reflink_allocate_cow(
> goto convert;
> }
>
> - error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
> - XFS_QMOPT_RES_REGBLKS);
> - if (error)
> - goto out_trans_cancel;
> + error = xfs_trans_reserve_quota_nblks(&tp, ip, resblks, 0,
> + XFS_QMOPT_RES_REGBLKS, "a_retry);
> + if (error) {
> + /* This function must return with the ILOCK held. */
> + xfs_ilock(ip, *lockmode);
> + return error;
> + }
> + if (quota_retry)
> + goto retry;
>
> xfs_trans_ijoin(tp, ip, 0);
>
> @@ -1000,9 +1007,11 @@ xfs_reflink_remap_extent(
> unsigned int resblks;
> bool smap_real;
> bool dmap_written = xfs_bmap_is_written_extent(dmap);
> + bool quota_retry = false;
> int nimaps;
> int error;
>
> +retry:
> /* Start a rolling transaction to switch the mappings */
> resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
> error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> @@ -1087,10 +1096,12 @@ 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,
> + XFS_QMOPT_RES_REGBLKS, "a_retry);
> if (error)
> - goto out_cancel;
> + goto out;
> + if (quota_retry)
> + goto retry;
> }
>
> if (smap_real) {
> diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> index 3315498a6fa1..c6abe1f1106c 100644
> --- a/fs/xfs/xfs_trans_dquot.c
> +++ b/fs/xfs/xfs_trans_dquot.c
> @@ -16,6 +16,7 @@
> #include "xfs_quota.h"
> #include "xfs_qm.h"
> #include "xfs_trace.h"
> +#include "xfs_icache.h"
>
> STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *);
>
> @@ -770,21 +771,40 @@ xfs_trans_reserve_quota_bydquots(
> return error;
> }
>
> -
> /*
> - * Lock the dquot and change the reservation if we can.
> - * This doesn't change the actual usage, just the reservation.
> - * The inode sent in is locked.
> + * Lock the dquot and change the reservation if we can. This doesn't change
> + * the actual usage, just the reservation. The caller must hold ILOCK_EXCL on
> + * the inode. If @retry is not a NULL pointer, the caller must ensure that
> + * *retry is set to false before the first time this function is called.
> + *
> + * If the quota reservation fails because we hit a quota limit (and retry is
> + * not a NULL pointer, and *retry is true), this function will try to invoke
> + * the speculative preallocation gc scanner to reduce quota usage. In order to
> + * do that, we cancel the transaction, NULL out tpp, and drop the ILOCK. If we
> + * actually do some freeing work, *retry will be set to true.
> + *
> + * This function ends one of four ways:
> + * a) if retry is NULL, returns the result of trying to change the quota
> + * reservation, with *tpp still set and the inode still locked;
> + * b) returns an error code with *tpp cancelled and set to NULL, and the inode
> + * unlocked;
> + * c) returns zero with *tpp cancelled and set to NULL, the inode unlocked,
> + * and *retry is true, which means we cleared space and the caller should
> + * try again with a new transaction;
> + * d) returns zero with *tpp still set, the inode still locked, and *retry
> + * is false, which means the reservation succeeded.
> */
> int
> xfs_trans_reserve_quota_nblks(
> - struct xfs_trans *tp,
> + struct xfs_trans **tpp,
> struct xfs_inode *ip,
> int64_t nblks,
> long ninos,
> - uint flags)
> + unsigned int flags,
> + bool *retry)
> {
> struct xfs_mount *mp = ip->i_mount;
> + int error, err2;
>
> if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
> return 0;
> @@ -795,13 +815,35 @@ xfs_trans_reserve_quota_nblks(
> 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. */
> + error = xfs_trans_reserve_quota_bydquots(*tpp, mp, ip->i_udquot,
> + ip->i_gdquot, ip->i_pdquot, nblks, ninos, flags);
> +
> + /* Exit immediately if the caller did not want retries. */
> + if (retry == NULL)
> + return error;
> +
> /*
> - * Reserve nblks against these dquots, with trans as the mediator.
> + * If the caller /can/ handle retries, we always cancel the transaction
> + * on error, even if we aren't going to attempt a gc scan.
> */
> - return xfs_trans_reserve_quota_bydquots(tp, mp,
> - ip->i_udquot, ip->i_gdquot,
> - ip->i_pdquot,
> - nblks, ninos, flags);
> + if (error) {
> + xfs_trans_cancel(*tpp);
> + *tpp = NULL;
> + xfs_iunlock(ip, XFS_ILOCK_EXCL);
> + }
> +
> + /* We only allow one retry for EDQUOT/ENOSPC. */
> + if (*retry || (error != -EDQUOT && error != -ENOSPC)) {
> + *retry = false;
> + return error;
> + }
> +
> + /* Try to free some quota for this file's dquots. */
> + err2 = xfs_blockgc_free_quota(ip, 0, retry);
> + if (err2)
> + return err2;
> + return *retry ? 0 : error;
> }
>
> /* Change the quota reservations for an inode creation activity. */
>
next prev parent reply other threads:[~2021-01-19 3:57 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-18 22:11 [PATCHSET v3 00/11] xfs: try harder to reclaim space when we run out Darrick J. Wong
2021-01-18 22:12 ` [PATCH 01/11] xfs: refactor messy xfs_inode_free_quota_* functions Darrick J. Wong
2021-01-18 22:12 ` [PATCH 02/11] xfs: don't stall cowblocks scan if we can't take locks Darrick J. Wong
2021-01-19 6:49 ` Christoph Hellwig
2021-01-18 22:12 ` [PATCH 03/11] xfs: xfs_inode_free_quota_blocks should scan project quota Darrick J. Wong
2021-01-18 22:12 ` [PATCH 04/11] xfs: move and rename xfs_inode_free_quota_blocks to avoid conflicts Darrick J. Wong
2021-01-19 6:53 ` Christoph Hellwig
2021-01-18 22:12 ` [PATCH 05/11] xfs: pass flags and return gc errors from xfs_blockgc_free_quota Darrick J. Wong
2021-01-19 6:59 ` Christoph Hellwig
2021-01-18 22:12 ` [PATCH 06/11] xfs: flush eof/cowblocks if we can't reserve quota for file blocks Darrick J. Wong
2021-01-19 3:56 ` Darrick J. Wong [this message]
2021-01-19 7:08 ` Christoph Hellwig
2021-01-19 19:43 ` Darrick J. Wong
2021-01-18 22:12 ` [PATCH 07/11] xfs: flush eof/cowblocks if we can't reserve quota for inode creation Darrick J. Wong
2021-01-18 22:12 ` [PATCH 08/11] xfs: flush eof/cowblocks if we can't reserve quota for chown Darrick J. Wong
2021-01-18 22:12 ` [PATCH 09/11] xfs: add a tracepoint for blockgc scans Darrick J. Wong
2021-01-19 7:11 ` Christoph Hellwig
2021-01-18 22:12 ` [PATCH 10/11] xfs: refactor xfs_icache_free_{eof,cow}blocks call sites Darrick J. Wong
2021-01-18 22:12 ` [PATCH 11/11] xfs: flush speculative space allocations when we run out of space Darrick J. Wong
2021-01-23 18:51 [PATCHSET v4 00/11] xfs: try harder to reclaim space when we run out Darrick J. Wong
2021-01-23 18:52 ` [PATCH 06/11] xfs: flush eof/cowblocks if we can't reserve quota for file blocks Darrick J. Wong
2021-01-24 9:39 ` Christoph Hellwig
2021-01-25 18:16 ` Brian Foster
2021-01-25 18:57 ` Darrick J. Wong
2021-01-26 13:26 ` Brian Foster
2021-01-26 21:12 ` Darrick J. Wong
2021-01-27 14:19 ` Brian Foster
2021-01-27 17:19 ` Darrick J. Wong
2021-01-28 6:02 [PATCHSET v5 00/11] xfs: try harder to reclaim space when we run out Darrick J. Wong
2021-01-28 6:02 ` [PATCH 06/11] xfs: flush eof/cowblocks if we can't reserve quota for file blocks Darrick J. Wong
2021-01-28 9:26 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210119035626.GM3134581@magnolia \
--to=djwong@kernel.org \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).