示例#1
0
void
showjobs(int change, int mode)
{
	int jobno;
	struct job *jp;

	TRACE(("showjobs(%d) called\n", change));
	checkzombies();
	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
		if (! jp->used)
			continue;
		if (jp->nprocs == 0) {
			freejob(jp);
			continue;
		}
		if (change && ! jp->changed)
			continue;
		showjob(jp, mode);
		jp->changed = 0;
		/* Hack: discard jobs for which $! has not been referenced
		 * in interactive mode when they terminate.
		 */
		if (jp->state == JOBDONE && !jp->remembered &&
				(iflag || jp != bgjob)) {
			freejob(jp);
		}
	}
}
示例#2
0
void
freejobs()
{
	struct job *jp;

	collectjobs(WNOHANG);

	if (jobnote) {
		int savefd = setb(2);
		for (jp = joblst; jp; jp = jp->j_nxtp) {
			if (jp->j_flag & J_NOTIFY) {
				if (jp->j_jid)
					printjob(jp, PR_DFL);
				else if (jp->j_flag & J_FOREGND)
					printjob(jp, PR_STAT);
				else
					printjob(jp, PR_STAT|PR_PGID);
			}
		}
		(void) setb(savefd);
	}

	if (jobdone) {
		for (jp = joblst; jp; jp = jp->j_nxtp) {
			if (jp->j_flag & J_DONE)
				freejob(jp);
		}
	}
}
示例#3
0
int
waitcmd(int argc, char **argv)
{
	struct job *job;
	int status, retval;
	struct job *jp;

	nextopt("");

	if (!*argptr) {
		/* wait for all jobs */
		jp = jobtab;
		if (jobs_invalid)
			return 0;
		for (;;) {
			if (jp >= jobtab + njobs) {
				/* no running procs */
				return 0;
			}
			if (!jp->used || jp->state != JOBRUNNING) {
				jp++;
				continue;
			}
			if (dowait(WBLOCK, NULL) == -1)
			       return 128 + SIGINT;
			jp = jobtab;
		}
	}

	retval = 127;		/* XXXGCC: -Wuninitialized */
	for (; *argptr; argptr++) {
		job = getjob(*argptr, 1);
		if (!job) {
			retval = 127;
			continue;
		}
		/* loop until process terminated or stopped */
		while (job->state == JOBRUNNING) {
			if (dowait(WBLOCK|WNOFREE, job) == -1)
			       return 128 + SIGINT;
		}
		status = job->ps[job->nprocs ? job->nprocs - 1 : 0].status;
		if (WIFEXITED(status))
			retval = WEXITSTATUS(status);
#if JOBS
		else if (WIFSTOPPED(status))
			retval = WSTOPSIG(status) + 128;
#endif
		else {
			/* XXX: limits number of signals */
			retval = WTERMSIG(status) + 128;
		}
		if (!iflag)
			freejob(job);
	}
	return retval;
}
示例#4
0
struct job *
makejob(union node *node, int nprocs)
{
	int i;
	struct job *jp;

	if (jobs_invalid) {
		for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) {
			if (jp->used)
				freejob(jp);
		}
		jobs_invalid = 0;
	}

	for (i = njobs, jp = jobtab ; ; jp++) {
		if (--i < 0) {
			INTOFF;
			if (njobs == 0) {
				jobtab = ckmalloc(4 * sizeof jobtab[0]);
			} else {
				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
				memcpy(jp, jobtab, njobs * sizeof jp[0]);
				/* Relocate `ps' pointers */
				for (i = 0; i < njobs; i++)
					if (jp[i].ps == &jobtab[i].ps0)
						jp[i].ps = &jp[i].ps0;
				ckfree(jobtab);
				jobtab = jp;
			}
			jp = jobtab + njobs;
			for (i = 4 ; --i >= 0 ; )
				jobtab[njobs++].used = 0;
			INTON;
			break;
		}
		if (jp->used == 0)
			break;
	}
	INTOFF;
	jp->state = JOBRUNNING;
	jp->used = 1;
	jp->changed = 0;
	jp->nprocs = 0;
#if JOBS
	jp->jobctl = jobctl;
	set_curjob(jp, 1);
#endif
	if (nprocs > 1) {
		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
	} else {
		jp->ps = &jp->ps0;
	}
	INTON;
	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
	    jp - jobtab + 1));
	return jp;
}
示例#5
0
int
waitforjob(struct job *jp)
{
#if JOBS
	int mypgrp = getpgrp();
#endif
	int status;
	int st;

	INTOFF;
	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
	while (jp->state == JOBRUNNING) {
		dowait(WBLOCK, jp);
	}
#if JOBS
	if (jp->jobctl) {
		if (tcsetpgrp(ttyfd, mypgrp) == -1)
			error("Cannot set tty process group (%s) at %d",
			    strerror(errno), __LINE__);
	}
	if (jp->state == JOBSTOPPED && curjob != jp - jobtab)
		set_curjob(jp, 2);
#endif
	status = jp->ps[jp->nprocs - 1].status;
	/* convert to 8 bits */
	if (WIFEXITED(status))
		st = WEXITSTATUS(status);
#if JOBS
	else if (WIFSTOPPED(status))
		st = WSTOPSIG(status) + 128;
#endif
	else
		st = WTERMSIG(status) + 128;
	TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n",
		jp - jobtab + 1, jp->nprocs, status, st ));
#if JOBS
	if (jp->jobctl) {
		/*
		 * This is truly gross.
		 * If we're doing job control, then we did a TIOCSPGRP which
		 * caused us (the shell) to no longer be in the controlling
		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
		 * intuit from the subprocess exit status whether a SIGINT
		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
		 */
		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
			raise(SIGINT);
	}
#endif
	if (! JOBS || jp->state == JOBDONE)
		freejob(jp);
	INTON;
	return st;
}
示例#6
0
文件: jobs.c 项目: 0xffea/MINIX3
int
waitcmd(int argc, char **argv)
{
	struct job *job;
	int status, retval;
	struct job *jp;

	if (argc > 1) {
		job = getjob(argv[1]);
	} else {
		job = NULL;
	}

	/*
	 * Loop until a process is terminated or stopped, or a SIGINT is
	 * received.
	 */

	in_waitcmd++;
	do {
		if (job != NULL) {
			if (job->state) {
				status = job->ps[job->nprocs - 1].status;
				if (WIFEXITED(status))
					retval = WEXITSTATUS(status);
#if JOBS
				else if (WIFSTOPPED(status))
					retval = WSTOPSIG(status) + 128;
#endif
				else
					retval = WTERMSIG(status) + 128;
				if (! iflag)
					freejob(job);
				in_waitcmd--;
				return retval;
			}
		} else {
			for (jp = jobtab ; ; jp++) {
				if (jp >= jobtab + njobs) {	/* no running procs */
					in_waitcmd--;
					return 0;
				}
				if (jp->used && jp->state == 0)
					break;
			}
		}
	} while (dowait(1, (struct job *)NULL) != -1);
	in_waitcmd--;

	return 0;
}
示例#7
0
文件: jobs.c 项目: 0xffea/MINIX3
void
showjobs(int change, int sformat, int lformat)
{
	int jobno;
	struct job *jp;

	TRACE(("showjobs(%d) called\n", change));
	while (dowait(0, (struct job *)NULL) > 0);
	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
		if (! jp->used)
			continue;
		if (jp->nprocs == 0) {
			freejob(jp);
			continue;
		}
		if (change && ! jp->changed)
			continue;
		showjob(jp, 0, sformat, lformat);
		jp->changed = 0;
		if (jp->state == JOBDONE) {
			freejob(jp);
		}
	}
}
示例#8
0
void
showjobs(struct output *out, int mode)
{
	int jobno;
	struct job *jp;
	int silent = 0, gotpid;

	TRACE(("showjobs(%x) called\n", mode));

	/* If not even one one job changed, there is nothing to do */
	gotpid = dowait(0, NULL);
	while (dowait(0, NULL) > 0)
		continue;
#ifdef JOBS
	/*
	 * Check if we are not in our foreground group, and if not
	 * put us in it.
	 */
	if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {
		if (tcsetpgrp(ttyfd, getpid()) == -1)
			error("Cannot set tty process group (%s) at %d",
			    strerror(errno), __LINE__);
		TRACE(("repaired tty process group\n"));
		silent = 1;
	}
#endif
	if (jobs_invalid)
		return;

	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
		if (!jp->used)
			continue;
		if (jp->nprocs == 0) {
			freejob(jp);
			continue;
		}
		if ((mode & SHOW_CHANGED) && !jp->changed)
			continue;
		if (silent && jp->changed) {
			jp->changed = 0;
			continue;
		}
		showjob(out, jp, mode);
	}
}
示例#9
0
文件: cs.c 项目: brho/akaros
static void io(void)
{
	long n;
	uint8_t mdata[IOHDRSZ + Maxfdata];
	struct job *job;
	pthread_attr_t pth_attr;

	/*
	 * each request is handled via a thread. Somewhat less efficient than
	 * the old cs but way cleaner.
	 */

	pthread_attr_init(&pth_attr);
	pthread_attr_setdetachstate(&pth_attr, PTHREAD_CREATE_DETACHED);
	for (;;) {
		n = read9pmsg(mfd[0], mdata, sizeof(mdata));
		if (n <= 0)
			error(1, 0, "%s: %r", "mount read");
		job = newjob();
		if (convM2S(mdata, n, &job->request) != n) {
			fprintf(stderr,
			        "convM2S went south: format error %ux %ux %ux %ux %ux",
				mdata[0], mdata[1], mdata[2], mdata[3],
				mdata[4]);
			error(1, 0, "format error %ux %ux %ux %ux %ux",
			      mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
			freejob(job);
			continue;
		}
		/* stash the thread in the job so we can join them all
		 * later if we want to.
		 */
		if (pthread_create(&job->thread, &pth_attr, &job_thread, job)) {
			error(1, 0, "%s: %r", "Failed to create job");
			continue;
		}
	}
}
示例#10
0
文件: parallel.c 项目: girving/kalah
/* main parallism function */
void worker() {
  int i,j;

  for(;;) {
    /* find work */
    if (!(cj = freejob()) && !(cj = steal()))
      return;
    if (cj->status == JOB_DONE)   // done
      return;
   
    /* do work */
    cj->status = JOB_TAKEN;
    p_head = p_tail = 0;
    slow_crunch();
   
    /* aftermath */
    switch (cj->status) {
      case JOB_BLOCKED:   
        add_jobarray(cj); 
        cj = 0; 
        break;
    
      case JOB_DONE:      
        if (!cj->jid && master)   // done
          return;
        else {
          send_done(cj);
          free(cj);
          }
        break;
   
      case JOB_CANCELLED: 
        free(cj);
      }
    }
  }    
示例#11
0
static void
showjob(struct output *out, struct job *jp, int mode)
{
	int procno;
	int st;
	struct procstat *ps;
	int col;
	char s[64];

#if JOBS
	if (mode & SHOW_PGID) {
		/* just output process (group) id of pipeline */
		outfmt(out, "%ld\n", (long)jp->ps->pid);
		return;
	}
#endif

	procno = jp->nprocs;
	if (!procno)
		return;

	if (mode & SHOW_PID)
		mode |= SHOW_MULTILINE;

	if ((procno > 1 && !(mode & SHOW_MULTILINE))
	    || (mode & SHOW_SIGNALLED)) {
		/* See if we have more than one status to report */
		ps = jp->ps;
		st = ps->status;
		do {
			int st1 = ps->status;
			if (st1 != st)
				/* yes - need multi-line output */
				mode |= SHOW_MULTILINE;
			if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1))
				continue;
			if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f)
			    && st1 != SIGINT && st1 != SIGPIPE))
				mode |= SHOW_ISSIG;

		} while (ps++, --procno);
		procno = jp->nprocs;
	}

	if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) {
		if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) {
			TRACE(("showjob: freeing job %d\n", jp - jobtab + 1));
			freejob(jp);
		}
		return;
	}

	for (ps = jp->ps; --procno >= 0; ps++) {	/* for each process */
		if (ps == jp->ps)
			fmtstr(s, 16, "[%ld] %c ",
				(long)(jp - jobtab + 1),
#if JOBS
				jp == jobtab + curjob ? '+' :
				curjob != -1 && jp == jobtab +
					    jobtab[curjob].prev_job ? '-' :
#endif
				' ');
		else
			fmtstr(s, 16, "      " );
		col = strlen(s);
		if (mode & SHOW_PID) {
			fmtstr(s + col, 16, "%ld ", (long)ps->pid);
			     col += strlen(s + col);
		}
		if (ps->status == -1) {
			scopy("Running", s + col);
		} else if (WIFEXITED(ps->status)) {
			st = WEXITSTATUS(ps->status);
			if (st)
				fmtstr(s + col, 16, "Done(%d)", st);
			else
				fmtstr(s + col, 16, "Done");
		} else {
#if JOBS
			if (WIFSTOPPED(ps->status)) 
				st = WSTOPSIG(ps->status);
			else /* WIFSIGNALED(ps->status) */
#endif
				st = WTERMSIG(ps->status);
			st &= 0x7f;
			if (st < NSIG && sys_siglist[st])
				scopyn(sys_siglist[st], s + col, 32);
			else
				fmtstr(s + col, 16, "Signal %d", st);
			if (WCOREDUMP(ps->status)) {
				col += strlen(s + col);
				scopyn(" (core dumped)", s + col,  64 - col);
			}
		}
		col += strlen(s + col);
		outstr(s, out);
		do {
			outc(' ', out);
			col++;
		} while (col < 30);
		outstr(ps->cmd, out);
		if (mode & SHOW_MULTILINE) {
			if (procno > 0) {
				outc(' ', out);
				outc('|', out);
			}
		} else {
			while (--procno >= 0)
				outfmt(out, " | %s", (++ps)->cmd );
		}
		outc('\n', out);
	}
	flushout(out);
	jp->changed = 0;
	if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE))
		freejob(jp);
}
示例#12
0
static int
statjob(struct job *jp, int stat, int fg, int rc)
{
	pid_t tgid;
	int done = 0;

	if (WIFCONTINUED(stat)) {
		if (jp->j_flag & J_STOPPED) {
			jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY);
			jp->j_flag |= J_RUNNING;
			if (!fg && jp->j_jid) {
				jp->j_flag |= J_NOTIFY;
				jobnote++;
			}
		}
	} else if (WIFSTOPPED(stat)) {
		jp->j_xval = WSTOPSIG(stat);
		jp->j_flag &= ~J_RUNNING;
		jp->j_flag |= (J_SIGNALED|J_STOPPED);
		jp->j_pgid = getpgid(jp->j_pid);
		jp->j_tgid = jp->j_pgid;
		if (fg) {
			if (tgid = settgid(mypgid, jp->j_pgid))
				jp->j_tgid = tgid;
			else {
				jp->j_flag |= J_SAVETTY;
				tcgetattr(0, &jp->j_stty);
				(void) tcsetattr(0, TCSANOW, &mystty);
			}
		}
		if (jp->j_jid) {
			jp->j_flag |= J_NOTIFY;
			jobnote++;
		}
	} else {
		jp->j_flag &= ~J_RUNNING;
		jp->j_flag |= J_DONE;
		done++;
		jobdone++;
		if (WIFSIGNALED(stat)) {
			jp->j_xval = WTERMSIG(stat);
			jp->j_flag |= J_SIGNALED;
			if (WCOREDUMP(stat))
				jp->j_flag |= J_DUMPED;
			if (!fg || jp->j_xval != SIGINT) {
				jp->j_flag |= J_NOTIFY;
				jobnote++;
			}
		} else { /* WIFEXITED */
			jp->j_xval = WEXITSTATUS(stat);
			jp->j_flag &= ~J_SIGNALED;
			if (!fg && jp->j_jid) {
				jp->j_flag |= J_NOTIFY;
				jobnote++;
			}
		}
		if (fg) {
			if (!settgid(mypgid, jp->j_pgid) ||
			    !settgid(mypgid, getpgid(jp->j_pid)))
				tcgetattr(0, &mystty);
		}
	}
	if (rc) {
		exitval = jp->j_xval;
		if (jp->j_flag & J_SIGNALED)
			exitval |= SIGFLG;
		exitset();
	}
	if (done && !(jp->j_flag & J_NOTIFY))
		freejob(jp);
	return (done);
}
示例#13
0
文件: parallel.c 项目: girving/kalah
/* message handling routine */
void p_handle(int b) {
  int i,k,len,tid,tag;
  jobinfo *j;
  jobinfo tj; 
  pvm_bufinfo(b,&len,&tag,&tid);

  switch (tag) {
    case TAG_HELLO:
      if (master) {
        wtid = realloc(wtid,sizeof(int) * ++nw);
        wtid[nw-1] = tid;
        for (i=1;i<nw;i++) {
          pvm_initsend(0);
          k = i << BASE_SHIFT;
          pvm_pkint(&k,1,1);
          pvm_pkint(&nw,1,1);
          pvm_pkint(wtid,nw,1);
          pvm_send(wtid[i],TAG_WORKERS);
          }
        }
      break;

    case TAG_WORKERS: 
      pvm_upkint(&nextjid,1,1);      
      nextjid <<= BASE_SHIFT;
      pvm_upkint(&nw,1,1);
      free(wtid);
      wtid = malloc(sizeof(int) * nw);
      pvm_upkint(wtid,nw,1);
      break;

    case TAG_KILL:
      die("Received TAG_KILL.  Too lazy to do anything useful.\n");

    case TAG_REQUEST:
      if (j = freejob()) {
        pvm_initsend(0);
        pkjobinfo_active(j);
        pvm_send(tid,TAG_JOB);
        add_stolen(tid,j->jid);
        free(j);
        }
      else if (!victim(tid)) {
        pvm_initsend(0);
        pvm_send(tid,TAG_NO_JOB);
        }
      break; 

    case TAG_DONE:
      upkjobinfo_done(&tj);
      if (cj && cj->jid == tj.pjid)
        slow_absorb(cj,&tj.s);
      else if (!tj.jid && master) {
        j = malloc(sizeof(jobinfo)); 
        *j = tj;
        add_jobarray(j);
        }
      else if ((i = find_jobarray(tj.pjid)) >= 0) { 
        slow_absorb(ja[i],&tj.s);
        if (ja[i]->status == JOB_DONE && !(!ja[i]->jid && master)) {
          send_done(ja[i]);
          free(ja[i]); 
          del_jobarray(i);
          }
        }
      else if (tj.tid = find_stolen(tj.pjid))  // if 0, job was cancelled
        send_done(&tj);
      break; 
    
    case TAG_CANCEL:
      pvm_upkint(&k,1,1); 
      if (cj && cj->jid == k) {
        cj->status = JOB_CANCELLED;
        if (p_head > 0) 
          cancel_children(cj);
        p_head = 1000;
        add_stolen(0,cj->jid);
        }
      else if ((i = find_jobarray(k)) >= 0) { 
        cancel_children(ja[i]);
        add_stolen(0,ja[i]->jid); 
        free(ja[i]);
        del_jobarray(i);
        }
      else if (tid = find_stolen(k)) 
        send_cancel(tid,k); 
      break;

    case TAG_STAT:
    default:
      die("Warning: ignoring invalid message\n");
    }
  }
示例#14
0
文件: cs.c 项目: brho/akaros
static void *job_thread(void *arg)
{
	struct mfile *mf;
	struct job *job = arg;

	spinlock_lock(&dblock);
	mf = newfid(job->request.fid);

	if (debug)
		fprintf(stderr, "CS:%F", &job->request);
	switch (job->request.type) {
	default:
		fprintf(stderr, "CS:unknown request type %d", job->request.type);
		break;
	case Tversion:
		rversion(job);
		break;
	case Tauth:
		rauth(job);
		break;
	case Tflush:
		rflush(job);
		break;
	case Tattach:
		rattach(job, mf);
		break;
	case Twalk:
		rwalk(job, mf);
		break;
	case Topen:
		ropen(job, mf);
		break;
	case Tcreate:
		rcreate(job, mf);
		break;
	case Tread:
		rread(job, mf);
		break;
	case Twrite:
		rwrite(job, mf);
		break;
	case Tclunk:
		rclunk(job, mf);
		break;
	case Tremove:
		rremove(job, mf);
		break;
	case Tstat:
		rstat(job, mf);
		break;
	case Twstat:
		rwstat(job, mf);
		break;
	}
	spinlock_unlock(&dblock);

	freejob(job);

	if (debug)
		fprintf(stderr, "CS:Job done\n");
	return 0;
}
示例#15
0
文件: dns.c 项目: Earnestly/plan9
void
io(void)
{
	volatile long n;
	volatile uchar mdata[IOHDRSZ + Maxfdata];
	Job *volatile job;
	Mfile *volatile mf;
	volatile Request req;

	memset(&req, 0, sizeof req);
	/*
	 *  a slave process is sometimes forked to wait for replies from other
	 *  servers.  The master process returns immediately via a longjmp
	 *  through 'mret'.
	 */
	if(setjmp(req.mret))
		putactivity(0);
	req.isslave = 0;
	stop = 0;
	while(!stop){
		procsetname("%d %s/dns Twrites of %d 9p rpcs read; %d alarms",
			stats.qrecvd9p, mntpt, stats.qrecvd9prpc, stats.alarms);
		n = read9pmsg(mfd[0], mdata, sizeof mdata);
		if(n<=0){
			dnslog("error reading 9P from %s: %r", mntpt);
			sleep(2000);	/* don't thrash after read error */
			return;
		}

		stats.qrecvd9prpc++;
		job = newjob();
		if(convM2S(mdata, n, &job->request) != n){
			freejob(job);
			continue;
		}
		mf = newfid(job->request.fid, 0);
		if(debug)
			dnslog("%F", &job->request);

		getactivity(&req, 0);
		req.aborttime = timems() + Maxreqtm;
		req.from = "9p";

		switch(job->request.type){
		default:
			warning("unknown request type %d", job->request.type);
			break;
		case Tversion:
			rversion(job);
			break;
		case Tauth:
			rauth(job);
			break;
		case Tflush:
			rflush(job);
			break;
		case Tattach:
			rattach(job, mf);
			break;
		case Twalk:
			rwalk(job, mf);
			break;
		case Topen:
			ropen(job, mf);
			break;
		case Tcreate:
			rcreate(job, mf);
			break;
		case Tread:
			rread(job, mf);
			break;
		case Twrite:
			/* &req is handed to dnresolve() */
			rwrite(job, mf, &req);
			break;
		case Tclunk:
			rclunk(job, mf);
			break;
		case Tremove:
			rremove(job, mf);
			break;
		case Tstat:
			rstat(job, mf);
			break;
		case Twstat:
			rwstat(job, mf);
			break;
		}

		freejob(job);

		/*
		 *  slave processes die after replying
		 */
		if(req.isslave){
			putactivity(0);
			_exits(0);
		}

		putactivity(0);
	}
	/* kill any udp server, notifier, etc. processes */
	postnote(PNGROUP, getpid(), "die");
	sleep(1000);
}
示例#16
0
文件: dns.c 项目: 00001/plan9port
void
ioproc0(void *v)
{
	long n;
	Mfile *mf;
	uchar mdata[IOHDRSZ + Maxfdata];
	Request req;
	Job *job;

	USED(v);

	for(;;){
		n = read9pmsg(mfd[0], mdata, sizeof mdata);
		if(n <= 0){
			syslog(0, logfile, "error reading mntpt: %r");
			break;
		}
		job = newjob();
		if(convM2S(mdata, n, &job->request) != n){
			freejob(job);
			continue;
		}
		if(debug)
			syslog(0, logfile, "%F", &job->request);

		getactivity(&req);
		req.aborttime = now + 60;	/* don't spend more than 60 seconds */

		mf = nil;
		switch(job->request.type){
		case Tversion:
		case Tauth:
		case Tflush:
			break;
		case Tattach:
			mf = newfid(job->request.fid, 1);
			if(mf == nil){
				sendmsg(job, "fid in use");
				goto skip;
			}
			break;
		default:
			mf = newfid(job->request.fid, 0);
			if(mf == nil){
				sendmsg(job, "unknown fid");
				goto skip;
			}
			break;
		}

		switch(job->request.type){
		default:
			syslog(1, logfile, "unknown request type %d", job->request.type);
			break;
		case Tversion:
			rversion(job);
			break;
		case Tauth:
			rauth(job);
			break;
		case Tflush:
			rflush(job);
			break;
		case Tattach:
			rattach(job, mf);
			break;
		case Twalk:
			rwalk(job, mf);
			break;
		case Topen:
			ropen(job, mf);
			break;
		case Tcreate:
			rcreate(job, mf);
			break;
		case Tread:
			rread(job, mf);
			break;
		case Twrite:
			rwrite(job, mf, &req);
			break;
		case Tclunk:
			rclunk(job, mf);
			break;
		case Tremove:
			rremove(job, mf);
			break;
		case Tstat:
			rstat(job, mf);
			break;
		case Twstat:
			rwstat(job, mf);
			break;
		}
skip:
		freejob(job);
		putactivity();
	}
}