Under Plan 9 from Bell Labs, one queries or sets the system clock by
reading or writing text strings to a special file named /dev/time.
I implemented such a facility for Linux. A read of /dev/time produces
four decimal numbers: epoch seconds, nanoseconds since start of epoch,
jiffies since boot, and jiffies per second. Writing a decimal number to
/dev/time sets the system clock to the given number of epoch seconds.
Anyone who is permitted to write to /dev/time may set the clock.
Granting this privilege becomes as easy as modifying groups and file
permissions.
Signed-off-by: Christopher Brannon <[email protected]>
---
Documentation/time-device.txt | 49 ++++++++++++++++++
arch/um/Kconfig.char | 11 ++++
drivers/char/Kconfig | 11 ++++
drivers/char/Makefile | 2 +
drivers/char/devtime.c | 112 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 185 insertions(+), 0 deletions(-)
create mode 100644 Documentation/time-device.txt
create mode 100644 drivers/char/devtime.c
diff --git a/Documentation/time-device.txt b/Documentation/time-device.txt
new file mode 100644
index 0000000..6294732
--- /dev/null
+++ b/Documentation/time-device.txt
@@ -0,0 +1,49 @@
+/dev/time for Linux
+===================
+
+Christopher M. Brannon <[email protected]>
+
+Inspiration
+-----------
+This document describes an implementation for the Linux kernel of a facility
+that is provided by the Plan 9 operating system from Bell Laboratories [1].
+
+Functionality
+-------------
+/dev/time provides a file-based interface to the system clock.
+Using this interface, one can query or set the system clock by reading or
+writing text strings. A read of /dev/time yields four decimal integers:
+seconds since start of epoch, nanoseconds since start of epoch,
+jiffies since boot, and jiffies per second.
+Writing a decimal number n to /dev/time sets the system clock to the
+date and time which is n seconds greater than January 1, 1970, 00:00:00 GMT.
+
+Examples
+--------
+cat /dev/time
+# Produces: 1236121128 123612012877063000 495497 300,
+# at time of writing on a test machine.
+echo 287604960 > /dev/time
+# sets the clock to the approximate time of my birth.
+
+Use Case
+--------
+Traditionally, super-user privileges were required in order to set the
+system clock under Linux.
+Since the advent of capabilities, any process having the CAP_SYS_TIME
+capability may perform this operation.
+The /dev/time device ties privileges to file permissions. If a user
+can write to /dev/time, then he can set the system clock.
+
+Difference from Plan 9
+-----------------------
+This implementation differs from Plan 9 in one respect. the Plan 9
+Programmer's Manual exactly specifies the format of data read from the
+device, including the widths of the four numeric fields [1]. This Linux
+implementation does not pad values with whitespace, so the four fields
+are of variable width.
+
+References
+----------
+[1] Plan 9 Programmers Manual, section 3.
+http://plan9.bell-labs.com/magic/man2html/3/cons
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 70dabd1..7d0da78 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -236,4 +236,15 @@ config MMAPPER
This driver allows a host file to be used as emulated IO memory inside
UML.
+config DEVTIME
+ tristate "/dev/time virtual device support."
+ depends on EXPERIMENTAL
+ help
+ This device provides a file-based interface to the system clock.
+ The interface is based on the /dev/time device used in the
+ Plan 9 operating system from Bell Labs.
+ See <file:Documentation/time-device.txt> for a full description.
+ To compile this driver as a module, choose M here: the
+ module will be called devtime.
+
endmenu
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 735bbe2..5bad918 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -97,6 +97,17 @@ config DEVKMEM
kind of kernel debugging operations.
When in doubt, say "N".
+config DEVTIME
+ tristate "/dev/time virtual device support."
+ depends on EXPERIMENTAL
+ help
+ This device provides a file-based interface to the system clock.
+ The interface is based on the /dev/time device used in the
+ Plan 9 operating system from Bell Labs.
+ See <file:Documentation/time-device.txt> for a full description.
+ To compile this driver as a module, choose M here: the
+ module will be called devtime.
+
config SERIAL_NONSTANDARD
bool "Non-standard serial port support"
depends on HAS_IOMEM
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 9caf5b5..aba7403 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,8 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o
+obj-$(CONFIG_DEVTIME) += devtime.o
+
# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c
diff --git a/drivers/char/devtime.c b/drivers/char/devtime.c
new file mode 100644
index 0000000..5e4ca66
--- /dev/null
+++ b/drivers/char/devtime.c
@@ -0,0 +1,112 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/time.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+
+MODULE_AUTHOR("Christopher Brannon <[email protected]>");
+MODULE_LICENSE("GPL");
+
+const long long NS_PER_SEC = 1000000000;
+const long long NS_PER_USEC = 1000;
+const size_t time_bufsize = 256;
+
+static ssize_t time_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t time_write(struct file *, const char __user *, size_t, loff_t *);
+
+static const struct file_operations time_fops = {
+ .owner = THIS_MODULE,
+ .read = time_read,
+ .write = time_write,
+};
+
+static struct miscdevice timedev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "time",
+ .fops = &time_fops
+};
+
+static int time2text(char *buffer, size_t bufsize)
+{
+ int count = 0;
+ struct timeval tv;
+ long long nanos;
+
+/* jiffies isn't 0 at boot time; its value is INITIAL_JIFFIES. */
+ u64 ticks = get_jiffies_64() - INITIAL_JIFFIES;
+
+ do_gettimeofday(&tv);
+ nanos = tv.tv_sec * NS_PER_SEC + tv.tv_usec * NS_PER_USEC;
+ count =
+ scnprintf(buffer, bufsize, "%ld %lld %llu %d\n", tv.tv_sec, nanos,
+ ticks, HZ);
+ return count;
+}
+
+static int text2time(char *buffer)
+{
+ struct timespec tv;
+ int result = strict_strtol(buffer, 10, &tv.tv_sec);
+ if ((result == 0) && (tv.tv_sec > 0)) {
+ tv.tv_nsec = 0;
+ do_settimeofday(&tv);
+ } else
+ result = -EINVAL; /* only positive longs are valid. */
+ return result;
+}
+
+static ssize_t
+time_read(struct file *f, char __user *buffer, size_t count, loff_t * offset)
+{
+ int result = 0;
+ if (*offset != 0)
+ result = 0;
+ else {
+ char tmpbuf[time_bufsize];
+ int timetextlen = time2text(tmpbuf, time_bufsize);
+ unsigned long readcount = min(count, (size_t) timetextlen);
+ if (timetextlen <= 0)
+ return -EAGAIN;
+ if (!copy_to_user(buffer, tmpbuf, readcount)) {
+ *offset += readcount;
+ result = readcount;
+ } else
+ result = -EFAULT;
+ }
+ return result;
+}
+
+static ssize_t
+time_write(struct file *f, const char __user * buffer, size_t count,
+ loff_t *offset)
+{
+ unsigned int result = 0;
+ char tmpbuf[time_bufsize];
+
+ if (*offset != 0)
+ return -EINVAL;
+ if (count > ((size_t) time_bufsize - 1))
+ return -EINVAL; /* Likely trying to feed bogus data anyway. */
+ result = copy_from_user(tmpbuf, buffer, count);
+ if (result)
+ return -EFAULT;
+ tmpbuf[count] = '\0';
+ if (text2time(tmpbuf))
+ return -EINVAL;
+ return count;
+}
+
+static int __init time_init(void)
+{
+ return misc_register(&timedev);
+}
+
+static void __exit time_exit(void)
+{
+ misc_deregister(&timedev);
+}
+
+module_init(time_init);
+module_exit(time_exit);
--
1.6.1.3
On Tue, Mar 03, 2009 at 09:06:46PM -0600, Christopher Brannon wrote:
> Under Plan 9 from Bell Labs, one queries or sets the system clock by
> reading or writing text strings to a special file named /dev/time.
> I implemented such a facility for Linux. A read of /dev/time produces
> four decimal numbers: epoch seconds, nanoseconds since start of epoch,
> jiffies since boot, and jiffies per second. Writing a decimal number to
> /dev/time sets the system clock to the given number of epoch seconds.
> Anyone who is permitted to write to /dev/time may set the clock.
> Granting this privilege becomes as easy as modifying groups and file
> permissions.
>
> Signed-off-by: Christopher Brannon <[email protected]>
I'm starting to see a few plan9 specific devices being proposed
recently, with one making it into the staging tree recently (the p9auth
interface). Should we just start lumping them all together so to keep
them in one place? drivers/plan9/ ?
> ---
> Documentation/time-device.txt | 49 ++++++++++++++++++
> arch/um/Kconfig.char | 11 ++++
> drivers/char/Kconfig | 11 ++++
> drivers/char/Makefile | 2 +
> drivers/char/devtime.c | 112 +++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 185 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/time-device.txt
> create mode 100644 drivers/char/devtime.c
>
> diff --git a/Documentation/time-device.txt b/Documentation/time-device.txt
> new file mode 100644
> index 0000000..6294732
> --- /dev/null
> +++ b/Documentation/time-device.txt
> @@ -0,0 +1,49 @@
> +/dev/time for Linux
> +===================
> +
> +Christopher M. Brannon <[email protected]>
> +
> +Inspiration
> +-----------
> +This document describes an implementation for the Linux kernel of a facility
> +that is provided by the Plan 9 operating system from Bell Laboratories [1].
> +
> +Functionality
> +-------------
> +/dev/time provides a file-based interface to the system clock.
> +Using this interface, one can query or set the system clock by reading or
> +writing text strings. A read of /dev/time yields four decimal integers:
> +seconds since start of epoch, nanoseconds since start of epoch,
> +jiffies since boot, and jiffies per second.
> +Writing a decimal number n to /dev/time sets the system clock to the
> +date and time which is n seconds greater than January 1, 1970, 00:00:00 GMT.
> +
> +Examples
> +--------
> +cat /dev/time
> +# Produces: 1236121128 123612012877063000 495497 300,
> +# at time of writing on a test machine.
> +echo 287604960 > /dev/time
> +# sets the clock to the approximate time of my birth.
> +
> +Use Case
> +--------
> +Traditionally, super-user privileges were required in order to set the
> +system clock under Linux.
> +Since the advent of capabilities, any process having the CAP_SYS_TIME
> +capability may perform this operation.
> +The /dev/time device ties privileges to file permissions. If a user
> +can write to /dev/time, then he can set the system clock.
> +
> +Difference from Plan 9
> +-----------------------
> +This implementation differs from Plan 9 in one respect. the Plan 9
> +Programmer's Manual exactly specifies the format of data read from the
> +device, including the widths of the four numeric fields [1]. This Linux
> +implementation does not pad values with whitespace, so the four fields
> +are of variable width.
> +
> +References
> +----------
> +[1] Plan 9 Programmers Manual, section 3.
> +http://plan9.bell-labs.com/magic/man2html/3/cons
> diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
> index 70dabd1..7d0da78 100644
> --- a/arch/um/Kconfig.char
> +++ b/arch/um/Kconfig.char
> @@ -236,4 +236,15 @@ config MMAPPER
> This driver allows a host file to be used as emulated IO memory inside
> UML.
>
> +config DEVTIME
> + tristate "/dev/time virtual device support."
> + depends on EXPERIMENTAL
> + help
> + This device provides a file-based interface to the system clock.
> + The interface is based on the /dev/time device used in the
> + Plan 9 operating system from Bell Labs.
> + See <file:Documentation/time-device.txt> for a full description.
> + To compile this driver as a module, choose M here: the
> + module will be called devtime.
> +
> endmenu
> diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
> index 735bbe2..5bad918 100644
> --- a/drivers/char/Kconfig
> +++ b/drivers/char/Kconfig
> @@ -97,6 +97,17 @@ config DEVKMEM
> kind of kernel debugging operations.
> When in doubt, say "N".
>
> +config DEVTIME
> + tristate "/dev/time virtual device support."
> + depends on EXPERIMENTAL
> + help
> + This device provides a file-based interface to the system clock.
> + The interface is based on the /dev/time device used in the
> + Plan 9 operating system from Bell Labs.
> + See <file:Documentation/time-device.txt> for a full description.
> + To compile this driver as a module, choose M here: the
> + module will be called devtime.
> +
> config SERIAL_NONSTANDARD
> bool "Non-standard serial port support"
> depends on HAS_IOMEM
> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
> index 9caf5b5..aba7403 100644
> --- a/drivers/char/Makefile
> +++ b/drivers/char/Makefile
> @@ -111,6 +111,8 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
> obj-$(CONFIG_JS_RTC) += js-rtc.o
> js-rtc-y = rtc.o
>
> +obj-$(CONFIG_DEVTIME) += devtime.o
> +
> # Files generated that shall be removed upon make clean
> clean-files := consolemap_deftbl.c defkeymap.c
>
> diff --git a/drivers/char/devtime.c b/drivers/char/devtime.c
> new file mode 100644
> index 0000000..5e4ca66
> --- /dev/null
> +++ b/drivers/char/devtime.c
> @@ -0,0 +1,112 @@
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/time.h>
> +#include <linux/jiffies.h>
> +#include <linux/uaccess.h>
> +
> +MODULE_AUTHOR("Christopher Brannon <[email protected]>");
> +MODULE_LICENSE("GPL");
> +
> +const long long NS_PER_SEC = 1000000000;
> +const long long NS_PER_USEC = 1000;
> +const size_t time_bufsize = 256;
> +
> +static ssize_t time_read(struct file *, char __user *, size_t, loff_t *);
> +static ssize_t time_write(struct file *, const char __user *, size_t, loff_t *);
> +
> +static const struct file_operations time_fops = {
> + .owner = THIS_MODULE,
> + .read = time_read,
> + .write = time_write,
> +};
> +
> +static struct miscdevice timedev = {
> + .minor = MISC_DYNAMIC_MINOR,
> + .name = "time",
> + .fops = &time_fops
> +};
> +
> +static int time2text(char *buffer, size_t bufsize)
> +{
> + int count = 0;
> + struct timeval tv;
> + long long nanos;
> +
> +/* jiffies isn't 0 at boot time; its value is INITIAL_JIFFIES. */
> + u64 ticks = get_jiffies_64() - INITIAL_JIFFIES;
Are you sure this will handle the roll-over properly?
> + do_gettimeofday(&tv);
> + nanos = tv.tv_sec * NS_PER_SEC + tv.tv_usec * NS_PER_USEC;
> + count =
> + scnprintf(buffer, bufsize, "%ld %lld %llu %d\n", tv.tv_sec, nanos,
> + ticks, HZ);
> + return count;
> +}
> +
> +static int text2time(char *buffer)
> +{
> + struct timespec tv;
> + int result = strict_strtol(buffer, 10, &tv.tv_sec);
> + if ((result == 0) && (tv.tv_sec > 0)) {
> + tv.tv_nsec = 0;
> + do_settimeofday(&tv);
> + } else
> + result = -EINVAL; /* only positive longs are valid. */
> + return result;
> +}
> +
> +static ssize_t
> +time_read(struct file *f, char __user *buffer, size_t count, loff_t * offset)
> +{
> + int result = 0;
> + if (*offset != 0)
> + result = 0;
> + else {
> + char tmpbuf[time_bufsize];
Not good to put 256 bytes on the stack. Dynamically allocate it?
> + int timetextlen = time2text(tmpbuf, time_bufsize);
> + unsigned long readcount = min(count, (size_t) timetextlen);
As was recently pointed out to me, we have min_t() for when you need to
cast like this.
> + if (timetextlen <= 0)
> + return -EAGAIN;
If it equals 0, shouldn't you return 0? And how could it be negative?
thanks,
greg k-h
On Tue, Mar 3, 2009 at 7:06 PM, Christopher Brannon <[email protected]> wrote:
> Under Plan 9 from Bell Labs, one queries or sets the system clock by
> reading or writing text strings to a special file named /dev/time.
> I implemented such a facility for Linux. ?A read of /dev/time produces
> four decimal numbers: epoch seconds, nanoseconds since start of epoch,
> jiffies since boot, and jiffies per second.
Ehh. Why would we want to export raw kernel internal values like
jiffies and HZ?
I think the CLOCK_MONOTONIC clockid would probably be a better value to export.
thanks
-john
On Fri, Mar 6, 2009 at 12:57 PM, Greg KH <[email protected]> wrote:
> On Tue, Mar 03, 2009 at 09:06:46PM -0600, Christopher Brannon wrote:
>> Under Plan 9 from Bell Labs, one queries or sets the system clock by
>> reading or writing text strings to a special file named /dev/time.
>> I implemented such a facility for Linux. ?A read of /dev/time produces
>> four decimal numbers: epoch seconds, nanoseconds since start of epoch,
>> jiffies since boot, and jiffies per second. ?Writing a decimal number to
>> /dev/time sets the system clock to the given number of epoch seconds.
>> Anyone who is permitted to write to /dev/time may set the clock.
>> Granting this privilege becomes as easy as modifying groups and file
>> permissions.
>>
>> Signed-off-by: Christopher Brannon <[email protected]>
>
> I'm starting to see a few plan9 specific devices being proposed
> recently, with one making it into the staging tree recently (the p9auth
> interface). ?Should we just start lumping them all together so to keep
> them in one place? ?drivers/plan9/ ?
That might be a good idea, assuming it doesn't start up a flamewar.
The Glendix folks are working hard to get a lot of these device files
and filesystems implemented and it would be nice to see them have a
place to feel welcome.
Would it be very involved to get a little sandbox for these things?
>
>
>> ---
>> ?Documentation/time-device.txt | ? 49 ++++++++++++++++++
>> ?arch/um/Kconfig.char ? ? ? ? ?| ? 11 ++++
>> ?drivers/char/Kconfig ? ? ? ? ?| ? 11 ++++
>> ?drivers/char/Makefile ? ? ? ? | ? ?2 +
>> ?drivers/char/devtime.c ? ? ? ?| ?112 +++++++++++++++++++++++++++++++++++++++++
>> ?5 files changed, 185 insertions(+), 0 deletions(-)
>> ?create mode 100644 Documentation/time-device.txt
>> ?create mode 100644 drivers/char/devtime.c
>>
>> diff --git a/Documentation/time-device.txt b/Documentation/time-device.txt
>> new file mode 100644
>> index 0000000..6294732
>> --- /dev/null
>> +++ b/Documentation/time-device.txt
>> @@ -0,0 +1,49 @@
>> +/dev/time for Linux
>> +===================
>> +
>> +Christopher M. Brannon <[email protected]>
>> +
>> +Inspiration
>> +-----------
>> +This document describes an implementation for the Linux kernel of a facility
>> +that is provided by the Plan 9 operating system from Bell Laboratories [1].
>> +
>> +Functionality
>> +-------------
>> +/dev/time provides a file-based interface to the system clock.
>> +Using this interface, one can query or set the system clock by reading or
>> +writing text strings. ?A read of /dev/time yields four decimal integers:
>> +seconds since start of epoch, nanoseconds since start of epoch,
>> +jiffies since boot, and jiffies per second.
>> +Writing a decimal number n to /dev/time sets the system clock to the
>> +date and time which is n seconds greater than January 1, 1970, 00:00:00 GMT.
>> +
>> +Examples
>> +--------
>> +cat /dev/time
>> +# Produces: 1236121128 123612012877063000 495497 300,
>> +# at time of writing on a test machine.
>> +echo 287604960 > /dev/time
>> +# sets the clock to the approximate time of my birth.
>> +
>> +Use Case
>> +--------
>> +Traditionally, super-user privileges were required in order to set the
>> +system clock under Linux.
>> +Since the advent of capabilities, any process having the CAP_SYS_TIME
>> +capability may perform this operation.
>> +The /dev/time device ties privileges to file permissions. ?If a user
>> +can write to /dev/time, then he can set the system clock.
>> +
>> +Difference from Plan 9
>> +-----------------------
>> +This implementation differs from Plan 9 in one respect. ?the Plan 9
>> +Programmer's Manual exactly specifies the format of data read from the
>> +device, including the widths of the four numeric fields [1]. ?This Linux
>> +implementation does not pad values with whitespace, so the four fields
>> +are of variable width.
>> +
>> +References
>> +----------
>> +[1] Plan 9 Programmers Manual, section 3.
>> +http://plan9.bell-labs.com/magic/man2html/3/cons
>> diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
>> index 70dabd1..7d0da78 100644
>> --- a/arch/um/Kconfig.char
>> +++ b/arch/um/Kconfig.char
>> @@ -236,4 +236,15 @@ config MMAPPER
>> ? ? ? ? This driver allows a host file to be used as emulated IO memory inside
>> ? ? ? ? UML.
>>
>> +config DEVTIME
>> + ? ? tristate "/dev/time virtual device support."
>> + ? ? depends on EXPERIMENTAL
>> + ? ? help
>> + ? ? ? This device provides a file-based interface to the system clock.
>> + ? ? ? The interface is based on the /dev/time device used in the
>> + ? ? ? Plan 9 operating system from Bell Labs.
>> + ? ? ? See <file:Documentation/time-device.txt> for a full description.
>> + ? ? ? To compile this driver as a module, choose M here: the
>> + ? ? ? module will be called devtime.
>> +
>> ?endmenu
>> diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
>> index 735bbe2..5bad918 100644
>> --- a/drivers/char/Kconfig
>> +++ b/drivers/char/Kconfig
>> @@ -97,6 +97,17 @@ config DEVKMEM
>> ? ? ? ? kind of kernel debugging operations.
>> ? ? ? ? When in doubt, say "N".
>>
>> +config DEVTIME
>> + ? ? tristate "/dev/time virtual device support."
>> + ? ? depends on EXPERIMENTAL
>> + ? ? help
>> + ? ? ? This device provides a file-based interface to the system clock.
>> + ? ? ? The interface is based on the /dev/time device used in the
>> + ? ? ? Plan 9 operating system from Bell Labs.
>> + ? ? ? See <file:Documentation/time-device.txt> for a full description.
>> + ? ? ? To compile this driver as a module, choose M here: the
>> + ? ? ? module will be called devtime.
>> +
>> ?config SERIAL_NONSTANDARD
>> ? ? ? bool "Non-standard serial port support"
>> ? ? ? depends on HAS_IOMEM
>> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
>> index 9caf5b5..aba7403 100644
>> --- a/drivers/char/Makefile
>> +++ b/drivers/char/Makefile
>> @@ -111,6 +111,8 @@ obj-$(CONFIG_PS3_FLASH) ? ? ? ? ? += ps3flash.o
>> ?obj-$(CONFIG_JS_RTC) ? ? ? ? += js-rtc.o
>> ?js-rtc-y = rtc.o
>>
>> +obj-$(CONFIG_DEVTIME) ? ? ? ? ? ? ? ?+= devtime.o
>> +
>> ?# Files generated that shall be removed upon make clean
>> ?clean-files := consolemap_deftbl.c defkeymap.c
>>
>> diff --git a/drivers/char/devtime.c b/drivers/char/devtime.c
>> new file mode 100644
>> index 0000000..5e4ca66
>> --- /dev/null
>> +++ b/drivers/char/devtime.c
>> @@ -0,0 +1,112 @@
>> +#include <linux/init.h>
>> +#include <linux/module.h>
>> +#include <linux/fs.h>
>> +#include <linux/miscdevice.h>
>> +#include <linux/time.h>
>> +#include <linux/jiffies.h>
>> +#include <linux/uaccess.h>
>> +
>> +MODULE_AUTHOR("Christopher Brannon <[email protected]>");
>> +MODULE_LICENSE("GPL");
>> +
>> +const long long NS_PER_SEC = 1000000000;
>> +const long long NS_PER_USEC = 1000;
>> +const size_t time_bufsize = 256;
>> +
>> +static ssize_t time_read(struct file *, char __user *, size_t, loff_t *);
>> +static ssize_t time_write(struct file *, const char __user *, size_t, loff_t *);
>> +
>> +static const struct file_operations time_fops = {
>> + ? ? .owner = THIS_MODULE,
>> + ? ? .read = time_read,
>> + ? ? .write = time_write,
>> +};
>> +
>> +static struct miscdevice timedev = {
>> + ? ? .minor = MISC_DYNAMIC_MINOR,
>> + ? ? .name = "time",
>> + ? ? .fops = &time_fops
>> +};
>> +
>> +static int time2text(char *buffer, size_t bufsize)
>> +{
>> + ? ? int count = 0;
>> + ? ? struct timeval tv;
>> + ? ? long long nanos;
>> +
>> +/* jiffies isn't 0 at boot time; its value is INITIAL_JIFFIES. */
>> + ? ? u64 ticks = get_jiffies_64() - INITIAL_JIFFIES;
>
> Are you sure this will handle the roll-over properly?
>
>> + ? ? do_gettimeofday(&tv);
>> + ? ? nanos = tv.tv_sec * NS_PER_SEC + tv.tv_usec * NS_PER_USEC;
>> + ? ? count =
>> + ? ? ? ? scnprintf(buffer, bufsize, "%ld %lld %llu %d\n", tv.tv_sec, nanos,
>> + ? ? ? ? ? ? ? ? ? ticks, HZ);
>> + ? ? return count;
>> +}
>> +
>> +static int text2time(char *buffer)
>> +{
>> + ? ? struct timespec tv;
>> + ? ? int result = strict_strtol(buffer, 10, &tv.tv_sec);
>> + ? ? if ((result == 0) && (tv.tv_sec > 0)) {
>> + ? ? ? ? ? ? tv.tv_nsec = 0;
>> + ? ? ? ? ? ? do_settimeofday(&tv);
>> + ? ? } else
>> + ? ? ? ? ? ? result = -EINVAL; ? ? ? /* only positive longs are valid. */
>> + ? ? return result;
>> +}
>> +
>> +static ssize_t
>> +time_read(struct file *f, char __user *buffer, size_t count, loff_t * offset)
>> +{
>> + ? ? int result = 0;
>> + ? ? if (*offset != 0)
>> + ? ? ? ? ? ? result = 0;
>> + ? ? else {
>> + ? ? ? ? ? ? char tmpbuf[time_bufsize];
>
> Not good to put 256 bytes on the stack. ?Dynamically allocate it?
>
>> + ? ? ? ? ? ? int timetextlen = time2text(tmpbuf, time_bufsize);
>> + ? ? ? ? ? ? unsigned long readcount = min(count, (size_t) timetextlen);
>
> As was recently pointed out to me, we have min_t() for when you need to
> cast like this.
>
>> + ? ? ? ? ? ? if (timetextlen <= 0)
>> + ? ? ? ? ? ? ? ? ? ? return -EAGAIN;
>
> If it equals 0, shouldn't you return 0? ?And how could it be negative?
>
> thanks,
>
> greg k-h
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at ?http://www.tux.org/lkml/
>
On Sat, Mar 07, 2009 at 12:43:43AM -0500, J.R. Mauro wrote:
> On Fri, Mar 6, 2009 at 12:57 PM, Greg KH <[email protected]> wrote:
> > On Tue, Mar 03, 2009 at 09:06:46PM -0600, Christopher Brannon wrote:
> >> Under Plan 9 from Bell Labs, one queries or sets the system clock by
> >> reading or writing text strings to a special file named /dev/time.
> >> I implemented such a facility for Linux. ?A read of /dev/time produces
> >> four decimal numbers: epoch seconds, nanoseconds since start of epoch,
> >> jiffies since boot, and jiffies per second. ?Writing a decimal number to
> >> /dev/time sets the system clock to the given number of epoch seconds.
> >> Anyone who is permitted to write to /dev/time may set the clock.
> >> Granting this privilege becomes as easy as modifying groups and file
> >> permissions.
> >>
> >> Signed-off-by: Christopher Brannon <[email protected]>
> >
> > I'm starting to see a few plan9 specific devices being proposed
> > recently, with one making it into the staging tree recently (the p9auth
> > interface). ?Should we just start lumping them all together so to keep
> > them in one place? ?drivers/plan9/ ?
>
> That might be a good idea, assuming it doesn't start up a flamewar.
I don't think if we keep it all in one place, it would.
> The Glendix folks are working hard to get a lot of these device files
> and filesystems implemented and it would be nice to see them have a
> place to feel welcome.
>
> Would it be very involved to get a little sandbox for these things?
drivers/plan9 looks like a nice place to me, any objections?
thanks,
greg k-h
John Stultz wrote:
> On Tue, Mar 3, 2009 at 7:06 PM, Christopher Brannon <[email protected]> wrote:
> > I implemented such a facility for Linux. A read of /dev/time produces
> > four decimal numbers: epoch seconds, nanoseconds since start of epoch,
> > jiffies since boot, and jiffies per second.
>
> Ehh. Why would we want to export raw kernel internal values like
> jiffies and HZ?
>
> I think the CLOCK_MONOTONIC clockid would probably be a better value to export.
I'll look at CLOCK_MONOTONIC clockid. I'm more than glad to export something
more appropriate, including nothing at all (dummy values, perhaps).
-- Chris
Greg KH wrote:
> On Sat, Mar 07, 2009 at 12:43:43AM -0500, J.R. Mauro wrote:
> > That might be a good idea, assuming it doesn't start up a flamewar.
>
> I don't think if we keep it all in one place, it would.
>
> > The Glendix folks are working hard to get a lot of these device files
> > and filesystems implemented and it would be nice to see them have a
> > place to feel welcome.
> > Would it be very involved to get a little sandbox for these things?
>
> drivers/plan9 looks like a nice place to me, any objections?
Treating all of the Plan 9 devices as a group seems good,
especially if it applies to Kconfig.
During the config process, one could easily ignore the whole group.
-- Chris
On 3/7/09, Greg KH <[email protected]> wrote:
> On Sat, Mar 07, 2009 at 12:43:43AM -0500, J.R. Mauro wrote:
>> On Fri, Mar 6, 2009 at 12:57 PM, Greg KH <[email protected]> wrote:
>> > On Tue, Mar 03, 2009 at 09:06:46PM -0600, Christopher Brannon wrote:
>> >> Under Plan 9 from Bell Labs, one queries or sets the system clock by
>> >> reading or writing text strings to a special file named /dev/time.
>> >> I implemented such a facility for Linux. A read of /dev/time produces
>> >> four decimal numbers: epoch seconds, nanoseconds since start of epoch,
>> >> jiffies since boot, and jiffies per second. Writing a decimal number
>> >> to
>> >> /dev/time sets the system clock to the given number of epoch seconds.
>> >> Anyone who is permitted to write to /dev/time may set the clock.
>> >> Granting this privilege becomes as easy as modifying groups and file
>> >> permissions.
>> >>
>> >> Signed-off-by: Christopher Brannon <[email protected]>
>> >
>> > I'm starting to see a few plan9 specific devices being proposed
>> > recently, with one making it into the staging tree recently (the p9auth
>> > interface). Should we just start lumping them all together so to keep
>> > them in one place? drivers/plan9/ ?
>>
>> That might be a good idea, assuming it doesn't start up a flamewar.
>
> I don't think if we keep it all in one place, it would.
>
>> The Glendix folks are working hard to get a lot of these device files
>> and filesystems implemented and it would be nice to see them have a
>> place to feel welcome.
>>
>> Would it be very involved to get a little sandbox for these things?
>
> drivers/plan9 looks like a nice place to me, any objections?
>
Sounds good to keep this all together, as more things come in. We
don't want to male a mess :-)
> thanks,
>
> greg k-h
>
Hi!
> Under Plan 9 from Bell Labs, one queries or sets the system clock by
> reading or writing text strings to a special file named /dev/time.
> I implemented such a facility for Linux. A read of /dev/time produces
> four decimal numbers: epoch seconds, nanoseconds since start of epoch,
> jiffies since boot, and jiffies per second. Writing a decimal
> number to
Jiffies are strange... and I guess time should be exported as 123.456
(seconds . fractional part). That way we are not limited to
nanoseconds...
Same interface can be used for setting precise time...
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue, Mar 03, 2009 at 09:06:46PM -0600, Christopher Brannon wrote:
<snip>
>@@ -0,0 +1,112 @@
>+#include <linux/init.h>
>+#include <linux/module.h>
>+#include <linux/fs.h>
>+#include <linux/miscdevice.h>
>+#include <linux/time.h>
>+#include <linux/jiffies.h>
>+#include <linux/uaccess.h>
>+
>+MODULE_AUTHOR("Christopher Brannon <[email protected]>");
>+MODULE_LICENSE("GPL");
>+
>+const long long NS_PER_SEC = 1000000000;
>+const long long NS_PER_USEC = 1000;
>+const size_t time_bufsize = 256;
I notice that you use this "const" as an array size below, so
you are using VLA, yes, C99 supports it but this is in the kernel,
try to avoid this by using marco:
#define BUFSIZE 256
And yes, C's const sucks. :)
>+
>+static ssize_t time_read(struct file *, char __user *, size_t, loff_t *);
>+static ssize_t time_write(struct file *, const char __user *, size_t, loff_t *);
>+
>+static const struct file_operations time_fops = {
>+ .owner = THIS_MODULE,
>+ .read = time_read,
>+ .write = time_write,
>+};
>+
>+static struct miscdevice timedev = {
>+ .minor = MISC_DYNAMIC_MINOR,
>+ .name = "time",
>+ .fops = &time_fops
>+};
>+
>+static int time2text(char *buffer, size_t bufsize)
>+{
>+ int count = 0;
>+ struct timeval tv;
>+ long long nanos;
>+
>+/* jiffies isn't 0 at boot time; its value is INITIAL_JIFFIES. */
>+ u64 ticks = get_jiffies_64() - INITIAL_JIFFIES;
>+
>+ do_gettimeofday(&tv);
>+ nanos = tv.tv_sec * NS_PER_SEC + tv.tv_usec * NS_PER_USEC;
>+ count =
>+ scnprintf(buffer, bufsize, "%ld %lld %llu %d\n", tv.tv_sec, nanos,
>+ ticks, HZ);
>+ return count;
>+}
>+
>+static int text2time(char *buffer)
>+{
>+ struct timespec tv;
>+ int result = strict_strtol(buffer, 10, &tv.tv_sec);
>+ if ((result == 0) && (tv.tv_sec > 0)) {
>+ tv.tv_nsec = 0;
>+ do_settimeofday(&tv);
>+ } else
>+ result = -EINVAL; /* only positive longs are valid. */
>+ return result;
>+}
>+
>+static ssize_t
>+time_read(struct file *f, char __user *buffer, size_t count, loff_t * offset)
>+{
>+ int result = 0;
>+ if (*offset != 0)
>+ result = 0;
>+ else {
>+ char tmpbuf[time_bufsize];
>+ int timetextlen = time2text(tmpbuf, time_bufsize);
>+ unsigned long readcount = min(count, (size_t) timetextlen);
>+ if (timetextlen <= 0)
>+ return -EAGAIN;
>+ if (!copy_to_user(buffer, tmpbuf, readcount)) {
>+ *offset += readcount;
>+ result = readcount;
>+ } else
>+ result = -EFAULT;
>+ }
>+ return result;
>+}
>+
>+static ssize_t
>+time_write(struct file *f, const char __user * buffer, size_t count,
>+ loff_t *offset)
>+{
>+ unsigned int result = 0;
>+ char tmpbuf[time_bufsize];
>+
>+ if (*offset != 0)
>+ return -EINVAL;
>+ if (count > ((size_t) time_bufsize - 1))
>+ return -EINVAL; /* Likely trying to feed bogus data anyway. */
>+ result = copy_from_user(tmpbuf, buffer, count);
>+ if (result)
>+ return -EFAULT;
>+ tmpbuf[count] = '\0';
>+ if (text2time(tmpbuf))
>+ return -EINVAL;
>+ return count;
>+}
>+
>+static int __init time_init(void)
>+{
>+ return misc_register(&timedev);
>+}
>+
>+static void __exit time_exit(void)
>+{
>+ misc_deregister(&timedev);
>+}
>+
>+module_init(time_init);
>+module_exit(time_exit);
>--
>1.6.1.3
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>the body of a message to [email protected]
>More majordomo info at http://vger.kernel.org/majordomo-info.html
>Please read the FAQ at http://www.tux.org/lkml/
--
Do what you love, f**k the rest! F**k the regulations!
On Sat, Mar 07, 2009 at 10:23:05AM -0600, Chris Brannon wrote:
> John Stultz wrote:
> > On Tue, Mar 3, 2009 at 7:06 PM, Christopher Brannon <[email protected]> wrote:
> > > I implemented such a facility for Linux. A read of /dev/time produces
> > > four decimal numbers: epoch seconds, nanoseconds since start of epoch,
> > > jiffies since boot, and jiffies per second.
> >
> > Ehh. Why would we want to export raw kernel internal values like
> > jiffies and HZ?
> >
> > I think the CLOCK_MONOTONIC clockid would probably be a better value to export.
>
> I'll look at CLOCK_MONOTONIC clockid. I'm more than glad to export something
> more appropriate, including nothing at all (dummy values, perhaps).
Chris, are the current values exactly what one would get if reading /dev/time on
Plan 9? If possible, it would be nice to aim for 100% compatibility as there are
folks trying to get complete Plan 9 binary compatibility working in Linux.
>
> -- Chris
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
J.R. Mauro
() ascii ribbon campaign - against html e-mail
/\ http://www.asciiribbon.org - against Microsoft attachments
J.R. Mauro wrote:
> On Sat, Mar 07, 2009 at 10:23:05AM -0600, Chris Brannon wrote:
> > John Stultz wrote:
> > > Ehh. Why would we want to export raw kernel internal values like
> > > jiffies and HZ?
> > >
> > > I think the CLOCK_MONOTONIC clockid would probably be a better value to
> > > export.
> >
> > I'll look at CLOCK_MONOTONIC clockid. I'm more than glad to export
> > something > more appropriate, including nothing at all (dummy values,
> > perhaps).
>
> Chris, are the current values exactly what one would get if reading /dev/time
> onPlan 9?
> If possible, it would be nice to aim for 100% compatibility as there are
> folks trying to get complete Plan 9 binary compatibility working in Linux.
On Plan 9, the last two values are architecture-dependent.
I rewrote my patch to export nanoseconds since boot and nanoseconds per
second, but either choice should be ok from the standpoint of compatibility.
I am going to rework this patch to eliminate the inconsistencies
with the Plan 9 interface.
Thanks to Jochen Vos for pointing out the error in the documentation.
I forgot to change my example to reflect the change to the code.
-- Chris