/*===========================================================================* * update_refcount_and_destroy * *===========================================================================*/ void update_refcount_and_destroy(void) { int i, j; for (i = 0, j = 0; i < shm_list_nr; i++) { u8_t rc; rc = vm_getrefcount(sef_self(), (void *) shm_list[i].page); if (rc == (u8_t) -1) { printf("IPC: can't find physical region.\n"); continue; } shm_list[i].shmid_ds.shm_nattch = rc - 1; if (shm_list[i].shmid_ds.shm_nattch || !(shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) { if (i != j) shm_list[j] = shm_list[i]; j++; } else { int size = shm_list[i].shmid_ds.shm_segsz; if (size % PAGE_SIZE) size += PAGE_SIZE - size % PAGE_SIZE; munmap((void *)shm_list[i].page, size); } } shm_list_nr = j; }
/*===========================================================================* * blockdriver_announce * *===========================================================================*/ void blockdriver_announce(int type) { /* Announce we are up after a fresh start or a restart. */ int r; char key[DS_MAX_KEYLEN]; char label[DS_MAX_KEYLEN]; char *driver_prefix = "drv.blk."; /* Callers are allowed to use ipc_sendrec to communicate with drivers. * For this reason, there may blocked callers when a driver restarts. * Ask the kernel to unblock them (if any). Note that most block drivers * will not restart statefully, and thus will skip this code. */ if (type == SEF_INIT_RESTART) { if ((r = sys_statectl(SYS_STATE_CLEAR_IPC_REFS)) != OK) panic("blockdriver_init: sys_statectl failed: %d", r); } /* Publish a driver up event. */ if ((r = ds_retrieve_label_name(label, sef_self())) != OK) panic("blockdriver_init: unable to get own label: %d", r); snprintf(key, DS_MAX_KEYLEN, "%s%s", driver_prefix, label); if ((r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE)) != OK) panic("blockdriver_init: unable to publish driver up event: %d", r); /* Expect an open for any device before serving regular driver requests. */ clear_open_devs(); /* Initialize or reset the message queue. */ mq_init(); }
/*===========================================================================* * cch_check * *===========================================================================*/ static void cch_check(void) { int i; for (i = 0; i < NR_INODES; ++i) { if (inode[i].i_count != cch[i] && req_nr != REQ_GETNODE && req_nr != REQ_PUTNODE && req_nr != REQ_READSUPER && req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT && req_nr != REQ_SYNC && req_nr != REQ_LOOKUP) { printf("MFS(%d) inode(%lu) cc: %d req_nr: %d\n", sef_self(), inode[i].i_num, inode[i].i_count - cch[i], req_nr); } cch[i] = inode[i].i_count; } }
/*===========================================================================* * netdriver_announce * *===========================================================================*/ void netdriver_announce() { /* Announce we are up after a fresh start or restart. */ int r; char key[DS_MAX_KEYLEN]; char label[DS_MAX_KEYLEN]; char *driver_prefix = "drv.net."; /* Publish a driver up event. */ r = ds_retrieve_label_name(label, sef_self()); if (r != OK) { panic("driver_announce: unable to get own label: %d\n", r); } snprintf(key, DS_MAX_KEYLEN, "%s%s", driver_prefix, label); r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE); if (r != OK) { panic("driver_announce: unable to publish driver up event: %d\n", r); } conf_expected = TRUE; }
/*===========================================================================* * do_shmat * *===========================================================================*/ int do_shmat(message *m) { int id, flag; vir_bytes addr; void *ret; struct shm_struct *shm; id = m->m_lc_ipc_shmat.id; addr = (vir_bytes) m->m_lc_ipc_shmat.addr; flag = m->m_lc_ipc_shmat.flag; if (addr && (addr % PAGE_SIZE)) { if (flag & SHM_RND) addr -= (addr % PAGE_SIZE); else return EINVAL; } if (!(shm = shm_find_id(id))) return EINVAL; if (flag & SHM_RDONLY) flag = 0444; else flag = 0666; if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag)) return EACCES; ret = vm_remap(who_e, sef_self(), (void *)addr, (void *)shm->page, shm->shmid_ds.shm_segsz); if (ret == MAP_FAILED) return ENOMEM; shm->shmid_ds.shm_atime = time(NULL); shm->shmid_ds.shm_lpid = getnpid(who_e); /* nattach is updated lazily */ m->m_lc_ipc_shmat.retaddr = ret; return OK; }
/*===========================================================================* * sef_cb_lu_prepare * *===========================================================================*/ static int sef_cb_lu_prepare(int state) { /* This function is called to decide whether we can enter the given live * update state, and to prepare for such an update. If we are requested to * update to a request-free or protocol-free state, make sure there is no work * pending or being processed, and shut down all worker threads. */ switch (state) { case SEF_LU_STATE_REQUEST_FREE: case SEF_LU_STATE_PROTOCOL_FREE: if (!blockdriver_mt_is_idle()) { printf("libblockdriver(%d): not idle, blocking update\n", sef_self()); break; } blockdriver_mt_suspend(); return OK; } return ENOTREADY; }
/*===========================================================================* * do_shmget * *===========================================================================*/ int do_shmget(message *m) { struct shm_struct *shm; long key, size, old_size; int flag; int id; key = m->m_lc_ipc_shmget.key; old_size = size = m->m_lc_ipc_shmget.size; flag = m->m_lc_ipc_shmget.flag; if ((shm = shm_find_key(key))) { if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag)) return EACCES; if ((flag & IPC_CREAT) && (flag & IPC_EXCL)) return EEXIST; if (size && shm->shmid_ds.shm_segsz < size) return EINVAL; id = shm->id; } else { /* no key found */ if (!(flag & IPC_CREAT)) return ENOENT; if (size <= 0) return EINVAL; /* round up to a multiple of PAGE_SIZE */ if (size % PAGE_SIZE) size += PAGE_SIZE - size % PAGE_SIZE; if (size <= 0) return EINVAL; if (shm_list_nr == MAX_SHM_NR) return ENOMEM; /* TODO: shmmni should be changed... */ if (identifier == SHMMNI) return ENOSPC; shm = &shm_list[shm_list_nr]; memset(shm, 0, sizeof(struct shm_struct)); shm->page = (vir_bytes) mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); if (shm->page == (vir_bytes) MAP_FAILED) return ENOMEM; shm->vm_id = vm_getphys(sef_self(), (void *) shm->page); memset((void *)shm->page, 0, size); shm->shmid_ds.shm_perm.cuid = shm->shmid_ds.shm_perm.uid = getnuid(who_e); shm->shmid_ds.shm_perm.cgid = shm->shmid_ds.shm_perm.gid = getngid(who_e); shm->shmid_ds.shm_perm.mode = flag & 0777; shm->shmid_ds.shm_segsz = old_size; shm->shmid_ds.shm_atime = 0; shm->shmid_ds.shm_dtime = 0; shm->shmid_ds.shm_ctime = time(NULL); shm->shmid_ds.shm_cpid = getnpid(who_e); shm->shmid_ds.shm_lpid = 0; shm->shmid_ds.shm_nattch = 0; shm->id = id = identifier++; shm->key = key; shm_list_nr++; } m->m_lc_ipc_shmget.retid = id; return OK; }