struct vfsconf *
vfs_byname_kld(const char *fstype, struct thread *td, int *error)
{
	struct vfsconf *vfsp;
	int fileid;

	vfsp = vfs_byname(fstype);
	if (vfsp != NULL)
		return (vfsp);

	/* Try to load the respective module. */
	*error = kern_kldload(td, fstype, &fileid);
	if (*error)
		return (NULL);

	/* Look up again to see if the VFS was loaded. */
	vfsp = vfs_byname(fstype);
	if (vfsp == NULL) {
		(void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE);
		*error = ENODEV;
		return (NULL);
	}
	return (vfsp);
}
Example #2
0
static int
ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
	 struct mbuf *control, struct thread *td)
{
	struct ngpcb *const pcbp = sotongpcb(so);
	struct ngsock *const priv = NG_NODE_PRIVATE(pcbp->sockdata->node);
	struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
	struct ng_mesg *msg;
	struct mbuf *m0;
	item_p item;
	char *path = NULL;
	int len, error = 0;
	struct ng_apply_info apply;

#ifdef	NOTYET
	if (control && (error = ng_internalize(control, td))) {
		if (pcbp->sockdata == NULL) {
			error = ENOTCONN;
			goto release;
		}
	}
#else	/* NOTYET */
	if (control) {
		error = EINVAL;
		goto release;
	}
#endif	/* NOTYET */

	/* Require destination as there may be >= 1 hooks on this node. */
	if (addr == NULL) {
		error = EDESTADDRREQ;
		goto release;
	}

	/*
	 * Allocate an expendable buffer for the path, chop off
	 * the sockaddr header, and make sure it's NUL terminated.
	 */
	len = sap->sg_len - 2;
	path = kmalloc(len + 1, M_NETGRAPH_PATH, M_WAITOK);
	bcopy(sap->sg_data, path, len);
	path[len] = '\0';

	/*
	 * Move the actual message out of mbufs into a linear buffer.
	 * Start by adding up the size of the data. (could use mh_len?)
	 */
	for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next)
		len += m0->m_len;

	/*
	 * Move the data into a linear buffer as well.
	 * Messages are not delivered in mbufs.
	 */
	msg = kmalloc(len + 1, M_NETGRAPH_MSG, M_WAITOK);
	m_copydata(m, 0, len, (char *)msg);

	if (msg->header.version != NG_VERSION) {
		kfree(msg, M_NETGRAPH_MSG);
		error = EINVAL;
		goto release;
	}

	/*
	 * Hack alert!
	 * We look into the message and if it mkpeers a node of unknown type, we
	 * try to load it. We need to do this now, in syscall thread, because if
	 * message gets queued and applied later we will get panic.
	 */
	if (msg->header.typecookie == NGM_GENERIC_COOKIE &&
	    msg->header.cmd == NGM_MKPEER) {
		struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
		struct ng_type *type;

		if ((type = ng_findtype(mkp->type)) == NULL) {
			char filename[NG_TYPESIZ + 3];
			int fileid;

			/* Not found, try to load it as a loadable module. */
			snprintf(filename, sizeof(filename), "ng_%s",
			    mkp->type);
			error = kern_kldload(curthread, filename, &fileid);
			if (error != 0) {
				kfree(msg, M_NETGRAPH_MSG);
				goto release;
			}

			/* See if type has been loaded successfully. */
			if ((type = ng_findtype(mkp->type)) == NULL) {
				kfree(msg, M_NETGRAPH_MSG);
				(void)kern_kldunload(curthread, fileid,
				    LINKER_UNLOAD_NORMAL);
				error =  ENXIO;
				goto release;
			}
		}
	}

	item = ng_package_msg(msg, NG_WAITOK);
	if ((error = ng_address_path((pcbp->sockdata->node), item, path, 0))
	    != 0) {
#ifdef TRACE_MESSAGES
		printf("ng_address_path: errx=%d\n", error);
#endif
		goto release;
	}

#ifdef TRACE_MESSAGES
	printf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n",
		item->el_dest->nd_ID,
		msg->header.typecookie,
		msg->header.cmd,
		msg->header.cmdstr,
		msg->header.flags,
		msg->header.token,
		item->el_dest->nd_type->name);
#endif
	SAVE_LINE(item);
	/*
	 * We do not want to return from syscall until the item
	 * is processed by destination node. We register callback
	 * on the item, which will update priv->error when item
	 * was applied.
	 * If ng_snd_item() has queued item, we sleep until
	 * callback wakes us up.
	 */
	bzero(&apply, sizeof(apply));
	apply.apply = ng_socket_item_applied;
	apply.context = priv;
	item->apply = &apply;
	priv->error = -1;

	error = ng_snd_item(item, 0);

	mtx_lock(&priv->mtx);
	if (priv->error == -1)
		msleep(priv, &priv->mtx, 0, "ngsock", 0);
	mtx_unlock(&priv->mtx);
	KASSERT(priv->error != -1,
	    ("ng_socket: priv->error wasn't updated"));
	error = priv->error;

release:
	if (path != NULL)
		kfree(path, M_NETGRAPH_PATH);
	if (control != NULL)
		m_freem(control);
	if (m != NULL)
		m_freem(m);
	return (error);
}