Message ID | 20250408104209.1852036-3-john.g.garry@oracle.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | large atomic writes for xfs | expand |
On Tue, Apr 08, 2025 at 10:41:59AM +0000, John Garry wrote: > From: "Darrick J. Wong" <djwong@kernel.org> > > Add selected helpers to estimate the transaction reservation required to > write various log intent and buffer items to the log. These helpers > will be used by the online repair code for more precise estimations of > how much work can be done in a single transaction. > > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > Signed-off-by: John Garry <john.g.garry@oracle.com> > --- > fs/xfs/libxfs/xfs_trans_resv.c | 6 +++--- > fs/xfs/libxfs/xfs_trans_resv.h | 4 ++++ > fs/xfs/xfs_bmap_item.c | 10 ++++++++++ > fs/xfs/xfs_bmap_item.h | 3 +++ > fs/xfs/xfs_buf_item.c | 19 +++++++++++++++++++ > fs/xfs/xfs_buf_item.h | 3 +++ > fs/xfs/xfs_extfree_item.c | 10 ++++++++++ > fs/xfs/xfs_extfree_item.h | 3 +++ > fs/xfs/xfs_log_cil.c | 4 +--- > fs/xfs/xfs_log_priv.h | 13 +++++++++++++ > fs/xfs/xfs_refcount_item.c | 10 ++++++++++ > fs/xfs/xfs_refcount_item.h | 3 +++ > fs/xfs/xfs_rmap_item.c | 10 ++++++++++ > fs/xfs/xfs_rmap_item.h | 3 +++ > 14 files changed, 95 insertions(+), 6 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c > index 13d00c7166e1..ce1393bd3561 100644 > --- a/fs/xfs/libxfs/xfs_trans_resv.c > +++ b/fs/xfs/libxfs/xfs_trans_resv.c > @@ -47,7 +47,7 @@ xfs_buf_log_overhead(void) > * will be changed in a transaction. size is used to tell how many > * bytes should be reserved per item. > */ > -STATIC uint > +uint > xfs_calc_buf_res( > uint nbufs, > uint size) > @@ -84,7 +84,7 @@ xfs_allocfree_block_count( > * in the same transaction as an allocation or a free, so we compute them > * separately. > */ > -static unsigned int > +unsigned int > xfs_refcountbt_block_count( > struct xfs_mount *mp, > unsigned int num_ops) > @@ -129,7 +129,7 @@ xfs_rtrefcountbt_block_count( > * additional to the records and pointers that fit inside the inode > * forks. > */ > -STATIC uint > +uint > xfs_calc_inode_res( > struct xfs_mount *mp, > uint ninodes) > diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h > index 0554b9d775d2..e76052028cc9 100644 > --- a/fs/xfs/libxfs/xfs_trans_resv.h > +++ b/fs/xfs/libxfs/xfs_trans_resv.h > @@ -97,6 +97,10 @@ struct xfs_trans_resv { > > void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); > uint xfs_allocfree_block_count(struct xfs_mount *mp, uint num_ops); > +unsigned int xfs_refcountbt_block_count(struct xfs_mount *mp, > + unsigned int num_ops); > +uint xfs_calc_buf_res(uint nbufs, uint size); > +uint xfs_calc_inode_res(struct xfs_mount *mp, uint ninodes); Why are these exported? They aren't used in this patch, and any code that doing calculate log reservation calculation should really be placed in xfs_trans_resv.c along with all the existing log reservation calculations... -Dave
On Wed, Apr 09, 2025 at 08:50:57AM +1000, Dave Chinner wrote: > On Tue, Apr 08, 2025 at 10:41:59AM +0000, John Garry wrote: > > From: "Darrick J. Wong" <djwong@kernel.org> > > > > Add selected helpers to estimate the transaction reservation required to > > write various log intent and buffer items to the log. These helpers > > will be used by the online repair code for more precise estimations of > > how much work can be done in a single transaction. > > > > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> > > Signed-off-by: John Garry <john.g.garry@oracle.com> > > --- > > fs/xfs/libxfs/xfs_trans_resv.c | 6 +++--- > > fs/xfs/libxfs/xfs_trans_resv.h | 4 ++++ > > fs/xfs/xfs_bmap_item.c | 10 ++++++++++ > > fs/xfs/xfs_bmap_item.h | 3 +++ > > fs/xfs/xfs_buf_item.c | 19 +++++++++++++++++++ > > fs/xfs/xfs_buf_item.h | 3 +++ > > fs/xfs/xfs_extfree_item.c | 10 ++++++++++ > > fs/xfs/xfs_extfree_item.h | 3 +++ > > fs/xfs/xfs_log_cil.c | 4 +--- > > fs/xfs/xfs_log_priv.h | 13 +++++++++++++ > > fs/xfs/xfs_refcount_item.c | 10 ++++++++++ > > fs/xfs/xfs_refcount_item.h | 3 +++ > > fs/xfs/xfs_rmap_item.c | 10 ++++++++++ > > fs/xfs/xfs_rmap_item.h | 3 +++ > > 14 files changed, 95 insertions(+), 6 deletions(-) > > > > diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c > > index 13d00c7166e1..ce1393bd3561 100644 > > --- a/fs/xfs/libxfs/xfs_trans_resv.c > > +++ b/fs/xfs/libxfs/xfs_trans_resv.c > > @@ -47,7 +47,7 @@ xfs_buf_log_overhead(void) > > * will be changed in a transaction. size is used to tell how many > > * bytes should be reserved per item. > > */ > > -STATIC uint > > +uint > > xfs_calc_buf_res( > > uint nbufs, > > uint size) > > @@ -84,7 +84,7 @@ xfs_allocfree_block_count( > > * in the same transaction as an allocation or a free, so we compute them > > * separately. > > */ > > -static unsigned int > > +unsigned int > > xfs_refcountbt_block_count( > > struct xfs_mount *mp, > > unsigned int num_ops) > > @@ -129,7 +129,7 @@ xfs_rtrefcountbt_block_count( > > * additional to the records and pointers that fit inside the inode > > * forks. > > */ > > -STATIC uint > > +uint > > xfs_calc_inode_res( > > struct xfs_mount *mp, > > uint ninodes) > > diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h > > index 0554b9d775d2..e76052028cc9 100644 > > --- a/fs/xfs/libxfs/xfs_trans_resv.h > > +++ b/fs/xfs/libxfs/xfs_trans_resv.h > > @@ -97,6 +97,10 @@ struct xfs_trans_resv { > > > > void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); > > uint xfs_allocfree_block_count(struct xfs_mount *mp, uint num_ops); > > +unsigned int xfs_refcountbt_block_count(struct xfs_mount *mp, > > + unsigned int num_ops); > > +uint xfs_calc_buf_res(uint nbufs, uint size); > > +uint xfs_calc_inode_res(struct xfs_mount *mp, uint ninodes); > > Why are these exported? They aren't used in this patch, and any code > that doing calculate log reservation calculation should really be > placed in xfs_trans_resv.c along with all the existing log > reservation calculations... I've redone this in a different manner, will send a full patchset after it runs through QA. --D > -Dave > -- > Dave Chinner > david@fromorbit.com
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 13d00c7166e1..ce1393bd3561 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -47,7 +47,7 @@ xfs_buf_log_overhead(void) * will be changed in a transaction. size is used to tell how many * bytes should be reserved per item. */ -STATIC uint +uint xfs_calc_buf_res( uint nbufs, uint size) @@ -84,7 +84,7 @@ xfs_allocfree_block_count( * in the same transaction as an allocation or a free, so we compute them * separately. */ -static unsigned int +unsigned int xfs_refcountbt_block_count( struct xfs_mount *mp, unsigned int num_ops) @@ -129,7 +129,7 @@ xfs_rtrefcountbt_block_count( * additional to the records and pointers that fit inside the inode * forks. */ -STATIC uint +uint xfs_calc_inode_res( struct xfs_mount *mp, uint ninodes) diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h index 0554b9d775d2..e76052028cc9 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.h +++ b/fs/xfs/libxfs/xfs_trans_resv.h @@ -97,6 +97,10 @@ struct xfs_trans_resv { void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); uint xfs_allocfree_block_count(struct xfs_mount *mp, uint num_ops); +unsigned int xfs_refcountbt_block_count(struct xfs_mount *mp, + unsigned int num_ops); +uint xfs_calc_buf_res(uint nbufs, uint size); +uint xfs_calc_inode_res(struct xfs_mount *mp, uint ninodes); unsigned int xfs_calc_itruncate_reservation_minlogsize(struct xfs_mount *mp); unsigned int xfs_calc_write_reservation_minlogsize(struct xfs_mount *mp); diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index 3d52e9d7ad57..c62b9c1dd448 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -77,6 +77,11 @@ xfs_bui_item_size( *nbytes += xfs_bui_log_format_sizeof(buip->bui_format.bui_nextents); } +unsigned int xfs_bui_item_overhead(unsigned int nr) +{ + return xlog_item_space(1, xfs_bui_log_format_sizeof(nr)); +} + /* * This is called to fill in the vector of log iovecs for the * given bui log item. We use only 1 iovec, and we point that @@ -168,6 +173,11 @@ xfs_bud_item_size( *nbytes += sizeof(struct xfs_bud_log_format); } +unsigned int xfs_bud_item_overhead(void) +{ + return xlog_item_space(1, sizeof(struct xfs_bud_log_format)); +} + /* * This is called to fill in the vector of log iovecs for the * given bud log item. We use only 1 iovec, and we point that diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h index 6fee6a508343..655b30bc1736 100644 --- a/fs/xfs/xfs_bmap_item.h +++ b/fs/xfs/xfs_bmap_item.h @@ -72,4 +72,7 @@ struct xfs_bmap_intent; void xfs_bmap_defer_add(struct xfs_trans *tp, struct xfs_bmap_intent *bi); +unsigned int xfs_bui_item_overhead(unsigned int nr); +unsigned int xfs_bud_item_overhead(void); + #endif /* __XFS_BMAP_ITEM_H__ */ diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 19eb0b7a3e58..f89fb81517c9 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -103,6 +103,25 @@ xfs_buf_item_size_segment( return; } +/* + * Compute the worst case log item overhead for an invalidated buffer with the + * given map count and block size. + */ +unsigned int +xfs_buf_inval_item_overhead( + unsigned int map_count, + unsigned int blocksize) +{ + unsigned int chunks = DIV_ROUND_UP(blocksize, XFS_BLF_CHUNK); + unsigned int bitmap_size = DIV_ROUND_UP(chunks, NBWORD); + unsigned int ret = + offsetof(struct xfs_buf_log_format, blf_data_map) + + (bitmap_size * sizeof_field(struct xfs_buf_log_format, + blf_data_map[0])); + + return ret * map_count; +} + /* * Return the number of log iovecs and space needed to log the given buf log * item. diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 8cde85259a58..a273f45b558d 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h @@ -64,6 +64,9 @@ static inline void xfs_buf_dquot_iodone(struct xfs_buf *bp) void xfs_buf_iodone(struct xfs_buf *); bool xfs_buf_log_check_iovec(struct xfs_log_iovec *iovec); +unsigned int xfs_buf_inval_item_overhead(unsigned int map_count, + unsigned int blocksize); + extern struct kmem_cache *xfs_buf_item_cache; #endif /* __XFS_BUF_ITEM_H__ */ diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 777438b853da..3454eb643627 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -83,6 +83,11 @@ xfs_efi_item_size( *nbytes += xfs_efi_log_format_sizeof(efip->efi_format.efi_nextents); } +unsigned int xfs_efi_item_overhead(unsigned int nr) +{ + return xlog_item_space(1, xfs_efi_log_format_sizeof(nr)); +} + /* * This is called to fill in the vector of log iovecs for the * given efi log item. We use only 1 iovec, and we point that @@ -254,6 +259,11 @@ xfs_efd_item_size( *nbytes += xfs_efd_log_format_sizeof(efdp->efd_format.efd_nextents); } +unsigned int xfs_efd_item_overhead(unsigned int nr) +{ + return xlog_item_space(1, xfs_efd_log_format_sizeof(nr)); +} + /* * This is called to fill in the vector of log iovecs for the * given efd log item. We use only 1 iovec, and we point that diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h index 41b7c4306079..ebb237a4ae87 100644 --- a/fs/xfs/xfs_extfree_item.h +++ b/fs/xfs/xfs_extfree_item.h @@ -94,4 +94,7 @@ void xfs_extent_free_defer_add(struct xfs_trans *tp, struct xfs_extent_free_item *xefi, struct xfs_defer_pending **dfpp); +unsigned int xfs_efi_item_overhead(unsigned int nr); +unsigned int xfs_efd_item_overhead(unsigned int nr); + #endif /* __XFS_EXTFREE_ITEM_H__ */ diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 1ca406ec1b40..f66d2d430e4f 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -309,9 +309,7 @@ xlog_cil_alloc_shadow_bufs( * Then round nbytes up to 64-bit alignment so that the initial * buffer alignment is easy to calculate and verify. */ - nbytes += niovecs * - (sizeof(uint64_t) + sizeof(struct xlog_op_header)); - nbytes = round_up(nbytes, sizeof(uint64_t)); + nbytes = xlog_item_space(niovecs, nbytes); /* * The data buffer needs to start 64-bit aligned, so round up diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index f3d78869e5e5..39a102cc1b43 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -698,4 +698,17 @@ xlog_kvmalloc( return p; } +/* + * Given a count of iovecs and space for a log item, compute the space we need + * in the log to store that data plus the log headers. + */ +static inline unsigned int +xlog_item_space( + unsigned int niovecs, + unsigned int nbytes) +{ + nbytes += niovecs * (sizeof(uint64_t) + sizeof(struct xlog_op_header)); + return round_up(nbytes, sizeof(uint64_t)); +} + #endif /* __XFS_LOG_PRIV_H__ */ diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c index fe2d7aab8554..02defb711641 100644 --- a/fs/xfs/xfs_refcount_item.c +++ b/fs/xfs/xfs_refcount_item.c @@ -78,6 +78,11 @@ xfs_cui_item_size( *nbytes += xfs_cui_log_format_sizeof(cuip->cui_format.cui_nextents); } +unsigned int xfs_cui_item_overhead(unsigned int nr) +{ + return xlog_item_space(1, xfs_cui_log_format_sizeof(nr)); +} + /* * This is called to fill in the vector of log iovecs for the * given cui log item. We use only 1 iovec, and we point that @@ -179,6 +184,11 @@ xfs_cud_item_size( *nbytes += sizeof(struct xfs_cud_log_format); } +unsigned int xfs_cud_item_overhead(void) +{ + return xlog_item_space(1, sizeof(struct xfs_cud_log_format)); +} + /* * This is called to fill in the vector of log iovecs for the * given cud log item. We use only 1 iovec, and we point that diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h index bfee8f30c63c..5976cf0a04a6 100644 --- a/fs/xfs/xfs_refcount_item.h +++ b/fs/xfs/xfs_refcount_item.h @@ -76,4 +76,7 @@ struct xfs_refcount_intent; void xfs_refcount_defer_add(struct xfs_trans *tp, struct xfs_refcount_intent *ri); +unsigned int xfs_cui_item_overhead(unsigned int nr); +unsigned int xfs_cud_item_overhead(void); + #endif /* __XFS_REFCOUNT_ITEM_H__ */ diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c index 89decffe76c8..452300725641 100644 --- a/fs/xfs/xfs_rmap_item.c +++ b/fs/xfs/xfs_rmap_item.c @@ -77,6 +77,11 @@ xfs_rui_item_size( *nbytes += xfs_rui_log_format_sizeof(ruip->rui_format.rui_nextents); } +unsigned int xfs_rui_item_overhead(unsigned int nr) +{ + return xlog_item_space(1, xfs_rui_log_format_sizeof(nr)); +} + /* * This is called to fill in the vector of log iovecs for the * given rui log item. We use only 1 iovec, and we point that @@ -180,6 +185,11 @@ xfs_rud_item_size( *nbytes += sizeof(struct xfs_rud_log_format); } +unsigned int xfs_rud_item_overhead(void) +{ + return xlog_item_space(1, sizeof(struct xfs_rud_log_format)); +} + /* * This is called to fill in the vector of log iovecs for the * given rud log item. We use only 1 iovec, and we point that diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h index 40d331555675..0dac2cfe4567 100644 --- a/fs/xfs/xfs_rmap_item.h +++ b/fs/xfs/xfs_rmap_item.h @@ -75,4 +75,7 @@ struct xfs_rmap_intent; void xfs_rmap_defer_add(struct xfs_trans *tp, struct xfs_rmap_intent *ri); +unsigned int xfs_rui_item_overhead(unsigned int nr); +unsigned int xfs_rud_item_overhead(void); + #endif /* __XFS_RMAP_ITEM_H__ */