diff --git a/kernel/clock.c b/kernel/clock.c index b748a3495..838f8959f 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -39,7 +39,7 @@ */ FORWARD _PROTOTYPE( void init_clock, (void) ); FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) ); -FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) ); +FORWARD _PROTOTYPE( void do_clocktick, (message *m_ptr) ); FORWARD _PROTOTYPE( void load_update, (void)); /* The CLOCK's timers queue. The functions in operate on this. @@ -74,10 +74,13 @@ PUBLIC void clock_task() /* Go get a message. */ result = receive(ANY, &m); + if(result != OK) + panic("receive() failed", result); + /* Handle the request. Only clock ticks are expected. */ switch (m.m_type) { case HARD_INT: - result = do_clocktick(&m); /* handle clock tick */ + do_clocktick(&m); /* handle clock tick */ break; default: /* illegal request type */ kprintf("CLOCK: illegal request %d from %d.\n", @@ -89,7 +92,7 @@ PUBLIC void clock_task() /*===========================================================================* * do_clocktick * *===========================================================================*/ -PRIVATE int do_clocktick(m_ptr) +PRIVATE void do_clocktick(m_ptr) message *m_ptr; /* pointer to request message */ { /* Despite its name, this routine is not called on every clock tick. It @@ -103,9 +106,10 @@ message *m_ptr; /* pointer to request message */ * place in the queues. As a side-effect a new process will be scheduled. */ if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) { - if(prev_ptr->p_rts_flags == 0) /* if it was runnable .. */ - lock_dequeue(prev_ptr); /* take it off the queues */ - lock_enqueue(prev_ptr); /* and reinsert it again */ + if(prev_ptr->p_rts_flags == 0) { /* if it was runnable .. */ + lock_dequeue(prev_ptr); /* take it off the queues */ + lock_enqueue(prev_ptr); /* and reinsert it again */ + } } /* Check if a clock timer expired and run its watchdog function. */ @@ -115,8 +119,7 @@ message *m_ptr; /* pointer to request message */ TMR_NEVER : clock_timers->tmr_exp_time; } - /* Inhibit sending a reply. */ - return(EDONTREPLY); + return; } /*===========================================================================* diff --git a/kernel/main.c b/kernel/main.c index d0223980b..1e93aefcb 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -150,12 +150,8 @@ PUBLIC void main() } /* Set ready. The HARDWARE task is never ready. */ - if (rp->p_nr != HARDWARE) { - rp->p_rts_flags = 0; /* runnable if no flags */ - lock_enqueue(rp); /* add to scheduling queues */ - } else { - rp->p_rts_flags = NO_PRIORITY; /* prevent from running */ - } + if (rp->p_nr == HARDWARE) RTS_LOCK_SET(rp, NO_PRIORITY); + RTS_LOCK_UNSET(rp, SLOT_FREE); /* remove SLOT_FREE and schedule */ /* Code and data segments must be allocated in protected mode. */ alloc_segments(rp); diff --git a/kernel/proc.c b/kernel/proc.c index 2e6a717c9..dede6f9e4 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -104,7 +104,7 @@ long bit_map; /* notification event set or flags */ vir_clicks vlo, vhi; /* virtual clicks containing message to send */ #if 1 - if (caller_ptr->p_rts_flags & SLOT_FREE) + if (RTS_ISSET(caller_ptr, SLOT_FREE)) { kprintf("called by the dead?!?\n"); return EINVAL; @@ -243,10 +243,10 @@ int src_dst; /* src or dst process */ /* Check whether the last process in the chain has a dependency. If it * has not, the cycle cannot be closed and we are done. */ - if (xp->p_rts_flags & RECEIVING) { /* xp has dependency */ + if (RTS_ISSET(xp, RECEIVING)) { /* xp has dependency */ if(xp->p_getfrom_e == ANY) src_dst = ANY; else okendpt(xp->p_getfrom_e, &src_dst); - } else if (xp->p_rts_flags & SENDING) { /* xp has dependency */ + } else if (RTS_ISSET(xp, SENDING)) { /* xp has dependency */ okendpt(xp->p_sendto_e, &src_dst); } else { return(0); /* not a deadlock */ @@ -289,23 +289,22 @@ unsigned flags; /* system call flags */ dst_p = _ENDPOINT_P(dst_e); dst_ptr = proc_addr(dst_p); - if (dst_ptr->p_rts_flags & NO_ENDPOINT) return EDSTDIED; + if (RTS_ISSET(dst_ptr, NO_ENDPOINT)) return EDSTDIED; /* Check if 'dst' is blocked waiting for this message. The destination's * SENDING flag may be set when its SENDREC call blocked while sending. */ - if ( (dst_ptr->p_rts_flags & (RECEIVING | SENDING)) == RECEIVING && + if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) && (dst_ptr->p_getfrom_e == ANY || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { /* Destination is indeed waiting for this message. */ CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr, dst_ptr->p_messbuf); - if ((dst_ptr->p_rts_flags &= ~RECEIVING) == 0) enqueue(dst_ptr); + RTS_UNSET(dst_ptr, RECEIVING); } else if ( ! (flags & NON_BLOCKING)) { /* Destination is not waiting. Block and dequeue caller. */ caller_ptr->p_messbuf = m_ptr; - if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); - caller_ptr->p_rts_flags |= SENDING; + RTS_SET(caller_ptr, SENDING); caller_ptr->p_sendto_e = dst_e; /* Process is now blocked. Put in on the destination's queue. */ @@ -344,7 +343,7 @@ unsigned flags; /* system call flags */ else { okendpt(src_e, &src_p); - if (proc_addr(src_p)->p_rts_flags & NO_ENDPOINT) return ESRCDIED; + if (RTS_ISSET(proc_addr(src_p), NO_ENDPOINT)) return ESRCDIED; } @@ -352,7 +351,7 @@ unsigned flags; /* system call flags */ * The caller's SENDING flag may be set if SENDREC couldn't send. If it is * set, the process should be blocked. */ - if (!(caller_ptr->p_rts_flags & SENDING)) { + if (!RTS_ISSET(caller_ptr, SENDING)) { /* Check if there are pending notifications, except for SENDREC. */ if (! (caller_ptr->p_misc_flags & REPLY_PENDING)) { @@ -386,7 +385,7 @@ unsigned flags; /* system call flags */ while (*xpp != NIL_PROC) { if (src_e == ANY || src_p == proc_nr(*xpp)) { #if 1 - if ((*xpp)->p_rts_flags & SLOT_FREE) + if (RTS_ISSET(*xpp, SLOT_FREE)) { kprintf("listening to the dead?!?\n"); return EINVAL; @@ -395,7 +394,7 @@ unsigned flags; /* system call flags */ /* Found acceptable message. Copy it and update status. */ CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr); - if (((*xpp)->p_rts_flags &= ~SENDING) == 0) enqueue(*xpp); + RTS_UNSET(*xpp, SENDING); *xpp = (*xpp)->p_q_link; /* remove from queue */ return(OK); /* report success */ } @@ -409,8 +408,7 @@ unsigned flags; /* system call flags */ if ( ! (flags & NON_BLOCKING)) { caller_ptr->p_getfrom_e = src_e; caller_ptr->p_messbuf = m_ptr; - if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); - caller_ptr->p_rts_flags |= RECEIVING; + RTS_SET(caller_ptr, RECEIVING); return(OK); } else { return(ENOTREADY); @@ -431,7 +429,7 @@ int dst; /* which process to notify */ /* Check to see if target is blocked waiting for this message. A process * can be both sending and receiving during a SENDREC system call. */ - if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && + if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) && ! (dst_ptr->p_misc_flags & REPLY_PENDING) && (dst_ptr->p_getfrom_e == ANY || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { @@ -443,8 +441,7 @@ int dst; /* which process to notify */ BuildMess(&m, proc_nr(caller_ptr), dst_ptr); CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m, dst_ptr, dst_ptr->p_messbuf); - dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */ - if (dst_ptr->p_rts_flags == 0) enqueue(dst_ptr); + RTS_UNSET(dst_ptr, RECEIVING); return(OK); } diff --git a/kernel/proc.h b/kernel/proc.h index 9f0a264a4..4ce8cc6a4 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -12,7 +12,7 @@ #include #include "const.h" #include "priv.h" - + struct proc { struct stackframe_s p_reg; /* process' registers saved in stack frame */ struct segframe p_seg; /* segment descriptors */ @@ -60,6 +60,50 @@ struct proc { #define NO_PRIV 0x80 /* keep forked system process from running */ #define NO_ENDPOINT 0x100 /* process cannot send or receive messages */ +/* These runtime flags can be tested and manipulated by these macros. */ + +#define RTS_ISSET(rp, f) (((rp)->p_rts_flags & (f)) == (f)) + + +/* Set flag and dequeue if the process was runnable. */ +#define RTS_SET(rp, f) \ + do { \ + if(!(rp)->p_rts_flags) { dequeue(rp); } \ + (rp)->p_rts_flags |= (f); \ + } while(0) + +/* Clear flag and enqueue if the process was not runnable but is now. */ +#define RTS_UNSET(rp, f) \ + do { \ + int rts; \ + rts = (rp)->p_rts_flags; \ + (rp)->p_rts_flags &= ~(f); \ + if(rts && !(rp)->p_rts_flags) { enqueue(rp); } \ + } while(0) + +/* Set flag and dequeue if the process was runnable. */ +#define RTS_LOCK_SET(rp, f) \ + do { \ + if(!(rp)->p_rts_flags) { lock_dequeue(rp); } \ + (rp)->p_rts_flags |= (f); \ + } while(0) + +/* Clear flag and enqueue if the process was not runnable but is now. */ +#define RTS_LOCK_UNSET(rp, f) \ + do { \ + int rts; \ + rts = (rp)->p_rts_flags; \ + (rp)->p_rts_flags &= ~(f); \ + if(rts && !(rp)->p_rts_flags) { lock_enqueue(rp); } \ + } while(0) + +/* Set flags to this value. */ +#define RTS_LOCK_SETFLAGS(rp, f) \ + do { \ + if(!(rp)->p_rts_flags && (f)) { lock_dequeue(rp); } \ + (rp)->p_rts_flags = (f); \ + } while(0) + /* Misc flags */ #define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */ #define MF_VM 0x08 /* process uses VM */ diff --git a/kernel/system.c b/kernel/system.c index 68d577d0b..fc7f94f25 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -30,6 +30,7 @@ #include "debug.h" #include "kernel.h" #include "system.h" +#include "proc.h" #include #include #include @@ -67,8 +68,9 @@ PUBLIC void sys_task() initialize(); while (TRUE) { + int r; /* Get work. Block and wait until a request message arrives. */ - receive(ANY, &m); + if((r=receive(ANY, &m)) != OK) panic("system: receive() failed", r); sys_call_code = (unsigned) m.m_type; call_nr = sys_call_code - KERNEL_CALL; who_e = m.m_source; @@ -216,7 +218,8 @@ int proc_type; /* system or user process flag */ } else { rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */ rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */ - rc->p_priv->s_flags = 0; /* no initial flags */ + + /* s_flags of this shared structure are to be once at system startup. */ } return(OK); } @@ -292,9 +295,8 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */ rp = proc_addr(proc_nr); if (! sigismember(&rp->p_pending, sig_nr)) { sigaddset(&rp->p_pending, sig_nr); - if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */ - if (rp->p_rts_flags == 0) lock_dequeue(rp); /* make not ready */ - rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */ + if (! (RTS_ISSET(rp, SIGNALED))) { /* other pending */ + RTS_LOCK_SET(rp, SIGNALED | SIG_PENDING); send_sig(PM_PROC_NR, SIGKSIG); } } @@ -473,13 +475,12 @@ register struct proc *rc; /* slot of process to clean up */ if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc)); /* Make sure that the exiting process is no longer scheduled. */ - if (rc->p_rts_flags == 0) lock_dequeue(rc); - rc->p_rts_flags |= NO_ENDPOINT; + RTS_LOCK_SET(rc, NO_ENDPOINT); /* If the process happens to be queued trying to send a * message, then it must be removed from the message queues. */ - if (rc->p_rts_flags & SENDING) { + if (RTS_ISSET(rc, SENDING)) { int target_proc; okendpt(rc->p_sendto_e, &target_proc); @@ -511,21 +512,20 @@ register struct proc *rc; /* slot of process to clean up */ unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id); /* Check if process is receiving from exiting process. */ - if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) { + if (RTS_ISSET(rp, RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) { rp->p_reg.retreg = ESRCDIED; /* report source died */ - rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */ + RTS_LOCK_UNSET(rp, RECEIVING); /* no longer receiving */ #if DEBUG_ENABLE_IPC_WARNINGS kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc)); #endif - if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */ } - if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) { + if (RTS_ISSET(rp, SENDING) && + rp->p_sendto_e == rc->p_endpoint) { rp->p_reg.retreg = EDSTDIED; /* report destination died */ - rp->p_rts_flags &= ~SENDING; /* no longer sending */ + RTS_LOCK_UNSET(rp, SENDING); #if DEBUG_ENABLE_IPC_WARNINGS kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc)); #endif - if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */ } } } diff --git a/kernel/system/do_endksig.c b/kernel/system/do_endksig.c index 642a77669..1e62dc05b 100644 --- a/kernel/system/do_endksig.c +++ b/kernel/system/do_endksig.c @@ -31,12 +31,11 @@ message *m_ptr; /* pointer to request message */ return EINVAL; rp = proc_addr(proc); - if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL); + if (!RTS_ISSET(rp, SIG_PENDING)) return(EINVAL); /* PM has finished one kernel signal. Perhaps process is ready now? */ - if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */ - if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */ - lock_enqueue(rp); /* ready if no flags */ + if (!RTS_ISSET(rp, SIGNALED)) /* new signal arrived */ + RTS_LOCK_UNSET(rp, SIG_PENDING); /* remove pending flag */ return(OK); } diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index 909d63f3e..dca66d9c1 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -40,8 +40,7 @@ register message *m_ptr; /* pointer to request message */ (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_seg.p_ldt[0])); #endif rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ - rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ - if (rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, RECEIVING); /* PM does not reply to EXEC call */ /* Save command name for debugging, ps(1) output, etc. */ phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR, (vir_bytes) P_NAME_LEN - 1); diff --git a/kernel/system/do_exit.c b/kernel/system/do_exit.c index 165ea855c..99d6d6c68 100644 --- a/kernel/system/do_exit.c +++ b/kernel/system/do_exit.c @@ -52,7 +52,6 @@ register struct proc *rc; /* slot of process to clean up */ register struct proc **xpp; /* iterate over caller queue */ int i; int sys_id; - char saved_rts_flags; /* Don't clear if already cleared. */ if(isemptyp(rc)) return; @@ -63,8 +62,10 @@ register struct proc *rc; /* slot of process to clean up */ /* Turn off any alarm timers at the clock. */ reset_timer(&priv(rc)->s_alarm_timer); - /* Make sure that the exiting process is no longer scheduled. */ - if (rc->p_rts_flags == 0) lock_dequeue(rc); + /* Make sure that the exiting process is no longer scheduled, + * and mark slot as FREE. + */ + RTS_LOCK_SETFLAGS(rc, SLOT_FREE); /* Check the table with IRQ hooks to see if hooks should be released. */ for (i=0; i < NR_IRQ_HOOKS; i++) { @@ -80,8 +81,6 @@ register struct proc *rc; /* slot of process to clean up */ * this point. All important fields are reinitialized when the * slots are assigned to another, new process. */ - saved_rts_flags = rc->p_rts_flags; - rc->p_rts_flags = SLOT_FREE; if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE; /* Clean up virtual memory */ diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index b1daba701..63016e146 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -26,7 +26,7 @@ register message *m_ptr; /* pointer to request message */ register struct proc *rpc; /* child process pointer */ struct proc *rpp; /* parent process pointer */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ - int i, gen; + int i, gen, r; int p_proc; if(!isokendpt(m_ptr->PR_ENDPT, &p_proc)) @@ -51,10 +51,6 @@ register message *m_ptr; /* pointer to request message */ rpc->p_nr = m_ptr->PR_SLOT; /* this was obliterated by copy */ rpc->p_endpoint = _ENDPOINT(gen, rpc->p_nr); /* new endpoint of slot */ - /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ - rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP); - sigemptyset(&rpc->p_pending); - rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */ rpc->p_user_time = 0; /* set all the accounting times to 0 */ rpc->p_sys_time = 0; @@ -79,7 +75,13 @@ register message *m_ptr; /* pointer to request message */ m_ptr->PR_ENDPT = rpc->p_endpoint; /* Install new map */ - return newmap(rpc, map_ptr); + r = newmap(rpc, map_ptr); + + /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ + RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP)); + sigemptyset(&rpc->p_pending); + + return r; } #endif /* USE_FORK */ diff --git a/kernel/system/do_getksig.c b/kernel/system/do_getksig.c index 95d85a507..1bf0e165f 100644 --- a/kernel/system/do_getksig.c +++ b/kernel/system/do_getksig.c @@ -29,12 +29,12 @@ message *m_ptr; /* pointer to request message */ /* Find the next process with pending signals. */ for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { - if (rp->p_rts_flags & SIGNALED) { + if (RTS_ISSET(rp, SIGNALED)) { /* store signaled process' endpoint */ m_ptr->SIG_ENDPT = rp->p_endpoint; m_ptr->SIG_MAP = rp->p_pending; /* pending signals map */ sigemptyset(&rp->p_pending); /* ball is in PM's court */ - rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ + RTS_LOCK_UNSET(rp, SIGNALED); /* blocked by SIG_PENDING */ return(OK); } } diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c index b595334a7..a179f5631 100644 --- a/kernel/system/do_newmap.c +++ b/kernel/system/do_newmap.c @@ -20,7 +20,6 @@ message *m_ptr; /* pointer to request message */ register struct proc *rp; /* process whose map is to be loaded */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ phys_bytes src_phys; /* physical address of map at the PM */ - int old_flags; /* value of flags before modification */ int proc; map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; @@ -41,7 +40,6 @@ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ { /* Fetch the memory map from PM. */ phys_bytes src_phys; /* physical address of map at the PM */ - int old_flags; /* value of flags before modification */ int proc; /* Copy the map from PM. */ @@ -52,8 +50,6 @@ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ (phys_bytes)sizeof(rp->p_memmap)); alloc_segments(rp); - old_flags = rp->p_rts_flags; /* save the previous value of the flags */ - if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); return(OK); } diff --git a/kernel/system/do_nice.c b/kernel/system/do_nice.c index 64a23ab78..e31403fc3 100644 --- a/kernel/system/do_nice.c +++ b/kernel/system/do_nice.c @@ -28,10 +28,8 @@ PUBLIC int do_nice(message *m_ptr) rp = proc_addr(proc_nr); if (pri == PRIO_STOP) { - /* Take process off the scheduling queues. */ - if(rp->p_rts_flags == 0) lock_dequeue(rp); - rp->p_rts_flags |= NO_PRIORITY; + RTS_LOCK_SET(rp, NO_PRIORITY); return(OK); } else if (pri >= PRIO_MIN && pri <= PRIO_MAX) { @@ -48,10 +46,9 @@ PUBLIC int do_nice(message *m_ptr) /* Make sure the process is not running while changing its priority. * Put the process back in its new queue if it is runnable. */ - if(rp->p_rts_flags == 0) lock_dequeue(rp); - rp->p_rts_flags &= ~NO_PRIORITY; + RTS_LOCK_SET(rp, NO_PRIORITY); rp->p_max_priority = rp->p_priority = new_q; - if (! rp->p_rts_flags) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, NO_PRIORITY); return(OK); } diff --git a/kernel/system/do_privctl.c b/kernel/system/do_privctl.c index 50231a458..d3ffe07d0 100644 --- a/kernel/system/do_privctl.c +++ b/kernel/system/do_privctl.c @@ -28,7 +28,6 @@ message *m_ptr; /* pointer to request message */ register struct priv *sp; int proc_nr; int priv_id; - int old_flags; int i; phys_bytes caller_phys, kernel_phys; struct io_range io_range; @@ -49,7 +48,7 @@ message *m_ptr; /* pointer to request message */ switch(m_ptr->CTL_REQUEST) { case SYS_PRIV_INIT: - if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM); + if (! RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Make sure this process has its own privileges structure. This may * fail, since there are only a limited number of system processes. @@ -136,25 +135,17 @@ message *m_ptr; /* pointer to request message */ } /* Done. Privileges have been set. Allow process to run again. */ - old_flags = rp->p_rts_flags; /* save value of the flags */ - rp->p_rts_flags &= ~NO_PRIV; - if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, NO_PRIV); return(OK); case SYS_PRIV_USER: - if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM); - - /* Make this process an ordinary user process. - */ + /* Make this process an ordinary user process. */ + if (!RTS_ISSET(rp, NO_PRIV)) return(EPERM); if ((i=get_priv(rp, 0)) != OK) return(i); - - /* Done. Privileges have been set. Allow process to run again. */ - old_flags = rp->p_rts_flags; /* save value of the flags */ - rp->p_rts_flags &= ~NO_PRIV; - if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, NO_PRIV); return(OK); case SYS_PRIV_ADD_IO: - if (rp->p_rts_flags & NO_PRIV) + if (RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Only system processes get I/O resources? */ @@ -180,7 +171,7 @@ message *m_ptr; /* pointer to request message */ return OK; case SYS_PRIV_ADD_MEM: - if (rp->p_rts_flags & NO_PRIV) + if (RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Only system processes get memory resources? */ @@ -208,7 +199,7 @@ message *m_ptr; /* pointer to request message */ return OK; case SYS_PRIV_ADD_IRQ: - if (rp->p_rts_flags & NO_PRIV) + if (RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Only system processes get IRQs? */ diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 38bc2b19b..efe89395a 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -61,7 +61,7 @@ endpoint_t *e_granter; /* new granter (magic grants) */ * EINVAL for grant-out-of-range, in case this turns out to be * interesting information.) */ - if((granter_proc->p_rts_flags & NO_PRIV) || !(priv(granter_proc)) || + if(RTS_ISSET(granter_proc, NO_PRIV) || !(priv(granter_proc)) || priv(granter_proc)->s_grant_table < 1) { kprintf("grant verify failed in ep %d proc %d: " "no priv table, or no grant table\n", diff --git a/kernel/system/do_setgrant.c b/kernel/system/do_setgrant.c index 7f353e33a..39044bab4 100644 --- a/kernel/system/do_setgrant.c +++ b/kernel/system/do_setgrant.c @@ -22,7 +22,7 @@ message *m_ptr; rp = proc_addr(who_p); /* Copy grant table set in priv. struct. */ - if ((rp->p_rts_flags & NO_PRIV) || !(priv(rp))) { + if (RTS_ISSET(rp, NO_PRIV) || !(priv(rp))) { r = EPERM; } else { _K_SET_GRANT_TABLE(rp, diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index b118edb34..0b37bac89 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -93,10 +93,10 @@ message *m_ptr; /* pointer to request message */ rp->p_reg.pc = (reg_t) smsg.sm_sighandler; /* Reschedule if necessary. */ - if(rp->p_rts_flags & NO_PRIORITY) { - rp->p_rts_flags &= ~NO_PRIORITY; - if (rp->p_rts_flags == 0) lock_enqueue(rp); - } else kprintf("system: warning: sigsend a running process\n"); + if(RTS_ISSET(rp, NO_PRIORITY)) + RTS_LOCK_UNSET(rp, NO_PRIORITY); + else + kprintf("system: warning: sigsend a running process\n"); return(OK); } diff --git a/kernel/system/do_trace.c b/kernel/system/do_trace.c index 19299b3af..0e12f0ba5 100644 --- a/kernel/system/do_trace.c +++ b/kernel/system/do_trace.c @@ -55,8 +55,7 @@ register message *m_ptr; if (isemptyp(rp)) return(EIO); switch (tr_request) { case T_STOP: /* stop process */ - if (rp->p_rts_flags == 0) lock_dequeue(rp); - rp->p_rts_flags |= P_STOP; + RTS_LOCK_SET(rp, P_STOP); rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */ return(OK); @@ -126,15 +125,13 @@ register message *m_ptr; break; case T_RESUME: /* resume execution */ - rp->p_rts_flags &= ~P_STOP; - if (rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, P_STOP); m_ptr->CTL_DATA = 0; break; case T_STEP: /* set trace bit */ rp->p_reg.psw |= TRACEBIT; - rp->p_rts_flags &= ~P_STOP; - if (rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, P_STOP); m_ptr->CTL_DATA = 0; break; diff --git a/servers/is/dmp_kernel.c b/servers/is/dmp_kernel.c index 43c355d1a..2ac0f3daf 100644 --- a/servers/is/dmp_kernel.c +++ b/servers/is/dmp_kernel.c @@ -137,24 +137,6 @@ PUBLIC void irqtab_dmp() struct irq_hook irq_hooks[NR_IRQ_HOOKS]; int irq_actids[NR_IRQ_VECTORS]; struct irq_hook *e; /* irq tab entry */ - char *irq[] = { - "clock", /* 00 */ - "keyboard", /* 01 */ - "cascade", /* 02 */ - "rs232", /* 03 */ - "rs232", /* 04 */ - "NIC(eth)", /* 05 */ - "floppy", /* 06 */ - "printer", /* 07 */ - "", /* 08 */ - "", /* 09 */ - "", /* 10 */ - "", /* 11 */ - "", /* 12 */ - "", /* 13 */ - "at_wini_0", /* 14 */ - "at_wini_1", /* 15 */ - }; if ((r = sys_getirqhooks(irq_hooks)) != OK) { report("IS","warning: couldn't get copy of irq hooks", r); @@ -173,7 +155,7 @@ PUBLIC void irqtab_dmp() #endif printf("IRQ policies dump shows use of kernel's IRQ hooks.\n"); - printf("-h.id- -proc.nr- -IRQ vector (nr.)- -policy- -notify id-\n"); + printf("-h.id- -proc.nr- -irq nr- -policy- -notify id-\n"); for (i=0; iproc_nr_e); - printf(" %9.9s (%02d) ", irq[e->irq], e->irq); + printf(" (%02d) ", e->irq); printf(" %s", (e->policy & IRQ_REENABLE) ? "reenable" : " - "); printf(" %d", e->notify_id); if (irq_actids[e->irq] & (1 << i)) diff --git a/servers/mfs/glo.h b/servers/mfs/glo.h index 36cd88329..01686272c 100644 --- a/servers/mfs/glo.h +++ b/servers/mfs/glo.h @@ -33,7 +33,7 @@ EXTERN int SELF_E; EXTERN struct inode *chroot_dir; EXTERN short path_processed; /* number of characters processed */ -EXTERN char user_path[PATH_MAX]; /* pathname to be processed */ +EXTERN char user_path[PATH_MAX+1]; /* pathname to be processed */ EXTERN char *vfs_slink_storage; EXTERN int symloop; diff --git a/servers/mfs/link.c b/servers/mfs/link.c index 0e76712b5..13db3af03 100644 --- a/servers/mfs/link.c +++ b/servers/mfs/link.c @@ -586,6 +586,7 @@ off_t newsize; /* inode must become this size */ /* Next correct the inode size. */ if(!waspipe) rip->i_size = newsize; else wipe_inode(rip); /* Pipes can only be truncated to 0. */ + rip->i_update |= CTIME | MTIME; rip->i_dirt = DIRTY; return OK; @@ -642,6 +643,9 @@ off_t start, end; /* range of bytes to free (end uninclusive) */ for(p = nextblock(start, zone_size)/zone_size; p < e; p ++) write_map(rip, p*zone_size, NO_ZONE, WMAP_FREE); + rip->i_update |= CTIME | MTIME; + rip->i_dirt = DIRTY; + return OK; } diff --git a/servers/mfs/open.c b/servers/mfs/open.c index b2889e21d..eb5245b9c 100644 --- a/servers/mfs/open.c +++ b/servers/mfs/open.c @@ -91,6 +91,8 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E); case I_REGULAR: /* Truncate regular file if O_TRUNC. */ if (oflags & O_TRUNC) { + panic(__FILE__, "O_TRUNC in mfs.", oflags); +#if 0 if ((r = forbidden(rip, W_BIT)) !=OK) break; truncate_inode(rip, 0); wipe_inode(rip); @@ -99,6 +101,7 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E); * cache flush. */ rw_inode(rip, WRITING); +#endif } break; diff --git a/servers/mfs/path.c b/servers/mfs/path.c index e5459c3cf..9158f8def 100644 --- a/servers/mfs/path.c +++ b/servers/mfs/path.c @@ -43,7 +43,7 @@ PUBLIC int lookup() /* Check length. */ len = fs_m_in.REQ_PATH_LEN; - if(len > sizeof(string)) return E2BIG; /* too big for buffer */ + if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ if(len < 1) return EINVAL; /* too small for \0 */ /* Copy the pathname and set up caller's user and group id */ @@ -55,8 +55,10 @@ PUBLIC int lookup() } /* Verify this is a null-terminated path. */ - if(user_path[len-1] != '\0') + if(user_path[len-1] != '\0') { + printf("mfs:lookup: didn't get null-terminated string.\n"); return EINVAL; + } caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; diff --git a/servers/mfs/protect.c b/servers/mfs/protect.c index a2d1d609b..ecf80c246 100644 --- a/servers/mfs/protect.c +++ b/servers/mfs/protect.c @@ -50,6 +50,9 @@ printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E); rip->i_update |= CTIME; rip->i_dirt = DIRTY; + /* Return full new mode to caller. */ + fs_m_out.RES_MODE = rip->i_mode; + put_inode(rip); return(OK); } @@ -94,7 +97,11 @@ printf("MFS(%d) get_inode by fs_chown() failed\n", SELF_E); rip->i_dirt = DIRTY; } + /* Update caller on current mode, as it may have changed. */ + fs_m_out.RES_MODE = rip->i_mode; + put_inode(rip); + return(r); } diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 51d31e168..13c207b16 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -142,8 +142,8 @@ PUBLIC void dev_status(message *m) if(endpt == NONE) { printf("FS: proc with " "grant %d from %d not found (revive)\n", - st.m_source, - st.REP_IO_GRANT); + st.REP_IO_GRANT, + st.m_source); continue; } } diff --git a/servers/vfs/filedes.c b/servers/vfs/filedes.c index b070e517d..2503d2a62 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -3,13 +3,14 @@ * The entry points into this file are * get_fd: look for free file descriptor and free filp slots * get_filp: look up the filp entry for a given file descriptor - * find_filp: find a filp slot that points to a given inode + * find_filp: find a filp slot that points to a given vnode * inval_filp: invalidate a filp and associated fd's, only let close() * happen on it */ #include #include +#include #include "fs.h" #include "file.h" @@ -30,8 +31,6 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt) register struct filp *f; register int i; - *k = -1; /* we need a way to tell if file desc found */ - /* Search the fproc fp_filp table for a free file descriptor. */ for (i = start; i < OPEN_MAX; i++) { if (fp->fp_filp[i] == NIL_FILP && !FD_ISSET(i, &fp->fp_filp_inuse)) { @@ -42,10 +41,11 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt) } /* Check to see if a file descriptor has been found. */ - if (*k < 0) return(EMFILE); /* this is why we initialized k to -1 */ + if (i >= OPEN_MAX) return(EMFILE); /* Now that a file descriptor has been found, look for a free filp slot. */ for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { + assert(f->filp_count >= 0); if (f->filp_count == 0) { f->filp_mode = bits; f->filp_pos = cvu64(0); @@ -92,7 +92,7 @@ int fild; /* file descriptor */ *===========================================================================*/ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits) { -/* Find a filp slot that refers to the inode 'rip' in a way as described +/* Find a filp slot that refers to the vnode 'vp' in a way as described * by the mode bit 'bits'. Used for determining whether somebody is still * interested in either end of a pipe. Also used when opening a FIFO to * find partners to share a filp field with (to shared the file position). @@ -103,6 +103,7 @@ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits) for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)){ + assert(f->filp_count > 0); return(f); } } diff --git a/servers/vfs/glo.h b/servers/vfs/glo.h index 454425cd7..829353b37 100644 --- a/servers/vfs/glo.h +++ b/servers/vfs/glo.h @@ -24,7 +24,7 @@ EXTERN int who_p, who_e; /* caller's proc number, endpoint */ EXTERN int call_nr; /* system call number */ EXTERN message mount_m_in; /* the input message itself */ -EXTERN char user_fullpath[PATH_MAX]; /* storage for user path name */ +EXTERN char user_fullpath[PATH_MAX+1]; /* storage for user path name */ EXTERN short cum_path_processed; /* number of characters processed */ /* The following variables are used for returning results to the caller. */ diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 49a8233e7..47018444c 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -133,6 +133,8 @@ PUBLIC int main() panic(__FILE__, "check_vrefs failed at line", __LINE__); } #endif + + } return(OK); /* shouldn't come here */ } @@ -170,9 +172,10 @@ PRIVATE void get_work() } for(;;) { + int r; /* Normal case. No one to revive. */ - if (receive(ANY, &m_in) != OK) - panic(__FILE__,"fs receive error", NO_NUM); + if ((r=receive(ANY, &m_in)) != OK) + panic(__FILE__,"fs receive error", r); who_e = m_in.m_source; who_p = _ENDPOINT_P(who_e); diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 6eb207027..cfa347665 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -491,7 +491,6 @@ Dev_t dev; } if (count > 1) { - printf("VFSunmount: %d filesystem is busy count: %d\n", dev, count); return(EBUSY); /* can't umount a busy file system */ } diff --git a/servers/vfs/open.c b/servers/vfs/open.c index ae8756299..42a05622e 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -26,6 +26,7 @@ #include "lock.h" #include "param.h" #include +#include #include #include "vnode.h" @@ -117,10 +118,6 @@ PRIVATE int common_open(register int oflags, mode_t omode) vp= NULL; -#if 0 - printf("common_open: for '%s'\n", user_fullpath); -#endif - /* Fill in lookup request fields */ Xlookup_req.path = user_fullpath; Xlookup_req.lastc = Xlastc; @@ -146,11 +143,18 @@ PRIVATE int common_open(register int oflags, mode_t omode) { if (pathrem == NULL) panic(__FILE__, "no pathrem", NO_NUM); - if (strchr(pathrem, '/') == 0) + + /* If any path remains, but no '/', O_CREAT can continue. + * If no path remains, a null filename was provided so ENOENT + * remains. + */ + if(*pathrem) { + if (strchr(pathrem, '/') == 0) r= OK; - else - { + else + { printf("common_open: / in pathrem\n"); + } } } @@ -278,8 +282,6 @@ PRIVATE int common_open(register int oflags, mode_t omode) break; case I_NAMED_PIPE: - printf("common_open: setting I_PIPE, inode %d on dev 0x%x\n", - vp->v_inode_nr, vp->v_dev); vp->v_pipe = I_PIPE; vp->v_isfifo= TRUE; oflags |= O_APPEND; /* force append mode */ @@ -291,6 +293,7 @@ PRIVATE int common_open(register int oflags, mode_t omode) * file position will be automatically shared. */ b = (bits & R_BIT ? R_BIT : W_BIT); + assert(fil_ptr->filp_count == 1); fil_ptr->filp_count = 0; /* don't find self */ if ((filp2 = find_filp(vp, b)) != NIL_FILP) { /* Co-reader or writer found. Use it.*/ @@ -428,15 +431,10 @@ struct vnode **vpp; break; case I_NAMED_PIPE: - printf("x_open (fifo): reference count %d, fd %d\n", - vp->v_ref_count, vp->v_fs_count); if (vp->v_ref_count == 1) { - printf("x_open (fifo): first reference, size %u\n", - vp->v_size); if (vp->v_size != 0) { - printf("x_open (fifo): clearing\n"); r= truncate_vn(vp, 0); if (r != OK) { @@ -465,8 +463,6 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits, * processes hanging on the pipe. */ - printf("pipe_open: setting I_PIPE, inode %d on dev 0x%x\n", - vp->v_inode_nr, vp->v_dev); vp->v_pipe = I_PIPE; if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) { @@ -735,6 +731,12 @@ int fd_nr; /* If a write has been done, the inode is already marked as DIRTY. */ if (--rfilp->filp_count == 0) { + if (vp->v_pipe == I_PIPE) { + /* Last reader or writer is going. Tell MFS about latest + * pipe size. + */ + truncate_vn(vp, vp->v_size); + } if (vp->v_pipe == I_PIPE && vp->v_ref_count > 1) { /* Save the file position in the v-node in case needed later. * The read and write positions are saved separately. diff --git a/servers/vfs/path.c b/servers/vfs/path.c index fa6051f97..c005911d6 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -43,6 +43,7 @@ node_details_t *node; /* Empty (start) path? */ if (fullpath[0] == '\0') { + node->inode_nr = 0; return ENOENT; } @@ -178,6 +179,8 @@ char **pathrem; /* Empty (start) path? */ if (fullpath[0] == '\0') { + node->inode_nr = 0; + *pathrem = fullpath; return ENOENT; } @@ -314,7 +317,7 @@ struct vnode **vpp; if (res.inode_nr == 0) { printf("lookup_vp: lookup returned no inode\n"); - printf("lookup_res = %d, last = '%s'\n", + printf("lookup_res = %d, last = '%s'\n\n", lookup_res, lookup_req->lastc); *vpp= NULL; return lookup_res; @@ -386,7 +389,7 @@ char **pathrem; if (res.inode_nr == 0) { printf("Xlookup_vp: lookup returned no inode\n"); - printf("lookup_res = %d, last = '%s'\n", + printf("lookup_res = %d, last = '%s'\n\n", lookup_res, lookup_req->lastc); *vpp= NULL; return lookup_res; diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c index 093bc2200..3ac498b72 100644 --- a/servers/vfs/protect.c +++ b/servers/vfs/protect.c @@ -34,7 +34,8 @@ PUBLIC int do_chmod() struct chmod_req req; struct lookup_req lookup_req; struct node_details res; - int r; + struct vnode *vp; + int r, ch_mode; if (call_nr == CHMOD) { /* Perform the chmod(name, mode) system call. */ @@ -58,13 +59,21 @@ PUBLIC int do_chmod() } else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); + /* Find vnode, if it's in use. */ + vp = find_vnode(req.fs_e, req.inode_nr); + /* Fill in request message fields.*/ req.uid = fp->fp_effuid; req.gid = fp->fp_effgid; req.rmode = m_in.mode; /* Issue request */ - return req_chmod(&req); + if((r = req_chmod(&req, &ch_mode)) != OK) return r; + + if(vp != NIL_VNODE) + vp->v_mode = ch_mode; + + return OK; } /*===========================================================================* @@ -78,7 +87,8 @@ PUBLIC int do_chown() struct chown_req req; struct lookup_req lookup_req; struct node_details res; - int r; + struct vnode *vp; + int r, ch_mode; if (call_nr == CHOWN) { /* Perform the chmod(name, mode) system call. */ @@ -102,6 +112,9 @@ PUBLIC int do_chown() } else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); + /* Find vnode, if it's in use. */ + vp = find_vnode(req.fs_e, req.inode_nr); + /* Fill in request message fields.*/ req.uid = fp->fp_effuid; req.gid = fp->fp_effgid; @@ -109,7 +122,15 @@ PUBLIC int do_chown() req.newgid = m_in.group; /* Issue request */ - return req_chown(&req); + r = req_chown(&req, &ch_mode); + + if(r == OK && vp) { + vp->v_uid = m_in.owner; + vp->v_gid = m_in.group; + vp->v_mode = ch_mode; + } + + return r; } @@ -207,7 +228,9 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired) /* If access desired is not a subset of what is allowed, it is refused. */ r = OK; - if ((perm_bits | access_desired) != perm_bits) r = EACCES; + if ((perm_bits | access_desired) != perm_bits) { + r = EACCES; + } /* Check to see if someone is trying to write on a file system that is * mounted read-only. diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index bfcca929f..1248f5f18 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -133,7 +133,8 @@ _PROTOTYPE( int do_getdents, (void) ); _PROTOTYPE( int read_write, (int rw_flag) ); /* request.c */ -_PROTOTYPE( int req_getnode, (node_req_t *req, node_details_t *res) ); +#define req_getnode(req, res) req_getnode_f(__FILE__, __LINE__, (req), (res)) +_PROTOTYPE( int req_getnode_f, (char *file, int line, node_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) ); _PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode, @@ -144,8 +145,8 @@ _PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_clone_opcl, (clone_opcl_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_ftrunc, (ftrunc_req_t *req) ); -_PROTOTYPE( int req_chown, (chown_req_t *req) ); -_PROTOTYPE( int req_chmod, (chmod_req_t *req) ); +_PROTOTYPE( int req_chown, (chown_req_t *req, int *mode) ); +_PROTOTYPE( int req_chmod, (chmod_req_t *req, int *mode) ); _PROTOTYPE( int req_access, (access_req_t *req) ); _PROTOTYPE( int req_mknod, (mknod_req_t *req) ); _PROTOTYPE( int req_mkdir, (mkdir_req_t *req) ); @@ -240,3 +241,4 @@ _PROTOTYPE( void fs_expire_timers, (clock_t now) ); _PROTOTYPE( void fs_cancel_timer, (timer_t *tp) ); _PROTOTYPE( void fs_init_timer, (timer_t *tp) ); + diff --git a/servers/vfs/read.c b/servers/vfs/read.c index d142d33dd..54ef44cba 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -21,6 +21,7 @@ #include "fproc.h" #include "param.h" #include +#include #include #include "vnode.h" @@ -45,7 +46,7 @@ int rw_flag; /* READING or WRITING */ /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */ register struct filp *f; register struct vnode *vp; - off_t bytes_left, f_size; + off_t bytes_left; u64_t position; unsigned int off, cum_io; int op, oflags, r, chunk, usr, seg, block_spec, char_spec; @@ -97,7 +98,6 @@ int rw_flag; /* READING or WRITING */ oflags = f->filp_flags; vp = f->filp_vno; - f_size = vp->v_size; r = OK; if (vp->v_pipe == I_PIPE) { @@ -119,7 +119,6 @@ int rw_flag; /* READING or WRITING */ } if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) { - f_size = ULONG_MAX; if (vp->v_sdev == NO_DEV) panic(__FILE__,"read_write tries to read from " " block device NO_DEV", NO_NUM); @@ -155,11 +154,11 @@ int rw_flag; /* READING or WRITING */ position = res.new_pos; cum_io += res.cum_io; } - /* Regular files */ + /* Regular files (and pipes) */ else { if (rw_flag == WRITING && block_spec == 0) { /* Check for O_APPEND flag. */ - if (oflags & O_APPEND) position = cvul64(f_size); + if (oflags & O_APPEND) position = cvul64(vp->v_size); /* Check in advance to see if file will grow too big. */ if (cmp64ul(position, vp->v_vmnt->m_max_file_size - m_in.nbytes) > 0) @@ -175,8 +174,9 @@ int rw_flag; /* READING or WRITING */ } if (partial_cnt > 0) { - /* So taht we don't need to deal with partial count - * in the FS process */ + /* So that we don't need to deal with partial count + * in the FS process. + */ m_in.nbytes = MIN(m_in.nbytes, partial_cnt); partial_pipe = 1; } @@ -192,11 +192,17 @@ int rw_flag; /* READING or WRITING */ req.user_addr = m_in.buffer; req.inode_index = vp->v_index; - if (vp->v_isfifo) - { - printf("read_write: %s for FIFO @ %u size %u\n", - (rw_flag == READING) ? "read" : "write", - ex64lo(position), m_in.nbytes); + /* Truncate read request at size (mustn't do this for special files). */ + if((rw_flag == READING) && + cmp64ul(add64ul(position, req.num_of_bytes), vp->v_size) > 0) { + /* Position always should fit in an off_t (LONG_MAX). */ + off_t pos32; + assert(cmp64ul(position, LONG_MAX) <= 0); + pos32 = cv64ul(position); + assert(pos32 >= 0); + assert(pos32 <= LONG_MAX); + req.num_of_bytes = vp->v_size - pos32; + assert(req.num_of_bytes >= 0); } /* Issue request */ @@ -215,7 +221,7 @@ int rw_flag; /* READING or WRITING */ /* On write, update file size and access time. */ if (rw_flag == WRITING) { if (regular || mode_word == I_DIRECTORY) { - if (cmp64ul(position, f_size) > 0) + if (cmp64ul(position, vp->v_size) > 0) { if (ex64hi(position) != 0) { diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 4f620911d..b4ca2810e 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -28,12 +28,16 @@ #include "vnode.h" #include "param.h" -FORWARD _PROTOTYPE(int fs_sendrec, (endpoint_t fs_e, message *reqm)); +FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm)); + +#define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m)) /*===========================================================================* * req_getnode * *===========================================================================*/ -PUBLIC int req_getnode(req, res) +PUBLIC int req_getnode_f(file, line, req, res) +char *file; +int line; node_req_t *req; node_details_t *res; { @@ -278,10 +282,12 @@ ftrunc_req_t *req; /*===========================================================================* * req_chmod * *===========================================================================*/ -PUBLIC int req_chmod(req) +PUBLIC int req_chmod(req, ch_mode) chmod_req_t *req; +int *ch_mode; { message m; + int r; /* Fill in request message */ m.m_type = REQ_CHMOD; @@ -291,17 +297,24 @@ chmod_req_t *req; m.REQ_GID = req->gid; /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + r = fs_sendrec(req->fs_e, &m); + + /* Copy back actual mode. */ + if(ch_mode) *ch_mode = m.RES_MODE; + + return r; } /*===========================================================================* * req_chown * *===========================================================================*/ -PUBLIC int req_chown(req) +PUBLIC int req_chown(req, ch_mode) chown_req_t *req; +int *ch_mode; { message m; + int r; /* Fill in request message */ m.m_type = REQ_CHOWN; @@ -312,7 +325,12 @@ chown_req_t *req; m.REQ_NEW_GID = req->newgid; /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + r = fs_sendrec(req->fs_e, &m); + + /* Return new mode to caller. */ + if(ch_mode) *ch_mode = m.RES_MODE; + + return r; } @@ -955,7 +973,7 @@ _t *res; /*===========================================================================* * fs_sendrec * *===========================================================================*/ -PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) +PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) { /* This is the low level function that sends requests to FS processes. * It also handles driver recovery mechanism and reissuing the @@ -964,7 +982,7 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) int r, old_driver_e, new_driver_e; message origm, m; struct vmnt *vmp; - + /* Make a copy of the request so that we can load it back in * case of a dead driver */ origm = *reqm; @@ -972,8 +990,8 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) for (;;) { /* Do the actual send, receive */ if (OK != (r=sendrec(fs_e, reqm))) { - printf("VFS: error sending message. FS_e: %d req_nr: %d err: %d\n", - fs_e, reqm->m_type, r); + printf("VFS:fs_sendrec:%s:%d: error sending message. FS_e: %d req_nr: %d err: %d\n", + file, line, fs_e, reqm->m_type, r); } if(r == OK) { @@ -984,9 +1002,9 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) /* Dead driver */ if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { old_driver_e = NONE; - /* Find old driver enpoint */ + /* Find old driver by endpoint */ for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { - if (vmp->m_fs_e == reqm->m_source) { /* found FS */ + if (vmp->m_fs_e == fs_e) { /* found FS */ old_driver_e = vmp->m_driver_e; dmap_unmap_by_endpt(old_driver_e); /* unmap driver */ break; @@ -994,10 +1012,8 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) } /* No FS ?? */ - if (old_driver_e == NONE) { - panic(__FILE__, "VFSdead_driver: couldn't find FS\n", - old_driver_e); - } + if (old_driver_e == NONE) + panic(__FILE__, "VFSdead_driver: couldn't find FS\n", fs_e); /* Wait for a new driver. */ for (;;) { diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index 2b90d2a81..544a315c8 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -141,7 +141,14 @@ int len; /* length of the directory name string */ put_vnode(vp); return ENOTDIR; } - + + /* Access check */ + r = forbidden(vp, X_BIT); + if (r != OK) { + put_vnode(vp); + return r; + } + return change_into(iip, vp); } diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index b5410c3c5..97f12a3d7 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -17,6 +17,7 @@ #include "file.h" #include "fproc.h" #include "param.h" +#include "vmnt.h" PRIVATE int panicking; /* inhibits recursive panics during sync */ @@ -35,6 +36,11 @@ int flag; /* M3 means path may be in message */ register char *rpu, *rpm; int r; + if (len > PATH_MAX) { + err_code = ENAMETOOLONG; + return(EGENERIC); + } + if(len >= sizeof(user_fullpath)) { panic(__FILE__, "fetch_name: len too much for user_fullpath", len); } @@ -42,11 +48,7 @@ int flag; /* M3 means path may be in message */ /* Check name length for validity. */ if (len <= 0) { err_code = EINVAL; - return(EGENERIC); - } - - if (len > PATH_MAX) { - err_code = ENAMETOOLONG; + printf("vfs: fetch_name: len %d?\n", len); return(EGENERIC); } @@ -100,7 +102,7 @@ int num; /* number to go with it */ if (panicking) return; /* do not panic during a sync */ panicking = TRUE; /* prevent another panic during the sync */ - printf("FS panic (%s): %s ", who, mess); + printf("VFS panic (%s): %s ", who, mess); if (num != NO_NUM) printf("%d",num); (void) do_sync(); /* flush everything to the disk */ sys_exit(SELF); @@ -148,4 +150,3 @@ PUBLIC time_t clock_time() return( (time_t) (boottime + (uptime/HZ))); } -