On Tue, 16 Nov 2010, Eric Sandeen wrote: > On 10/26/10 12:54 PM, Lukas Czerner wrote: > > In order to provide generic "discard" function for all e2fsprogs tools > > add a discard function prototype into struct_io_manager. Specific > > function for specific io managers can be crated that way. > > > > This commit also creates unix_discard function which uses BLKDISCARD > > ioctl to discard data blocks on the block device and bind it into > > unit_io_manager structure to be available for all e2fsprogs tools. > > Note that BLKDISCARD is still Linux specific ioctl, however other > > unix systems may provide similar functionality. So far the > > unix_discard() remains linux specific hence is embedded in #ifdef > > __linux__ macro. > > > > Signed-off-by: Lukas Czerner <lczerner@xxxxxxxxxx> > > --- > > lib/ext2fs/ext2_io.h | 2 ++ > > lib/ext2fs/unix_io.c | 41 +++++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 43 insertions(+), 0 deletions(-) > > > > diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h > > index ccc9c8b..d202007 100644 > > --- a/lib/ext2fs/ext2_io.h > > +++ b/lib/ext2fs/ext2_io.h > > @@ -83,6 +83,8 @@ struct struct_io_manager { > > int count, void *data); > > errcode_t (*write_blk64)(io_channel channel, unsigned long long block, > > int count, const void *data); > > + errcode_t (*discard)(io_channel channel, unsigned long long block, > > + unsigned long long count, const void *data); > > long reserved[16]; > > }; > > > > diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c > > index 1df1fdd..5b6cdec 100644 > > --- a/lib/ext2fs/unix_io.c > > +++ b/lib/ext2fs/unix_io.c > > @@ -115,6 +115,8 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, > > int count, void *data); > > static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, > > int count, const void *data); > > +static errcode_t unix_discard(io_channel channel, unsigned long long block, > > + unsigned long long count, const void *data); > > > > static struct struct_io_manager struct_unix_manager = { > > EXT2_ET_MAGIC_IO_MANAGER, > > @@ -130,6 +132,7 @@ static struct struct_io_manager struct_unix_manager = { > > unix_get_stats, > > unix_read_blk64, > > unix_write_blk64, > > + unix_discard, > > }; > > > > io_manager unix_io_manager = &struct_unix_manager; > > @@ -834,3 +837,41 @@ static errcode_t unix_set_option(io_channel channel, const char *option, > > } > > return EXT2_ET_INVALID_ARGUMENT; > > } > > + > > +#ifdef __linux__ > > + > > +#ifndef BLKDISCARD > > +#define BLKDISCARD _IO(0x12,119) > > +#endif > > + > > +static errcode_t unix_discard(io_channel channel, unsigned long long block, > > + unsigned long long count, const void *data) > > +{ > > + > > + struct struct_ext2_filsys *fs; > > + struct unix_private_data *u_priv; > > + errcode_t retval = 0; > > + __uint64_t range[2]; > > + int blocksize; > > + > > + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); > > + u_priv = (struct unix_private_data *) channel->private_data; > > + EXT2_CHECK_MAGIC(u_priv, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); > > + > > + fs = (struct struct_ext2_filsys *) data; > > + if (!fs) > > + return EXT2_ET_INVALID_ARGUMENT; > > + > > + blocksize = EXT2_BLOCK_SIZE(fs->super); > > This seems a little convoluted; you pass in *data, which gets you the fs, > from which you get the super, from which you get the blocksize, > which is all that you ever actually use here: > > > + range[0] = (__uint64_t)(block); > > + range[1] = (__uint64_t)(count); > > + range[0] *= (__uint64_t)(blocksize); > > + range[1] *= (__uint64_t)(blocksize); > > any reason to not just pass in the blocksize? > > Maybe this is for flexibility for not-linux, but I guess we don't know what > they need anyway...? > > And if you do that you can change "u_priv" to "data" just to match the > other handlers, perhaps. You're right, I was so closely following the example that I forget that it can be done more simply. Does this looks good to you ? static errcode_t unix_discard(io_channel channel, unsigned long long block, unsigned long long count, const void *blocksize) { unsigned int *bsize = (unsigned int *) blocksize; struct unix_private_data *data; errcode_t retval = 0; __uint64_t range[2]; EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); if (!blocksize) return EXT2_ET_INVALID_ARGUMENT; range[0] = (__uint64_t)(block); range[1] = (__uint64_t)(count); range[0] *= (__uint64_t)(*bsize); range[1] *= (__uint64_t)(*bsize); return ioctl(data->dev, BLKDISCARD, &range); } then we can call it like this: ret = manager->discard(fs->io, start, count, &fs->blocksize); Thanks a lot for reviewing this! -Lukas > > -Eric > > > + return ioctl(u_priv->dev, BLKDISCARD, &range); > > +} > > + > > +#else > > +#define unix_discard(channel, block, count) EXT2_ET_UNIMPLEMENTED > > +#endif > > -- -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html