240 lines · 3.9 KB · C
RawDownload
#include "all.h"#include "mem.h" typedef struct{	Rendez	r;	char	cowner;		// 0 = free, 1 = devcopy	char	cmd;	char	iowner;	char	icmd; 	char	src[30];	char	dst[30];	Device	*from;	Device	*to;	vlong	start;	vlong	p;	vlong	end;	vlong	lim;	ulong	t0;}Dcopy; static Dcopy d; static intsetup(Dcopy *d){	Devsize tosize; 	if((d->from = devstr(d->src)) == 0){		print("bad src device %s\n", d->src);		return -1;	}	if(strcmp(d->dst, "nil") == 0)		d->to = nil;	else if((d->to = devstr(d->dst)) == 0){		print("bad dest device %s\n", d->dst);		return -1;	}	devinit(d->from);	d->lim = devsize(d->from);	if(d->to){		devinit(d->to);		tosize = devsize(d->to);	}else		tosize = 1LL<<62;	if(tosize < d->lim)		d->lim = tosize;	if(d->end >= 0 && d->end < d->lim)		d->lim = d->end;	return 0;} static Offprefetch(Dcopy *d, Off a, Off ra, Off lim){	if(a+RAGAP*5 < lim)		lim = a+RAGAP*5;	while(ra < lim){		ra++;		preread(d->from, ra);	}	return ra+1;} static voiddevcopy(Dcopy *d){	ulong t;	Iobuf *b, *w;	Off ra; 	d->t0 = Ticks;	ra = d->start;	for(d->p = d->start; d->p < d->lim; d->p++){		if(d->iowner){			d->iowner = 0;			break;		}		ra = prefetch(d, d->p, ra, d->lim);		b = getbuf(d->from, d->p, Bread);		if(b == 0){			print("devcopy: %lld not written yet.\n", d->p);			continue;		}		if(d->to){			w = getbuf(d->to, b->addr, 0);			memmove(w->iobuf, b->iobuf, RBUFSIZE);			w->flags |= Bmod;			putbuf(w);		}		putbuf(b);	}	t = Ticks-d->t0;	print("devcopy: halt %T\n", time());	print("copied %lld blocks from %Z to %Z\n", d->p-d->start, d->from, d->to);	print("\t" "%,ld ticks\n", t);	if(t)		print("\t" "%,lld bytes/sec\n", (d->p-d->start)*RBUFSIZE*HZ/t); 	d->start = d->p;} static intowner(void *v){	return ((Dcopy*)v)->cowner;} voiddevcopyproc(void){	for(;;){		sleep(&d.r, owner, &d); 		switch(d.cmd){		case 'c':			if(setup(&d) == -1)				break;		case 'r':			print("devcopy: %lld blocks from %Z to %Z\n", d.lim-d.start, d.from, d.to);			devcopy(&d);			break;		default:			print("bad devcopy command\n");			break;		}		d.cowner = 0;		d.cmd = 0;	}} static voiddcpause(void){	if(d.cowner != 1){		print("copy not running\n");		return;	}	if(d.iowner != 0){		print("interrupt already issued\n");		return;	}	d.icmd = 'x';	d.iowner = 1;} static voiddcresume(void){	if(d.cowner == 1 || d.iowner == 1){		print("copy already running\n");		return;	}	if(d.from == 0 || d.to == 0){		print("not started\n");		return;	}	d.cmd = 'r';	d.cowner = 1;	wakeup(&d.r);} static voiddchelp(void){	print("usage: devcopy start fdev tdev [start [end]]\n");	print("usage: devcopy pause\n");	print("usage: devcopy resume\n");} static voiddcstart(int c, char **v){	if(d.cowner != 0 || d.iowner != 0){		print("copy already running\n");		return;	}	d.start = 0;	d.end = -1;	d.p = 0;	d.lim = 0;	switch(c){	default:		dchelp();		return;	case 5:		d.end = number(v[4], 0, 0);	case 4:		d.start = number(v[3], 0, 0);	case 3:		if(strlen(v[1]) >= sizeof d.src || strlen(v[2]) >= sizeof d.dst){			print("device strings too long\n");			return;		}		snprint(d.src, sizeof d.src, "%s", v[1]);		snprint(d.dst, sizeof d.dst, "%s", v[2]);		break;	}	d.cmd = 'c';	d.cowner = 1;	wakeup(&d.r);} static voidpstat(void){	char s[12*2+2], *state;	ulong t; 	if(d.end != -1)		snprint(s, sizeof s, "%,lld", d.lim);	else		snprint(s, sizeof s, "%,lld/%,lld", d.lim, d.end);	state = d.cowner == 0 ? "idle" : "run";	print("%s %,lld <- %,lld <- %s %Z %Z\n", state, d.start, d.p, s, d.from, d.to);	if(d.cowner == 0)		return;	print("\t" "%,ld ticks\n", t = Ticks-d.t0);	if(t)		print("\t" "%,lld bytes/sec\n", (d.p-d.start)*RBUFSIZE*HZ/t);} voidcmd_devcopy(int c, char **v){	if(c == 1){		pstat();		return;	} 	v++, c--;	if(strcmp("start", *v) == 0)		dcstart(c, v);	else if(strcmp("pause", *v) == 0)		dcpause();	else if(strcmp("resume", *v) == 0)		dcresume();	else		dchelp();}