X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=kernel%2Ftime.c;h=d5400f6af052db4b430f13e257ce615dc38cea9c;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=167a72a078ea9237937cf865f975ae8522bc714a;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/kernel/time.c b/kernel/time.c index 167a72a07..d5400f6af 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -31,6 +31,10 @@ #include #include #include +#include +#include +#include + #include #include @@ -49,12 +53,10 @@ EXPORT_SYMBOL(sys_tz); * sys_gettimeofday(). Is this for backwards compatibility? If so, * why not move it into the appropriate arch directory (for those * architectures that need it). - * - * XXX This function is NOT 64-bit clean! */ -asmlinkage long sys_time(int __user * tloc) +asmlinkage long sys_time(time_t __user * tloc) { - int i; + time_t i; struct timeval tv; do_gettimeofday(&tv); @@ -77,13 +79,17 @@ asmlinkage long sys_time(int __user * tloc) asmlinkage long sys_stime(time_t __user *tptr) { struct timespec tv; + int err; - if (!capable(CAP_SYS_TIME)) - return -EPERM; if (get_user(tv.tv_sec, tptr)) return -EFAULT; tv.tv_nsec = 0; + + err = security_settime(&tv, NULL); + if (err) + return err; + do_settimeofday(&tv); return 0; } @@ -145,10 +151,12 @@ inline static void warp_clock(void) int do_sys_settimeofday(struct timespec *tv, struct timezone *tz) { static int firsttime = 1; + int error = 0; + + error = security_settime(tv, tz); + if (error) + return error; - if (!capable(CAP_SYS_TIME)) - return -EPERM; - if (tz) { /* SMP safe, global irq locking makes it work. */ sys_tz = *tz; @@ -408,7 +416,7 @@ asmlinkage long sys_adjtimex(struct timex __user *txc_p) return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret; } -struct timespec current_kernel_time(void) +inline struct timespec current_kernel_time(void) { struct timespec now; unsigned long seq; @@ -424,6 +432,50 @@ struct timespec current_kernel_time(void) EXPORT_SYMBOL(current_kernel_time); +/** + * current_fs_time - Return FS time + * @sb: Superblock. + * + * Return the current time truncated to the time granuality supported by + * the fs. + */ +struct timespec current_fs_time(struct super_block *sb) +{ + struct timespec now = current_kernel_time(); + return timespec_trunc(now, sb->s_time_gran); +} +EXPORT_SYMBOL(current_fs_time); + +/** + * timespec_trunc - Truncate timespec to a granuality + * @t: Timespec + * @gran: Granuality in ns. + * + * Truncate a timespec to a granuality. gran must be smaller than a second. + * Always rounds down. + * + * This function should be only used for timestamps returned by + * current_kernel_time() or CURRENT_TIME, not with do_gettimeofday() because + * it doesn't handle the better resolution of the later. + */ +struct timespec timespec_trunc(struct timespec t, unsigned gran) +{ + /* + * Division is pretty slow so avoid it for common cases. + * Currently current_kernel_time() never returns better than + * jiffies resolution. Exploit that. + */ + if (gran <= jiffies_to_usecs(1) * 1000) { + /* nothing */ + } else if (gran == 1000000000) { + t.tv_nsec = 0; + } else { + t.tv_nsec -= t.tv_nsec % gran; + } + return t; +} +EXPORT_SYMBOL(timespec_trunc); + #ifdef CONFIG_TIME_INTERPOLATION void getnstimeofday (struct timespec *tv) { @@ -478,8 +530,6 @@ int do_settimeofday (struct timespec *tv) return 0; } -EXPORT_SYMBOL(do_settimeofday); - void do_gettimeofday (struct timeval *tv) { unsigned long seq, nsec, usec, sec, offset; @@ -519,8 +569,6 @@ void getnstimeofday(struct timespec *tv) } #endif -EXPORT_SYMBOL(getnstimeofday); - #if (BITS_PER_LONG < 64) u64 get_jiffies_64(void) {