Re: [PATCH] xfs: clean up xfs_mount allocation and dynamic initializers

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

 



On Wed, Mar 21, 2018 at 10:27:28AM -0700, Darrick J. Wong wrote:
> On Wed, Mar 21, 2018 at 12:13:25PM -0400, Brian Foster wrote:
> > Most of the generic data structures embedded in xfs_mount are
> > dynamically initialized immediately after mp is allocated. A few
> > fields are left out and initialized during the xfs_mountfs()
> > sequence, after mp has been attached to the superblock.
> > 
> > To clean this up and help prevent premature access of associated
> > fields, refactor xfs_mount allocation and all dependent init calls
> > into a new helper. This self-documents that all low level data
> > structures (i.e., locks, trees, etc.) should be initialized before
> > xfs_mount is attached to the superblock.
> > 
> > Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
> > ---
> > 
> > I realized after the fact that this steps on the ability to instrument
> > the use-before-init variant[1] of the problematic radix tree access on
> > failed mount issue that Dave tracked down. This is because we'd
> > immediately initialize the structure and thus a subsequent memset()
> > would ultimately require another proper initialization.
> 
> That's simply a matter of re-calling
> 
> 	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
> 
> after the msleep, right?
> 

I suppose that may work (I'll let Dave chime in)...

> > As Dave noted in that thread, we could alternatively instrument the
> > use-after-free variant of the problem with a post-free delay of the mp.
> > I actually wonder if a last step instrumented failure in fill_super()
> > might be a more broadly useful test because it provides future coverage
> > of the entire mount teardown sequence rather than just the bad radix
> > tree access.
> 
> That sounds like a very good idea, there's a lot of complex stuff that
> has to be unwound and at least I've stumbled over getting it right.
> 

... but it sounds like we agree this may be preferable anyways. ;)

> > On the flipside, this patch isn't the cleanup of the century so I'd be
> > fine with dropping it in favor of [1], but I think it's worthy enough to
> > consider.
> > 
> > Brian
> > 
> > [1] https://marc.info/?l=linux-xfs&m=152152202700598&w=2
> > 
> >  fs/xfs/libxfs/xfs_sb.c |  1 -
> >  fs/xfs/xfs_mount.c     |  2 --
> >  fs/xfs/xfs_super.c     | 39 +++++++++++++++++++++++++++++----------
> >  3 files changed, 29 insertions(+), 13 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> > index a55f7a45fa78..53433cc024fd 100644
> > --- a/fs/xfs/libxfs/xfs_sb.c
> > +++ b/fs/xfs/libxfs/xfs_sb.c
> > @@ -731,7 +731,6 @@ xfs_sb_mount_common(
> >  	struct xfs_sb	*sbp)
> >  {
> >  	mp->m_agfrotor = mp->m_agirotor = 0;
> 
> Can this be removed since we're using kzalloc now?
> 

Hm, that's one example where we actually don't rely on the zeroed
allocation. I suppose we could remove that, but note this patch doesn't
introduce the use of kzalloc(). I actually don't mind seeing code like
the above if the developer wants to be clear about intent. (I also don't
consider it a requirement given the use of kzalloc(), so just my .02).

> Mostly looks ok to me, though I wonder if the INIT_DONE flag can be
> replaced with radix_tree_empty() now that we're guaranteed never to see
> an mp with an uninitialized perag radix tree?
> 

I'm not sure we even need that. The lookup should just return NULL if
the tree is empty or partially populated. That's probably what already
happens today due to kzalloc(), so this patch is really just more of a
cleanup...

(It sounds like Dave was looking into more generic shrinker changes and
thus may have other reasons to avoid the flag anyways, but that's for
the other[1] thread...).

Brian

> --D
> 
> > -	spin_lock_init(&mp->m_agirotor_lock);
> >  	mp->m_maxagi = mp->m_sb.sb_agcount;
> >  	mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
> >  	mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
> > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> > index 6f5a5e6764d8..a901b86772f8 100644
> > --- a/fs/xfs/xfs_mount.c
> > +++ b/fs/xfs/xfs_mount.c
> > @@ -817,8 +817,6 @@ xfs_mountfs(
> >  	/*
> >  	 * Allocate and initialize the per-ag data.
> >  	 */
> > -	spin_lock_init(&mp->m_perag_lock);
> > -	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
> >  	error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
> >  	if (error) {
> >  		xfs_warn(mp, "Failed per-ag init: %d", error);
> > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> > index 951271f57d00..612c1d5348b3 100644
> > --- a/fs/xfs/xfs_super.c
> > +++ b/fs/xfs/xfs_super.c
> > @@ -1579,29 +1579,48 @@ xfs_destroy_percpu_counters(
> >  	percpu_counter_destroy(&mp->m_fdblocks);
> >  }
> >  
> > -STATIC int
> > -xfs_fs_fill_super(
> > -	struct super_block	*sb,
> > -	void			*data,
> > -	int			silent)
> > +static struct xfs_mount *
> > +xfs_mount_alloc(
> > +	struct super_block	*sb)
> >  {
> > -	struct inode		*root;
> > -	struct xfs_mount	*mp = NULL;
> > -	int			flags = 0, error = -ENOMEM;
> > +	struct xfs_mount	*mp;
> >  
> >  	mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL);
> >  	if (!mp)
> > -		goto out;
> > +		return NULL;
> >  
> > +	mp->m_super = sb;
> >  	spin_lock_init(&mp->m_sb_lock);
> > +	spin_lock_init(&mp->m_agirotor_lock);
> > +	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
> > +	spin_lock_init(&mp->m_perag_lock);
> >  	mutex_init(&mp->m_growlock);
> >  	atomic_set(&mp->m_active_trans, 0);
> >  	INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
> >  	INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);
> >  	INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker);
> >  	mp->m_kobj.kobject.kset = xfs_kset;
> > +	return mp;
> > +}
> >  
> > -	mp->m_super = sb;
> > +
> > +STATIC int
> > +xfs_fs_fill_super(
> > +	struct super_block	*sb,
> > +	void			*data,
> > +	int			silent)
> > +{
> > +	struct inode		*root;
> > +	struct xfs_mount	*mp = NULL;
> > +	int			flags = 0, error = -ENOMEM;
> > +
> > +	/*
> > +	 * allocate mp and do all low-level struct initializations before we
> > +	 * attach it to the super
> > +	 */
> > +	mp = xfs_mount_alloc(sb);
> > +	if (!mp)
> > +		goto out;
> >  	sb->s_fs_info = mp;
> >  
> >  	error = xfs_parseargs(mp, (char *)data);
> > -- 
> > 2.13.6
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux