static void testdiv(void) { u64_t q, r; #if TIMED struct timeval tvstart, tvend; printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n", ex64hi(i), ex64lo(i), ex64hi(j), ex64lo(j)); fflush(stdout); if (gettimeofday(&tvstart, NULL) < 0) ERR; #endif /* division by zero has a separate test */ if (cmp64u(j, 0) == 0) { testdiv0(); return; } /* perform division, store q in k to make ERR more informative */ q = div64(i, j); r = rem64(i, j); k = q; #if TIMED if (gettimeofday(&tvend, NULL) < 0) ERR; tvend.tv_sec -= tvstart.tv_sec; tvend.tv_usec -= tvstart.tv_usec; if (tvend.tv_usec < 0) { tvend.tv_sec -= 1; tvend.tv_usec += 1000000; } printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n", ex64hi(q), ex64lo(q), ex64hi(r), ex64lo(r), tvend.tv_sec, tvend.tv_usec); fflush(stdout); #endif /* compare to 64/32-bit division if possible */ if (!ex64hi(j)) { if (cmp64(q, div64u64(i, ex64lo(j))) != 0) ERR; if (!ex64hi(q)) { if (cmp64u(q, div64u(i, ex64lo(j))) != 0) ERR; } if (cmp64u(r, rem64u(i, ex64lo(j))) != 0) ERR; /* compare to 32-bit division if possible */ if (!ex64hi(i)) { if (cmp64u(q, ex64lo(i) / ex64lo(j)) != 0) ERR; if (cmp64u(r, ex64lo(i) % ex64lo(j)) != 0) ERR; } } /* check results using i = q j + r and r < j */ if (cmp64(i, add64(mul64(q, j), r)) != 0) ERR; if (cmp64(r, j) >= 0) ERR; }
/*===========================================================================* * do_llseek * *===========================================================================*/ int do_llseek() { /* Perform the llseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; u64_t pos, newpos; int r = OK, seekfd, seekwhence; long off_hi, off_lo; seekfd = job_m_in.ls_fd; seekwhence = job_m_in.whence; off_hi = job_m_in.offset_high; off_lo = job_m_in.offset_lo; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code); /* No lseek on pipes. */ if (S_ISFIFO(rfilp->filp_vno->v_mode)) { unlock_filp(rfilp); return(ESPIPE); } /* The value of 'whence' determines the start position to use. */ switch(seekwhence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: unlock_filp(rfilp); return(EINVAL); } newpos = add64(pos, make64(off_lo, off_hi)); /* Check for overflow. */ if ((off_hi > 0) && cmp64(newpos, pos) < 0) r = EINVAL; else if ((off_hi < 0) && cmp64(newpos, pos) > 0) r = EINVAL; else { /* insert the new position into the output message */ m_out.reply_l1 = ex64lo(newpos); m_out.reply_l2 = ex64hi(newpos); if (cmp64(newpos, rfilp->filp_pos) != 0) { rfilp->filp_pos = newpos; /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); } } unlock_filp(rfilp); return(r); }
/*===========================================================================* * actual_llseek * *===========================================================================*/ int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence, u64_t offset) { /* Perform the llseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; u64_t pos, newpos; int r = OK; long off_hi = ex64hi(offset); /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp2(rfp, seekfd, VNODE_READ)) == NULL) { return(err_code); } /* No lseek on pipes. */ if (S_ISFIFO(rfilp->filp_vno->v_mode)) { unlock_filp(rfilp); return(ESPIPE); } /* The value of 'whence' determines the start position to use. */ switch(seekwhence) { case SEEK_SET: pos = ((u64_t)(0)); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = ((u64_t)(rfilp->filp_vno->v_size)); break; default: unlock_filp(rfilp); return(EINVAL); } newpos = pos + offset; /* Check for overflow. */ if ((off_hi > 0) && cmp64(newpos, pos) < 0) r = EINVAL; else if ((off_hi < 0) && cmp64(newpos, pos) > 0) r = EINVAL; else { /* insert the new position into the output message */ m_out->reply_l1 = ex64lo(newpos); m_out->reply_l2 = ex64hi(newpos); if (cmp64(newpos, rfilp->filp_pos) != 0) { rfilp->filp_pos = newpos; /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); } } unlock_filp(rfilp); return(r); }
/*===========================================================================* * get_range * *===========================================================================*/ static size_t get_range(struct fbd_rule *rule, u64_t pos, size_t *size, u64_t *skip) { /* Compute the range within the given request range that is affected * by the given rule, and optionally the number of bytes preceding * the range that are also affected by the rule. */ u64_t delta; size_t off; int to_eof; to_eof = cmp64(rule->start, rule->end) >= 0; if (cmp64(pos, rule->start) > 0) { if (skip != NULL) *skip = sub64(pos, rule->start); off = 0; } else { if (skip != NULL) *skip = cvu64(0); delta = sub64(rule->start, pos); assert(ex64hi(delta) == 0); off = ex64lo(delta); } if (!to_eof) { assert(cmp64(pos, rule->end) < 0); delta = sub64(rule->end, pos); if (cmp64u(delta, *size) < 0) *size = ex64lo(delta); } assert(*size > off); *size -= off; return off; }
/*===========================================================================* * scall_lseek * *===========================================================================*/ int scall_lseek() { /* Perform the lseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; int r; long offset; u64_t pos, newpos; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code); /* No lseek on pipes. */ if (rfilp->filp_vno->v_pipe == I_PIPE) return -ESPIPE; /* The value of 'whence' determines the start position to use. */ switch(m_in.whence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: return(-EINVAL); } offset= m_in.offset_lo; if (offset >= 0) newpos= add64ul(pos, offset); else newpos= sub64ul(pos, -offset); /* Check for overflow. */ if (ex64hi(newpos) != 0) return -EINVAL; if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); if (r != 0) return r; } rfilp->filp_pos = newpos; return ex64lo(newpos); }
static void testmul(void) { int kdone, kidx; u32_t ilo = ex64lo(i), jlo = ex64lo(j); u64_t prod = mul64(i, j); int prodbits; /* compute maximum index of highest-order bit */ prodbits = bsr64(i) + bsr64(j) + 1; if (cmp64u(i, 0) == 0 || cmp64u(j, 0) == 0) prodbits = -1; if (bsr64(prod) > prodbits) ERR; /* compare to 32-bit multiplication if possible */ if (ex64hi(i) == 0 && ex64hi(j) == 0) { if (cmp64(prod, mul64u(ilo, jlo)) != 0) ERR; /* if there is no overflow we can check against pure 32-bit */ if (prodbits < 32 && cmp64u(prod, ilo * jlo) != 0) ERR; } /* in 32-bit arith low-order DWORD matches regardless of overflow */ if (ex64lo(prod) != ilo * jlo) ERR; /* multiplication by zero yields zero */ if (prodbits < 0 && cmp64u(prod, 0) != 0) ERR; /* if there is no overflow, check absence of zero divisors */ if (prodbits >= 0 && prodbits < 64 && cmp64u(prod, 0) == 0) ERR; /* commutativity */ if (cmp64(prod, mul64(j, i)) != 0) ERR; /* loop though all argument value combinations for third argument */ for (kdone = 0, kidx = 0; k = getargval(kidx, &kdone), !kdone; kidx++) { /* associativity */ if (cmp64(mul64(mul64(i, j), k), mul64(i, mul64(j, k))) != 0) ERR; /* left and right distributivity */ if (cmp64(mul64(add64(i, j), k), add64(mul64(i, k), mul64(j, k))) != 0) ERR; if (cmp64(mul64(i, add64(j, k)), add64(mul64(i, j), mul64(i, k))) != 0) ERR; } }
/*===========================================================================* * do_llseek * *===========================================================================*/ PUBLIC int do_llseek() { /* Perform the llseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; u64_t pos, newpos; int r; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp(m_in.ls_fd)) == NULL) return(err_code); /* No lseek on pipes. */ if (rfilp->filp_vno->v_pipe == I_PIPE) return(ESPIPE); /* The value of 'whence' determines the start position to use. */ switch(m_in.whence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: return(EINVAL); } newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high)); /* Check for overflow. */ if (((long)m_in.offset_high > 0) && cmp64(newpos, pos) < 0) return(EINVAL); if (((long)m_in.offset_high < 0) && cmp64(newpos, pos) > 0) return(EINVAL); if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); if (r != OK) return(r); } rfilp->filp_pos = newpos; m_out.reply_l1 = ex64lo(newpos); m_out.reply_l2 = ex64hi(newpos); return(OK); }
int actual_lseek(message *m_out, int seekfd, int seekwhence, off_t offset) { /* Perform the lseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; int r = OK; u64_t pos, newpos; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code); /* No lseek on pipes. */ if (S_ISFIFO(rfilp->filp_vno->v_mode)) { unlock_filp(rfilp); return(ESPIPE); } /* The value of 'whence' determines the start position to use. */ switch(seekwhence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: unlock_filp(rfilp); return(EINVAL); } if (offset >= 0) newpos = add64ul(pos, offset); else newpos = sub64ul(pos, -offset); /* Check for overflow. */ if (ex64hi(newpos) != 0) { r = EOVERFLOW; } else if ((off_t) ex64lo(newpos) < 0) { /* no negative file size */ r = EOVERFLOW; } else { /* insert the new position into the output message */ m_out->reply_l1 = ex64lo(newpos); if (cmp64(newpos, rfilp->filp_pos) != 0) { rfilp->filp_pos = newpos; /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); } } unlock_filp(rfilp); return(r); }
/*===========================================================================* * do_lseek * *===========================================================================*/ PUBLIC int do_lseek() { /* Perform the lseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; int r = OK; long offset; u64_t pos, newpos; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code); /* No lseek on pipes. */ if (rfilp->filp_vno->v_pipe == I_PIPE) { unlock_filp(rfilp); return(ESPIPE); } /* The value of 'whence' determines the start position to use. */ switch(m_in.whence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: unlock_filp(rfilp); return(EINVAL); } offset = m_in.offset_lo; if (offset >= 0) newpos = add64ul(pos, offset); else newpos = sub64ul(pos, -offset); /* Check for overflow. */ if (ex64hi(newpos) != 0) r = EINVAL; else { rfilp->filp_pos = newpos; /* insert the new position into the output message */ m_out.reply_l1 = ex64lo(newpos); if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); } } unlock_filp(rfilp); return(r); }
/*================================================================ * sizeup - determine device size *===============================================================*/ block_t sizeup(char * device) { block_t d; #if defined(__minix) u64_t bytes, resize; u32_t rem; #else off_t size; #endif if ((fd = open(device, O_RDONLY)) == -1) { if (errno != ENOENT) perror("sizeup open"); return 0; } #if defined(__minix) if(minix_sizeup(device, &bytes) < 0) { perror("sizeup"); return 0; } d = div64u(bytes, block_size); rem = rem64u(bytes, block_size); resize = add64u(mul64u(d, block_size), rem); if(cmp64(resize, bytes) != 0) { /* Assume block_t is unsigned */ d = (block_t)(-1ul); fprintf(stderr, "%s: truncating FS at %lu blocks\n", progname, (unsigned long)d); } #else size = lseek(fd, 0, SEEK_END); if (size == (off_t) -1) err(1, "cannot get device size fd=%d: %s", fd, device); /* Assume block_t is unsigned */ if (size / block_size > (block_t)(-1ul)) { d = (block_t)(-1ul); fprintf(stderr, "%s: truncating FS at %lu blocks\n", progname, (unsigned long)d); } else d = size / block_size; #endif return d; }
double getidle(void) { u64_t stop, idle2; u64_t idelta, tdelta; double ifp, tfp, rfp; int r; if (!running) { if ((r = sys_getidletsc(&idle)) != OK) return -1.0; running = 1; read_tsc_64(&start); return 0.0; } else { read_tsc_64(&stop); running = 0; if ((r = sys_getidletsc(&idle2)) != OK) return -1.0; idelta = sub64(idle2, idle); tdelta = sub64(stop, start); if (cmp64(idelta, tdelta) >= 0) return 100.0; ifp = make_double(idelta); tfp = make_double(tdelta); rfp = ifp / tfp * 100.0; if (rfp < 0.0) rfp = 0.0; else if (rfp > 100.0) rfp = 100.0; return rfp; } running = !running; }
int cmp_ticks(const void *v1, const void *v2) { int c; struct tp *p1 = (struct tp *) v1, *p2 = (struct tp *) v2; int p1blocked, p2blocked; p1blocked = !!p1->p->p_rts_flags; p2blocked = !!p2->p->p_rts_flags; /* Primarily order by used number of cpu cycles. * * Exception: if in blockedverbose mode, a blocked * process is always printed after an unblocked * process, and used cpu cycles don't matter. * * In both cases, process slot number is a tie breaker. */ if(blockedverbose && (p1blocked || p2blocked)) { if(!p1blocked && p2blocked) return -1; if( p2blocked && !p1blocked) return 1; } else if((c=cmp64(p1->ticks, p2->ticks)) != 0) return -c; /* Process slot number is a tie breaker. */ if(p1->p->p_nr < p2->p->p_nr) return -1; if(p1->p->p_nr > p2->p->p_nr) return 1; fprintf(stderr, "unreachable.\n"); abort(); }
/*===========================================================================* * get_block * *===========================================================================*/ struct buf *get_block( register dev_t dev, /* on which device is the block? */ register block_t block, /* which block is wanted? */ int only_search /* if NO_READ, don't read, else act normal */ ) { /* Check to see if the requested block is in the block cache. If so, return * a pointer to it. If not, evict some other block and fetch it (unless * 'only_search' is 1). All the blocks in the cache that are not in use * are linked together in a chain, with 'front' pointing to the least recently * used block and 'rear' to the most recently used block. If 'only_search' is * 1, the block being requested will be overwritten in its entirety, so it is * only necessary to see if it is in the cache; if it is not, any free buffer * will do. It is not necessary to actually read the block in from disk. * If 'only_search' is PREFETCH, the block need not be read from the disk, * and the device is not to be marked on the block, so callers can tell if * the block returned is valid. * In addition to the LRU chain, there is also a hash chain to link together * blocks whose block numbers end with the same bit strings, for fast lookup. */ int b; static struct buf *bp, *prev_ptr; u64_t yieldid = VM_BLOCKID_NONE, getid = make64(dev, block); assert(buf_hash); assert(buf); assert(nr_bufs > 0); ASSERT(fs_block_size > 0); /* Search the hash chain for (dev, block). Do_read() can use * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when * someone wants to read from a hole in a file, in which case this search * is skipped */ if (dev != NO_DEV) { b = BUFHASH(block); bp = buf_hash[b]; while (bp != NULL) { if (bp->b_blocknr == block && bp->b_dev == dev) { /* Block needed has been found. */ if (bp->b_count == 0) rm_lru(bp); bp->b_count++; /* record that block is in use */ ASSERT(bp->b_bytes == fs_block_size); ASSERT(bp->b_dev == dev); ASSERT(bp->b_dev != NO_DEV); ASSERT(bp->bp); return(bp); } else { /* This block is not the one sought. */ bp = bp->b_hash; /* move to next block on hash chain */ } } } /* Desired block is not on available chain. Take oldest block ('front'). */ if ((bp = front) == NULL) panic("all buffers in use: %d", nr_bufs); if(bp->b_bytes < fs_block_size) { ASSERT(!bp->bp); ASSERT(bp->b_bytes == 0); if(!(bp->bp = alloc_contig( (size_t) fs_block_size, 0, NULL))) { printf("MFS: couldn't allocate a new block.\n"); for(bp = front; bp && bp->b_bytes < fs_block_size; bp = bp->b_next) ; if(!bp) { panic("no buffer available"); } } else { bp->b_bytes = fs_block_size; } } ASSERT(bp); ASSERT(bp->bp); ASSERT(bp->b_bytes == fs_block_size); ASSERT(bp->b_count == 0); rm_lru(bp); /* Remove the block that was just taken from its hash chain. */ b = BUFHASH(bp->b_blocknr); prev_ptr = buf_hash[b]; if (prev_ptr == bp) { buf_hash[b] = bp->b_hash; } else { /* The block just taken is not on the front of its hash chain. */ while (prev_ptr->b_hash != NULL) if (prev_ptr->b_hash == bp) { prev_ptr->b_hash = bp->b_hash; /* found it */ break; } else { prev_ptr = prev_ptr->b_hash; /* keep looking */ } } /* If the block taken is dirty, make it clean by writing it to the disk. * Avoid hysteresis by flushing all other dirty blocks for the same device. */ if (bp->b_dev != NO_DEV) { if (ISDIRTY(bp)) flushall(bp->b_dev); /* Are we throwing out a block that contained something? * Give it to VM for the second-layer cache. */ yieldid = make64(bp->b_dev, bp->b_blocknr); assert(bp->b_bytes == fs_block_size); BP_CLEARDEV(bp); } /* Fill in block's parameters and add it to the hash chain where it goes. */ if(dev == NO_DEV) BP_CLEARDEV(bp); else BP_SETDEV(bp, dev); bp->b_blocknr = block; /* fill in block number */ bp->b_count++; /* record that block is being used */ b = BUFHASH(bp->b_blocknr); bp->b_hash = buf_hash[b]; buf_hash[b] = bp; /* add to hash list */ if(dev == NO_DEV) { if(vmcache && cmp64(yieldid, VM_BLOCKID_NONE) != 0) { vm_yield_block_get_block(yieldid, VM_BLOCKID_NONE, bp->bp, fs_block_size); } return(bp); /* If the caller wanted a NO_DEV block, work is done. */ } /* Go get the requested block unless searching or prefetching. */ if(only_search == PREFETCH || only_search == NORMAL) { /* Block is not found in our cache, but we do want it * if it's in the vm cache. */ if(vmcache) { /* If we can satisfy the PREFETCH or NORMAL request * from the vm cache, work is done. */ if(vm_yield_block_get_block(yieldid, getid, bp->bp, fs_block_size) == OK) { return bp; } } } if(only_search == PREFETCH) { /* PREFETCH: don't do i/o. */ BP_CLEARDEV(bp); } else if (only_search == NORMAL) { read_block(bp); } else if(only_search == NO_READ) { /* we want this block, but its contents * will be overwritten. VM has to forget * about it. */ if(vmcache) { vm_forgetblock(getid); } } else panic("unexpected only_search value: %d", only_search); assert(bp->bp); return(bp); /* return the newly acquired block */ }
/*===========================================================================* * read_write * *===========================================================================*/ int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request) { iovec_s_t vectors[2][NR_IOREQS]; message m1, m2; cp_grant_id_t gids[2]; int r, both, count; gids[0] = gids[1] = GRANT_INVALID; /* Send two requests only if mirroring is enabled and the given request * is either FLT_READ2 or FLT_WRITE. */ both = (USE_MIRROR && request != FLT_READ); count = paired_grant(bufa, bufb, request, gids, vectors, *sizep, both); memset(&m1, 0, sizeof(m1)); m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER; m1.BDEV_COUNT = count; m1.BDEV_POS_LO = ex64lo(pos); m1.BDEV_POS_HI = ex64hi(pos); m2 = m1; m1.BDEV_GRANT = gids[0]; m2.BDEV_GRANT = gids[1]; r = paired_sendrec(&m1, &m2, both); paired_revoke(gids, vectors, count, both); if(r != OK) { #if DEBUG if (r != RET_REDO) printf("Filter: paired_sendrec returned %d\n", r); #endif return r; } if (m1.m_type != BDEV_REPLY || m1.BDEV_STATUS < 0) { printf("Filter: unexpected/invalid reply from main driver: " "(%x, %d)\n", m1.m_type, m1.BDEV_STATUS); return bad_driver(DRIVER_MAIN, BD_PROTO, (m1.m_type == BDEV_REPLY) ? m1.BDEV_STATUS : EFAULT); } if (m1.BDEV_STATUS != (ssize_t) *sizep) { printf("Filter: truncated reply from main driver\n"); /* If the driver returned a value *larger* than we requested, * OR if we did NOT exceed the disk size, then we should * report the driver for acting strangely! */ if (m1.BDEV_STATUS > (ssize_t) *sizep || cmp64(add64u(pos, m1.BDEV_STATUS), disk_size) < 0) return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT); /* Return the actual size. */ *sizep = m1.BDEV_STATUS; } if (both) { if (m2.m_type != BDEV_REPLY || m2.BDEV_STATUS < 0) { printf("Filter: unexpected/invalid reply from " "backup driver (%x, %d)\n", m2.m_type, m2.BDEV_STATUS); return bad_driver(DRIVER_BACKUP, BD_PROTO, m2.m_type == BDEV_REPLY ? m2.BDEV_STATUS : EFAULT); } if (m2.BDEV_STATUS != (ssize_t) *sizep) { printf("Filter: truncated reply from backup driver\n"); /* As above */ if (m2.BDEV_STATUS > (ssize_t) *sizep || cmp64(add64u(pos, m2.BDEV_STATUS), disk_size) < 0) return bad_driver(DRIVER_BACKUP, BD_PROTO, EFAULT); /* Return the actual size. */ if ((ssize_t) *sizep >= m2.BDEV_STATUS) *sizep = m2.BDEV_STATUS; } } return OK; }
/*===========================================================================* * driver_open * *===========================================================================*/ static int driver_open(int which) { /* Perform an open or close operation on the driver. This is * unfinished code: we should never be doing a blocking sendrec() to * the driver. */ message msg; cp_grant_id_t gid; struct partition part; sector_t sectors; int r; memset(&msg, 0, sizeof(msg)); msg.m_type = BDEV_OPEN; msg.BDEV_MINOR = driver[which].minor; msg.BDEV_ACCESS = R_BIT | W_BIT; msg.BDEV_ID = 0; r = sendrec(driver[which].endpt, &msg); if (r != OK) { /* Should we restart the driver now? */ printf("Filter: driver_open: sendrec returned %d\n", r); return RET_REDO; } if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) { printf("Filter: driver_open: sendrec returned %d, %d\n", msg.m_type, msg.BDEV_STATUS); return RET_REDO; } /* Take the opportunity to retrieve the hard disk size. */ gid = cpf_grant_direct(driver[which].endpt, (vir_bytes) &part, sizeof(part), CPF_WRITE); if(!GRANT_VALID(gid)) panic("invalid grant: %d", gid); memset(&msg, 0, sizeof(msg)); msg.m_type = BDEV_IOCTL; msg.BDEV_MINOR = driver[which].minor; msg.BDEV_REQUEST = DIOCGETP; msg.BDEV_GRANT = gid; msg.BDEV_ID = 0; r = sendrec(driver[which].endpt, &msg); cpf_revoke(gid); if (r != OK || msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) { /* Not sure what to do here, either. */ printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n", r, msg.m_type); return RET_REDO; } if(!size_known) { disk_size = part.size; size_known = 1; sectors = div64u(disk_size, SECTOR_SIZE); if(cmp64(mul64u(sectors, SECTOR_SIZE), disk_size)) { printf("Filter: partition too large\n"); return RET_REDO; } #if DEBUG printf("Filter: partition size: 0x%s / %lu sectors\n", print64(disk_size), sectors); #endif } else { if(cmp64(disk_size, part.size)) { printf("Filter: partition size mismatch (%s != %s)\n", print64(part.size), print64(disk_size)); return RET_REDO; } } return OK; }
/*===========================================================================* * m_block_ioctl * *===========================================================================*/ static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt, cp_grant_id_t grant) { /* I/O controls for the block devices of the memory driver. Currently there is * one I/O control specific to the memory driver: * - MIOCRAMSIZE: to set the size of the RAM disk. */ struct device *dv; u32_t ramdev_size; int s; void *mem; if (request != MIOCRAMSIZE) return EINVAL; /* Someone wants to create a new RAM disk with the given size. * A ramdisk can be created only once, and only on RAM disk device. */ if ((dv = m_block_part(minor)) == NULL) return ENXIO; if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) && minor != RAM_DEV_OLD) { printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", minor); return EINVAL; } /* Get request structure */ s= sys_safecopyfrom(endpt, grant, 0, (vir_bytes)&ramdev_size, sizeof(ramdev_size)); if (s != OK) return s; if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) { return(OK); } /* openct is 1 for the ioctl(). */ if(openct[minor] != 1) { printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n", minor, openct[minor]); return(EBUSY); } if(m_vaddrs[minor]) { u32_t size; if(ex64hi(dv->dv_size)) { panic("huge old ramdisk"); } size = ex64lo(dv->dv_size); minix_munmap((void *) m_vaddrs[minor], size); m_vaddrs[minor] = (vir_bytes) NULL; } #if DEBUG printf("MEM:%d: allocating ramdisk of size 0x%x\n", minor, ramdev_size); #endif /* Try to allocate a piece of memory for the RAM disk. */ if((mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE, MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) { printf("MEM: failed to get memory for ramdisk\n"); return(ENOMEM); } m_vaddrs[minor] = (vir_bytes) mem; dv->dv_size = cvul64(ramdev_size); return(OK); }