struct vnode *getf_vnode(void *fp) { struct spl_fileproc *sfp = (struct spl_fileproc *) fp; struct vnode *vp = NULL; uint32_t vid; if (!file_vnode_withvid(sfp->f_fd, &vp, &vid)) { file_drop(sfp->f_fd); } return vp; }
/* * getf(int fd) - hold a lock on a file descriptor, to be released by calling * releasef(). On OSX we will also look up the vnode of the fd for calls * to spl_vn_rdwr(). */ void *getf(int fd) { struct fileproc *fp = NULL; struct spl_fileproc *sfp = NULL; struct vnode *vp; uint32_t vid; /* * We keep the "fp" pointer as well, both for unlocking in releasef() and * used in vn_rdwr(). */ sfp = kmem_alloc(sizeof(*sfp), KM_SLEEP); if (!sfp) return NULL; if (fp_lookup(current_proc(), fd, &fp, 0/*!locked*/)) { kmem_free(sfp, sizeof(*sfp)); return (NULL); } /* * The f_vnode ptr is used to point back to the "sfp" node itself, as it is * the only information passed to vn_rdwr. */ sfp->f_vnode = sfp; sfp->f_fd = fd; sfp->f_offset = 0; sfp->f_proc = current_proc(); sfp->f_fp = fp; /* Also grab vnode, so we can fish out the minor, for onexit */ if (!file_vnode_withvid(fd, &vp, &vid)) { if (vnode_vtype(vp) != VDIR) { sfp->f_file = minor(vnode_specrdev(vp)); } file_drop(fd); } mutex_enter(&spl_getf_lock); list_insert_tail(&spl_getf_list, sfp); mutex_exit(&spl_getf_lock); //printf("SPL: new getf(%d) ret %p fp is %p so vnode set to %p\n", // fd, sfp, fp, sfp->f_vnode); return sfp; }
__private_extern__ int soioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) { struct sockopt sopt; int error = 0; int dropsockref = -1; socket_lock(so, 1); sopt.sopt_level = cmd; sopt.sopt_name = (int)data; sopt.sopt_p = p; /* Call the socket filter's ioctl handler for most ioctls */ if (IOCGROUP(cmd) != 'i' && IOCGROUP(cmd) != 'r') { int filtered = 0; struct socket_filter_entry *filter; for (filter = so->so_filt; filter && error == 0; filter = filter->sfe_next_onsocket) { if (filter->sfe_filter->sf_filter.sf_ioctl) { if (filtered == 0) { sflt_use(so); socket_unlock(so, 0); filtered = 1; } error = filter->sfe_filter->sf_filter. sf_ioctl(filter->sfe_cookie, so, cmd, data); } } if (filtered) { socket_lock(so, 0); sflt_unuse(so); } if (error != 0) goto out; } switch (cmd) { case FIONBIO: if (*(int *)data) so->so_state |= SS_NBIO; else so->so_state &= ~SS_NBIO; goto out; case FIOASYNC: if (*(int *)data) { so->so_state |= SS_ASYNC; so->so_rcv.sb_flags |= SB_ASYNC; so->so_snd.sb_flags |= SB_ASYNC; } else { so->so_state &= ~SS_ASYNC; so->so_rcv.sb_flags &= ~SB_ASYNC; so->so_snd.sb_flags &= ~SB_ASYNC; } goto out; case FIONREAD: *(int *)data = so->so_rcv.sb_cc; goto out; case SIOCSPGRP: so->so_pgid = *(int *)data; goto out; case SIOCGPGRP: *(int *)data = so->so_pgid; goto out; case SIOCATMARK: *(int *)data = (so->so_state&SS_RCVATMARK) != 0; goto out; case SIOCSETOT: { /* * Set socket level options here and then call protocol * specific routine. */ struct socket *cloned_so = NULL; int cloned_fd = *(int *)data; /* let's make sure it's either -1 or a valid file descriptor */ if (cloned_fd != -1) { error = file_socket(cloned_fd, &cloned_so); if (error) { goto out; } dropsockref = cloned_fd; } /* Always set socket non-blocking for OT */ so->so_state |= SS_NBIO; so->so_options |= SO_DONTTRUNC | SO_WANTMORE; so->so_flags |= SOF_NOSIGPIPE; if (cloned_so && so != cloned_so) { /* Flags options */ so->so_options |= cloned_so->so_options & ~SO_ACCEPTCONN; /* SO_LINGER */ if (so->so_options & SO_LINGER) so->so_linger = cloned_so->so_linger; /* SO_SNDBUF, SO_RCVBUF */ if (cloned_so->so_snd.sb_hiwat > 0) { if (sbreserve(&so->so_snd, cloned_so->so_snd.sb_hiwat) == 0) { error = ENOBUFS; goto out; } } if (cloned_so->so_rcv.sb_hiwat > 0) { if (sbreserve(&so->so_rcv, cloned_so->so_rcv.sb_hiwat) == 0) { error = ENOBUFS; goto out; } } /* SO_SNDLOWAT, SO_RCVLOWAT */ so->so_snd.sb_lowat = (cloned_so->so_snd.sb_lowat > so->so_snd.sb_hiwat) ? so->so_snd.sb_hiwat : cloned_so->so_snd.sb_lowat; so->so_rcv.sb_lowat = (cloned_so->so_rcv.sb_lowat > so->so_rcv.sb_hiwat) ? so->so_rcv.sb_hiwat : cloned_so->so_rcv.sb_lowat; /* SO_SNDTIMEO, SO_RCVTIMEO */ so->so_snd.sb_timeo = cloned_so->so_snd.sb_timeo; so->so_rcv.sb_timeo = cloned_so->so_rcv.sb_timeo; } error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p); /* Just ignore protocols that do not understand it */ if (error == EOPNOTSUPP) error = 0; goto out; } } /* * Interface/routing/protocol specific ioctls: * interface and routing ioctls should have a * different entry since a socket's unnecessary */ if (IOCGROUP(cmd) == 'i') { error = ifioctllocked(so, cmd, data, p); } else { if (IOCGROUP(cmd) == 'r') error = rtioctl(cmd, data, p); else error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p); } out: if (dropsockref != -1) file_drop(dropsockref); socket_unlock(so, 1); if (error == EJUSTRETURN) error = 0; return (error); }