Just some nitpicks, this otherwise looks fine. First during the last patches ifs as a variable name has started to really annoy me and I'm not sure why. I'd like to hear from the others, bu maybe just state might be a better name that flows easier? > +static void iomap_clear_range_dirty(struct folio *folio, size_t off, size_t len) > +{ > + struct iomap_folio_state *ifs = iomap_get_ifs(folio); > + > + if (!ifs) > + return; > + iomap_ifs_clear_range_dirty(folio, ifs, off, len); Maybe just do if (ifs) iomap_ifs_clear_range_dirty(folio, ifs, off, len); ? But also do we even need the ifs argument to iomap_ifs_clear_range_dirty after we've removed it everywhere else earlier? > + /* > + * When we have per-block dirty tracking, there can be > + * blocks within a folio which are marked uptodate > + * but not dirty. In that case it is necessary to punch > + * out such blocks to avoid leaking any delalloc blocks. > + */ > + ifs = iomap_get_ifs(folio); > + if (!ifs) > + goto skip_ifs_punch; > + > + last_byte = min_t(loff_t, end_byte - 1, > + (folio_next_index(folio) << PAGE_SHIFT) - 1); > + first_blk = offset_in_folio(folio, start_byte) >> blkbits; > + last_blk = offset_in_folio(folio, last_byte) >> blkbits; > + for (i = first_blk; i <= last_blk; i++) { > + if (!iomap_ifs_is_block_dirty(folio, ifs, i)) { > + ret = punch(inode, folio_pos(folio) + (i << blkbits), > + 1 << blkbits); > + if (ret) > + goto out; > + } > + } > + > +skip_ifs_punch: And happy to hear from the others, but to me having a helper for all the iomap_folio_state manipulation rather than having it in the middle of the function and jumped over if not needed would improve the code structure.