Re: [PATCH 13/47] libext2fs: add a way to check the theoretical maximum extent tree depth

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Dec 13, 2014 at 09:23:57PM -0500, Theodore Ts'o wrote:
> On Fri, Nov 07, 2014 at 01:52:12PM -0800, Darrick J. Wong wrote:
> > Add an API so that client programs can discover a reasonable maximum
> > extent tree depth.  This will eventually be used by e2fsck as one of
> > the criteria to decide if an extent-based file should have its extent
> > tree rebuilt.
> > 
> > +size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle)
> > +{
> > +	size_t iblock_sz = sizeof(((struct ext2_inode *)NULL)->i_block);
> > +	size_t iblock_extents = (iblock_sz - sizeof(struct ext3_extent_header)) /
> > +				sizeof(struct ext3_extent);
> > +	size_t extents_per_block = (handle->fs->blocksize -
> > +				    sizeof(struct ext3_extent_header)) /
> > +				   sizeof(struct ext3_extent);
> > +
> > +	return 1 + ((ul_log2(EXT_MAX_EXTENT_LBLK) - ul_log2(iblock_extents)) /
> > +		    ul_log2(extents_per_block));
> > +}
> > +
> 
> This patch is only used by patch #33, and it gets called for every
> single inode which is extent-mapped.
> 
> But if you look at the above code, there is nothing which is inode or
> handle specific.  The value is only dependent on fs->blocksize.  But
> to calculate this value the function calls ul_log2 three times, which
> is implemented using a looping construct.  So we will be recalculating
> what is effectively a constant value every single inode in an ext4
> file system, which seems very unfortunate.

How about I save the last fs->blocksize and the last result, and return the
cached last result if fs->blocksize == lastblocksize?

--D

> 
> BTW, there are some ways we could accelerate the log2 function, and
> I've considered implementing an ext2fs_log2_u32() and
> ext2fs_log2_u64() using something like this:
> 
> int log2i(unsigned int x)
> {
> 	if (!x)
> 		return 0;
> 
> 	return sizeof(unsigned int) * 8 - __builtin_clz(x) - 1;
> }
> 
> or
> 
> int log2u64(unsigned long long x)
> {
> 	if (!x)
> 		return 0;
> 
> 	return sizeof(unsigned long long) * 8 - __builtin_clzll(x) - 1;
> }
> 
> or
> 
> int generic_log2(unsigned int x)
> {
> 	int r = 0;
> 
> 	if (x >= ((unsigned int)(1) << 16)) {
> 		r += 16;
> 		x >>= 16;
> 	}
> 	if (x >= ((unsigned int)(1) << 8)) {
> 		r += 8;
> 		x >>= 8;
> 	}
> 	if (x >= ((unsigned int)(1) << 4)) {
> 		r += 4;
> 		x >>= 4;
> 	}
> 	if (x >= ((unsigned int)(1) << 2)) {
> 		r += 2;
> 		x >>= 2;
> 	}
> 	if (x >= ((unsigned int)(1) << 1)) {
> 		r += 1;
> 		x >>= 1;
> 	}
> 	return r;
> }
> 
> But it's not at all clear it's worth doing this because I haven't seen
> any place in e2fsprogs where we really should be calculating an
> integer log2 in a tight loop where performance should make a
> difference.  If we are, we're probably doing something wrong....
> 
> 	     	   	      	       	     	       - Ted
--
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




[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux