aboutsummaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2018-11-14 14:18:35 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2018-11-14 14:18:35 +0000
commit1c4ca7789029ae5478e160fd43b039b71523c0d2 (patch)
treeebe30c84784f39aefcec04c4927db112c2c93bf0 /sys/fs
parentd5aef6d6ca05d7d7d8aa53b410ecd6d63e18d083 (diff)
downloadsrc-1c4ca7789029ae5478e160fd43b039b71523c0d2.tar.gz
src-1c4ca7789029ae5478e160fd43b039b71523c0d2.zip
Add d_off support for multiple filesystems.
The d_off field has been added to the dirent structure recently. Currently filesystems don't support this feature. Support has been added and tested for zfs, ufs, ext2fs, fdescfs, msdosfs and unionfs. A stub implementation is available for cd9660, nandfs, udf and pseudofs but hasn't been tested. Motivation for this feature: our usecase is for a userspace nfs server (nfs-ganesha) with zfs. At the moment we cache direntry offsets by calling lseek once per entry, with this patch we can get the offset directly from getdirentries(2) calls which provides a significant speedup. Submitted by: Jack Halford <jack@gandi.net> Reviewed by: mckusick, pfg, rmacklem (previous versions) Sponsored by: Gandi.net MFC after: 1 week Differential revision: https://reviews.freebsd.org/D17917
Notes
Notes: svn path=/head/; revision=340431
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/fs/devfs/devfs_vnops.c2
-rw-r--r--sys/fs/ext2fs/ext2_lookup.c2
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c4
-rw-r--r--sys/fs/nandfs/nandfs_vnops.c2
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c2
-rw-r--r--sys/fs/udf/udf_vnops.c3
8 files changed, 19 insertions, 0 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index 84cee260d066..ca291c7c5a3f 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -576,6 +576,8 @@ cd9660_readdir(ap)
entryoffsetinblock;
idp->curroff += reclen;
+ /* NOTE: d_off is the offset of *next* entry. */
+ idp->current.d_off = idp->curroff;
switch (imp->iso_ftype) {
case ISO_FTYPE_RRIP:
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 5c0bf603ab9b..c046c4e88ad3 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1381,6 +1381,8 @@ devfs_readdir(struct vop_readdir_args *ap)
if (dp->d_reclen > uio->uio_resid)
break;
dp->d_fileno = de->de_inode;
+ /* NOTE: d_off is the offset for the *next* entry. */
+ dp->d_off = off + dp->d_reclen;
if (off >= uio->uio_offset) {
error = vfs_read_dirent(ap, dp, off);
if (error)
diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c
index 5de7b9a7a3b5..d5fc6f93542d 100644
--- a/sys/fs/ext2fs/ext2_lookup.c
+++ b/sys/fs/ext2fs/ext2_lookup.c
@@ -224,6 +224,8 @@ ext2_readdir(struct vop_readdir_args *ap)
dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen);
dstdp.d_name[dstdp.d_namlen] = '\0';
+ /* NOTE: d_off is the offset of the *next* entry. */
+ dstdp.d_off = offset + dp->e2d_reclen;
if (dstdp.d_reclen > uio->uio_resid) {
if (uio->uio_resid == startresid)
error = EINVAL;
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 7d94ddf17a51..d1731938f062 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -574,6 +574,8 @@ fdesc_readdir(struct vop_readdir_args *ap)
dp->d_fileno = i + FD_DESC;
break;
}
+ /* NOTE: d_off is the offset of the *next* entry. */
+ dp->d_off = UIO_MX * (i + 1);
if (dp->d_namlen != 0) {
/*
* And ship to userland
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index 0abcda4a99b4..e6172a25f6c0 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1558,6 +1558,8 @@ msdosfs_readdir(struct vop_readdir_args *ap)
break;
}
dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf);
+ /* NOTE: d_off is the offset of the *next* entry. */
+ dirbuf.d_off = offset + sizeof(struct direntry);
if (uio->uio_resid < dirbuf.d_reclen)
goto out;
error = uiomove(&dirbuf, dirbuf.d_reclen, uio);
@@ -1681,6 +1683,8 @@ msdosfs_readdir(struct vop_readdir_args *ap)
mbnambuf_flush(&nb, &dirbuf);
chksum = -1;
dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf);
+ /* NOTE: d_off is the offset of the *next* entry. */
+ dirbuf.d_off = offset + sizeof(struct direntry);
if (uio->uio_resid < dirbuf.d_reclen) {
brelse(bp);
goto out;
diff --git a/sys/fs/nandfs/nandfs_vnops.c b/sys/fs/nandfs/nandfs_vnops.c
index 80e98c368cd7..2b9f5364f69b 100644
--- a/sys/fs/nandfs/nandfs_vnops.c
+++ b/sys/fs/nandfs/nandfs_vnops.c
@@ -1233,6 +1233,8 @@ nandfs_readdir(struct vop_readdir_args *ap)
dirent.d_namlen = name_len;
strncpy(dirent.d_name, ndirent->name, name_len);
dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
+ /* NOTE: d_off is the offset of the *next* entry. */
+ dirent.d_off = diroffset + ndirent->rec_len;
DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
name_len, dirent.d_name));
}
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index 664949492906..1ffcb4c8098e 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -830,6 +830,8 @@ pfs_readdir(struct vop_readdir_args *va)
pfsent->entry.d_name[i] = pn->pn_name[i];
pfsent->entry.d_name[i] = 0;
pfsent->entry.d_namlen = i;
+ /* NOTE: d_off is the offset of the *next* entry. */
+ pfsent->entry.d_off = offset + PFS_DELEN;
switch (pn->pn_type) {
case pfstype_procdir:
KASSERT(p != NULL,
diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c
index 6e7706c5c7c5..30558cf86931 100644
--- a/sys/fs/udf/udf_vnops.c
+++ b/sys/fs/udf/udf_vnops.c
@@ -846,6 +846,7 @@ udf_readdir(struct vop_readdir_args *a)
dir.d_name[1] = '\0';
dir.d_namlen = 1;
dir.d_reclen = GENERIC_DIRSIZ(&dir);
+ dir.d_off = 1;
uiodir.dirent = &dir;
error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1);
if (error)
@@ -858,6 +859,7 @@ udf_readdir(struct vop_readdir_args *a)
dir.d_name[2] = '\0';
dir.d_namlen = 2;
dir.d_reclen = GENERIC_DIRSIZ(&dir);
+ dir.d_off = 2;
uiodir.dirent = &dir;
error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
} else {
@@ -867,6 +869,7 @@ udf_readdir(struct vop_readdir_args *a)
dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ?
DT_DIR : DT_UNKNOWN;
dir.d_reclen = GENERIC_DIRSIZ(&dir);
+ dir.d_off = ds->this_off;
uiodir.dirent = &dir;
error = udf_uiodir(&uiodir, dir.d_reclen, uio,
ds->this_off);