summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/syscall/stat.c
diff options
context:
space:
mode:
authorPavel Filipensky <Pavel.Filipensky@Sun.COM>2009-06-18 10:30:22 +0100
committerPavel Filipensky <Pavel.Filipensky@Sun.COM>2009-06-18 10:30:22 +0100
commit36b60d359f30acb8837a2d801b582ee5aa2c24f1 (patch)
tree517de3cd416896d5a69656d64e80805cd596feb2 /usr/src/uts/common/syscall/stat.c
parent129b3e6c5b0ac55b5021a4c38db6387b6acdaaf1 (diff)
downloadillumos-joyent-36b60d359f30acb8837a2d801b582ee5aa2c24f1.tar.gz
6539657 touch(1) does not set the nanosecond timestamp of a file correctly
Diffstat (limited to 'usr/src/uts/common/syscall/stat.c')
-rw-r--r--usr/src/uts/common/syscall/stat.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/usr/src/uts/common/syscall/stat.c b/usr/src/uts/common/syscall/stat.c
index 8bd03c2454..cf0fbe6d3f 100644
--- a/usr/src/uts/common/syscall/stat.c
+++ b/usr/src/uts/common/syscall/stat.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,8 +31,6 @@
* under license from the Regents of the University of California.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Get file attribute information through a file name or a file descriptor.
*/
@@ -59,6 +57,44 @@
#include <fs/fs_subr.h>
/*
+ * =========================================================
+ * "ROUND_TO_USEC" workaround for missing syscall interface.
+ * =========================================================
+ *
+ * Solaris does not provide interface to set the timestamp of a file in
+ * nanosecond granularity. POSIX.1-2008 specifies such syscall interface:
+ * futimens(), utimensat(). The modern filesystems like ZFS support
+ * nanosecond granular timestamps.
+ *
+ * Before the workaround was implemented:
+ *
+ * The timestamps were read with the nanosecond granularity but written
+ * only with the microsecond granularity. If the timestamp was copied by
+ * reading it with nanosecond granularity and by writing with the microsecond
+ * granularity, the nanosecond part of the timestamp was zero.
+ *
+ * Example: such copying of the timestamp is done by touch(1) if the '-r'
+ * option is used. 'touch -r' is used by build procuderes based on make(1S).
+ * The missing nanosecond part was breaking build procuderes and resulted in
+ * hard to diagnose build failures.
+ *
+ * After the workaround is implemented:
+ *
+ * The timestamps are in the kernel still stored with the nanosecond
+ * granularity. However, all the 'stat' syscalls now clear the nanosecond part
+ * in the timestamp values returned by these syscalls.
+ *
+ * The "ROUND_TO_USEC" workaround should be removed when the new syscall
+ * interface is available.
+ */
+int stat_force_usec_granularity = 1;
+
+#define ROUND_TO_USEC(tms) \
+{ \
+ (tms)->tv_nsec = (long)(((tms)->tv_nsec / 1000) * 1000); \
+}
+
+/*
* Get the vp to be stated and the cred to be used for the call
* to VOP_GETATTR
*/
@@ -252,6 +288,14 @@ cstat(vnode_t *vp, struct stat *ubp, int flag, cred_t *cr)
vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
if ((error = VOP_GETATTR(vp, &vattr, flag, cr, NULL)) != 0)
return (error);
+
+ /* Workaround - see beginning of the file for the details */
+ if (stat_force_usec_granularity) {
+ ROUND_TO_USEC(&(vattr.va_atime));
+ ROUND_TO_USEC(&(vattr.va_mtime));
+ ROUND_TO_USEC(&(vattr.va_ctime));
+ }
+
#ifdef _ILP32
/*
* (32-bit kernel, 32-bit applications, 32-bit files)
@@ -401,6 +445,13 @@ cstat32(vnode_t *vp, struct stat32 *ubp, int flag, struct cred *cr)
if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL))
return (error);
+ /* Workaround - see beginning of the file for the details */
+ if (stat_force_usec_granularity) {
+ ROUND_TO_USEC(&(vattr.va_atime));
+ ROUND_TO_USEC(&(vattr.va_mtime));
+ ROUND_TO_USEC(&(vattr.va_ctime));
+ }
+
/* devices are a special case, see comments in cstat */
if ((vattr.va_size > MAXOFF32_T) &&
((vp->v_type == VBLK) || (vp->v_type == VCHR))) {
@@ -521,6 +572,13 @@ cstat64(vnode_t *vp, struct stat64 *ubp, int flag, cred_t *cr)
if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL))
return (error);
+ /* Workaround - see beginning of the file for the details */
+ if (stat_force_usec_granularity) {
+ ROUND_TO_USEC(&(vattr.va_atime));
+ ROUND_TO_USEC(&(vattr.va_mtime));
+ ROUND_TO_USEC(&(vattr.va_ctime));
+ }
+
bzero(&lsb, sizeof (lsb));
lsb.st_dev = vattr.va_fsid;
lsb.st_ino = vattr.va_nodeid;
@@ -627,6 +685,13 @@ cstat64_32(vnode_t *vp, struct stat64_32 *ubp, int flag, cred_t *cr)
if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL))
return (error);
+ /* Workaround - see beginning of the file for the details */
+ if (stat_force_usec_granularity) {
+ ROUND_TO_USEC(&(vattr.va_atime));
+ ROUND_TO_USEC(&(vattr.va_mtime));
+ ROUND_TO_USEC(&(vattr.va_ctime));
+ }
+
if (!cmpldev(&st_dev, vattr.va_fsid) ||
!cmpldev(&st_rdev, vattr.va_rdev) ||
TIMESPEC_OVERFLOW(&(vattr.va_atime)) ||