Bug 278135

Summary: fusefs: pathconf(_PC_MIN_HOLE_SIZE) fails on new mountpoint with unopened file
Product: Base System Reporter: Alan Somers <asomers>
Component: kernAssignee: Alan Somers <asomers>
Status: In Progress ---    
Severity: Affects Many People Flags: asomers: mfc-stable14?
asomers: mfc-stable13+
Priority: ---    
Version: 15.0-CURRENT   
Hardware: Any   
OS: Any   
URL: https://reviews.freebsd.org/D44618

Description Alan Somers freebsd_committer freebsd_triage 2024-04-02 16:27:40 UTC
When a program calls pathconf(path, _PC_MIN_HOLE_SIZE) on a fusefs file system, if the kernel doesn't already know whether the file system supports FUSE_LSEEK, it must issue a FUSE_LSEEK operation to find out.  It sends that operation to the provided path.  BUT, the current implementation neglects to ensure that a fuse file handle is open.  That's a bug.  We never noticed it before because the test suite only uses fpathconf, not pathconf.

Steps to Reproduce
==================
1) Mount a file system that is known to support FUSE_LSEEK
2) Without doing any open(), stat(), access(), or similar, try pathconf("/mountpoint/hello.txt", _PC_MIN_HOLE_SIZE)
3) It ought to return 1, but it will instead fail with EINVAL
Comment 1 commit-hook freebsd_committer freebsd_triage 2024-06-24 16:08:04 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=6efba04df3f8c77b9b12f1df3e5124a7249b82fc

commit 6efba04df3f8c77b9b12f1df3e5124a7249b82fc
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-04-03 19:57:44 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-06-24 16:02:02 +0000

    fusefs: fix two bugs regarding _PC_MIN_HOLE_SIZE

    Background:

    If a user does pathconf(_, _PC_MIN_HOLE_SIZE) on a fusefs file system,
    the kernel must actually issue a FUSE_LSEEK operation in order to
    determine whether the server supports it.  We cache that result, so we
    only have to send FUSE_LSEEK the first time that _PC_MIN_HOLE_SIZE is
    requested on any given mountpoint.

    Problem 1:

    Unlike fpathconf, pathconf operates on files that may not be open.  But
    FUSE_LSEEK requires the file to be open.  As described in PR 278135,
    FUSE_LSEEK cannot be sent for unopened files, causing _PC_MIN_HOLE_size
    to wrongly report EINVAL.  We never noticed that before because the
    fusefs test suite only uses fpathconf, not pathconf.  Fix this bug by
    opening the file if necessary.

    Problem 2:

    On a completely sparse file, with no data blocks at all, FUSE_LSEEK with
    SEEK_DATA would fail to ENXIO.  That's correct behavior, but
    fuse_vnop_pathconf wrongly interpreted that as "FUSE_LSEEK not
    supported".  Fix the interpretation.

    PR:             278135
    MFC after:      1 week
    Sponsored by:   Axcient
    Differential Revision: https://reviews.freebsd.org/D44618

 sys/fs/fuse/fuse_vnops.c     |  48 ++++++++++++----
 tests/sys/fs/fusefs/lseek.cc | 129 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 167 insertions(+), 10 deletions(-)
Comment 2 commit-hook freebsd_committer freebsd_triage 2024-07-09 00:03:37 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=7f936b0cba08315c0127c425692369d0c162fbcf

commit 7f936b0cba08315c0127c425692369d0c162fbcf
Author:     Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2024-04-03 19:57:44 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2024-07-08 20:27:54 +0000

    fusefs: fix two bugs regarding _PC_MIN_HOLE_SIZE

    Background:

    If a user does pathconf(_, _PC_MIN_HOLE_SIZE) on a fusefs file system,
    the kernel must actually issue a FUSE_LSEEK operation in order to
    determine whether the server supports it.  We cache that result, so we
    only have to send FUSE_LSEEK the first time that _PC_MIN_HOLE_SIZE is
    requested on any given mountpoint.

    Problem 1:

    Unlike fpathconf, pathconf operates on files that may not be open.  But
    FUSE_LSEEK requires the file to be open.  As described in PR 278135,
    FUSE_LSEEK cannot be sent for unopened files, causing _PC_MIN_HOLE_size
    to wrongly report EINVAL.  We never noticed that before because the
    fusefs test suite only uses fpathconf, not pathconf.  Fix this bug by
    opening the file if necessary.

    Problem 2:

    On a completely sparse file, with no data blocks at all, FUSE_LSEEK with
    SEEK_DATA would fail to ENXIO.  That's correct behavior, but
    fuse_vnop_pathconf wrongly interpreted that as "FUSE_LSEEK not
    supported".  Fix the interpretation.

    PR:             278135
    Sponsored by:   Axcient
    Differential Revision: https://reviews.freebsd.org/D44618

    (cherry picked from commit 6efba04df3f8c77b9b12f1df3e5124a7249b82fc)

 sys/fs/fuse/fuse_vnops.c     |  48 ++++++++++++----
 tests/sys/fs/fusefs/lseek.cc | 129 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 167 insertions(+), 10 deletions(-)