1*16695Smckusick /* kern_acct.c 6.2 84/07/08 */ 212788Ssam 312788Ssam #include "../h/param.h" 412788Ssam #include "../h/systm.h" 512788Ssam #include "../h/dir.h" 612788Ssam #include "../h/user.h" 712788Ssam #include "../h/inode.h" 812788Ssam #include "../h/fs.h" 912788Ssam #include "../h/kernel.h" 1012788Ssam #include "../h/acct.h" 1112788Ssam #include "../h/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; 28*16695Smckusick 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 } 42*16695Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW; 43*16695Smckusick ndp->ni_segflg = UIO_USERSPACE; 44*16695Smckusick ndp->ni_dirp = uap->fname; 45*16695Smckusick 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; 7312788Ssam off_t siz; 7412788Ssam register struct acct *ap = &acctbuf; 7512788Ssam 7612788Ssam if (savacctp) { 7712788Ssam fs = savacctp->i_fs; 7812788Ssam if (freespace(fs, fs->fs_minfree + acctresume) > 0) { 7912788Ssam acctp = savacctp; 8012788Ssam savacctp = NULL; 8112788Ssam printf("Accounting resumed\n"); 8212788Ssam } 8312788Ssam } 8412788Ssam if ((ip = acctp) == NULL) 8512788Ssam return; 8612788Ssam fs = acctp->i_fs; 8712788Ssam if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) { 8812788Ssam savacctp = acctp; 8912788Ssam acctp = NULL; 9012788Ssam printf("Accounting suspended\n"); 9112788Ssam return; 9212788Ssam } 9312788Ssam ilock(ip); 9412788Ssam for (i = 0; i < sizeof (ap->ac_comm); i++) 9512788Ssam ap->ac_comm[i] = u.u_comm[i]; 9612788Ssam ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec); 9712788Ssam ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec); 9812788Ssam ap->ac_etime = compress((long)time.tv_sec - u.u_start); 9912788Ssam ap->ac_btime = u.u_start; 10012788Ssam ap->ac_uid = u.u_ruid; 10112788Ssam ap->ac_gid = u.u_rgid; 10212788Ssam ap->ac_mem = 0; 10312788Ssam if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec) 10412788Ssam ap->ac_mem = 10512788Ssam (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i; 10612788Ssam ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock)); 10712788Ssam if (u.u_ttyp) 10812788Ssam ap->ac_tty = u.u_ttyd; 10912788Ssam else 11012788Ssam ap->ac_tty = NODEV; 11112788Ssam ap->ac_flag = u.u_acflag; 11212788Ssam siz = ip->i_size; 11312788Ssam u.u_error = 0; /* XXX */ 11412788Ssam u.u_error = 11512788Ssam rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz, 11612788Ssam 1, (int *)0); 11712788Ssam if (u.u_error) 11812788Ssam itrunc(ip, (u_long)siz); 11912788Ssam iunlock(ip); 12012788Ssam } 12112788Ssam 12212788Ssam /* 12312788Ssam * Produce a pseudo-floating point representation 12412788Ssam * with 3 bits base-8 exponent, 13 bits fraction. 12512788Ssam */ 12612788Ssam compress(t) 12712788Ssam register long t; 12812788Ssam { 12912788Ssam register exp = 0, round = 0; 13012788Ssam 13112788Ssam while (t >= 8192) { 13212788Ssam exp++; 13312788Ssam round = t&04; 13412788Ssam t >>= 3; 13512788Ssam } 13612788Ssam if (round) { 13712788Ssam t++; 13812788Ssam if (t >= 8192) { 13912788Ssam t >>= 3; 14012788Ssam exp++; 14112788Ssam } 14212788Ssam } 14312788Ssam return ((exp<<13) + t); 14412788Ssam } 145