On Wed, Jun 15, 2016 at 6:33 PM, Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> wrote: > On Wed, Jun 15, 2016 at 06:01:41PM +0200, Daniel Vetter wrote: >> On Wed, Jun 15, 2016 at 01:10:35PM +0100, Chris Wilson wrote: >> > On Tue, Jun 14, 2016 at 08:51:07PM +0200, Daniel Vetter wrote: >> > > There can only be one current master, and it's for the overall device. >> > > Render/control minors don't support master-based auth at all. >> > > >> > > This simplifies the master logic a lot, at least in my eyes: All these >> > > additional pointer chases are just confusing. >> > >> > One master for the device, on the struct drm_device, as opposed to hidden >> > behind the first of three minors, makes sense. >> > >> > > @@ -128,13 +128,13 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv) >> > > lockdep_assert_held_once(&dev->master_mutex); >> > > >> > > /* create a new master */ >> > > - fpriv->minor->master = drm_master_create(fpriv->minor->dev); >> > > - if (!fpriv->minor->master) >> > > + dev->master = drm_master_create(dev); >> > > + if (!dev->master) >> > > return -ENOMEM; >> > > >> > > /* take another reference for the copy in the local file priv */ >> > > old_master = fpriv->master; >> > > - fpriv->master = drm_master_get(fpriv->minor->master); >> > > + fpriv->master = drm_master_get(dev->master); >> > > >> > > if (dev->driver->master_create) { >> > > ret = dev->driver->master_create(dev, fpriv->master); >> > >> > > @@ -234,10 +234,10 @@ int drm_master_open(struct drm_file *file_priv) >> > > /* if there is no current master make this fd it, but do not create >> > > * any master object for render clients */ >> > > mutex_lock(&dev->master_mutex); >> > > - if (!file_priv->minor->master) >> > > + if (!dev->master) >> > > ret = drm_new_set_master(dev, file_priv); >> > > else >> > > - file_priv->master = drm_master_get(file_priv->minor->master); >> > > + file_priv->master = drm_master_get(dev->master); >> > > mutex_unlock(&dev->master_mutex); >> > >> > You could take the opportunity to make this a bit simpler: >> > >> > if (!READ_ONCE(dev->master)) { >> > int ret; >> > >> > ret = 0; >> > mutex_lock(&dev->master_mutex); >> > if (!dev->master) >> > ret = drm_new_master(dev); >> > mutex_unlock(&dev->master_mutex); >> > if (ret) >> > return ret; >> > } >> > >> > file_priv->master = drm_master_get(dev->master); >> >> drm_master_get(dev->master) must be under the master_mutex, without it we >> could race with a drm_master_put(&dev->master) and end up doing a kref_get >> when the refcount already reached 0. > > Something is very fishy then. The behaviour of drm_new_master() would > appear to be to create a drm_master owned by the device, but really it is > owned by file_priv? > > * checks back on drm_master > > So drm_master is the authentication structure that needs to be unique to > a hierachy. So drm_new_set_master() and here really do appear backwards. > > The old drm_new_set_master() makes more sense, it assigns to the > file_priv, and then performs a setmaster operation. In that ordering, > you could even do the file_priv local operation of creating the new > master structure before taking the lock to perform setmaster. I didn't change the logic, the old new_set_master didn't first create the master for file_priv, it first created it for file_priv->minor, and that drm_minor is the device-unique drm_minor for the primary/legacy node. The change only moves from that drm_minor for the legacy node to the drm_device. Wrt refences, every file_priv holds a ref for it's master. On top of that the current master structure (after this patch stored in dev->master, before in dev->minors[legacy]->master. The only tricky bit is that when the current master closes, we do an implicit dropmaster first. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel