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.