8343785: (fs) Remove syscalls that set file times with microsecond precision

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2024-11-14 16:27:22 +00:00
parent 68164a4847
commit 7e9dfa4ae4
7 changed files with 89 additions and 305 deletions

View file

@ -72,42 +72,25 @@ class UnixFileAttributeViews {
// permission check
file.checkWrite();
boolean haveFd = false;
boolean useFutimes = false;
boolean useFutimens = false;
boolean useLutimes = false;
boolean useUtimensat = false;
// use a file descriptor if possible to avoid a race due to
// accessing a path more than once as the file at that path could
// change.
// if path is a symlink, then the open should fail with ELOOP and
// the path will be used instead of the file descriptor.
int fd = -1;
try {
if (!followLinks) {
// these path-based syscalls also work if following links
if (!(useUtimensat = utimensatSupported())) {
useLutimes = lutimesSupported();
}
}
if (!useUtimensat && !useLutimes) {
fd = file.openForAttributeAccess(followLinks);
if (fd != -1) {
haveFd = true;
if (!(useFutimens = futimensSupported())) {
useFutimes = futimesSupported();
}
}
}
fd = file.openForAttributeAccess(followLinks);
} catch (UnixException x) {
if (!(x.errno() == ENXIO ||
(x.errno() == ELOOP && (useUtimensat || useLutimes)))) {
if (!(x.errno() == ENXIO || (x.errno() == ELOOP))) {
x.rethrowAsIOException(file);
}
}
try {
// assert followLinks || !UnixFileAttributes.get(fd).isSymbolicLink();
// if not changing both attributes then need existing attributes
if (lastModifiedTime == null || lastAccessTime == null) {
try {
UnixFileAttributes attrs = haveFd ?
UnixFileAttributes attrs = fd >= 0 ?
UnixFileAttributes.get(fd) :
UnixFileAttributes.get(file, followLinks);
if (lastModifiedTime == null)
@ -120,28 +103,20 @@ class UnixFileAttributeViews {
}
// update times
TimeUnit timeUnit = (useFutimens || useUtimensat) ?
TimeUnit.NANOSECONDS : TimeUnit.MICROSECONDS;
long modValue = lastModifiedTime.to(timeUnit);
long accessValue= lastAccessTime.to(timeUnit);
long modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS);
long accessValue= lastAccessTime.to(TimeUnit.NANOSECONDS);
boolean retry = false;
try {
if (useFutimens) {
if (fd >= 0)
futimens(fd, accessValue, modValue);
} else if (useFutimes) {
futimes(fd, accessValue, modValue);
} else if (useLutimes) {
lutimes(file, accessValue, modValue);
} else if (useUtimensat) {
else
utimensat(AT_FDCWD, file, accessValue, modValue,
followLinks ? 0 : AT_SYMLINK_NOFOLLOW);
} else {
utimes(file, accessValue, modValue);
}
} catch (UnixException x) {
// if futimes/utimes fails with EINVAL and one/both of the times is
// negative then we adjust the value to the epoch and retry.
// if utimensat fails with EINVAL and one/both of
// the times is negative then we adjust the value to the
// epoch and retry.
if (x.errno() == EINVAL &&
(modValue < 0L || accessValue < 0L)) {
retry = true;
@ -153,18 +128,11 @@ class UnixFileAttributeViews {
if (modValue < 0L) modValue = 0L;
if (accessValue < 0L) accessValue= 0L;
try {
if (useFutimens) {
if (fd >= 0)
futimens(fd, accessValue, modValue);
} else if (useFutimes) {
futimes(fd, accessValue, modValue);
} else if (useLutimes) {
lutimes(file, accessValue, modValue);
} else if (useUtimensat) {
else
utimensat(AT_FDCWD, file, accessValue, modValue,
followLinks ? 0 : AT_SYMLINK_NOFOLLOW);
} else {
utimes(file, accessValue, modValue);
}
} catch (UnixException x) {
x.rethrowAsIOException(file);
}

View file

@ -577,14 +577,14 @@ abstract class UnixFileSystem
// copy time stamps last
if (flags.copyBasicAttributes) {
try {
if (dfd >= 0 && futimesSupported()) {
futimes(dfd,
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
if (dfd >= 0) {
futimens(dfd,
attrs.lastAccessTime().to(TimeUnit.NANOSECONDS),
attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS));
} else {
utimes(target,
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
utimensat(AT_FDCWD, target,
attrs.lastAccessTime().to(TimeUnit.NANOSECONDS),
attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS), 0);
}
} catch (UnixException x) {
// unable to set times
@ -727,15 +727,9 @@ abstract class UnixFileSystem
// copy time attributes
if (flags.copyBasicAttributes) {
try {
if (futimesSupported()) {
futimes(fo,
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
} else {
utimes(target,
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
}
futimens(fo,
attrs.lastAccessTime().to(TimeUnit.NANOSECONDS),
attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS));
} catch (UnixException x) {
if (flags.failIfUnableToCopyBasic)
x.rethrowAsIOException(target);
@ -814,9 +808,10 @@ abstract class UnixFileSystem
}
if (flags.copyBasicAttributes) {
try {
utimes(target,
attrs.lastAccessTime().to(TimeUnit.MICROSECONDS),
attrs.lastModifiedTime().to(TimeUnit.MICROSECONDS));
utimensat(AT_FDCWD, target,
attrs.lastAccessTime().to(TimeUnit.NANOSECONDS),
attrs.lastModifiedTime().to(TimeUnit.NANOSECONDS),
0);
} catch (UnixException x) {
if (flags.failIfUnableToCopyBasic)
x.rethrowAsIOException(target);

View file

@ -347,28 +347,6 @@ class UnixNativeDispatcher {
}
private static native void fchmod0(int fd, int mode) throws UnixException;
/**
* utimes(const char* path, const struct timeval times[2])
*/
static void utimes(UnixPath path, long times0, long times1)
throws UnixException
{
try (NativeBuffer buffer = copyToNativeBuffer(path)) {
utimes0(buffer.address(), times0, times1);
}
}
private static native void utimes0(long pathAddress, long times0, long times1)
throws UnixException;
/**
* futimes(int fildes, const struct timeval times[2])
*/
static void futimes(int fd, long times0, long times1) throws UnixException {
futimes0(fd, times0, times1);
}
private static native void futimes0(int fd, long times0, long times1)
throws UnixException;
/**
* futimens(int fildes, const struct timespec times[2])
*/
@ -378,19 +356,6 @@ class UnixNativeDispatcher {
private static native void futimens0(int fd, long times0, long times1)
throws UnixException;
/**
* lutimes(const char* path, const struct timeval times[2])
*/
static void lutimes(UnixPath path, long times0, long times1)
throws UnixException
{
try (NativeBuffer buffer = copyToNativeBuffer(path)) {
lutimes0(buffer.address(), times0, times1);
}
}
private static native void lutimes0(long pathAddress, long times0, long times1)
throws UnixException;
/**
* utimensat(int fd, const char* path,
* const struct timeval times[2], int flags)
@ -568,11 +533,7 @@ class UnixNativeDispatcher {
* Capabilities
*/
private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls
private static final int SUPPORTS_FUTIMES = 1 << 2;
private static final int SUPPORTS_FUTIMENS = 1 << 3;
private static final int SUPPORTS_LUTIMES = 1 << 4;
private static final int SUPPORTS_UTIMENSAT = 1 << 5;
private static final int SUPPORTS_XATTR = 1 << 6;
private static final int SUPPORTS_XATTR = 1 << 3;
private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features
private static final int capabilities;
@ -583,34 +544,6 @@ class UnixNativeDispatcher {
return (capabilities & SUPPORTS_OPENAT) != 0;
}
/**
* Supports futimes
*/
static boolean futimesSupported() {
return (capabilities & SUPPORTS_FUTIMES) != 0;
}
/**
* Supports futimens
*/
static boolean futimensSupported() {
return (capabilities & SUPPORTS_FUTIMENS) != 0;
}
/**
* Supports lutimes
*/
static boolean lutimesSupported() {
return (capabilities & SUPPORTS_LUTIMES) != 0;
}
/**
* Supports utimensat
*/
static boolean utimensatSupported() {
return (capabilities & SUPPORTS_UTIMENSAT) != 0;
}
/**
* Supports file birth (creation) time attribute
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -415,9 +415,9 @@ class UnixSecureDirectoryStream
}
// update times
try {
futimes(fd,
lastAccessTime.to(TimeUnit.MICROSECONDS),
lastModifiedTime.to(TimeUnit.MICROSECONDS));
futimens(fd,
lastAccessTime.to(TimeUnit.NANOSECONDS),
lastModifiedTime.to(TimeUnit.NANOSECONDS));
} catch (UnixException x) {
x.rethrowAsIOException(file);
}