Skip to content

Commit f017b0a

Browse files
oleg-nesterovbrauner
authored andcommitted
pipe: don't update {a,c,m}time for anonymous pipes
These numbers are visible in fstat() but hopefully nobody uses this information and file_accessed/file_update_time are not that cheap. Stupid test-case: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <sys/ioctl.h> #include <sys/time.h> static char buf[17 * 4096]; static struct timeval TW, TR; int wr(int fd, int size) { int c, r; struct timeval t0, t1; gettimeofday(&t0, NULL); for (c = 0; (r = write(fd, buf, size)) > 0; c += r); gettimeofday(&t1, NULL); timeradd(&TW, &t1, &TW); timersub(&TW, &t0, &TW); return c; } int rd(int fd, int size) { int c, r; struct timeval t0, t1; gettimeofday(&t0, NULL); for (c = 0; (r = read(fd, buf, size)) > 0; c += r); gettimeofday(&t1, NULL); timeradd(&TR, &t1, &TR); timersub(&TR, &t0, &TR); return c; } int main(int argc, const char *argv[]) { int fd[2], nb = 1, loop, size; assert(argc == 3); loop = atoi(argv[1]); size = atoi(argv[2]); assert(pipe(fd) == 0); assert(ioctl(fd[0], FIONBIO, &nb) == 0); assert(ioctl(fd[1], FIONBIO, &nb) == 0); assert(size <= sizeof(buf)); while (loop--) assert(wr(fd[1], size) == rd(fd[0], size)); struct timeval tt; timeradd(&TW, &TR, &tt); printf("TW = %lu.%03lu TR = %lu.%03lu TT = %lu.%03lu\n", TW.tv_sec, TW.tv_usec/1000, TR.tv_sec, TR.tv_usec/1000, tt.tv_sec, tt.tv_usec/1000); return 0; } Before: # for i in 1 2 3; do /host/tmp/test 10000 100; done TW = 8.047 TR = 5.845 TT = 13.893 TW = 8.091 TR = 5.872 TT = 13.963 TW = 8.083 TR = 5.885 TT = 13.969 After: # for i in 1 2 3; do /host/tmp/test 10000 100; done TW = 4.752 TR = 4.664 TT = 9.416 TW = 4.684 TR = 4.608 TT = 9.293 TW = 4.736 TR = 4.652 TT = 9.388 Signed-off-by: Oleg Nesterov <oleg@redhat.com> Link: https://lore.kernel.org/r/20250205181812.GC13817@redhat.com Tested-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 262b2fa commit f017b0a

1 file changed

Lines changed: 29 additions & 12 deletions

File tree

fs/pipe.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ static inline unsigned int pipe_update_tail(struct pipe_inode_info *pipe,
248248
}
249249

250250
static ssize_t
251-
pipe_read(struct kiocb *iocb, struct iov_iter *to)
251+
anon_pipe_read(struct kiocb *iocb, struct iov_iter *to)
252252
{
253253
size_t total_len = iov_iter_count(to);
254254
struct file *filp = iocb->ki_filp;
@@ -404,8 +404,15 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
404404
if (wake_next_reader)
405405
wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);
406406
kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
407+
return ret;
408+
}
409+
410+
static ssize_t
411+
fifo_pipe_read(struct kiocb *iocb, struct iov_iter *to)
412+
{
413+
int ret = anon_pipe_read(iocb, to);
407414
if (ret > 0)
408-
file_accessed(filp);
415+
file_accessed(iocb->ki_filp);
409416
return ret;
410417
}
411418

@@ -426,7 +433,7 @@ static inline bool pipe_writable(const struct pipe_inode_info *pipe)
426433
}
427434

428435
static ssize_t
429-
pipe_write(struct kiocb *iocb, struct iov_iter *from)
436+
anon_pipe_write(struct kiocb *iocb, struct iov_iter *from)
430437
{
431438
struct file *filp = iocb->ki_filp;
432439
struct pipe_inode_info *pipe = filp->private_data;
@@ -604,11 +611,21 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
604611
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
605612
if (wake_next_writer)
606613
wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM);
607-
if (ret > 0 && sb_start_write_trylock(file_inode(filp)->i_sb)) {
608-
int err = file_update_time(filp);
609-
if (err)
610-
ret = err;
611-
sb_end_write(file_inode(filp)->i_sb);
614+
return ret;
615+
}
616+
617+
static ssize_t
618+
fifo_pipe_write(struct kiocb *iocb, struct iov_iter *from)
619+
{
620+
int ret = anon_pipe_write(iocb, from);
621+
if (ret > 0) {
622+
struct file *filp = iocb->ki_filp;
623+
if (sb_start_write_trylock(file_inode(filp)->i_sb)) {
624+
int err = file_update_time(filp);
625+
if (err)
626+
ret = err;
627+
sb_end_write(file_inode(filp)->i_sb);
628+
}
612629
}
613630
return ret;
614631
}
@@ -1234,8 +1251,8 @@ static int fifo_open(struct inode *inode, struct file *filp)
12341251

12351252
const struct file_operations pipefifo_fops = {
12361253
.open = fifo_open,
1237-
.read_iter = pipe_read,
1238-
.write_iter = pipe_write,
1254+
.read_iter = fifo_pipe_read,
1255+
.write_iter = fifo_pipe_write,
12391256
.poll = pipe_poll,
12401257
.unlocked_ioctl = pipe_ioctl,
12411258
.release = pipe_release,
@@ -1245,8 +1262,8 @@ const struct file_operations pipefifo_fops = {
12451262

12461263
static const struct file_operations pipeanon_fops = {
12471264
.open = fifo_open,
1248-
.read_iter = pipe_read,
1249-
.write_iter = pipe_write,
1265+
.read_iter = anon_pipe_read,
1266+
.write_iter = anon_pipe_write,
12501267
.poll = pipe_poll,
12511268
.unlocked_ioctl = pipe_ioctl,
12521269
.release = pipe_release,

0 commit comments

Comments
 (0)