Merge unp_bind() into uipc_bind(), as it is called only from uipc_bind().

This commit is contained in:
Robert Watson 2006-07-23 11:02:12 +00:00
parent 6d32873c29
commit dd47f5ca9c

View File

@ -155,7 +155,6 @@ static struct mtx unp_mtx;
*/
static struct task unp_gc_task;
static int unp_bind(struct unpcb *,struct sockaddr *, struct thread *);
static int unp_connect(struct socket *,struct sockaddr *, struct thread *);
static int unp_connect2(struct socket *so, struct socket *so2, int);
static void unp_disconnect(struct unpcb *);
@ -249,14 +248,97 @@ uipc_attach(struct socket *so, int proto, struct thread *td)
static int
uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
{
struct sockaddr_un *soun = (struct sockaddr_un *)nam;
struct vattr vattr;
int error, namelen;
struct nameidata nd;
struct unpcb *unp;
int error;
struct vnode *vp;
struct mount *mp;
char *buf;
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_bind: unp == NULL"));
UNP_LOCK();
error = unp_bind(unp, nam, td);
/*
* XXXRW: This test-and-set of unp_vnode is non-atomic; the unlocked
* read here is fine, but the value of unp_vnode needs to be tested
* again after we do all the lookups to see if the pcb is still
* unbound?
*/
if (unp->unp_vnode != NULL) {
UNP_UNLOCK();
return (EINVAL);
}
namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
if (namelen <= 0) {
UNP_UNLOCK();
return (EINVAL);
}
UNP_UNLOCK();
buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
strlcpy(buf, soun->sun_path, namelen + 1);
mtx_lock(&Giant);
restart:
mtx_assert(&Giant, MA_OWNED);
NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
buf, td);
/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
error = namei(&nd);
if (error)
goto done;
vp = nd.ni_vp;
if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp == vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
if (vp != NULL) {
vrele(vp);
error = EADDRINUSE;
goto done;
}
error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
if (error)
goto done;
goto restart;
}
VATTR_NULL(&vattr);
vattr.va_type = VSOCK;
vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
#ifdef MAC
error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
&vattr);
#endif
if (error == 0) {
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
}
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
if (error) {
vn_finished_write(mp);
goto done;
}
vp = nd.ni_vp;
ASSERT_VOP_LOCKED(vp, "unp_bind");
soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
UNP_LOCK();
vp->v_socket = unp->unp_socket;
unp->unp_vnode = vp;
unp->unp_addr = soun;
UNP_UNLOCK();
VOP_UNLOCK(vp, 0, td);
vn_finished_write(mp);
done:
mtx_unlock(&Giant);
free(buf, M_TEMP);
return (error);
}
@ -761,97 +843,6 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
return (error);
}
static int
unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
{
struct sockaddr_un *soun = (struct sockaddr_un *)nam;
struct vnode *vp;
struct mount *mp;
struct vattr vattr;
int error, namelen;
struct nameidata nd;
char *buf;
UNP_LOCK_ASSERT();
/*
* XXXRW: This test-and-set of unp_vnode is non-atomic; the unlocked
* read here is fine, but the value of unp_vnode needs to be tested
* again after we do all the lookups to see if the pcb is still
* unbound?
*/
if (unp->unp_vnode != NULL)
return (EINVAL);
namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
if (namelen <= 0)
return (EINVAL);
UNP_UNLOCK();
buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
strlcpy(buf, soun->sun_path, namelen + 1);
mtx_lock(&Giant);
restart:
mtx_assert(&Giant, MA_OWNED);
NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
buf, td);
/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
error = namei(&nd);
if (error)
goto done;
vp = nd.ni_vp;
if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp == vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
if (vp != NULL) {
vrele(vp);
error = EADDRINUSE;
goto done;
}
error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
if (error)
goto done;
goto restart;
}
VATTR_NULL(&vattr);
vattr.va_type = VSOCK;
vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
#ifdef MAC
error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
&vattr);
#endif
if (error == 0) {
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
}
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
if (error) {
vn_finished_write(mp);
goto done;
}
vp = nd.ni_vp;
ASSERT_VOP_LOCKED(vp, "unp_bind");
soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
UNP_LOCK();
vp->v_socket = unp->unp_socket;
unp->unp_vnode = vp;
unp->unp_addr = soun;
UNP_UNLOCK();
VOP_UNLOCK(vp, 0, td);
vn_finished_write(mp);
done:
mtx_unlock(&Giant);
free(buf, M_TEMP);
UNP_LOCK();
return (error);
}
static int
unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{