Пример #1
0
int bdev_minor_reopen(dev_t dev)
{
    /* Reopen all minor devices on a major device. This function duplicates some
     * code from elsewhere, because in this case we must avoid performing recovery.
     * FIXME: if reopening fails with a non-IPC error, we should attempt to close
     * all minors that we did manage to reopen so far, or they might stay open
     * forever.
     */
    endpoint_t endpt;
    message m;
    int i, j, r, major;

    major = major(dev);
    endpt = bdev_driver_get(dev);

    assert(endpt != NONE);

    for (i = 0; i < NR_OPEN_DEVS; i++) {
        if (major(open_dev[i].dev) != major)
            continue;

        /* Each minor device may have been opened multiple times. Send an open
         * request for each time that it was opened before. We could reopen it
         * just once, but then we'd have to keep a shadow open count as well.
         */
        for (j = 0; j < open_dev[i].count; j++) {
            memset(&m, 0, sizeof(m));
            m.m_type = BDEV_OPEN;
            m.m_lbdev_lblockdriver_msg.minor = minor(open_dev[i].dev);
            m.m_lbdev_lblockdriver_msg.access = open_dev[i].access;
            m.m_lbdev_lblockdriver_msg.id = NO_ID;

            if ((r = ipc_sendrec(endpt, &m)) != OK) {
                printf("bdev: IPC to driver (%d) failed (%d)\n",
                       endpt, r);
                return r;
            }

            if (m.m_type != BDEV_REPLY) {
                printf("bdev: driver (%d) sent weird response (%d)\n",
                       endpt, m.m_type);
                return EINVAL;
            }

            if (m.m_lblockdriver_lbdev_reply.id != NO_ID) {
                printf("bdev: driver (%d) sent invalid ID (%ld)\n",
                       endpt, m.m_lblockdriver_lbdev_reply.id);
                return EINVAL;
            }

            if ((r = m.m_lblockdriver_lbdev_reply.status) != OK) {
                printf("bdev: driver (%d) failed device reopen (%d)\n",
                       endpt, r);
                return r;
            }
        }
    }

    return OK;
}
Пример #2
0
/*===========================================================================*
 *                       sef_cb_lu_response_rs_reply        		     *
 *===========================================================================*/
int sef_cb_lu_response_rs_reply(message *m_ptr)
{
  int r;

  /* Inform RS that we're ready with the given result. */
  r = ipc_sendrec(RS_PROC_NR, m_ptr);
  if ( r != OK) {
      return r;
  }

  return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type;
}
Пример #3
0
/*===========================================================================*
 *				pci_init				     *
 *===========================================================================*/
void pci_init(void)
{
	int r;
	message m;

	r= ds_retrieve_label_endpt("pci", &pci_procnr);
	if (r != 0)
		panic("pci_init: unable to obtain label for 'pci': %d", r);

	m.m_type= BUSC_PCI_INIT;
	r= ipc_sendrec(pci_procnr, &m);
	if (r != 0)
		panic("pci_init: can't talk to PCI: %d", r);
	if (m.m_type != 0)
		panic("pci_init: got bad reply from PCI: %d", m.m_type);
}
Пример #4
0
/*
 * Perform synchronous communication with PTYFS, if PTYFS is actually running.
 * This function is expected to return only once PTYFS has acknowledged
 * processing the request, in order to avoid race conditions between PTYFS and
 * userland.  The function must always fail when PTYFS is not available for any
 * reason.  Return OK on success, or an IPC-level error on failure.
 */
static int
ptyfs_sendrec(message * m_ptr)
{
    endpoint_t endpt;

    /*
     * New pseudoterminals are created sufficiently rarely that we need not
     * optimize this by for example caching the PTYFS endpoint,  especially
     * since caching brings along new issues, such as having to reissue the
     * request if the cached endpoint turns out to be outdated (e.g., when
     * ptyfs is unmounted and remounted for whatever reason).
     */
    if (ds_retrieve_label_endpt("ptyfs", &endpt) != OK)
        return EDEADSRCDST; /* ptyfs is not available */

    return ipc_sendrec(endpt, m_ptr);
}
Пример #5
0
/*===========================================================================*
 *				pci_attr_w8				     *
 *===========================================================================*/
void pci_attr_w8(int devind, int port, u8_t value)
{
	int r;
	message m;

	m.m_type= BUSC_PCI_ATTR_W8;
	m.m2_i1= devind;
	m.m2_i2= port;
	m.m2_l1= value;

	r= ipc_sendrec(pci_procnr, &m);
	if (r != 0)
		panic("pci_attr_w8: can't talk to PCI: %d", r);

	if (m.m_type != 0)
		panic("pci_attr_w8: got bad reply from PCI: %d", m.m_type);
}
Пример #6
0
/*===========================================================================*
 *				pci_rescan_bus				     *
 *===========================================================================*/
void pci_rescan_bus(u8_t busnr)
{
	int r;
	message m;

	m.m_type= BUSC_PCI_RESCAN;
	m.m1_i1= busnr;

	r= ipc_sendrec(pci_procnr, &m);
	if (r != 0)
		panic("pci_rescan_bus: can't talk to PCI: %d", r);

	if (m.m_type != 0)
	{
		panic("pci_rescan_bus: got bad reply from PCI: %d", m.m_type);
	}
}
Пример #7
0
/*===========================================================================*
 *				fbd_close				     *
 *===========================================================================*/
static int fbd_close(devminor_t UNUSED(minor))
{
	/* Close a device. */
	message m;
	int r;

	/* We simply forward this request to the real driver. */
	memset(&m, 0, sizeof(m));
	m.m_type = BDEV_CLOSE;
	m.m_lbdev_lblockdriver_msg.minor = driver_minor;
	m.m_lbdev_lblockdriver_msg.id = 0;

	if ((r = ipc_sendrec(driver_endpt, &m)) != OK)
		panic("ipc_sendrec to driver failed (%d)\n", r);

	if (m.m_type != BDEV_REPLY)
		panic("invalid reply from driver (%d)\n", m.m_type);

	return m.m_lblockdriver_lbdev_reply.status;
}
Пример #8
0
/*===========================================================================*
 *				fbd_transfer_direct			     *
 *===========================================================================*/
static ssize_t fbd_transfer_direct(int do_write, u64_t position,
	endpoint_t endpt, iovec_t *iov, unsigned int count, int flags)
{
	/* Forward the entire transfer request, without any intervention. */
	iovec_s_t iovec[NR_IOREQS];
	cp_grant_id_t grant;
	message m;
	int i, r;

	for (i = 0; i < count; i++) {
		iovec[i].iov_size = iov[i].iov_size;
		iovec[i].iov_grant = cpf_grant_indirect(driver_endpt, endpt,
			iov[i].iov_addr);
		assert(iovec[i].iov_grant != GRANT_INVALID);
	}

	grant = cpf_grant_direct(driver_endpt, (vir_bytes) iovec,
		count * sizeof(iovec[0]), CPF_READ);
	assert(grant != GRANT_INVALID);

	m.m_type = do_write ? BDEV_SCATTER : BDEV_GATHER;
	m.m_lbdev_lblockdriver_msg.minor = driver_minor;
	m.m_lbdev_lblockdriver_msg.count = count;
	m.m_lbdev_lblockdriver_msg.grant = grant;
	m.m_lbdev_lblockdriver_msg.flags = flags;
	m.m_lbdev_lblockdriver_msg.id = 0;
	m.m_lbdev_lblockdriver_msg.pos = position;

	if ((r = ipc_sendrec(driver_endpt, &m)) != OK)
		panic("ipc_sendrec to driver failed (%d)\n", r);

	if (m.m_type != BDEV_REPLY)
		panic("invalid reply from driver (%d)\n", m.m_type);

	cpf_revoke(grant);

	for (i = 0; i < count; i++)
		cpf_revoke(iovec[i].iov_grant);

	return m.m_lblockdriver_lbdev_reply.status;
}
Пример #9
0
/*===========================================================================*
 *				fbd_ioctl				     *
 *===========================================================================*/
static int fbd_ioctl(devminor_t UNUSED(minor), unsigned long request,
	endpoint_t endpt, cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
{
	/* Handle an I/O control request. */
	cp_grant_id_t gid;
	message m;
	int r;

	/* We only handle the FBD requests, and pass on everything else. */
	switch (request) {
	case FBDCADDRULE:
	case FBDCDELRULE:
	case FBDCGETRULE:
		return rule_ctl(request, endpt, grant);
	}

	assert(grant != GRANT_INVALID);

	gid = cpf_grant_indirect(driver_endpt, endpt, grant);
	assert(gid != GRANT_INVALID);

	memset(&m, 0, sizeof(m));
	m.m_type = BDEV_IOCTL;
	m.m_lbdev_lblockdriver_msg.minor = driver_minor;
	m.m_lbdev_lblockdriver_msg.request = request;
	m.m_lbdev_lblockdriver_msg.grant = gid;
	m.m_lbdev_lblockdriver_msg.user = NONE;
	m.m_lbdev_lblockdriver_msg.id = 0;

	if ((r = ipc_sendrec(driver_endpt, &m)) != OK)
		panic("ipc_sendrec to driver failed (%d)\n", r);

	if (m.m_type != BDEV_REPLY)
		panic("invalid reply from driver (%d)\n", m.m_type);

	cpf_revoke(gid);

	return m.m_lblockdriver_lbdev_reply.status;
}
Пример #10
0
/*===========================================================================*
 *		            sef_cb_init_fresh                                *
 *===========================================================================*/
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
{
/* Initialize the process manager. */
  int s;
  static struct boot_image image[NR_BOOT_PROCS];
  register struct boot_image *ip;
  static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
				SIGEMT, SIGFPE, SIGBUS, SIGSEGV };
  static char ign_sigs[] = { SIGCHLD, SIGWINCH, SIGCONT, SIGINFO };
  static char noign_sigs[] = { SIGILL, SIGTRAP, SIGEMT, SIGFPE, 
				SIGBUS, SIGSEGV };
  register struct mproc *rmp;
  register char *sig_ptr;
  message mess;

  /* Initialize process table, including timers. */
  for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
	init_timer(&rmp->mp_timer);
	rmp->mp_magic = MP_MAGIC;
	rmp->mp_sigact = mpsigact[rmp - mproc];
	rmp->mp_eventsub = NO_EVENTSUB;
  }

  /* Build the set of signals which cause core dumps, and the set of signals
   * that are by default ignored.
   */
  sigemptyset(&core_sset);
  for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++)
	sigaddset(&core_sset, *sig_ptr);
  sigemptyset(&ign_sset);
  for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++)
	sigaddset(&ign_sset, *sig_ptr);
  sigemptyset(&noign_sset);
  for (sig_ptr = noign_sigs; sig_ptr < noign_sigs+sizeof(noign_sigs); sig_ptr++)
	sigaddset(&noign_sset, *sig_ptr);

  /* Obtain a copy of the boot monitor parameters.
   */
  if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK)
      panic("get monitor params failed: %d", s);

  /* Initialize PM's process table. Request a copy of the system image table 
   * that is defined at the kernel level to see which slots to fill in.
   */
  if (OK != (s=sys_getimage(image))) 
  	panic("couldn't get image table: %d", s);
  procs_in_use = 0;				/* start populating table */
  for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
  	if (ip->proc_nr >= 0) {			/* task have negative nrs */
  		procs_in_use += 1;		/* found user process */

		/* Set process details found in the image table. */
		rmp = &mproc[ip->proc_nr];	
  		strlcpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
  		(void) sigemptyset(&rmp->mp_ignore);	
  		(void) sigemptyset(&rmp->mp_sigmask);
  		(void) sigemptyset(&rmp->mp_catch);
		if (ip->proc_nr == INIT_PROC_NR) {	/* user process */
  			/* INIT is root, we make it father of itself. This is
  			 * not really OK, INIT should have no father, i.e.
  			 * a father with pid NO_PID. But PM currently assumes 
  			 * that mp_parent always points to a valid slot number.
  			 */
  			rmp->mp_parent = INIT_PROC_NR;
  			rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
			rmp->mp_flags |= IN_USE; 

			/* Set scheduling info */
			rmp->mp_scheduler = KERNEL;
			rmp->mp_nice = get_nice_value(USR_Q);
		}
		else {					/* system process */
  			if(ip->proc_nr == RS_PROC_NR) {
  				rmp->mp_parent = INIT_PROC_NR;
  			}
  			else {
  				rmp->mp_parent = RS_PROC_NR;
  			}
  			rmp->mp_pid = get_free_pid();
			rmp->mp_flags |= IN_USE | PRIV_PROC;

			/* RS schedules this process */
			rmp->mp_scheduler = NONE;
			rmp->mp_nice = get_nice_value(SRV_Q);
		}

		/* Get kernel endpoint identifier. */
		rmp->mp_endpoint = ip->endpoint;

		/* Tell VFS about this system process. */
		memset(&mess, 0, sizeof(mess));
		mess.m_type = VFS_PM_INIT;
		mess.VFS_PM_SLOT = ip->proc_nr;
		mess.VFS_PM_PID = rmp->mp_pid;
		mess.VFS_PM_ENDPT = rmp->mp_endpoint;
  		if (OK != (s=ipc_send(VFS_PROC_NR, &mess)))
			panic("can't sync up with VFS: %d", s);
  	}
  }

  /* Tell VFS that no more system processes follow and synchronize. */
  memset(&mess, 0, sizeof(mess));
  mess.m_type = VFS_PM_INIT;
  mess.VFS_PM_ENDPT = NONE;
  if (ipc_sendrec(VFS_PROC_NR, &mess) != OK || mess.m_type != OK)
	panic("can't sync up with VFS");

 system_hz = sys_hz();

  /* Initialize user-space scheduling. */
  sched_init();

  return(OK);
}
Пример #11
0
/*===========================================================================*
 *				fbd_transfer_copy			     *
 *===========================================================================*/
static ssize_t fbd_transfer_copy(int do_write, u64_t position,
	endpoint_t endpt, iovec_t *iov, unsigned int count, size_t size,
	int flags)
{
	/* Interpose on the request. */
	iovec_s_t iovec[NR_IOREQS];
	struct vscp_vec vscp_vec[SCPVEC_NR];
	cp_grant_id_t grant;
	size_t off, len;
	message m;
	char *ptr;
	int i, j, r;
	ssize_t rsize;

	assert(count > 0 && count <= SCPVEC_NR);

	if (size > BUF_SIZE) {
		printf("FBD: allocating memory for %d bytes\n", size);

		ptr = alloc_contig(size, 0, NULL);

		assert(ptr != NULL);
	}
	else ptr = fbd_buf;

	/* For write operations, first copy in the data to write. */
	if (do_write) {
		for (i = off = 0; i < count; i++) {
			len = iov[i].iov_size;

			vscp_vec[i].v_from = endpt;
			vscp_vec[i].v_to = SELF;
			vscp_vec[i].v_gid = iov[i].iov_addr;
			vscp_vec[i].v_offset = 0;
			vscp_vec[i].v_addr = (vir_bytes) (ptr + off);
			vscp_vec[i].v_bytes = len;

			off += len;
		}

		if ((r = sys_vsafecopy(vscp_vec, i)) != OK)
			panic("vsafecopy failed (%d)\n", r);

		/* Trigger write hook. */
		rule_io_hook(ptr, size, position, FBD_FLAG_WRITE);
	}

	/* Allocate grants for the data, in the same chunking as the original
	 * vector. This avoids performance fluctuations with bad hardware as
	 * observed with the filter driver.
	 */
	for (i = off = 0; i < count; i++) {
		len = iov[i].iov_size;

		iovec[i].iov_size = len;
		iovec[i].iov_grant = cpf_grant_direct(driver_endpt,
			(vir_bytes) (ptr + off), len,
			do_write ? CPF_READ : CPF_WRITE);
		assert(iovec[i].iov_grant != GRANT_INVALID);

		off += len;
	}

	grant = cpf_grant_direct(driver_endpt, (vir_bytes) iovec,
		count * sizeof(iovec[0]), CPF_READ);
	assert(grant != GRANT_INVALID);

	m.m_type = do_write ? BDEV_SCATTER : BDEV_GATHER;
	m.m_lbdev_lblockdriver_msg.minor = driver_minor;
	m.m_lbdev_lblockdriver_msg.count = count;
	m.m_lbdev_lblockdriver_msg.grant = grant;
	m.m_lbdev_lblockdriver_msg.flags = flags;
	m.m_lbdev_lblockdriver_msg.id = 0;
	m.m_lbdev_lblockdriver_msg.pos = position;

	if ((r = ipc_sendrec(driver_endpt, &m)) != OK)
		panic("ipc_sendrec to driver failed (%d)\n", r);

	if (m.m_type != BDEV_REPLY)
		panic("invalid reply from driver (%d)\n", m.m_type);

	cpf_revoke(grant);

	for (i = 0; i < count; i++)
		cpf_revoke(iovec[i].iov_grant);

	/* For read operations, finish by copying out the data read. */
	if (!do_write) {
		/* Trigger read hook. */
		rule_io_hook(ptr, size, position, FBD_FLAG_READ);

		/* Upon success, copy back whatever has been processed. */
		rsize = m.m_lblockdriver_lbdev_reply.status;
		for (i = j = off = 0; rsize > 0 && i < count; i++) {
			len = MIN(rsize, iov[i].iov_size);

			vscp_vec[j].v_from = SELF;
			vscp_vec[j].v_to = endpt;
			vscp_vec[j].v_gid = iov[i].iov_addr;
			vscp_vec[j].v_offset = 0;
			vscp_vec[j].v_addr = (vir_bytes) (ptr + off);
			vscp_vec[j].v_bytes = len;

			off += len;
			rsize -= len;
			j++;
		}

		if (j > 0 && (r = sys_vsafecopy(vscp_vec, j)) != OK)
			panic("vsafecopy failed (%d)\n", r);
	}

	if (ptr != fbd_buf)
		free_contig(ptr, size);

	return m.m_lblockdriver_lbdev_reply.status;
}