STRUCT DMA_BUF(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… NAME πŸ’…

struct dma_buf β€” the shared buffer object, bestie. It's the kernel API manual page, and we're gonna get you so comfy with this struct.

Okay so before we dive in: this whole thing is one giant C struct that represents a buffer lots of different devices can share. Think of it as the group chat of memory β€” everyone's in it, everyone can see the messages, and there are rules about who gets to type when. 🫢


✨ SYNOPSIS ✨

Here's the whole struct, laid out exactly how it lives in the kernel. No cap, this is the real shape:

struct dma_buf {
    size_t size;
    struct file *file;
    struct list_head attachments;
    const struct dma_buf_ops *ops;
    unsigned vmapping_counter;
    struct iosys_map vmap_ptr;
    const char *exp_name;
    const char *name;
    spinlock_t name_lock;
    struct module *owner;
    struct list_head list_node;
    void *priv;
    struct dma_resv *resv;
    wait_queue_head_t poll;
    struct dma_buf_poll_cb_t {
      struct dma_fence_cb cb;
      wait_queue_head_t *poll;
      __poll_t active;
    } cb_in, cb_out;
 };

πŸŽ€ Members πŸŽ€

Time for a member-by-member vibe check. Every single one, in order, because we don't skip. πŸ’–

  • size β€” how big the buffer is. It's an invariant over the lifetime of the buffer, meaning it does not change, periodt. Set it and forget it.
  • file β€” the file pointer, used for sharing buffers across, and for refcounting. Peep dma_buf_get and dma_buf_put for the whole refcount situation.
  • attachments β€” a list of dma_buf_attachment that denotes all the devices attached, and it's protected by the dma_resv lock resv. Like a guest list, and resv is the bouncer.
  • ops β€” the dma_buf_ops associated with this buffer object. The behavior package, iykyk.
  • vmapping_counter β€” used internally to refcnt the vmaps returned by dma_buf_vmap. Protected by resv. Internal business only, don't touch. πŸ™ˆ
  • vmap_ptr β€” the current vmap ptr if vmapping_counter > 0. Protected by resv.
  • exp_name β€” name of the exporter. Useful for debugging. And it must not be NULL. Like, at all. 🚨
  • name β€” the userspace-provided name. Default value is NULL. If it's not NULL, the length cannot be longer than DMA_BUF_NAME_LEN, including the NIL char. Useful for accounting and debugging. Read/Write accesses are protected by name_lock.

See the IOCTLs DMA_BUF_SET_NAME or DMA_BUF_SET_NAME_A/B.

  • name_lock β€” spinlock to protect name access for read access.
  • owner β€” pointer to the exporter module; used for refcounting when the exporter is a kernel module.
  • list_node β€” node for dma_buf accounting and debugging.
  • priv β€” exporter specific private data for this buffer object. Exporter's own little diary. πŸ“
  • resv β€” the reservation object linked to this dma-buf.

πŸ”₯ IMPLICIT SYNCHRONIZATION RULES: πŸ”₯

Drivers which support implicit synchronization of buffer access as e.g. exposed in Implicit Fence Poll Support_ must follow the below rules. No exceptions, bestie, this is the whole assignment:

  • Drivers must add a read fence through dma_resv_add_fence with the DMA_RESV_USAGE_READ flag for anything the userspace API considers a read access. This highly depends upon the API and window system.
  • Similarly, drivers must add a write fence through dma_resv_add_fence with the DMA_RESV_USAGE_WRITE flag for anything the userspace API considers write access.
  • Drivers may just always add a write fence, since that only causes unnecessary synchronization, but no correctness issues. Slightly extra, but valid. πŸ’…
  • Some drivers only expose a synchronous userspace API with no pipelining across drivers. These do not set any fences for their access. An example here is v4l.
  • Driver should use dma_resv_usage_rw when retrieving fences as dependency for implicit synchronization.

πŸ¦‹ DYNAMIC IMPORTER RULES: πŸ¦‹

Dynamic importers β€” see dma_buf_attachment_is_dynamic β€” have additional constraints on how they set up fences:

  • Dynamic importers must obey the write fences and wait for them to signal before allowing access to the buffer's underlying storage through the device.
  • Dynamic importers should set fences for any access that they can't disable immediately from their dma_buf_attach_ops.invalidate_mappings callback.

πŸ‘‘ IMPORTANT: πŸ‘‘

All drivers and memory management related functions must obey the struct dma_resv rules β€” specifically the rules for updating and obeying fences. See enum dma_resv_usage for further descriptions. This is not a suggestion, this is the law. 😭

And now, back to the members. We didn't forget about these three, they were just chillin' down here:

  • poll β€” for userspace poll support.
  • cb_in β€” for userspace poll support.
  • cb_out β€” for userspace poll support.

🌸 Description 🌸

This represents a shared buffer, created by calling dma_buf_export. The userspace representation is a normal file descriptor, and you create that by calling dma_buf_fd. So the fancy kernel object has a totally normal everyday fd face for userspace. Main character energy with a relatable disguise. ✨

Shared dma buffers are reference counted using dma_buf_put and get_dma_buf. Keep those counts honest, or things get weird.

Device DMA access is handled by the separate struct dma_buf_attachment β€” not by this struct itself, okay? Different struct, different job. 🌈


🧚 SEE ALSO 🧚

Kernel file ./include/linux/dma-buf.h, plus the whole friend group:


πŸ’œ And that's the page, bestie! This one lives over in ./include/linux, and the version stamp on it says October 2026, with the footer reading struct dma_buf(9). Go forth and share those buffers responsibly. Slay. πŸŽ€

πŸ“¦ where this page comes from