plan 9 kernel history: overview | file list | diff list

1998/0916/port/devmntstats.c (diff list | history)

port/devmntstats.c on 1998/0916
1998/0916    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
 
void (*mntstats)(int, Chan*, uvlong); 
 
enum 
{ 
	Qmntstat = 1<<12, 
 
	Nhash=	31, 
	Nms=	256, 
	Nrpc=	(Tmax-Tnop)/2, 
}; 
 
typedef struct Mntstats Mntstats; 
struct Mntstats 
{ 
	Mntstats *next; 
	int	inuse; 
	Chan	c; 
	uvlong	hi[Nrpc];		/* high water time spent/msg type */ 
	uvlong	tot[Nrpc];		/* cumulative time spent/msg type */ 
	uvlong	bytes[Nrpc];		/* cumulative bytes xfered */ 
	ulong	n[Nrpc];		/* number of messages/msg type */ 
	ulong	last100[Nrpc];		/* avg time for last 100 */ 
}; 
 
static struct 
{ 
	Lock; 
	Mntstats	*hash[Nhash]; 
	Mntstats	all[Nms]; 
	int		n; 
} msalloc; 
 
static void 
_mntstats(int type, Chan *c, uvlong start) 
{ 
	uint h; 
	Mntstats **l, *m; 
	uvlong elapsed; 
	ulong x; 
 
	elapsed = fastticks(nil) - start; 
	type -= Tnop; 
	type >>= 1; 
 
	h = (c->dev<<4)+(c->type<<2)+c->qid.path; 
	h %= Nhash; 
	for(l = &msalloc.hash[h]; *l; l = &(*l)->next) 
		if(eqchan(&(*l)->c, c, 0)) 
			break; 
	m = *l; 
 
	if(m == nil){ 
		lock(&msalloc); 
		for(m = msalloc.all; m < &msalloc.all[Nms]; m++) 
			if(m->inuse && eqchan(&m->c, c, 0)) 
				break; 
		if(m == &msalloc.all[Nms]) 
			for(m = msalloc.all; m < &msalloc.all[Nms]; m++){ 
				if(m->inuse == 0){ 
					m->inuse = 1; 
					m->c = *c; 
					*l = m; 
					msalloc.n++; 
					break; 
				} 
			} 
		unlock(&msalloc); 
		if(m >= &msalloc.all[Nms]) 
			return; 
	} 
 
	if(m->hi[type] < elapsed) 
		m->hi[type] = elapsed; 
	m->tot[type] += elapsed; 
	m->n[type]++; 
	x = elapsed; 
	m->last100[type] = (m->last100[type]*127 + x)>>7; 
} 
 
static int 
mntstatsgen(Chan *c, Dirtab*, int, int i, Dir *dp) 
{ 
	Qid q; 
	char name[NAMELEN]; 
	Mntstats *m; 
 
	m = &msalloc.all[i]; 
	if(i > Nms || m->inuse == 0) 
		return -1; 
 
	q = (Qid){Qmntstat+i, 0}; 
	snprint(name, NAMELEN, "%C%lud.%lux", devtab[m->c.type]->dc, m->c.dev, m->c.qid.path); 
	devdir(c, q, name, 0, eve, 0666, dp); 
 
	return 1; 
} 
 
static void 
mntstatsinit(void) 
{ 
	mntstats = _mntstats; 
} 
 
static Chan* 
mntstatsattach(char *spec) 
{ 
	return devattach('z', spec); 
} 
 
static int 
mntstatswalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, 0, msalloc.n, mntstatsgen); 
} 
 
static void 
mntstatsstat(Chan *c, char *dp) 
{ 
	devstat(c, dp, 0, msalloc.n, mntstatsgen); 
} 
 
static Chan* 
mntstatsopen(Chan *c, int omode) 
{ 
	return devopen(c, omode, 0, msalloc.n, mntstatsgen); 
} 
 
static void 
mntstatsclose(Chan*) 
{ 
} 
 
enum 
{ 
	Nline=	80, 
}; 
 
char *rpcname[Nrpc] = 
{ 
	"nop", 
	"osession", 
	"error", 
	"flush", 
	"oattach", 
	"clone", 
	"walk", 
	"open", 
	"create", 
	"read", 
	"write", 
	"clunk", 
	"remove", 
	"stat", 
	"wstat", 
	"clwalk", 
	"auth", 
	"session", 
	"attach", 
}; 
 
static long 
mntstatsread(Chan *c, void *buf, long n, vlong off) 
{ 
	char *a, *start; 
	ulong o; 
	char xbuf[Nline+1]; 
	Mntstats *m; 
	uvlong avg; 
 
	start = a = buf; 
 
	if(n <= 0) 
		return n; 
 
	if(c->qid.path & CHDIR) 
		return devdirread(c, buf, n, 0, msalloc.n, mntstatsgen); 
 
	m = &msalloc.all[c->qid.path - Qmntstat]; 
	o = off; 
	if((o % Nline) != 0) 
		error(Ebadarg); 
	n = n/Nline; 
	o = o/Nline; 
	while(n > 0 && o < Nrpc){ 
		if(m->n[o] > 0) 
			avg = m->tot[o]/m->n[o]; 
		else 
			avg = 0; 
		sprint(xbuf, "%-8.8s %16.0llud %16.0llud %9.0lud %16.0llud %9.0lud\n", 
				rpcname[o],  m->hi[o], 
				m->tot[o], m->n[o], avg, m->last100[o]); 
		memmove(a, xbuf, Nline); 
		a += Nline; 
		o++; 
		n--; 
	} 
	return a - start; 
} 
 
static long 
mntstatswrite(Chan*, void*, long, vlong) 
{ 
	lock(&msalloc); 
	memset(msalloc.all, 0, sizeof(msalloc.all)); 
	msalloc.n = 0; 
	unlock(&msalloc); 
	return 0; 
} 
 
Dev mntstatsdevtab = { 
	'z', 
	"mntstats", 
 
	devreset, 
	mntstatsinit, 
	mntstatsattach, 
	devclone, 
	mntstatswalk, 
	mntstatsstat, 
	mntstatsopen, 
	devcreate, 
	mntstatsclose, 
	mntstatsread, 
	devbread, 
	mntstatswrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)