On Fri, 1 Dec 2017 14:43:06 +0100, Phil Sutter wrote:
> On Thu, Nov 30, 2017 at 05:35:39PM -0800, Jakub Kicinski wrote:
> [...]
> > +static int nsim_vfs_enable(struct netdevsim *ns, unsigned int num_vfs)
> > +{
> > +   ns->vfconfigs = kcalloc(num_vfs, sizeof(struct nsim_vf_config),
> > +                           GFP_KERNEL);
> > +   if (!ns->vfconfigs)
> > +           return -ENOMEM;
> > +   ns->num_vfs = num_vfs;
> > +
> > +   return 0;
> > +}
> > +
> > +static void nsim_vfs_disable(struct netdevsim *ns)
> > +{
> > +   kfree(ns->vfconfigs);
> > +   ns->vfconfigs = NULL;
> > +   ns->num_vfs = 0;
> > +}  
> 
> Why not something like:
> 
> | static int nsim_vfs_set(struct netdevsim *ns, unsigned int num_vfs)
> | {
> |     void *ptr = krealloc(ns->vfconfigs,
> |                          num_vfs * sizeof(struct nsim_vf_config),
> |                          GFP_KERNEL);
> | 
> |     if (!ptr)
> |             return -ENOMEM;
> | 
> |     ns->vfconfigs = ptr;
> |     ns->num_vfs = num_vfs;
> |     return 0;
> | }

Um.  It either frees or allocates, never reallocates so I felt realloc
is misleading.  ZERO_SIZE_PTR is less clearly a NULL than a NULL.  I
will have to specify __GFP_ZERO.  It's not a calloc so there could be
potentially some overflows?

> > +static ssize_t
> > +nsim_numvfs_store(struct device *dev, struct device_attribute *attr,
> > +             const char *buf, size_t count)
> > +{
> > +   struct netdevsim *ns = to_nsim(dev);
> > +   unsigned int num_vfs;
> > +   int ret;
> > +
> > +   ret = kstrtouint(buf, 0, &num_vfs);
> > +   if (ret)
> > +           return ret;
> > +
> > +   rtnl_lock();
> > +   if (ns->num_vfs == num_vfs)
> > +           goto exit_good;  
> 
> Then replace this:
> 
> > +   if (ns->num_vfs && num_vfs) {
> > +           ret = -EBUSY;
> > +           goto exit_unlock;
> > +   }
> > +
> > +   if (num_vfs) {
> > +           ret = nsim_vfs_enable(ns, num_vfs);
> > +           if (ret)
> > +                   goto exit_unlock;
> > +   } else {
> > +           nsim_vfs_disable(ns);
> > +   }  
> 
> with just:
> 
> |     nsim_vfs_set(ns, num_vfs);

I'm trying to mirror the PCI subsystem behaviour here, which only
allows enable or disable, not increase.  I felt we should follow how
real devices behave:

        /* enable VFs */
        if (pdev->sriov->num_VFs) {
                dev_warn(&pdev->dev, "%d VFs already enabled. Disable before 
enabling %d VFs\n",
                         pdev->sriov->num_VFs, num_vfs);
                return -EBUSY;
        }

So IOW this is intentional.

> > +   ret = count;
> > +exit_unlock:
> > +   rtnl_unlock();
> > +
> > +   return ret;
> > +}  
> 
> [...]
> 
> > +static void nsim_free(struct net_device *dev)
> > +{
> > +   struct netdevsim *ns = netdev_priv(dev);
> > +
> > +   device_unregister(&ns->dev);
> >  }  
> 
> Shouldn't this also kfree(ns->vfconfigs)?

It's in uninit, I will move it to release.

Reply via email to