diff options
author | jhb <jhb@FreeBSD.org> | 2006-07-21 20:40:13 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2006-07-21 20:40:13 +0000 |
commit | 8a1f79ab85c00574b27570ea0a8fc13018f8d7f4 (patch) | |
tree | 4e40399b541abc00aa6ef6725ce6c658473c296f /sys/dev/streams | |
parent | 6370253bdc1d9199f89dc3a29376633daec69c12 (diff) | |
download | FreeBSD-src-8a1f79ab85c00574b27570ea0a8fc13018f8d7f4.zip FreeBSD-src-8a1f79ab85c00574b27570ea0a8fc13018f8d7f4.tar.gz |
Clean up the svr4 socket cache and streams code some to make it more easily
locked.
- Move all the svr4 socket cache code into svr4_socket.c, specifically
move svr4_delete_socket() over from streams.c. Make the socket cache
entry structure and svr4_head private to svr4_socket.c as a result.
- Add a mutex to protect the svr4 socket cache.
- Change svr4_find_socket() to copy the sockaddr_un struct into a
caller-supplied sockaddr_un rather than giving the caller a pointer to
our internal one. This removes the one case where code outside of
svr4_socket.c could access data in the cache.
- Add an eventhandler for process_exit and process_exec to purge the cache
of any entries for the exiting or execing process.
- Add methods to init and destroy the socket cache and call them from the
svr4 ABI module's event handler.
- Conditionally grab Giant around socreate() in streamsopen().
- Use fdclose() instead of inlining it in streamsopen() when handling
socreate() failure.
- Only allocate a stream structure and attach it to a socket in
streamsopen(). Previously, if a svr4 program performed a stream
operation on an arbitrary socket not opened via the streams device,
we would attach streams state data to it and change f_ops of the
associated struct file while it was in use. The latter was especially
not safe, and if a program wants a stream object it should open it via
the streams device anyway.
- Don't bother locking so_emuldata in the streams code now that we only
touch it right after creating a socket (in streamsopen()) or when
tearing it down when the file is closed.
- Remove D_NEEDGIANT from the streams device as it is no longer needed.
Diffstat (limited to 'sys/dev/streams')
-rw-r--r-- | sys/dev/streams/streams.c | 104 |
1 files changed, 29 insertions, 75 deletions
diff --git a/sys/dev/streams/streams.c b/sys/dev/streams/streams.c index 804d064..5c1377c 100644 --- a/sys/dev/streams/streams.c +++ b/sys/dev/streams/streams.c @@ -68,8 +68,6 @@ static int svr4_soo_close(struct file *, struct thread *); static int svr4_ptm_alloc(struct thread *); static d_open_t streamsopen; -struct svr4_sockcache_head svr4_head; - /* * Device minor numbers */ @@ -101,7 +99,6 @@ static struct fileops svr4_netops = { static struct cdevsw streams_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = streamsopen, .d_name = "streams", }; @@ -119,7 +116,6 @@ streams_modevent(module_t mod, int type, void *unused) { switch (type) { case MOD_LOAD: - TAILQ_INIT(&svr4_head); dt_ptm = make_dev(&streams_cdevsw, dev_ptm, 0, 0, 0666, "ptm"); dt_arp = make_dev(&streams_cdevsw, dev_arp, 0, 0, 0666, @@ -187,13 +183,12 @@ MODULE_VERSION(streams, 1); static int streamsopen(struct cdev *dev, int oflags, int devtype, struct thread *td) { - int type, protocol; - int fd, extraref; - struct file *fp; + struct filedesc *fdp; + struct svr4_strm *st; struct socket *so; - int error; - int family; - struct proc *p = td->td_proc; + struct file *fp; + int family, type, protocol; + int error, fd; if (td->td_dupfd >= 0) return ENODEV; @@ -244,34 +239,40 @@ streamsopen(struct cdev *dev, int oflags, int devtype, struct thread *td) return EOPNOTSUPP; } + fdp = td->td_proc->p_fd; if ((error = falloc(td, &fp, &fd)) != 0) return error; /* An extra reference on `fp' has been held for us by falloc(). */ - if ((error = socreate(family, &so, type, protocol, - td->td_ucred, td)) != 0) { - FILEDESC_LOCK_FAST(p->p_fd); - /* Check the fd table entry hasn't changed since we made it. */ - extraref = 0; - if (p->p_fd->fd_ofiles[fd] == fp) { - p->p_fd->fd_ofiles[fd] = NULL; - extraref = 1; - } - FILEDESC_UNLOCK_FAST(p->p_fd); - if (extraref) - fdrop(fp, td); - fdrop(fp, td); - return error; + NET_LOCK_GIANT(); + error = socreate(family, &so, type, protocol, td->td_ucred, td); + NET_UNLOCK_GIANT(); + if (error) { + fdclose(fdp, fp, fd, td); + fdrop(fp, td); + return error; } - FILEDESC_LOCK_FAST(p->p_fd); + FILEDESC_LOCK_FAST(fdp); fp->f_data = so; fp->f_flag = FREAD|FWRITE; fp->f_ops = &svr4_netops; fp->f_type = DTYPE_SOCKET; - FILEDESC_UNLOCK_FAST(p->p_fd); + FILEDESC_UNLOCK_FAST(fdp); + + /* + * Allocate a stream structure and attach it to this socket. + * We don't bother locking so_emuldata for SVR4 stream sockets as + * its value is constant for the lifetime of the stream once it + * is initialized here. + */ + st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK); + st->s_family = so->so_proto->pr_domain->dom_family; + st->s_cmd = ~0; + st->s_afd = -1; + st->s_eventmask = 0; + so->so_emuldata = st; - (void)svr4_stream_get(fp); fdrop(fp, td); td->td_dupfd = fd; return ENXIO; @@ -334,59 +335,12 @@ svr4_stream_get(fp) struct file *fp; { struct socket *so; - struct svr4_strm *st; if (fp == NULL || fp->f_type != DTYPE_SOCKET) return NULL; so = fp->f_data; - - /* - * mpfixme: lock socketbuffer here - */ - if (so->so_emuldata) { - return so->so_emuldata; - } - - /* Allocate a new one. */ - st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK); - st->s_family = so->so_proto->pr_domain->dom_family; - st->s_cmd = ~0; - st->s_afd = -1; - st->s_eventmask = 0; - /* - * avoid a race where we loose due to concurrancy issues - * of two threads trying to allocate the so_emuldata. - */ - if (so->so_emuldata) { - /* lost the race, use the existing emuldata */ - FREE(st, M_TEMP); - st = so->so_emuldata; - } else { - /* we won, or there was no race, use our copy */ - so->so_emuldata = st; - fp->f_ops = &svr4_netops; - } - - return st; -} - -void -svr4_delete_socket(p, fp) - struct proc *p; - struct file *fp; -{ - struct svr4_sockcache_entry *e; - void *cookie = ((struct socket *)fp->f_data)->so_emuldata; - - TAILQ_FOREACH(e, &svr4_head, entries) - if (e->p == p && e->cookie == cookie) { - TAILQ_REMOVE(&svr4_head, e, entries); - DPRINTF(("svr4_delete_socket: %s [%p,%d,%d]\n", - e->sock.sun_path, p, (int)e->dev, e->ino)); - free(e, M_TEMP); - return; - } + return so->so_emuldata; } static int |