Message ID | 20240508061220.967970-7-yi.zhang@huaweicloud.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ext4: support adding multi-delalloc blocks | expand |
On Wed 08-05-24 14:12:16, Zhang Yi wrote: > From: Zhang Yi <yi.zhang@huawei.com> > > Rename ext4_es_insert_delayed_block() to ext4_es_insert_delayed_extent() > and pass length parameter to make it insert multiple delalloc blocks at > a time. For the case of bigalloc, split the allocated parameter to > lclu_allocated and end_allocated. lclu_allocated indicates the > allocation state of the cluster which is containing the lblk, > end_allocated indicates the allocation state of the extent end, clusters > in the middle of delay allocated extent must be unallocated. > > Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Looks good. Feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > fs/ext4/extents_status.c | 70 ++++++++++++++++++++++++++----------- > fs/ext4/extents_status.h | 5 +-- > fs/ext4/inode.c | 2 +- > include/trace/events/ext4.h | 16 +++++---- > 4 files changed, 62 insertions(+), 31 deletions(-) > > diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c > index 4a00e2f019d9..23caf1f028b0 100644 > --- a/fs/ext4/extents_status.c > +++ b/fs/ext4/extents_status.c > @@ -2052,34 +2052,49 @@ bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk) > } > > /* > - * ext4_es_insert_delayed_block - adds a delayed block to the extents status > - * tree, adding a pending reservation where > - * needed > + * ext4_es_insert_delayed_extent - adds some delayed blocks to the extents > + * status tree, adding a pending reservation > + * where needed > * > * @inode - file containing the newly added block > - * @lblk - logical block to be added > - * @allocated - indicates whether a physical cluster has been allocated for > - * the logical cluster that contains the block > + * @lblk - start logical block to be added > + * @len - length of blocks to be added > + * @lclu_allocated/end_allocated - indicates whether a physical cluster has > + * been allocated for the logical cluster > + * that contains the start/end block. Note that > + * end_allocated should always be set to false > + * if the start and the end block are in the > + * same cluster > */ > -void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, > - bool allocated) > +void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk, > + ext4_lblk_t len, bool lclu_allocated, > + bool end_allocated) > { > + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); > struct extent_status newes; > + ext4_lblk_t end = lblk + len - 1; > int err1 = 0, err2 = 0, err3 = 0; > struct extent_status *es1 = NULL; > struct extent_status *es2 = NULL; > - struct pending_reservation *pr = NULL; > + struct pending_reservation *pr1 = NULL; > + struct pending_reservation *pr2 = NULL; > > if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) > return; > > - es_debug("add [%u/1) delayed to extent status tree of inode %lu\n", > - lblk, inode->i_ino); > + es_debug("add [%u/%u) delayed to extent status tree of inode %lu\n", > + lblk, len, inode->i_ino); > + if (!len) > + return; > + > + WARN_ON_ONCE((EXT4_B2C(sbi, lblk) == EXT4_B2C(sbi, end)) && > + end_allocated); > > newes.es_lblk = lblk; > - newes.es_len = 1; > + newes.es_len = len; > ext4_es_store_pblock_status(&newes, ~0, EXTENT_STATUS_DELAYED); > - trace_ext4_es_insert_delayed_block(inode, &newes, allocated); > + trace_ext4_es_insert_delayed_extent(inode, &newes, lclu_allocated, > + end_allocated); > > ext4_es_insert_extent_check(inode, &newes); > > @@ -2088,11 +2103,15 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, > es1 = __es_alloc_extent(true); > if ((err1 || err2) && !es2) > es2 = __es_alloc_extent(true); > - if ((err1 || err2 || err3) && allocated && !pr) > - pr = __alloc_pending(true); > + if (err1 || err2 || err3) { > + if (lclu_allocated && !pr1) > + pr1 = __alloc_pending(true); > + if (end_allocated && !pr2) > + pr2 = __alloc_pending(true); > + } > write_lock(&EXT4_I(inode)->i_es_lock); > > - err1 = __es_remove_extent(inode, lblk, lblk, NULL, es1); > + err1 = __es_remove_extent(inode, lblk, end, NULL, es1); > if (err1 != 0) > goto error; > /* Free preallocated extent if it didn't get used. */ > @@ -2112,13 +2131,22 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, > es2 = NULL; > } > > - if (allocated) { > - err3 = __insert_pending(inode, lblk, &pr); > + if (lclu_allocated) { > + err3 = __insert_pending(inode, lblk, &pr1); > if (err3 != 0) > goto error; > - if (pr) { > - __free_pending(pr); > - pr = NULL; > + if (pr1) { > + __free_pending(pr1); > + pr1 = NULL; > + } > + } > + if (end_allocated) { > + err3 = __insert_pending(inode, end, &pr2); > + if (err3 != 0) > + goto error; > + if (pr2) { > + __free_pending(pr2); > + pr2 = NULL; > } > } > error: > diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h > index d9847a4a25db..3c8e2edee5d5 100644 > --- a/fs/ext4/extents_status.h > +++ b/fs/ext4/extents_status.h > @@ -249,8 +249,9 @@ extern void ext4_exit_pending(void); > extern void ext4_init_pending_tree(struct ext4_pending_tree *tree); > extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk); > extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk); > -extern void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, > - bool allocated); > +extern void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk, > + ext4_lblk_t len, bool lclu_allocated, > + bool end_allocated); > extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk, > ext4_lblk_t len); > extern void ext4_clear_inode_es(struct inode *inode); > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c > index de157aebc306..f64fe8b873ce 100644 > --- a/fs/ext4/inode.c > +++ b/fs/ext4/inode.c > @@ -1702,7 +1702,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) > } > } > > - ext4_es_insert_delayed_block(inode, lblk, allocated); > + ext4_es_insert_delayed_extent(inode, lblk, 1, allocated, false); > return 0; > } > > diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h > index a697f4b77162..6b41ac61310f 100644 > --- a/include/trace/events/ext4.h > +++ b/include/trace/events/ext4.h > @@ -2478,11 +2478,11 @@ TRACE_EVENT(ext4_es_shrink, > __entry->scan_time, __entry->nr_skipped, __entry->retried) > ); > > -TRACE_EVENT(ext4_es_insert_delayed_block, > +TRACE_EVENT(ext4_es_insert_delayed_extent, > TP_PROTO(struct inode *inode, struct extent_status *es, > - bool allocated), > + bool lclu_allocated, bool end_allocated), > > - TP_ARGS(inode, es, allocated), > + TP_ARGS(inode, es, lclu_allocated, end_allocated), > > TP_STRUCT__entry( > __field( dev_t, dev ) > @@ -2491,7 +2491,8 @@ TRACE_EVENT(ext4_es_insert_delayed_block, > __field( ext4_lblk_t, len ) > __field( ext4_fsblk_t, pblk ) > __field( char, status ) > - __field( bool, allocated ) > + __field( bool, lclu_allocated ) > + __field( bool, end_allocated ) > ), > > TP_fast_assign( > @@ -2501,16 +2502,17 @@ TRACE_EVENT(ext4_es_insert_delayed_block, > __entry->len = es->es_len; > __entry->pblk = ext4_es_show_pblock(es); > __entry->status = ext4_es_status(es); > - __entry->allocated = allocated; > + __entry->lclu_allocated = lclu_allocated; > + __entry->end_allocated = end_allocated; > ), > > TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s " > - "allocated %d", > + "allocated %d %d", > MAJOR(__entry->dev), MINOR(__entry->dev), > (unsigned long) __entry->ino, > __entry->lblk, __entry->len, > __entry->pblk, show_extent_status(__entry->status), > - __entry->allocated) > + __entry->lclu_allocated, __entry->end_allocated) > ); > > /* fsmap traces */ > -- > 2.39.2 >
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 4a00e2f019d9..23caf1f028b0 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -2052,34 +2052,49 @@ bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk) } /* - * ext4_es_insert_delayed_block - adds a delayed block to the extents status - * tree, adding a pending reservation where - * needed + * ext4_es_insert_delayed_extent - adds some delayed blocks to the extents + * status tree, adding a pending reservation + * where needed * * @inode - file containing the newly added block - * @lblk - logical block to be added - * @allocated - indicates whether a physical cluster has been allocated for - * the logical cluster that contains the block + * @lblk - start logical block to be added + * @len - length of blocks to be added + * @lclu_allocated/end_allocated - indicates whether a physical cluster has + * been allocated for the logical cluster + * that contains the start/end block. Note that + * end_allocated should always be set to false + * if the start and the end block are in the + * same cluster */ -void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, - bool allocated) +void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk, + ext4_lblk_t len, bool lclu_allocated, + bool end_allocated) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct extent_status newes; + ext4_lblk_t end = lblk + len - 1; int err1 = 0, err2 = 0, err3 = 0; struct extent_status *es1 = NULL; struct extent_status *es2 = NULL; - struct pending_reservation *pr = NULL; + struct pending_reservation *pr1 = NULL; + struct pending_reservation *pr2 = NULL; if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) return; - es_debug("add [%u/1) delayed to extent status tree of inode %lu\n", - lblk, inode->i_ino); + es_debug("add [%u/%u) delayed to extent status tree of inode %lu\n", + lblk, len, inode->i_ino); + if (!len) + return; + + WARN_ON_ONCE((EXT4_B2C(sbi, lblk) == EXT4_B2C(sbi, end)) && + end_allocated); newes.es_lblk = lblk; - newes.es_len = 1; + newes.es_len = len; ext4_es_store_pblock_status(&newes, ~0, EXTENT_STATUS_DELAYED); - trace_ext4_es_insert_delayed_block(inode, &newes, allocated); + trace_ext4_es_insert_delayed_extent(inode, &newes, lclu_allocated, + end_allocated); ext4_es_insert_extent_check(inode, &newes); @@ -2088,11 +2103,15 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, es1 = __es_alloc_extent(true); if ((err1 || err2) && !es2) es2 = __es_alloc_extent(true); - if ((err1 || err2 || err3) && allocated && !pr) - pr = __alloc_pending(true); + if (err1 || err2 || err3) { + if (lclu_allocated && !pr1) + pr1 = __alloc_pending(true); + if (end_allocated && !pr2) + pr2 = __alloc_pending(true); + } write_lock(&EXT4_I(inode)->i_es_lock); - err1 = __es_remove_extent(inode, lblk, lblk, NULL, es1); + err1 = __es_remove_extent(inode, lblk, end, NULL, es1); if (err1 != 0) goto error; /* Free preallocated extent if it didn't get used. */ @@ -2112,13 +2131,22 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, es2 = NULL; } - if (allocated) { - err3 = __insert_pending(inode, lblk, &pr); + if (lclu_allocated) { + err3 = __insert_pending(inode, lblk, &pr1); if (err3 != 0) goto error; - if (pr) { - __free_pending(pr); - pr = NULL; + if (pr1) { + __free_pending(pr1); + pr1 = NULL; + } + } + if (end_allocated) { + err3 = __insert_pending(inode, end, &pr2); + if (err3 != 0) + goto error; + if (pr2) { + __free_pending(pr2); + pr2 = NULL; } } error: diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h index d9847a4a25db..3c8e2edee5d5 100644 --- a/fs/ext4/extents_status.h +++ b/fs/ext4/extents_status.h @@ -249,8 +249,9 @@ extern void ext4_exit_pending(void); extern void ext4_init_pending_tree(struct ext4_pending_tree *tree); extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk); extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk); -extern void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, - bool allocated); +extern void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk, + ext4_lblk_t len, bool lclu_allocated, + bool end_allocated); extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len); extern void ext4_clear_inode_es(struct inode *inode); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index de157aebc306..f64fe8b873ce 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1702,7 +1702,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) } } - ext4_es_insert_delayed_block(inode, lblk, allocated); + ext4_es_insert_delayed_extent(inode, lblk, 1, allocated, false); return 0; } diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index a697f4b77162..6b41ac61310f 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h @@ -2478,11 +2478,11 @@ TRACE_EVENT(ext4_es_shrink, __entry->scan_time, __entry->nr_skipped, __entry->retried) ); -TRACE_EVENT(ext4_es_insert_delayed_block, +TRACE_EVENT(ext4_es_insert_delayed_extent, TP_PROTO(struct inode *inode, struct extent_status *es, - bool allocated), + bool lclu_allocated, bool end_allocated), - TP_ARGS(inode, es, allocated), + TP_ARGS(inode, es, lclu_allocated, end_allocated), TP_STRUCT__entry( __field( dev_t, dev ) @@ -2491,7 +2491,8 @@ TRACE_EVENT(ext4_es_insert_delayed_block, __field( ext4_lblk_t, len ) __field( ext4_fsblk_t, pblk ) __field( char, status ) - __field( bool, allocated ) + __field( bool, lclu_allocated ) + __field( bool, end_allocated ) ), TP_fast_assign( @@ -2501,16 +2502,17 @@ TRACE_EVENT(ext4_es_insert_delayed_block, __entry->len = es->es_len; __entry->pblk = ext4_es_show_pblock(es); __entry->status = ext4_es_status(es); - __entry->allocated = allocated; + __entry->lclu_allocated = lclu_allocated; + __entry->end_allocated = end_allocated; ), TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s " - "allocated %d", + "allocated %d %d", MAJOR(__entry->dev), MINOR(__entry->dev), (unsigned long) __entry->ino, __entry->lblk, __entry->len, __entry->pblk, show_extent_status(__entry->status), - __entry->allocated) + __entry->lclu_allocated, __entry->end_allocated) ); /* fsmap traces */