[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 27113c22f77 1/2: Minor improvements to write-region heuristic
From: |
Po Lu |
Subject: |
master 27113c22f77 1/2: Minor improvements to write-region heuristic |
Date: |
Tue, 8 Aug 2023 04:19:02 -0400 (EDT) |
branch: master
commit 27113c22f77b7a409c33b956a1a8d8be2d5bc673
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Minor improvements to write-region heuristic
* src/androidvfs.c (android_saf_stat): Set STATB->st_dev.
(android_fstat): Likewise.
(NATIVE_NAME): Seek to start of file after truncation.
* src/fileio.c (write_region): Use stat instead of open+fstat
to obtain updated mtime.
---
src/androidvfs.c | 15 ++++++++++++-
src/fileio.c | 68 +++++++++++++++++++++++++++++---------------------------
2 files changed, 49 insertions(+), 34 deletions(-)
diff --git a/src/androidvfs.c b/src/androidvfs.c
index 93927ccc86b..8e742f8b26f 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -4013,6 +4013,7 @@ android_saf_stat (const char *uri_name, const char
*id_name,
memset (statb, 0, sizeof *statb);
statb->st_size = MAX (0, MIN (TYPE_MAXIMUM (off_t), size));
statb->st_mode = mode;
+ statb->st_dev = -4;
#ifdef STAT_TIMESPEC
STAT_TIMESPEC (statb, st_mtim).tv_sec = mtim / 1000;
STAT_TIMESPEC (statb, st_mtim).tv_nsec = (mtim % 1000) * 1000000;
@@ -6169,7 +6170,14 @@ NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject
object)
JNIEXPORT jboolean JNICALL
NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd)
{
- return ftruncate (fd, 0) != -1;
+ if (ftruncate (fd, 0) < 0)
+ return false;
+
+ /* Reset the file pointer. */
+ if (lseek (fd, 0, SEEK_SET) < 0)
+ return false;
+
+ return true;
}
#ifdef __clang__
@@ -6722,6 +6730,11 @@ android_fstat (int fd, struct stat *statb)
parcel_fd = open_parcel_fds;
for (; parcel_fd; parcel_fd = parcel_fd->next)
{
+ if (parcel_fd->fd == fd)
+ /* Set STATB->st_dev to a negative device number, signifying
+ that it's contained within a content provider. */
+ statb->st_dev = -4;
+
if (parcel_fd->fd == fd
&& timespec_valid_p (parcel_fd->mtime))
{
diff --git a/src/fileio.c b/src/fileio.c
index 26b7e193f0a..5d01e10f0ef 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5582,42 +5582,44 @@ write_region (Lisp_Object start, Lisp_Object end,
Lisp_Object filename,
if (timespec_valid_p (modtime)
&& ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system))
{
- int desc1 = emacs_open (fn, O_WRONLY, 0);
- if (desc1 >= 0)
+ struct stat st1;
+
+ /* The code below previously tried to open FN O_WRONLY,
+ subsequently calling fstat on the opened file descriptor.
+ This proved inefficient and resulted in FN being truncated
+ under several Android filesystems, and as such has been
+ changed to a call to `stat'. */
+
+ if (emacs_fstatat (AT_FDCWD, fn, &st1, 0) == 0
+ && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
{
- struct stat st1;
- if (sys_fstat (desc1, &st1) == 0
- && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino)
+ /* Use the heuristic if it appears to be valid. With neither
+ O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the
+ file, the time stamp won't change. Also, some non-POSIX
+ systems don't update an empty file's time stamp when
+ truncating it. Finally, file systems with 100 ns or worse
+ resolution sometimes seem to have bugs: on a system with ns
+ resolution, checking ns % 100 incorrectly avoids the heuristic
+ 1% of the time, but the problem should be temporary as we will
+ try again on the next time stamp. */
+ bool use_heuristic
+ = ((open_flags & (O_EXCL | O_TRUNC)) != 0
+ && st.st_size != 0
+ && modtime.tv_nsec % 100 != 0);
+
+ struct timespec modtime1 = get_stat_mtime (&st1);
+ if (use_heuristic
+ && timespec_cmp (modtime, modtime1) == 0
+ && st.st_size == st1.st_size)
{
- /* Use the heuristic if it appears to be valid. With neither
- O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the
- file, the time stamp won't change. Also, some non-POSIX
- systems don't update an empty file's time stamp when
- truncating it. Finally, file systems with 100 ns or worse
- resolution sometimes seem to have bugs: on a system with ns
- resolution, checking ns % 100 incorrectly avoids the heuristic
- 1% of the time, but the problem should be temporary as we will
- try again on the next time stamp. */
- bool use_heuristic
- = ((open_flags & (O_EXCL | O_TRUNC)) != 0
- && st.st_size != 0
- && modtime.tv_nsec % 100 != 0);
-
- struct timespec modtime1 = get_stat_mtime (&st1);
- if (use_heuristic
- && timespec_cmp (modtime, modtime1) == 0
- && st.st_size == st1.st_size)
- {
- timestamp_file_system = st.st_dev;
- valid_timestamp_file_system = 1;
- }
- else
- {
- st.st_size = st1.st_size;
- modtime = modtime1;
- }
+ timestamp_file_system = st.st_dev;
+ valid_timestamp_file_system = 1;
+ }
+ else
+ {
+ st.st_size = st1.st_size;
+ modtime = modtime1;
}
- emacs_close (desc1);
}
}