> > >  static ssize_t userdatum_value_store(struct config_item *item, const 
> > > char *buf,
> > > @@ -937,7 +953,9 @@ static ssize_t userdatum_value_store(struct 
> > > config_item *item, const char *buf,
> > >
> > >       ud = to_userdata(item->ci_parent);
> > >       nt = userdata_to_target(ud);
> > > -     update_userdata(nt);
> > > +     ret = update_userdata(nt);
> > > +     if (ret < 0)
> > > +             goto out_unlock;
> > >       ret = count;
> > >  out_unlock:
> > >       mutex_unlock(&dynamic_netconsole_mutex);
> > > @@ -1193,7 +1211,10 @@ static struct configfs_attribute 
> > > *netconsole_target_attrs[] = {
> > >
> > >  static void netconsole_target_release(struct config_item *item)
> > >  {
> > > -     kfree(to_target(item));
> > > +     struct netconsole_target *nt = to_target(item);
> >
> > Thinking about this now, I suppose netconsole might be reading this in
> > parallel, and then we are freeing userdata mid-air.
> >
> > Don't we need the target_list_lock in here ?
> 
> This method is called after drop_netconsole_target(), which removes
> the target from target_list. This guarantees that we won't race with
> write_ext_msg().
> Also, a config_group cannot be removed while it still has child items.
> This guarantees that we won't race with userdata or attribute
> operations.
> So I believe this is safe.

Thanks for checking it!

--breno

Reply via email to