Re: per-open device private data, mmap

2003-03-14 Thread Eric Anholt
On Fri, 2003-03-14 at 13:59, Eric Anholt wrote:
 To work properly, the DRM needs an area of memory per open of the device
 which stores information on whether that fd is authenticated and also to
 have a unique identifier for use in the lock.  Currently we use
 drm_find_file_by_proc to get the private data and use the pid as the
 unique identifier, but for example this causes problems if a fork occurs
 (threaded linux programs).  This information is needed in the entry
 points (open, close, ioctl). (read, write, and poll from the current
 code are being stubbed out because they are unnecessary).
 
 To do this, I'm working on following what dev/streams/streams.c does in
 creating a new struct file and setting its own fileops and using the
 f_data field for the pointer to the private data.  This looks pretty
 good for open/close/ioctl, but there's a problem with mmap.  Currently
 we use drm_find_file_by_proc in the mmap handler to see if that process
 is authenticated, but there's no way from the mmap handler to get the
 private data because the struct file * isn't passed in.  My initial
 thought was to instead check the authentication in the DRM(mapbufs)
 ioctl, where the vm_mmap is done by the X Server or clients.  The
 problem with this is that a process could still do an mmap() on the fd
 and avoid the authentication check.
 
 What I'm wondering at this point is, is there any way to prevent the
 mmap() from succeeding (nothing legitimate uses mmap -- it's all done
 with the mapbufs ioctl), or a way to make it so from the device's mmap
 handler I can detect whether mmap() or mapbufs made the mapping, or to
 have different mmap handlers for those two vm_mmap callers.  What's the
 best way to do this?

Gah, and the instant I hit 'send' I realize that things /do/ use mmap
and mapbufs is only for agp/sg memory.  I guess it'll be okay to keep
drm_find_file_by_proc and grab authentication information from there; it
shouldn't be too big of an issue.  The unique identifier is the big
problem and the fileops trick should work for that.

However, is this going to get easier some day?  Are there any plans to
pass the struct file down to the drivers and have a void * in there for
private data?

Also, we need to be blocking SIGSTOP and such things while the lock is
held so that people don't hang the X Server by suspending a client while
it holds the lock.  Does anyone know about how to do this?

-- 
Eric Anholt[EMAIL PROTECTED]  
http://people.freebsd.org/~anholt/ [EMAIL PROTECTED]


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message


Re: per-open device private data, mmap

2003-03-14 Thread Andrew Gallatin

Eric Anholt writes:
  shouldn't be too big of an issue.  The unique identifier is the big
  problem and the fileops trick should work for that.
  
  However, is this going to get easier some day?  Are there any plans to
  pass the struct file down to the drivers and have a void * in there for
  private data?
  

I think that phk is working on this for 6.x

In the meantime, I have a new driver Im developing which uses the
fileops trick you describe, but takes it a step further and conjurs up
a new vnode.  That makes it work with mmap.  I've not run into
any problems yet, but it is lightly tested.

Cheers,

Drew


/*
 * Conjure up our own vnode out of thin air.  We need the
 * vnode so that we can stash a pointer to the per-connection
 * priv struct for use in open/close/ioctl and mmap.  This is
 * tricky, because we need make it look enough like the device
 * vnode so that VOP_GETATTR() works on the slave vnode in mmap()
 */

static int
xxx_conjur_vnode(dev_t dev, struct thread *td)
{
  int error, fd;
  struct filedesc *fdp;
  struct file *fp;
  struct vnode *vn = NULL, *vd = NULL;
  struct cdev *rdev;

  fdp = td-td_proc-p_fd;
  if (fdp == NULL)
return (0);

  if (td-td_dupfd = 0)
return ENODEV;

  rdev = xxx_malloc(sizeof(*rdev), M_WAITOK);

  if ((error = falloc(td, fp, fd)) != 0)
goto abort_with_rdev;

  vd = SLIST_FIRST(dev-si_hlist);

  if ((error = getnewvnode(none, vd-v_mount, vd-v_op, vn)))
goto abort_with_falloc;

  vn-v_type = VCHR;

  /*  really should clone v_vdata  not copy pointer */
  vn-v_data = vd-v_data;/* for VTOI in devfs_getattr() */

  /* copy our cdev info */
  vn-v_rdev = rdev;
  bcopy(vd-v_rdev, vn-v_rdev, sizeof(*rdev));

  /* finally, save the data pointer (our softc) */
  vn-v_rdev-si_drv2 = 0;

  fp-f_data = (caddr_t)vn;
  fp-f_flag = FREAD|FWRITE;
  fp-f_ops = xxx_fileops;
  fp-f_type = DTYPE_VNODE;   /* so that we can mmap */

  /*
   * Save the new fd as dupfd in the proc structure, then we have
   * open() return the special error code (ENXIO).  Returning with a
   * dupfd and ENXIO causes magic things to happen in kern_open().
   */
  td-td_dupfd = fd;
  return 0;

 abort_with_rdev:
  xxx_free(rdev);

 abort_with_falloc:
  FILEDESC_LOCK(fdp);
  fdp-fd_ofiles[fd] = NULL;
  FILEDESC_UNLOCK(fdp);
  fdrop(fp, td);


  return (error);

}

static int
xxx_fileclose(struct file *fp, struct thread *td)
{
  int ready_to_close;
  struct vnode *vn;
  struct cdev *rdev;
  xxx_port_state_t *ps;

  vn = (struct vnode *)fp-f_data;
  rdev = vn-v_rdev;
  ps = rdev-si_drv2;
  rdev-si_drv2 = NULL;

  /* replace the vnode ops so that devfs doesn't try to reclaim
 anything */
  vn-v_op = spec_vnodeop_p;
  vn-v_type = VNON; /* don't want to freedev() in vgonel()*/
  vgone(vn);

  /* free our private rdev */
  xxx_free(rdev);

  if (ps) {
xxx_mutex_enter(ps-sync);

/* Close the port if there are no more mappings */
ready_to_close = ps-ref_count == 0;
XXX_DEBUG_PRINT (XXX_DEBUG_OPENCLOSE,
(Board %d, port %d closed\n, ps-is-id, ps-port));

xxx_mutex_exit(ps-sync);

if (ready_to_close) {
  xxx_common_close (ps);
} else {
  XXX_INFO ((Application closed file descriptor while 
mappings still alive: port destruct delayed\n));
}
  }

  return (0);
}


static int
xxx_mmap(dev_t dev, vm_offset_t offset,
#if MMAP_RETURNS_PINDEX == 0
vm_offset_t *paddr,
#endif
int nprot)
{
  int status;
  xxx_port_state_t *ps;
  void *kva;
#if MMAP_RETURNS_PINDEX
  vm_offset_t phys;
  vm_offset_t *paddr = phys;
#endif

  ps = (xxx_port_state_t *)dev-si_drv2;
...


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message


Re: per-open device private data, mmap

2003-03-14 Thread Poul-Henning Kamp
In message [EMAIL PROTECTED], Eric Anholt writes:
To work properly, the DRM needs an area of memory per open of the device
which stores information on whether that fd is authenticated and also to
have a unique identifier for use in the lock.

I have some plans for this for 6.x but we would have multiple respiratory
failures in the re@ team if I even think about it until the RELENG_5
branch has been laid down, so for now you're on your own.

-- 
Poul-Henning Kamp   | UNIX since Zilog Zeus 3.20
[EMAIL PROTECTED] | TCP/IP since RFC 956
FreeBSD committer   | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-hackers in the body of the message