/*===========================================================================* * fs_breadwrite_s * *===========================================================================*/ PUBLIC int fs_breadwrite_s(void) { int r, rw_flag, chunk, block_size; cp_grant_id_t gid; int nrbytes; u64_t position; unsigned int off, cum_io; mode_t mode_word; int completed, r2 = OK; /* Pseudo inode for rw_chunk */ struct inode rip; r = OK; /* Get the values from the request message */ rw_flag = (fs_m_in.m_type == REQ_BREAD_S ? READING : WRITING); gid = fs_m_in.REQ_XFD_GID; position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI); nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES; block_size = get_block_size(fs_m_in.REQ_XFD_BDEV); rip.i_zone[0] = fs_m_in.REQ_XFD_BDEV; rip.i_mode = I_BLOCK_SPECIAL; rip.i_size = 0; rdwt_err = OK; /* set to EIO if disk error occurs */ cum_io = 0; /* Split the transfer into chunks that don't span two blocks. */ while (nrbytes != 0) { off = rem64u(position, block_size); /* offset in blk*/ chunk = MIN(nrbytes, block_size - off); if (chunk < 0) chunk = block_size - off; /* Read or write 'chunk' bytes. */ r = rw_chunk_s(&rip, position, off, chunk, (unsigned) nrbytes, rw_flag, gid, cum_io, block_size, &completed); if (r != OK) break; /* EOF reached */ if (rdwt_err < 0) break; /* Update counters and pointers. */ nrbytes -= chunk; /* bytes yet to be read */ cum_io += chunk; /* bytes read so far */ position= add64ul(position, chunk); /* position within the file */ } fs_m_out.RES_XFD_POS_LO = ex64lo(position); fs_m_out.RES_XFD_POS_HI = ex64hi(position); if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; fs_m_out.RES_XFD_CUM_IO = cum_io; return(r); }
/*===========================================================================* * fs_breadwrite * *===========================================================================*/ int fs_breadwrite(void) { int r, rw_flag, completed; cp_grant_id_t gid; u64_t position; unsigned int off, cum_io, chunk, block_size; size_t nrbytes; /* Pseudo inode for rw_chunk */ struct inode rip; r = OK; /* Get the values from the request message */ rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING); gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; position = make64((unsigned long) fs_m_in.REQ_SEEK_POS_LO, (unsigned long) fs_m_in.REQ_SEEK_POS_HI); nrbytes = (size_t) fs_m_in.REQ_NBYTES; block_size = get_block_size( (dev_t) fs_m_in.REQ_DEV2); rip.i_block[0] = (block_t) fs_m_in.REQ_DEV2; rip.i_mode = I_BLOCK_SPECIAL; rip.i_size = 0; rdwt_err = OK; /* set to EIO if disk error occurs */ cum_io = 0; /* Split the transfer into chunks that don't span two blocks. */ while (nrbytes > 0) { off = rem64u(position, block_size); /* offset in blk*/ chunk = min(nrbytes, block_size - off); /* Read or write 'chunk' bytes. */ r = rw_chunk(&rip, position, off, chunk, nrbytes, rw_flag, gid, cum_io, block_size, &completed); if (r != OK) break; /* EOF reached */ if (rdwt_err < 0) break; /* Update counters and pointers. */ nrbytes -= chunk; /* bytes yet to be read */ cum_io += chunk; /* bytes read so far */ position = add64ul(position, chunk); /* position within the file */ } fs_m_out.RES_SEEK_POS_LO = ex64lo(position); fs_m_out.RES_SEEK_POS_HI = ex64hi(position); if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; fs_m_out.RES_NBYTES = cum_io; return(r); }
/*===========================================================================* * do_lseek * *===========================================================================*/ int do_lseek() { /* Perform the lseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; int r = OK, seekfd, seekwhence; off_t offset; u64_t pos, newpos; seekfd = job_m_in.ls_fd; seekwhence = job_m_in.whence; offset = (off_t) 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); } 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); }
/*===========================================================================* * 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); }
/*===========================================================================* * fs_bread * *===========================================================================*/ int fs_bread(void) { int r, rw_flag, chunk, block_size; cp_grant_id_t gid; int nrbytes; u64_t position; unsigned int off, cum_io; int completed; struct dir_record *dir; r = OK; rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING); gid = fs_m_in.REQ_GRANT; position = make64(fs_m_in.REQ_SEEK_POS_LO, fs_m_in.REQ_SEEK_POS_HI); nrbytes = (unsigned) fs_m_in.REQ_NBYTES; block_size = v_pri.logical_block_size_l; dir = v_pri.dir_rec_root; if(rw_flag == WRITING) return (EIO); /* Not supported */ rdwt_err = OK; /* set to EIO if disk error occurs */ cum_io = 0; /* Split the transfer into chunks that don't span two blocks. */ while (nrbytes != 0) { off = rem64u(position, block_size); /* offset in blk*/ chunk = MIN(nrbytes, block_size - off); if (chunk < 0) chunk = block_size - off; /* Read 'chunk' bytes. */ r = read_chunk(dir, position, off, chunk, (unsigned) nrbytes, gid, cum_io, block_size, &completed); if (r != OK) break; /* EOF reached */ if (rdwt_err < 0) break; /* Update counters and pointers. */ nrbytes -= chunk; /* bytes yet to be read */ cum_io += chunk; /* bytes read so far */ position= add64ul(position, chunk); /* position within the file */ } fs_m_out.RES_SEEK_POS_LO = ex64lo(position); fs_m_out.RES_SEEK_POS_HI = ex64hi(position); if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; fs_m_out.RES_NBYTES = cum_io; return(r); }