Re: [PATCH v1] tty: n_tty: use kvzalloc/kvfree for line discipline data

Xin Chen <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.serial
Message-ID <[email protected]>
On Mon, Aug 18, 2026, Greg KH wrote:
 > What specific "damage"?

The specific damage is that hci_send_cmd_sync() calls
skb_clone(hdev->sent_cmd, GFP_KERNEL) to set hdev->req_skb. If
that clone fails, hdev->req_skb stays NULL.  When the firmware reply
arrives, hci_req_cmd_complete() checks hdev->req_skb to find the
registered completion callback; finding NULL, it never calls
hci_cmd_sync_complete(), req_status stays HCI_REQ_PEND, and the
waiter in __hci_cmd_sync_sk() times out with -ETIMEDOUT.  The command
was sent and the firmware replied successfully — the damage is purely
that the completion path is broken.

 > But it's not consuming them "unnecessarily" as the memory is needed.
 > Why not fix the root problem here of having this be called so many
 > times that you are running out of memory?

The repeated calls are a normal consequence of the serdev open/close
retry logic in the BT transport layer; constraining that would require
changes in a different subsystem and would not address the underlying
fragility.  The real question is why skb_clone(GFP_KERNEL) fails at
all when the system is not truly OOM.

 > And why isn't memory being reclaimed properly if we do not have any
 > left in that free list?  The allocation can sleep, so it should be
 > always succeeding if the system isn't truly out of memory, as you
 > imply it is not.

This is the crux of the issue.  vzalloc() allocates order-0 pages
through vm_area_alloc_pages(), which takes the bulk allocation path
(alloc_pages_bulk_noprof) for order-0.  The bulk allocator uses
ALLOC_WMARK_LOW and does not perform direct reclaim — it is
intentionally a fast, non-sleeping path.  When the low watermark check
fails it falls through to goto failed, and vm_area_alloc_pages()
falls back to single-page alloc_pages() calls which can reclaim.
So vzalloc() itself can succeed even under pressure, but only after
consuming whatever order-0 pages were available via the bulk path first.

The problem is that skb_clone(GFP_KERNEL) in hci_send_cmd_sync()
is a single kmalloc-backed allocation.  It does not retry on failure
and has no reclaim loop of its own; if the zone is below the low
watermark at the moment it runs, it fails and returns NULL.  The window
is narrow but real: the bulk path in vzalloc() drains the PCP/buddy
order-0 lists below the low watermark; skb_clone() runs before
kswapd has had a chance to refill them; it fails silently.

Switching to kvzalloc_obj() serves the ~10 KB n_tty_data from the
kmalloc-16384 slab (an order-2 compound page), which does not touch
the order-0 free list at all, eliminating the pressure window entirely.

Thanks,
Xin Chen
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.