Re: [PATCH 06/32] target: Convert lu_gp_ref_cnt to kref

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

 



On Wed, 2014-02-05 at 14:02 -0800, Andy Grover wrote:
> Hi nab, I'm getting back to looking at this patchset, but wanted to just
> discuss and understand this one first because all the kref ones are
> similar. see below.
> 
> On 12/16/2013 12:52 PM, Nicholas A. Bellinger wrote:
> > On Fri, 2013-12-13 at 15:58 -0800, Andy Grover wrote:
> >> Use kref to handle reference counting
> >>
> >> Signed-off-by: Andy Grover <agrover@xxxxxxxxxx>
> >> ---
> >>  drivers/target/target_core_alua.c |   37 ++++++++++++++++++++-----------------
> >>  include/target/target_core_base.h |    2 +-
> >>  2 files changed, 21 insertions(+), 18 deletions(-)
> >>
> >> diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
> >> index 2ac2f11..8c01ade 100644
> >> --- a/drivers/target/target_core_alua.c
> >> +++ b/drivers/target/target_core_alua.c
> >> @@ -54,6 +54,16 @@ static LIST_HEAD(lu_gps_list);
> >>  
> >>  struct t10_alua_lu_gp *default_lu_gp;
> >>  
> >> +static void release_alua_lu_gp(struct kref *ref)
> >> +{
> >> +	struct t10_alua_lu_gp *lu_gp = container_of(ref, struct t10_alua_lu_gp, refcount);
> >> +
> >> +	kmem_cache_free(t10_alua_lu_gp_cache, lu_gp);
> >> +}
> >> +
> >> +#define get_alua_lu_gp(x) kref_get(&x->refcount)
> >> +#define put_alua_lu_gp(x) kref_put(&x->refcount, release_alua_lu_gp)
> >> +
> >>  /*
> >>   * REPORT_TARGET_PORT_GROUPS
> >>   *
> >> @@ -898,8 +908,7 @@ int core_alua_do_port_transition(
> >>  	local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem;
> >>  	spin_lock(&local_lu_gp_mem->lu_gp_mem_lock);
> >>  	lu_gp = local_lu_gp_mem->lu_gp;
> >> -	atomic_inc(&lu_gp->lu_gp_ref_cnt);
> >> -	smp_mb__after_atomic_inc();
> >> +	get_alua_lu_gp(lu_gp);
> >>  	spin_unlock(&local_lu_gp_mem->lu_gp_mem_lock);
> >>  	/*
> >>  	 * For storage objects that are members of the 'default_lu_gp',
> >> @@ -913,8 +922,8 @@ int core_alua_do_port_transition(
> >>  		 */
> >>  		core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
> >>  					md_buf, new_state, explicit);
> >> -		atomic_dec(&lu_gp->lu_gp_ref_cnt);
> >> -		smp_mb__after_atomic_dec();
> >> +
> >> +		put_alua_lu_gp(lu_gp);
> >>  		kfree(md_buf);
> >>  		return 0;
> >>  	}
> >> @@ -985,8 +994,7 @@ int core_alua_do_port_transition(
> >>  		l_tg_pt_gp->tg_pt_gp_id, (explicit) ? "explicit" : "implicit",
> >>  		core_alua_dump_state(new_state));
> >>  
> >> -	atomic_dec(&lu_gp->lu_gp_ref_cnt);
> >> -	smp_mb__after_atomic_dec();
> >> +	put_alua_lu_gp(lu_gp);
> >>  	kfree(md_buf);
> >>  	return 0;
> >>  }
> >> @@ -1107,7 +1115,8 @@ core_alua_allocate_lu_gp(const char *name, int def_group)
> >>  	INIT_LIST_HEAD(&lu_gp->lu_gp_node);
> >>  	INIT_LIST_HEAD(&lu_gp->lu_gp_mem_list);
> >>  	spin_lock_init(&lu_gp->lu_gp_lock);
> >> -	atomic_set(&lu_gp->lu_gp_ref_cnt, 0);
> >> +
> >> +	kref_init(&lu_gp->refcount);
> >>  
> >>  	if (def_group) {
> >>  		lu_gp->lu_gp_id = alua_lu_gps_counter++;
> >> @@ -1200,13 +1209,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
> >>  	list_del(&lu_gp->lu_gp_node);
> >>  	alua_lu_gps_count--;
> >>  	spin_unlock(&lu_gps_lock);
> >> -	/*
> >> -	 * Allow struct t10_alua_lu_gp * referenced by core_alua_get_lu_gp_by_name()
> >> -	 * in target_core_configfs.c:target_core_store_alua_lu_gp() to be
> >> -	 * released with core_alua_put_lu_gp_from_name()
> >> -	 */
> >> -	while (atomic_read(&lu_gp->lu_gp_ref_cnt))
> >> -		cpu_relax();
> >> +
> >>  	/*
> >>  	 * Release reference to struct t10_alua_lu_gp * from all associated
> >>  	 * struct se_device.
> >> @@ -1241,7 +1244,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
> >>  	}
> >>  	spin_unlock(&lu_gp->lu_gp_lock);
> >>  
> >> -	kmem_cache_free(t10_alua_lu_gp_cache, lu_gp);
> >> +	put_alua_lu_gp(lu_gp);
> >>  }
> >>  
> 
> > The assumption that it's safe to 'Release reference to struct
> > t10_alua_lu_gp * from all associated struct device' below the original
> > cpu_relax(), while there are still other process contexts doing their
> > respective put_alua_lu_gp() is totally wrong.
> 
> The only other spot is core_alua_do_port_transition, afaics. I think if
> it races with free_lu_gp, lu_gp will either be the old lu_gp (which no
> longer will have anything on lu_gp_mem_list) or will be default_lu_gp.
> If it's the old lu_gp then it iterates over an empty list, and then the
> lu_gp gets finally freed by the put() at the bottom.
> 
> > Furthermore, allowing a configfs_group_ops->drop_item() to return while
> > there are still active references from other process contexts means that
> > the parent struct config_group is no longer referenced counted (eg:
> > configfs child is removed), and introduces a whole host of potential
> > bugs.
> > 
> > So that said, NAK on this patch.
> 
> I think some of the other patches used drop_item() and thus were bad,
> but in this one the existing code is already calling
> core_alua_free_lu_gp() from release().
> 
> Thoughts?
> 

The problem with this patch and all of the other patches that follow the
same logic is the false assumption that it's safe to return from
configfs_group_operations->drop_item() before all references to the
underlying data structure containing the associated struct config_group
have been dropped.

In this particular case, target_core_alua_drop_lu_gp() ->
config_item_put() -> target_core_alua_lu_gp_release() ->
core_alua_free_lu_gp() is still being called from ->drop_item() via
target_core_alua_lu_gp_ops->release(), so the same holds true here as
well.

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux