lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 7 Jun 2018 16:47:18 -0400
From:   Eric Whitney <enwlinux@...il.com>
To:     Jan Kara <jack@...e.cz>
Cc:     Eric Whitney <enwlinux@...il.com>, linux-ext4@...r.kernel.org,
        tytso@....edu
Subject: Re: [RFC PATCH 1/5] ext4: fix reserved cluster accounting at delayed
 write time

* Jan Kara <jack@...e.cz>:
> On Sun 13-05-18 13:56:20, Eric Whitney wrote:
> > The code in ext4_da_map_blocks sometimes reserves space for more
> > delayed allocated clusters than it should, resulting in premature
> > ENOSPC, exceeded quota, and inaccurate free space reporting.
> > 
> > It fails to check the extents status tree for written and unwritten
> > clusters which have already been allocated and which share a cluster
> > with the block being delayed allocated.  In addition, it fails to
> > continue on and search the extent tree when no delayed allocated or
> > allocated clusters have been found in the extents status tree.  Written
> > extents may be purged from the extents status tree under memory pressure.
> > Only delayed and unwritten delayed extents are guaranteed to be retained.
> > 
> > Signed-off-by: Eric Whitney <enwlinux@...il.com>
> 
> Thanks for the patch Eric. Some comments are below.
> 
> > diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> > index c969275ce3ee..872782ba8bc3 100644
> > --- a/fs/ext4/extents.c
> > +++ b/fs/ext4/extents.c
> > @@ -3846,6 +3846,47 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
> >  	return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
> >  }
> >  
> > +/*
> > + * If the block range specified by @start and @end contains an es extent
> > + * matched by the matching function specified by @match_fn, return 1.  Else,
> > + * return 0.
> > + */
> > +int ext4_find_range(struct inode *inode,
> > +		    int (*match_fn)(struct extent_status *es),
> > +		    ext4_lblk_t start,
> > +		    ext4_lblk_t end)
> > +{
> > +	struct extent_status es;
> > +
> > +	ext4_es_find_extent_range(inode, match_fn, start, end, &es);
> > +	if (es.es_len == 0)
> > +		return 0; /* there is no matching extent in this tree */
> > +	else if (es.es_lblk <= start &&
> > +		 start < es.es_lblk + es.es_len)
> > +		return 1;
> > +	else if (start <= es.es_lblk && es.es_lblk <= end)
> > +		return 1;
> > +	else
> > +		return 0;
> 
> No need to elses here. Also how could is possibly happen that es.es_len > 0
> and we don't have an extent we want? That would be a bug in
> ext4_es_find_extent_range(), wouldn't it?

Hi, Jan:

Yes, I just cloned ext4_find_delalloc_range() here without looking too
critically at it.  I'll clean this up.

I think we can get an out of range extent here given the implementation
of __es_tree_search(), called by ext4_es_find_extent_range().  If "start"
isn't contained in an extent in the extents status tree, we could get back
an extent containing block numbers bigger than "start".  Rejecting a match
if es.es_lblk > end should handle that (and a xfstests-bld run of the 4k
test case appears to confirm).  So the conditional becomes:
	if (es.es_lblk > end || es.es_len == 0)
		return 0;
	else
		return 1;

> 
> > diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
> > index 763ef185dd17..0c395b5a57a2 100644
> > --- a/fs/ext4/extents_status.c
> > +++ b/fs/ext4/extents_status.c
> > @@ -296,6 +296,70 @@ void ext4_es_find_delayed_extent_range(struct inode *inode,
> >  	trace_ext4_es_find_delayed_extent_range_exit(inode, es);
> >  }
> >  
> > +/*
> > + * Find the first es extent in the block range specified by @lblk and @end
> > + * that satisfies the matching function specified by @match_fn.  If a
> > + * match is found, it's returned in @es.  If not, a struct extents_status
> > + * is returned in @es whose es_lblk, es_len, and es_pblk components are 0.
> > + *
> > + * This function is derived from ext4_es_find_delayed_extent_range().
> > + * In the future, it could be used to replace it with the use of a suitable
> > + * matching function to avoid redundant code.
> > + */
> 
> Yes, please do that - write a separate patch implementing
> ext4_es_find_extent_range() and make ext4_es_find_delayed_extent_range()
> use it.
> 
> Otherwise the patch looks good to me.

I'll do that.

Thanks for your review!

Eric

> 
> 								Honza
> -- 
> Jan Kara <jack@...e.com>
> SUSE Labs, CR

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux - Powered by OpenVZ