X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Facct.c;h=daf23c4efab4d8e87e52331546312ce2a2cb72bc;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=f0e2bd0458d2f43fc7516dd5b78b3c1535e70686;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/kernel/acct.c b/kernel/acct.c index f0e2bd045..daf23c4ef 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -302,6 +302,69 @@ static comp_t encode_comp_t(unsigned long value) return exp; } +#if ACCT_VERSION==1 || ACCT_VERSION==2 +/* + * encode an u64 into a comp2_t (24 bits) + * + * Format: 5 bit base 2 exponent, 20 bits mantissa. + * The leading bit of the mantissa is not stored, but implied for + * non-zero exponents. + * Largest encodable value is 50 bits. + */ + +#define MANTSIZE2 20 /* 20 bit mantissa. */ +#define EXPSIZE2 5 /* 5 bit base 2 exponent. */ +#define MAXFRACT2 ((1ul << MANTSIZE2) - 1) /* Maximum fractional value. */ +#define MAXEXP2 ((1 < (MAXFRACT2>>1)); + rnd = 0; + while (value > MAXFRACT2) { + rnd = value & 1; + value >>= 1; + exp++; + } + + /* + * If we need to round up, do it (and handle overflow correctly). + */ + if (rnd && (++value > MAXFRACT2)) { + value >>= 1; + exp++; + } + + if (exp > MAXEXP2) { + /* Overflow. Return largest representable number instead. */ + return (1ul << (MANTSIZE2+EXPSIZE2-1)) - 1; + } else { + return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1)); + } +} +#endif + +#if ACCT_VERSION==3 +/* + * encode an u64 into a 32 bit IEEE float + */ +static u32 encode_float(u64 value) +{ + unsigned exp = 190; + unsigned u; + + if (value==0) return 0; + while ((s64)value > 0){ + value <<= 1; + exp--; + } + u = (u32)(value >> 40) & 0x7fffffu; + return u | (exp << 23); +} +#endif + /* * Write an accounting entry for an exiting process * @@ -316,7 +379,7 @@ static comp_t encode_comp_t(unsigned long value) */ static void do_acct_process(long exitcode, struct file *file) { - struct acct ac; + acct_t ac; mm_segment_t fs; unsigned long vsize; unsigned long flim; @@ -333,20 +396,45 @@ static void do_acct_process(long exitcode, struct file *file) * Fill the accounting struct with the needed info as recorded * by the different kernel functions. */ - memset((caddr_t)&ac, 0, sizeof(struct acct)); + memset((caddr_t)&ac, 0, sizeof(acct_t)); + ac.ac_version = ACCT_VERSION | ACCT_BYTEORDER; strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm)); - elapsed = jiffies_64_to_clock_t(get_jiffies_64() - current->start_time); + elapsed = jiffies_64_to_AHZ(get_jiffies_64() - current->start_time); +#if ACCT_VERSION==3 + ac.ac_etime = encode_float(elapsed); +#else ac.ac_etime = encode_comp_t(elapsed < (unsigned long) -1l ? (unsigned long) elapsed : (unsigned long) -1l); - do_div(elapsed, USER_HZ); +#endif +#if ACCT_VERSION==1 || ACCT_VERSION==2 + { + /* new enlarged etime field */ + comp2_t etime = encode_comp2_t(elapsed); + ac.ac_etime_hi = etime >> 16; + ac.ac_etime_lo = (u16) etime; + } +#endif + do_div(elapsed, AHZ); ac.ac_btime = xtime.tv_sec - elapsed; - ac.ac_utime = encode_comp_t(jiffies_to_clock_t(current->utime)); - ac.ac_stime = encode_comp_t(jiffies_to_clock_t(current->stime)); + ac.ac_utime = encode_comp_t(jiffies_to_AHZ(current->utime)); + ac.ac_stime = encode_comp_t(jiffies_to_AHZ(current->stime)); /* we really need to bite the bullet and change layout */ ac.ac_uid = current->uid; ac.ac_gid = current->gid; +#if ACCT_VERSION==2 + ac.ac_ahz = AHZ; +#endif +#if ACCT_VERSION==1 || ACCT_VERSION==2 + /* backward-compatible 16 bit fields */ + ac.ac_uid16 = current->uid; + ac.ac_gid16 = current->gid; +#endif +#if ACCT_VERSION==3 + ac.ac_pid = current->pid; + ac.ac_ppid = current->parent->pid; +#endif read_lock(&tasklist_lock); /* pin current->signal */ ac.ac_tty = current->signal->tty ? @@ -395,7 +483,7 @@ static void do_acct_process(long exitcode, struct file *file) flim = current->rlim[RLIMIT_FSIZE].rlim_cur; current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; file->f_op->write(file, (char *)&ac, - sizeof(struct acct), &file->f_pos); + sizeof(acct_t), &file->f_pos); current->rlim[RLIMIT_FSIZE].rlim_cur = flim; set_fs(fs); }