On Tue, Oct 20, 2020 at 12:21:50PM -0400, Brian Foster wrote: > Ugh, so the above doesn't quite describe historical behavior. > block_truncate_page() converts an unwritten block if a page exists > (dirty or not), but bails out if a page doesn't exist. We could still do > the above, but if we wanted something more intelligent I think we need > to check for a page before we get the mapping to know whether we can > safely skip an unwritten block or need to write over it. Otherwise if we > check for a page within the actor, we have no way of knowing whether > there was a (possibly dirty) page that had been written back and/or > reclaimed since ->iomap_begin(). If we check for the page first, I think > that the iolock/mmaplock in the truncate path ensures that a page can't > be added before we complete. We might be able to take that further and > check for a dirty || writeback page, but that might be safer as a > separate patch. See the (compile tested only) diff below for an idea of > what I was thinking. The idea looks reasonable, but a few comment below: > +struct iomap_trunc_priv { > + bool *did_zero; I don't think there is any point on using a pointer here, when we can trivially copy out the scalar value. > + bool has_page; The naming of this flag really confuses me. Maybe has_data or in_pagecache might be better options? > +static loff_t > +iomap_truncate_page_actor(struct inode *inode, loff_t pos, loff_t count, > + void *data, struct iomap *iomap, struct iomap *srcmap) > +{ > + struct iomap_trunc_priv *priv = data; > + unsigned offset; > + int status; > + > + if (srcmap->type == IOMAP_HOLE) > + return count; > + if (srcmap->type == IOMAP_UNWRITTEN && !priv->has_page) > + return count; Maybe add a comment here to explain why priv->has_page matters? > + > + offset = offset_in_page(pos); I'd move this on the initialization line. > + ret = iomap_apply(inode, pos, blocksize - off, IOMAP_ZERO, ops, &priv, > + iomap_truncate_page_actor); > + if (ret <= 0) > + return ret; The check could just be < 0 and would be a little more obvious.