-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix lseek(SEEK_DATA/SEEK_HOLE) mmap consistency
When using lseek(2) to report data/holes memory mapped regions of the file were ignored. This could result in incorrect results. To handle this zfs_holey_common() was updated to asynchronously writeback any dirty mmap(2) regions prior to reporting holes. Additionally, while not strictly required, the dn_struct_rwlock is now held over the dirty check to prevent the dnode structure from changing. This ensures that a clean dnode can't be dirtied before the data/hole is located. The range lock is now also taken to ensure the call cannot race with zfs_write(). Furthermore, the code was refactored to provide a dnode_is_dirty() helper function which checks the dnode for any dirty records to determine its dirtiness. Reviewed-by: Matthew Ahrens <[email protected]> Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Rich Ercolani <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Issue #11900 Closes #12724
- Loading branch information
1 parent
4b87c19
commit de198f2
Showing
18 changed files
with
305 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/mmap_seek |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
include $(top_srcdir)/config/Rules.am | ||
|
||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin | ||
|
||
pkgexec_PROGRAMS = mmap_seek | ||
mmap_seek_SOURCES = mmap_seek.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* | ||
* CDDL HEADER START | ||
* | ||
* The contents of this file are subject to the terms of the | ||
* Common Development and Distribution License (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* | ||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||
* or http://www.opensolaris.org/os/licensing. | ||
* See the License for the specific language governing permissions | ||
* and limitations under the License. | ||
* | ||
* When distributing Covered Code, include this CDDL HEADER in each | ||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||
* If applicable, add the following below this CDDL HEADER, with the | ||
* fields enclosed by brackets "[]" replaced with your own identifying | ||
* information: Portions Copyright [yyyy] [name of copyright owner] | ||
* | ||
* CDDL HEADER END | ||
*/ | ||
|
||
/* | ||
* Copyright (c) 2021 by Lawrence Livermore National Security, LLC. | ||
*/ | ||
|
||
#include <unistd.h> | ||
#include <fcntl.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/mman.h> | ||
#include <errno.h> | ||
|
||
static void | ||
seek_data(int fd, off_t offset, off_t expected) | ||
{ | ||
off_t data_offset = lseek(fd, offset, SEEK_DATA); | ||
if (data_offset != expected) { | ||
fprintf(stderr, "lseek(fd, %d, SEEK_DATA) = %d (expected %d)\n", | ||
(int)offset, (int)data_offset, (int)expected); | ||
exit(2); | ||
} | ||
} | ||
|
||
static void | ||
seek_hole(int fd, off_t offset, off_t expected) | ||
{ | ||
off_t hole_offset = lseek(fd, offset, SEEK_HOLE); | ||
if (hole_offset != expected) { | ||
fprintf(stderr, "lseek(fd, %d, SEEK_HOLE) = %d (expected %d)\n", | ||
(int)offset, (int)hole_offset, (int)expected); | ||
exit(2); | ||
} | ||
} | ||
|
||
int | ||
main(int argc, char **argv) | ||
{ | ||
char *execname = argv[0]; | ||
char *file_path = argv[1]; | ||
char *buf = NULL; | ||
int err; | ||
|
||
if (argc != 4) { | ||
(void) printf("usage: %s <file name> <file size> " | ||
"<block size>\n", argv[0]); | ||
exit(1); | ||
} | ||
|
||
int fd = open(file_path, O_RDWR | O_CREAT, 0666); | ||
if (fd == -1) { | ||
(void) fprintf(stderr, "%s: %s: ", execname, file_path); | ||
perror("open"); | ||
exit(2); | ||
} | ||
|
||
off_t file_size = atoi(argv[2]); | ||
off_t block_size = atoi(argv[3]); | ||
|
||
if (block_size * 2 > file_size) { | ||
(void) fprintf(stderr, "file size must be at least " | ||
"double the block size\n"); | ||
exit(2); | ||
} | ||
|
||
err = ftruncate(fd, file_size); | ||
if (err == -1) { | ||
perror("ftruncate"); | ||
exit(2); | ||
} | ||
|
||
if ((buf = mmap(NULL, file_size, PROT_READ | PROT_WRITE, | ||
MAP_SHARED, fd, 0)) == MAP_FAILED) { | ||
perror("mmap"); | ||
exit(2); | ||
} | ||
|
||
/* Verify the file is sparse and reports no data. */ | ||
seek_data(fd, 0, -1); | ||
|
||
/* Verify the file is reported as a hole. */ | ||
seek_hole(fd, 0, 0); | ||
|
||
/* Verify search beyond end of file is an error. */ | ||
seek_data(fd, 2 * file_size, -1); | ||
seek_hole(fd, 2 * file_size, -1); | ||
|
||
/* Dirty the first byte. */ | ||
memset(buf, 'a', 1); | ||
seek_data(fd, 0, 0); | ||
seek_data(fd, block_size, -1); | ||
seek_hole(fd, 0, block_size); | ||
seek_hole(fd, block_size, block_size); | ||
|
||
/* Dirty the first half of the file. */ | ||
memset(buf, 'b', file_size / 2); | ||
seek_data(fd, 0, 0); | ||
seek_data(fd, block_size, block_size); | ||
seek_hole(fd, 0, P2ROUNDUP(file_size / 2, block_size)); | ||
seek_hole(fd, block_size, P2ROUNDUP(file_size / 2, block_size)); | ||
|
||
/* Dirty the whole file. */ | ||
memset(buf, 'c', file_size); | ||
seek_data(fd, 0, 0); | ||
seek_data(fd, file_size * 3 / 4, | ||
P2ROUNDUP(file_size * 3 / 4, block_size)); | ||
seek_hole(fd, 0, file_size); | ||
seek_hole(fd, file_size / 2, file_size); | ||
|
||
/* Punch a hole (required compression be enabled). */ | ||
memset(buf + block_size, 0, block_size); | ||
seek_data(fd, 0, 0); | ||
seek_data(fd, block_size, 2 * block_size); | ||
seek_hole(fd, 0, block_size); | ||
seek_hole(fd, block_size, block_size); | ||
seek_hole(fd, 2 * block_size, file_size); | ||
|
||
err = munmap(buf, file_size); | ||
if (err == -1) { | ||
perror("munmap"); | ||
exit(2); | ||
} | ||
|
||
close(fd); | ||
|
||
return (0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.