Skip to content

Commit fa697b9

Browse files
authored
FreeBSD: Add posix_fadvise(POSIX_FADV_WILLNEED) support
As commit 320f0c6 did for Linux, connect POSIX_FADV_WILLNEED up to dmu_prefetch() on FreeBSD. While there, fix portability problems in tests/functional/fadvise. 1. Instead of relying on the numerical values of POSIX_FADV_XXX macros, accept macro names as arguments to the file_fadvise program. (The numbers happen to match on Linux and FreeBSD, but future systems may vary and it seems a little strange/raw to count on that.) 2. For implementation reasons, SEQUENTIAL doesn't reach ZFS via FreeBSD VFS currently (perhaps something that should be investigated in FreeBSD). Since on Linux we're treating SEQUENTIAL and WILLNEED the same, it doesn't really matter which one we use, so switch the test over to WILLNEED exercise the new prefetch code on both OSes the same way. Reviewed-by: Mateusz Guzik <[email protected]> Reviewed-by: Fedor Uporov <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Thomas Munro <[email protected]> Co-authored-by: Alexander Motin <[email protected]> Closes #17379
1 parent 00360ef commit fa697b9

File tree

8 files changed

+119
-14
lines changed

8 files changed

+119
-14
lines changed

module/os/freebsd/zfs/zfs_vnops_os.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6055,6 +6055,78 @@ zfs_freebsd_aclcheck(struct vop_aclcheck_args *ap)
60556055
return (EOPNOTSUPP);
60566056
}
60576057

6058+
#ifndef _SYS_SYSPROTO_H_
6059+
struct vop_advise_args {
6060+
struct vnode *a_vp;
6061+
off_t a_start;
6062+
off_t a_end;
6063+
int a_advice;
6064+
};
6065+
#endif
6066+
6067+
static int
6068+
zfs_freebsd_advise(struct vop_advise_args *ap)
6069+
{
6070+
vnode_t *vp = ap->a_vp;
6071+
off_t start = ap->a_start;
6072+
off_t end = ap->a_end;
6073+
int advice = ap->a_advice;
6074+
off_t len;
6075+
znode_t *zp;
6076+
zfsvfs_t *zfsvfs;
6077+
objset_t *os;
6078+
int error = 0;
6079+
6080+
if (end < start)
6081+
return (EINVAL);
6082+
6083+
error = vn_lock(vp, LK_SHARED);
6084+
if (error)
6085+
return (error);
6086+
6087+
zp = VTOZ(vp);
6088+
zfsvfs = zp->z_zfsvfs;
6089+
os = zp->z_zfsvfs->z_os;
6090+
6091+
if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
6092+
goto out_unlock;
6093+
6094+
/* kern_posix_fadvise points to the last byte, we want one past */
6095+
if (end != OFF_MAX)
6096+
end += 1;
6097+
len = end - start;
6098+
6099+
switch (advice) {
6100+
case POSIX_FADV_WILLNEED:
6101+
/*
6102+
* Pass on the caller's size directly, but note that
6103+
* dmu_prefetch_max will effectively cap it. If there really
6104+
* is a larger sequential access pattern, perhaps dmu_zfetch
6105+
* will detect it.
6106+
*/
6107+
dmu_prefetch(os, zp->z_id, 0, start, len,
6108+
ZIO_PRIORITY_ASYNC_READ);
6109+
break;
6110+
case POSIX_FADV_NORMAL:
6111+
case POSIX_FADV_RANDOM:
6112+
case POSIX_FADV_SEQUENTIAL:
6113+
case POSIX_FADV_DONTNEED:
6114+
case POSIX_FADV_NOREUSE:
6115+
/* ignored for now */
6116+
break;
6117+
default:
6118+
error = EINVAL;
6119+
break;
6120+
}
6121+
6122+
zfs_exit(zfsvfs, FTAG);
6123+
6124+
out_unlock:
6125+
VOP_UNLOCK(vp);
6126+
6127+
return (error);
6128+
}
6129+
60586130
static int
60596131
zfs_vptocnp(struct vop_vptocnp_args *ap)
60606132
{
@@ -6293,6 +6365,7 @@ struct vop_vector zfs_vnodeops = {
62936365
.vop_link = zfs_freebsd_link,
62946366
.vop_symlink = zfs_freebsd_symlink,
62956367
.vop_readlink = zfs_freebsd_readlink,
6368+
.vop_advise = zfs_freebsd_advise,
62966369
.vop_read = zfs_freebsd_read,
62976370
.vop_write = zfs_freebsd_write,
62986371
.vop_remove = zfs_freebsd_remove,

module/zfs/dmu.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,18 @@ dmu_prefetch_by_dnode(dnode_t *dn, int64_t level, uint64_t offset,
730730
*/
731731
rw_enter(&dn->dn_struct_rwlock, RW_READER);
732732
if (dn->dn_datablkshift != 0) {
733+
734+
/*
735+
* Limit prefetch to present blocks.
736+
*/
737+
uint64_t size = (dn->dn_maxblkid + 1) << dn->dn_datablkshift;
738+
if (offset >= size) {
739+
rw_exit(&dn->dn_struct_rwlock);
740+
return;
741+
}
742+
if (offset + len < offset || offset + len > size)
743+
len = size - offset;
744+
733745
/*
734746
* The object has multiple blocks. Calculate the full range
735747
* of blocks [start, end2) and then split it into two parts,

tests/runfiles/common.run

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,10 @@ tags = ['functional', 'direct']
717717
tests = ['exec_001_pos', 'exec_002_neg']
718718
tags = ['functional', 'exec']
719719

720+
[tests/functional/fadvise]
721+
tests = ['fadvise_willneed']
722+
tags = ['functional', 'fadvise']
723+
720724
[tests/functional/failmode]
721725
tests = ['failmode_dmu_tx_wait', 'failmode_dmu_tx_continue']
722726
tags = ['functional', 'failmode']

tests/runfiles/linux.run

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill',
112112
'zed_slow_io', 'zed_slow_io_many_vdevs', 'zed_diagnose_multiple']
113113
tags = ['functional', 'events']
114114

115-
[tests/functional/fadvise:Linux]
116-
tests = ['fadvise_sequential']
117-
tags = ['functional', 'fadvise']
118-
119115
[tests/functional/fallocate:Linux]
120116
tests = ['fallocate_prealloc', 'fallocate_zero-range']
121117
tags = ['functional', 'fallocate']

tests/zfs-tests/cmd/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/read_dos_attributes %D%/write_dos_attribu
140140

141141
scripts_zfs_tests_bin_PROGRAMS += %D%/randfree_file
142142
%C%_randfree_file_SOURCES = %D%/file/randfree_file.c
143+
endif
143144

144145
scripts_zfs_tests_bin_PROGRAMS += %D%/file_fadvise
145146
%C%_file_fadvise_SOURCES = %D%/file/file_fadvise.c
146-
endif

tests/zfs-tests/cmd/file/file_fadvise.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,41 @@ static void
4444
usage(void)
4545
{
4646
(void) fprintf(stderr,
47-
"usage: %s -f filename -a advise \n", execname);
47+
"usage: %s -f filename -a advice \n", execname);
4848
}
4949

50+
typedef struct advice_name {
51+
const char *name;
52+
int value;
53+
} advice_name;
54+
55+
static const struct advice_name table[] = {
56+
#define ADV(name) {#name, name}
57+
ADV(POSIX_FADV_NORMAL),
58+
ADV(POSIX_FADV_RANDOM),
59+
ADV(POSIX_FADV_SEQUENTIAL),
60+
ADV(POSIX_FADV_WILLNEED),
61+
ADV(POSIX_FADV_DONTNEED),
62+
ADV(POSIX_FADV_NOREUSE),
63+
{NULL}
64+
};
65+
5066
int
5167
main(int argc, char *argv[])
5268
{
5369
char *filename = NULL;
54-
int advise = 0;
70+
int advice = POSIX_FADV_NORMAL;
5571
int fd, ch;
5672
int err = 0;
5773

5874
while ((ch = getopt(argc, argv, "a:f:")) != EOF) {
5975
switch (ch) {
6076
case 'a':
61-
advise = atoll(optarg);
77+
advice = -1;
78+
for (const advice_name *p = table; p->name; ++p) {
79+
if (strcmp(p->name, optarg) == 0)
80+
advice = p->value;
81+
}
6282
break;
6383
case 'f':
6484
filename = optarg;
@@ -75,8 +95,8 @@ main(int argc, char *argv[])
7595
err++;
7696
}
7797

78-
if (advise < POSIX_FADV_NORMAL || advise > POSIX_FADV_NOREUSE) {
79-
(void) printf("advise is invalid\n");
98+
if (advice == -1) {
99+
(void) printf("advice is invalid\n");
80100
err++;
81101
}
82102

@@ -90,7 +110,7 @@ main(int argc, char *argv[])
90110
return (1);
91111
}
92112

93-
if (posix_fadvise(fd, 0, 0, advise) != 0) {
113+
if (posix_fadvise(fd, 0, 0, advice) != 0) {
94114
perror("posix_fadvise");
95115
close(fd);
96116
return (1);

tests/zfs-tests/tests/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
15261526
functional/exec/exec_002_neg.ksh \
15271527
functional/exec/setup.ksh \
15281528
functional/fadvise/cleanup.ksh \
1529-
functional/fadvise/fadvise_sequential.ksh \
1529+
functional/fadvise/fadvise_willneed.ksh \
15301530
functional/fadvise/setup.ksh \
15311531
functional/failmode/cleanup.ksh \
15321532
functional/failmode/failmode_dmu_tx_wait.ksh \

tests/zfs-tests/tests/functional/fadvise/fadvise_sequential.ksh renamed to tests/zfs-tests/tests/functional/fadvise/fadvise_willneed.ksh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#
4343

4444
# NOTE: if HAVE_FILE_FADVISE is not defined former data_size
45-
# should less or eaqul to latter one
45+
# should less or equal to latter one
4646

4747
verify_runnable "global"
4848

@@ -66,7 +66,7 @@ sync_pool $TESTPOOL
6666

6767
data_size1=$(kstat arcstats.data_size)
6868

69-
log_must file_fadvise -f $FILE -a 2
69+
log_must file_fadvise -f $FILE -a POSIX_FADV_WILLNEED
7070
sleep 10
7171

7272
data_size2=$(kstat arcstats.data_size)

0 commit comments

Comments
 (0)