From: Li Wang <liwang@kylinos.cn>
To: "Christian König" <christian.koenig@amd.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>,
Sumit Semwal <sumit.semwal@linaro.org>,
linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
linaro-mm-sig@lists.linaro.org, io-uring@vger.kernel.org,
linux-kernel@vger.kernel.org,
Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Subject: Re: [RFC PATCH] misc: fgds: enable GPU-NVMe direct I/O via POSIX and io_uring
Date: Thu, 10 Sep 2026 11:57:58 +0800 [thread overview]
Message-ID: <9447bb67-96e9-43b3-87c8-db231051fa2d@kylinos.cn> (raw)
In-Reply-To: <33c9db65-fa30-4d34-9026-98144ce1ed95@amd.com>
Hi Christian,
>>>> Nor why "fgds" is the name, that's going to be hard to remember, does it
>>>> stand for something?
>>>>
>>> "FGDS" stands for Fast GPUDirect Storage. GPUDirect Storage (GDS) is NVIDIA's
>>> technology enabling direct I/O between GPU memory and files on NVMe,
>>> widely used in LLM workloads to bypass CPU overhead.
>>
>> That's nvidia's specific solution, but this works on other devices,
>> right? Or just for that one platform?
>
> That was nvidia's specific and very hacky out of tree solution
Exactly, I completely agree with your viewpoint. In fact, we previously conducted
a deep analysis of NVIDIA's GDS implementation code, which was also one of the
motivations for us to develop fgds.
Please allow me to introduce NVIDIA's GDS implementation briefly:
NVIDIA introduced two kernel modules: one module called nvidia-fs, and the other module
is a customized NVMe driver replacing the Linux kernel's default NVMe driver.
nvidia-fs creates a device file for every NVIDIA GPU on the machine: /dev/nvidia-fs<gpu-id>.
Applications call cuFileBufRegister to register the GPU memory buffer to perform I/O.
cuFileBufRegister executes the following operations: calls nvidia-fs via ioctl. The
implementation of this ioctl allocates a corresponding phony buffer of the same size
in the host memory, and establishes a mapping between the CPU memory phony buffer
and the GPU memory buffer.
Then, the application calls cuFileRead/cuFileWrite to perform file I/O operations.
Its implementation calls ioctl on nvidia-fs with NVFS_IOCTL_READ/NVFS_IOCTL_WRITE
as parameters. Inside the ioctl implementation, it calls the common kernel interface
filp->f_op->read_iter/write_iter() on the file on NVME. These interfaces can only take
the CPU memory phony buffer address as a input, constructing read/write requests sent
through the block layer to the customized NVMe driver.
The customized NVMe driver intercepts the I/O operations, calls the nvidia-fs interface to
query, replaces the phony buffer address with the GPU memory dma address, and performs
DMA transfer between GPU memory and NVMe.
As we can see, this implementation is indeed very hacky and non-elegant. Furthermore,
as evaluated in this paper published in SC'25 [1], the phony buffer brings a considerable
performance overhead.
> which as far as I know is pretty much abandoned everywhere.
However, despite the overhead of phony buffers, GDS performance is still significantly higher
than transferring through CPU host memory (as shown in our performance benchmark tests [2]).
Therefore, GDS is actually still widely used in the LLM ecosystem. For instance, model loading
plugins used in inference engines like vLLM and SGLang—such as fastsafetensors and InstantTensor—
both support acceleration via GDS [3,4], with fastsafetensors enabling GDS by default for model loading.
Furthermore, LMCache, a plugin used for KV cache offloading in vLLM and SGLang, also supports
GDS acceleration [5]. PyTorch itself also provides file access APIs based on GDS [6].
>
> AMD came up with something similar, but all those approaches are so fundamentally broken that we didn't even considered upstreaming it.
>> And you are using this as a "bypass" for the normal accel subsystem,
>> shouldn't this be part of that subsystem instead of a custom user/kernel
>> api like you are creating here?
>
> As far as I know there is a patch set under review and even already partially merged which enables exactly that functionality as general feature for DMA-buf which is vendor independent and should at least in theory work with all drivers.
>
> I'm really surprised that somebody is still working on the vendor specific stuff.
As you pointed out, every vendor has been inventing their own way and interfaces to support GDS,
introducing custom kernel modules and proprietary UAPI interfaces, with varying performance that
leaves developers heavily frustrated. Apologies for not making this clear enough in our commit
messages, which understandably caused some confusion. We merely borrowed the name "GDS" to describe
the functional purpose of fgds.
In fact, we believe fgds offers four key advantages:
(1) GPU platform independence;
(2) POSIX/io_uring interface compatibility;
(3) Higher performance than GDS;
(4) Minimal kernel footprint and UAPI footprint
Regarding (1), (2), and (3), please allow me to briefly explain the design mechanism of fgds:
fgds turns a GPU memory buffer into a POSIX/io_uring-compatible user-space virtual address via
three main steps:
Step 1: Utilizing ZONE_DEVICE support, we remap the GPU memory exposed via PCIe BAR into struct pages
using devm_memremap_pages();
Step 2: Utilizing dma-buf support, the GPU memory buffer is exported as a dma-buf file descriptor (fd).
Using this fd as a bridge, we look up the corresponding DMA addresses for the GPU memory buffer inside
the kernel;
Step 3: Through mmap, we insert the struct pages corresponding to the GPU memory buffer into the userspace
VMA, mapping their physical/DMA addresses directly. The virtual address returned by mmap can then be directly
passed into standard POSIX or io_uring interfaces.
As you can see, since almost all major GPU vendors support exporting GPU memory buffers via dma-buf,
all remaining technical dependencies of fgds rely on standard Linux kernel infrastructure. Therefore,
fgds is completely vendor-agnostic and natively compatible with POSIX/io_uring without introducing any proprietary
vendor interfaces, which greatly simplifies development, deployment, operations and unifies standard usage.
Furthermore, because this technique completely eliminates the phony buffer, its performance is significantly
better than NVIDIA's GDS (as shown in our benchmarks [2]).
In addition, since fgds uses only the most fundamental dma-buf mechanisms, it relies on baseline dma-buf features
that have been supported in the upstream kernel for a long time, rather than any new dma-buf features currently
under active development. In fact, before we recently ported fgds to the latest kernel tree, it was developed
and ran on our internal 6.6 kernel. It has been running stably in our production clusters for over half a year
across various hardware platforms (including NVIDIA, AMD, and several other vendors) without requiring a single
line of GPU-platform-specific fgds code modification.
Regarding (4): We believe that implementing GDS-like functionality inherently requires kernel assistance to map
the GPU memory buffer to a valid userspace virtual address. This inevitably requires userspace-kernel interaction.
To the best of our knowledge, the mainline kernel currently lacks a dedicated, unified path for this specific interaction,
which is why various vendors ended up writing their own out-of-tree interfaces. In contrast, fgds introduces
only one single new ioctl parameter (REG_BUFFER, excluding UNREG_BUFFER), and confines its scope strictly to a
standalone device driver. We believe this achieves a minimal kernel footprint and minimal UAPI addition.
[1] https://dl.acm.org/doi/10.1145/3712285.3759862
[2] https://github.com/Storage-and-OS-for-AI/fgds
[3] https://github.com/foundation-model-stack/fastsafetensors/blob/main/docs/configuration.md
[4] https://github.com/scitix/InstantTensor/blob/main/csrc/loader_io_cufile.cpp
[5] https://github.com/LMCache/LMCache/blob/dev/lmcache/v1/storage_backend/gds_backend.py
[6] https://docs.pytorch.org/docs/2.14/generated/torch.cuda.gds.GdsFile.html
Thanks,
Li Wang> Regards,
> Christian.
>
>>
>> thanks,
>>
>> greg k-h
next prev parent reply other threads:[~2026-09-10 3:58 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 13:15 [RFC PATCH] misc: fgds: enable GPU-NVMe direct I/O via POSIX and io_uring Li Wang
2026-09-09 6:10 ` Greg Kroah-Hartman
2026-09-09 10:42 ` Li Wang
2026-09-09 13:35 ` Greg Kroah-Hartman
2026-09-09 13:45 ` Christian König
2026-09-10 3:57 ` Li Wang [this message]
2026-09-10 8:35 ` Christian König
2026-09-12 12:45 ` Pavel Begunkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9447bb67-96e9-43b3-87c8-db231051fa2d@kylinos.cn \
--to=liwang@kylinos.cn \
--cc=arnd@arndb.de \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=io-uring@vger.kernel.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=sumit.semwal@linaro.org \
--cc=zhaomengmeng@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox