On Fri, Dec 01, 2017 at 12:14:07PM -0800, Jakub Kicinski wrote: > 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?
I don't understand: How can overflows happen if I use malloc() instead of calloc()? > > > +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. Ah, I see. Yes, then it makes sense! Keeping this virtual VF functionality as close to real ones as possible is certainly feasible. > > > + 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. Oh, I missed that. If you're certain this won't lead to memleaks, no objection from my side. :) Cheers, Phil