From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794067744; b=HKnsR+iHgjn6MyWkwnWrJw6GrvkpFYp0V0TQe6NH3K/Bwx2+ewGoWzd2B4xcVXVGPGkM Zf3NuX6O7cTS+LrZ2E3cCIXOUqvHd0Q7MhsAZwVHfhY/xj3dR3NoFp1eKURlCuiIfQSxC 8eQhA6SPsyz8It2j4521k+rH1KmkyaWRP5TX70B6sJtJY3AWB96zkjyenTH+1RXtJ8wRa qoDe0ypy9l2vJCplljFspaAx38iT6iy6kxSO1CwJfu3z6dHRgPaiNmwJVgTQg5+VWY3eE outJamqqREi42elJp1+hGFJ87ddpw/NX2ToAfazt2VBgL2IG/GQpz0N71gtQkWVFRUw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794067744; h=DMARC-Filter:DKIM-Signature:Received:X-MC-Unique: X-Mimecast-MFC-AGG-ID:Received:Received:From:To:Cc:Subject:Date: Message-ID:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding:X-Scanned-By; bh=3Z8e3fK+ZhnEddkCEH910/bt5KAlOlYUbvMeZTifJLE=; b=SY6QsFKxrPN2u/IadS52NpBqM8yCnuGECha7i00IcjU62HrD4SD5CrnXwkpLu9OCZitt W6q1OmoMMshF8u0w3PCGtkMu5LjEYNJF0TT55FqkWZZVva3ZI/45vIQsLHIB5cGl01e/r /iH2Z53lrbMi21/EPRCZYUvDdaVdOqjrGWHMT95xUiQxImtipafBoNNFqw2fZTARQ3n35 +JEVzonA8NcCXGR0OTpzHcKWd2zREikHyj+XI24lVczfKFZwX/cz42VfRf/nhPTpuYli9 fhoEAR0rL68HLKEa/zbinVuR9AsEx8YYM10DxSiK1DNT8k1tdGJxhC8on93aRJzGJKQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ZBwXVEAT; arc=none smtp.remote-ip=170.10.129.124 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72872606D815 for ; Sat, 7 Nov 2026 16:09:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 72872606D815 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ZBwXVEAT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1794067742; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3Z8e3fK+ZhnEddkCEH910/bt5KAlOlYUbvMeZTifJLE=; b=ZBwXVEATEY/Dcao35X3y9okcqzGq7LKG/IxYT61Slx0X3M8Gv2hZPA0yXf5axgl63XYvyM /3wk/XV6MRP4/vs5KROq9AO717QlAaOiDng4gCGOimT5qgYkqkvTFcWDBQduq8bTl0Xwf8 5ddCnt3bb97KS3CqbVcBKafE5iJH2JQ= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-81-tUhOuirvN5y4TCXrMzcEbw-1; Sat, 07 Nov 2026 11:08:59 -0500 X-MC-Unique: tUhOuirvN5y4TCXrMzcEbw-1 X-Mimecast-MFC-AGG-ID: tUhOuirvN5y4TCXrMzcEbw_1794067736 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3AB4219560AF; Sat, 7 Nov 2026 16:08:56 +0000 (UTC) Received: from dhowells-thinkpadp1gen8.rmtgb.csb (headnet04.pony-001.prod.iad2.dc.redhat.com [10.2.32.116]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 54CE439203; Sat, 7 Nov 2026 16:08:51 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , Matthew Wilcox , Namjae Jeon , Marc Dionne , Stefan Metzmacher , Eric Van Hensbergen , Dominique Martinet , Ilya Dryomov , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Jens Axboe , Christoph Hellwig , linux-block@vger.kernel.org Subject: [PATCH v16 04/15] iov_iter: Add an API document for the bvecq structure Date: Sat, 7 Nov 2026 16:08:07 +0000 Message-ID: <20261107160823.1465553-5-dhowells@redhat.com> In-Reply-To: <20261107160823.1465553-1-dhowells@redhat.com> References: <20261107160823.1465553-1-dhowells@redhat.com> X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Add an API description document for the bvecq structure. Signed-off-by: David Howells cc: Paulo Alcantara (Red Hat) cc: Matthew Wilcox cc: Jens Axboe cc: Christoph Hellwig cc: linux-block@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- Documentation/core-api/bvecq.rst | 229 +++++++++++++++++++++++++++++++ Documentation/core-api/index.rst | 1 + MAINTAINERS | 1 + fs/netfs/bvecq.c | 2 + include/linux/bvecq.h | 2 + 5 files changed, 235 insertions(+) create mode 100644 Documentation/core-api/bvecq.rst diff --git a/Documentation/core-api/bvecq.rst b/Documentation/core-api/bvecq.rst new file mode 100644 index 000000000000..4a2b3e288982 --- /dev/null +++ b/Documentation/core-api/bvecq.rst @@ -0,0 +1,229 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= +bvecq - Chainable bio_vec queue structure +========================================= + +Author: David Howells + +.. Contents: + + * Overview + * Allocating bvecqs + * Refcounting + * Expandable buffer + * Producer functions + * Consumer functions + * Utility functions + * I/O iterators + * API Function Reference + + +Overview +======== + +The ``bvecq`` struct can be used to form chains of arrays of ``bio_vec`` +structures - kind of a single layer of indirection. Each bvecq segment points +to the previous and next bvecq segments in the chain, but is not intended to +form a circular queue as there are applications where the producer is adding to +one end whilst the consumer is taking off the other. + +To use this, the caller should do:: + + #include + +The publicly accessible members of the structure are:: + + struct bvecq { + struct bvecq *next; + struct bvecq *prev; + u32 priv; + u16 nr_slots; + u16 max_slots; + enum bvecq_mem mem_type:3; + struct bio_vec *bv; + ... + }; + +A pair of pointers are provided, ``next`` and ``prev``, that point to the +segments on either side of the segment being accessed. Whilst this is a +doubly-linked list, it is intentionally not a circular list; the outward +sibling pointers in terminal segments should be NULL. + +The ``priv`` member is for the owner of the bvecq to use as they will. + +The ``bv`` pointer points at an array of bio_vecs that list a number of regions +of memory. ``max_slots`` indicates how large the array is and ``nr_slots`` +says how much of the array is being used. Note that there are access functions +for nr_slots that insert appropriate barriering in the case that there are +separate producer and consumer threads. + +The ``mem_type`` member informs bvecq_put() of how to clean up the bio_vecs +attached to this segment. It can be one of: + + * ``BVECQ_MEM_EXTERNAL`` - Externally managed; no cleanup. + * ``BVECQ_MEM_PAGECACHE`` - Part of pagecache; put_page() used. + * ``BVECQ_MEM_GUP`` - Pinned userspace memory; unpin_user_page() used. + * ``BVECQ_MEM_ALLOCED`` - Allocated page; __free_pages() used, may be pooled. + + +Allocating bvecqs +================= + +A number of functions are provided to allocate bvecqs:: + + struct bvecq *bvecq_alloc_one(size_t nr_slots, + gfp_t gfp, + bool for_writeback); + struct bvecq *bvecq_alloc_chain(size_t nr_slots, + gfp_t gfp, + bool for_writeback); + struct bvecq *bvecq_alloc_buffer(size_t size, + gfp_t gfp, + bool for_writeback); + struct bvecq *bvecq_alloc_buffer2(size_t size, + unsigned int pre_slots, + gfp_t gfp, + bool for_writeback); + +The first of these, ``bvecq_alloc_one()`` allocates a single bvecq with at +least the requested number of inline slots. The size of the object is rounded +up to the size of the slab granule that it will be allocated in and the number +of slots increased appropriately to match. If ``for_writeback`` is set, then +the netfslib writeback bvecq pool will be used to backstop the allocation if +the initial slab request fails; in such a case, the number of slots will get +reduced to ``BVECQ_POOL_SLOTS``. + +Two convenience slot count constants are provided: + + * ``BVECQ_POOL_SLOTS`` - The right number of slots to alloc from the mempool + * ``BVECQ_4KB_SLOTS`` - The right number of slots to get a 4K allocation + +``bvecq_alloc_chain()`` will allocate a sufficiently large chain of bvecqs to +hold the requested number of slots, capping each allocation at 4K. + +``bvecq_alloc_buffer()`` will allocate a chain and populate it, allocating +sufficient pages to provide a buffer of the specified size attached to the +chain. ``bvecq_alloc_buffer2()`` is similar, but it reserves some unused +slots at the front of the chain. Note that these functions may add multipage +pages in the future. + + +Refcounting +=========== + +Each bvecq has a refcount and two functions are provided to handle that:: + + struct bvecq *bvecq_get(struct bvecq *bq); + void bvecq_put(struct bvecq *bq); + +The first of these gets a new reference and the second drops a reference. When +the refcount hits zero, the second iteratively drops the refs along the chain +until it hits a segment that has a refcount that doesn't reduce to zero. + + +Expandable buffer +================= + +This facility provides a function to manage an expandable buffer:: + + int bvecq_expand_buffer(struct bvecq **_buffer, + size_t *_cur_size, + size_t size, + gfp_t gfp); + +Pages are added to the bvecq chain and the chain expanded such that, on +returning, it holds ``size`` amount of space (without losing any content). The +caller needs to retain ``*_cur_size`` between calls as that tracks the amount +of space currently allocated. Note that pages in the chain may be allocated as +compound pages larger than PAGE_SIZE. + + +Producer functions +================== + +When building and filling a bvecq, there are a number of utility functions that +can be used to provide the correct barriering and to query the fields in the +bvecq currently being filled. + +Firstly, there's a function to check to see if a bvecq has any spare slots +left:: + + bool bvecq_is_full(const struct bvecq *bvecq); + +If not, ``bvecq_alloc_one()`` can be called to allocate a new segment which can +be initialised and then added to the chain with:: + + void bvecq_append(struct bvecq *to, struct bvecq *add); + +bio_vec slots in the segment can then be filled and the number of occupied +slots updated by calling:: + + void bvecq_filled_to(struct bvecq *bvecq, + unsigned int to); + +to insert the appropriate barrier. + + +Consumer functions +================== + +When consuming and destroying a bvecq, there are some utility functions for +that too, providing the needed barriering. Firstly, there's a function to find +out how many slots have been used in the current bvecq:: + + unsigned int bvecq_nr_slots_acquire(const struct bvecq *bvecq); + +Or, more conveniently, if the current slot position is valid within the bvecq:: + + bool bvecq_acquire_slot(const struct bvecq *bvecq, + unsigned int slot); + +If this returns true, the slot is valid and can be looked at; if it returns +false, the bvecq may have been consumed. If it has, the next bvecq can be +obtained by calling:: + + struct bvecq *bvecq_next(const struct bvecq *bq); + +which inserts the appropriate barrier - though bvecq_acquire_slot should be +rechecked after calling this in case the producer added more slots and then +extended the list. + + +Utility functions +================= + +A utility function is provided to list the bio_vecs pointed to by a bvecq +chain:: + + void bvecq_dump(const struct bvecq *bq); + + +I/O iterators +============= + +bvecq chains can be used with the ``iov_iter`` facility too. An iterator can +be initialised to point at a chain by calling:: + + void iov_iter_bvec_queue(struct iov_iter *i, + unsigned int direction, + const struct bvecq *bvecq, + unsigned int first_slot, + unsigned int offset, + size_t count); + +In addition to setting the iterator, direction and count, the first bvecq in +the chain to be iterated over is set, along with the starting slot in that +iterator and the offset into the slot. Once the iterator is set up, it can be +treated like any other I/O iterator. + +In a producer/consumer environment, it is expected that when an iterator is set +up, all the bvecqs and all the slots within the count of the iterator must +exist and must be populated before this function is called. + + +API Function Reference +====================== + +.. kernel-doc:: include/linux/bvecq.h +.. kernel-doc:: fs/netfs/bvecq.c diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index 92f91c6a0d79..e39edef58ab6 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -39,6 +39,7 @@ Library functionality that is used throughout the kernel. kref cleanup assoc_array + bvecq folio_queue xarray maple_tree diff --git a/MAINTAINERS b/MAINTAINERS index 6fa777744163..9cb3785a5bd2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10382,6 +10382,7 @@ M: Paulo Alcantara L: netfs@lists.linux.dev L: linux-fsdevel@vger.kernel.org S: Supported +F: Documentation/core-api/bvecq.rst F: Documentation/filesystems/caching/ F: Documentation/filesystems/netfs_library.rst F: fs/netfs/ diff --git a/fs/netfs/bvecq.c b/fs/netfs/bvecq.c index 06adb44ea93f..91264337805c 100644 --- a/fs/netfs/bvecq.c +++ b/fs/netfs/bvecq.c @@ -3,6 +3,8 @@ * * Copyright (C) 2026 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) + * + * See also Documentation/core-api/bvecq.rst */ #include diff --git a/include/linux/bvecq.h b/include/linux/bvecq.h index d9d3dd487a27..90e6eb9588bf 100644 --- a/include/linux/bvecq.h +++ b/include/linux/bvecq.h @@ -3,6 +3,8 @@ * * Copyright (C) 2026 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) + * + * See also Documentation/core-api/bvecq.rst */ #ifndef _LINUX_BVECQ_H