1*17088Sbloom /* kern_acct.c 6.5 84/08/29 */ 212788Ssam 3*17088Sbloom #include "param.h" 4*17088Sbloom #include "systm.h" 5*17088Sbloom #include "dir.h" 6*17088Sbloom #include "user.h" 7*17088Sbloom #include "inode.h" 8*17088Sbloom #include "fs.h" 9*17088Sbloom #include "kernel.h" 10*17088Sbloom #include "acct.h" 11*17088Sbloom #include "uio.h" 1212788Ssam 1312788Ssam /* 1412788Ssam * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY. 1512788Ssam */ 1612788Ssam struct inode *acctp; 1712788Ssam struct inode *savacctp; 1812788Ssam 1912788Ssam /* 2012788Ssam * Perform process accounting functions. 2112788Ssam */ 2212788Ssam sysacct() 2312788Ssam { 2412788Ssam register struct inode *ip; 2512788Ssam register struct a { 2612788Ssam char *fname; 2712788Ssam } *uap = (struct a *)u.u_ap; 2816695Smckusick register struct nameidata *ndp = &u.u_nd; 2912788Ssam 3012788Ssam if (suser()) { 3112788Ssam if (savacctp) { 3212788Ssam acctp = savacctp; 3312788Ssam savacctp = NULL; 3412788Ssam } 3512788Ssam if (uap->fname==NULL) { 3612788Ssam if (ip = acctp) { 3712788Ssam irele(ip); 3812788Ssam acctp = NULL; 3912788Ssam } 4012788Ssam return; 4112788Ssam } 4216695Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 4316695Smckusick ndp->ni_segflg = UIO_USERSPACE; 4416695Smckusick ndp->ni_dirp = uap->fname; 4516695Smckusick ip = namei(ndp); 4612788Ssam if(ip == NULL) 4712788Ssam return; 4812788Ssam if((ip->i_mode & IFMT) != IFREG) { 4912788Ssam u.u_error = EACCES; 5012788Ssam iput(ip); 5112788Ssam return; 5212788Ssam } 5312788Ssam if (acctp && (acctp->i_number != ip->i_number || 5412788Ssam acctp->i_dev != ip->i_dev)) 5512788Ssam irele(acctp); 5612788Ssam acctp = ip; 5712788Ssam iunlock(ip); 5812788Ssam } 5912788Ssam } 6012788Ssam 6112788Ssam int acctsuspend = 2; /* stop accounting when < 2% free space left */ 6212788Ssam int acctresume = 4; /* resume when free space risen to > 4% */ 6312788Ssam 6412788Ssam struct acct acctbuf; 6512788Ssam /* 6612788Ssam * On exit, write a record on the accounting file. 6712788Ssam */ 6812788Ssam acct() 6912788Ssam { 7012788Ssam register int i; 7112788Ssam register struct inode *ip; 7212788Ssam register struct fs *fs; 7316715Ssam register struct rusage *ru; 7412788Ssam off_t siz; 7516715Ssam struct timeval t; 7612788Ssam register struct acct *ap = &acctbuf; 7712788Ssam 7812788Ssam if (savacctp) { 7912788Ssam fs = savacctp->i_fs; 8012788Ssam if (freespace(fs, fs->fs_minfree + acctresume) > 0) { 8112788Ssam acctp = savacctp; 8212788Ssam savacctp = NULL; 8312788Ssam printf("Accounting resumed\n"); 8412788Ssam } 8512788Ssam } 8612788Ssam if ((ip = acctp) == NULL) 8712788Ssam return; 8812788Ssam fs = acctp->i_fs; 8912788Ssam if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) { 9012788Ssam savacctp = acctp; 9112788Ssam acctp = NULL; 9212788Ssam printf("Accounting suspended\n"); 9312788Ssam return; 9412788Ssam } 9512788Ssam ilock(ip); 9612788Ssam for (i = 0; i < sizeof (ap->ac_comm); i++) 9712788Ssam ap->ac_comm[i] = u.u_comm[i]; 9816715Ssam ru = &u.u_ru; 9916715Ssam ap->ac_utime = compress(ru->ru_utime.tv_sec, ru->ru_utime.tv_usec); 10016715Ssam ap->ac_stime = compress(ru->ru_stime.tv_sec, ru->ru_stime.tv_usec); 10116715Ssam t = time; 10216715Ssam timevalsub(&t, &u.u_start); 10316715Ssam ap->ac_etime = compress(t.tv_sec, t.tv_usec); 10416715Ssam ap->ac_btime = u.u_start.tv_sec; 10512788Ssam ap->ac_uid = u.u_ruid; 10612788Ssam ap->ac_gid = u.u_rgid; 10716715Ssam t = ru->ru_stime; 10816715Ssam timevaladd(&t, &ru->ru_utime); 10916719Skarels if (i = t.tv_sec * hz + t.tv_usec / tick) 11016715Ssam ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i; 11116715Ssam else 11216715Ssam ap->ac_mem = 0; 11316715Ssam ap->ac_mem >>= CLSIZELOG2; 11416715Ssam ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, 0); 11512788Ssam if (u.u_ttyp) 11612788Ssam ap->ac_tty = u.u_ttyd; 11712788Ssam else 11812788Ssam ap->ac_tty = NODEV; 11912788Ssam ap->ac_flag = u.u_acflag; 12012788Ssam siz = ip->i_size; 12112788Ssam u.u_error = 0; /* XXX */ 12212788Ssam u.u_error = 12312788Ssam rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz, 12412788Ssam 1, (int *)0); 12512788Ssam if (u.u_error) 12612788Ssam itrunc(ip, (u_long)siz); 12712788Ssam iunlock(ip); 12812788Ssam } 12912788Ssam 13012788Ssam /* 13112788Ssam * Produce a pseudo-floating point representation 13212788Ssam * with 3 bits base-8 exponent, 13 bits fraction. 13312788Ssam */ 13416715Ssam compress(t, ut) 13512788Ssam register long t; 13616715Ssam long ut; 13712788Ssam { 13812788Ssam register exp = 0, round = 0; 13912788Ssam 14016715Ssam t <<= 6; 14116715Ssam if (ut) 14216715Ssam t += ut / (1000000 / (1<<6)); 14312788Ssam while (t >= 8192) { 14412788Ssam exp++; 14512788Ssam round = t&04; 14612788Ssam t >>= 3; 14712788Ssam } 14812788Ssam if (round) { 14912788Ssam t++; 15012788Ssam if (t >= 8192) { 15112788Ssam t >>= 3; 15212788Ssam exp++; 15312788Ssam } 15412788Ssam } 15512788Ssam return ((exp<<13) + t); 15612788Ssam } 157