From nobody Sat Sep 26 02:00:39 2026 Received: from mx0b-00364e01.pphosted.com (mx0b-00364e01.pphosted.com [148.163.139.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8A442472AF for ; Sat, 5 Sep 2026 23:30:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.139.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788651032; cv=none; b=Q+RRhl7kpl+kXVHyHOXsP7XF7kc0KyKYOp3eilSZsmM/jLd1DzQ4wuNO9rbZt/eS33RVkaWlY15Gf/U9r8tf0ecmfRPVczeUy038GpUDZ3EwhT0iCafnYZXtvd2l2GrxePLKsEdeGbU05FPTAjbb4zvhgw3MBnMV90HO49UHxjU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788651032; c=relaxed/simple; bh=9WdIrSvi2Dd9/cHdtNtBKG51gzHcNlt3FXz2tP6eqRQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=it2S5N4tgcR7eaaMWjCwmiWw58Mxj6t9P6+QtYAi+CyN9VvYOVJ/k9xntMEs7okfMOMXonRuwqX6NuYqWZYRcH8/UG9i8++GUh7V58sBDq47wExbAS4VIlDrGLR+S5Laz1Br3sNCVLfQQIYMCvTlrZf/QvSM3Rtd7D72bpbhq44= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=columbia.edu; spf=pass smtp.mailfrom=columbia.edu; dkim=pass (2048-bit key) header.d=columbia.edu header.i=@columbia.edu header.b=VX0n9pZu; dkim=pass (2048-bit key) header.d=columbia.edu header.i=@columbia.edu header.b=XQw+wjsV; arc=none smtp.client-ip=148.163.139.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=columbia.edu Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=columbia.edu Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=columbia.edu header.i=@columbia.edu header.b="VX0n9pZu"; dkim=pass (2048-bit key) header.d=columbia.edu header.i=@columbia.edu header.b="XQw+wjsV" Received: from pps.filterd (m0167075.ppops.net [127.0.0.1]) by mx0b-00364e01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 685MZ9vH1951512 for ; Sat, 5 Sep 2026 19:30:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=columbia.edu; h= cc:content-transfer-encoding:content-type:date:from:message-id :mime-version:subject:to; s=pps01; bh=B54jHdq0L65Xn0XLXmBrgVwFYd kF1OSwoP0TYJa2eCw=; b=VX0n9pZuIRIeaYeoPVxazG235pBKDYrMKPSf/gRBO4 wXB8X/KliYvWiXqIMSlYxnSh4jgqtxsDzhyuCBOcO2CA4bxv2MoPKDHGJMUQk6tD Q2io2ogKJ64nRVJY7KY7KV66GNc+a4Sv7qB2Dg7FfFjx4XJ9RQ+2cqPeL9M3jHXp obJs4Nd7fc6uKpEZw/mZMymcMZujRjr6DxAc7qdmid0A7Xe9XN8ferYKk0zSFiuV K/ZfjcMUfkOVHU+fUOdwx0j3H4b5DVSXJ93975AxzW4WsUgTi0mej/G2wevNflT+ 3QAU/Dt6Jl96wkFixR9EMQl3l6uLBEBUNFXhsvDeIuUw== Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by mx0b-00364e01.pphosted.com (PPS) with ESMTPS id 4ggf2jka5g-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 05 Sep 2026 19:30:21 -0400 (EDT) Received: by mail-qk1-f200.google.com with SMTP id af79cd13be357-9382f9430deso398213185a.1 for ; Sat, 05 Sep 2026 16:30:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=columbia.edu; s=lionmail; t=1788651021; x=1789255821; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:content-type :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=B54jHdq0L65Xn0XLXmBrgVwFYdkF1OSwoP0TYJa2eCw=; b=XQw+wjsVWGgiLwkaFbNb4HdAFASuED7lVfJpX5uiPiu46OVo0bWU/neUJvG10hh2Jf GC+GmNoH2SICtUEFSSEoJ+sqIJ3mDSV5Rglu7B31NpR3Y+PWrng42nuakJn060HXSyk9 TeAlw4+GoMv5xlBlnDWxBtc+mXInIqbeqKuQTKy0gyPGI1gnOI1BAx+EFkVolbYCEMk5 ntrIPj6Ztuyntr2hMzY2Od8Lsscw5YzpLCNDcSX1fyztN0dCJ9N31piI/Wx6tuiTiSJQ PkiK9l/oPUb7E/Ql06UqQWcheB2zz8236usF6VHfnQ0pxbQOiSy43mKt77SvHrVQu00c 3H4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788651021; x=1789255821; h=cc:to:message-id:content-transfer-encoding:content-type :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=B54jHdq0L65Xn0XLXmBrgVwFYdkF1OSwoP0TYJa2eCw=; b=kc0/oPvgR3JvszTkiwIpCT8lW1fOYHw3uiCPICtkA0SjTF9/oK+xDA8MIPXKMJDbi7 gUF4lCyJkGBqtH3Jgc3ujDYywBPFiLeQbVNToNPkmBEIamuV+CvrkA8+IgtCRhfTT0Lo /d0zfm6Avx2sKELNciAexjEICyx50xWu5ZGpQ2HQIiYThKHzk+5GUVJw06ckQDIj3uol ies5NuKW4NkYrR6rrX1VA3omjoA5Xx1NCKsLUBDY00Qwr942ybYBnt0hi002MpkwmTGn KrskVhhrF1C4NOvc3MzjyPU2af0WZrBi8yuFIdjYK/FBg0UXAJyYLPf2TszMVKYI3+RI QmtQ== X-Forwarded-Encrypted: i=1; AKwUvBwZa3NdDhxkNlmoASXIhygsA5caPiXK1NcNCLaNM+mFt+F4y4ciwjXSEbKHF5HLEA8i+dNqEARYJg39/nI=@vger.kernel.org X-Gm-Message-State: AFuF++kQzMwof/TgEZRspkqZ3pAgf6kBDGNce4h8/rv1bc3sJGrPLhSm OYI5MqRZrXaK9Pl2a7pRIsefDPDVMQO02qkufBbTeHxHnsRQpIgwW3rhV6YRnvhh4Uv4JMZoMOL ZbTL51ivpM2XLGgkrpCBm5J64JN1AeX7EEn+k7dv3SYP4boRvHS+7FJ3T/D9wNDvDkBCAneI9 X-Gm-Gg: AYBFou1s6JHZZuOghsWC7ZZLoyHJFaOqxO4mb2uMTTKH3Qlof+AeXX9GQWQepXbOLlG D2pHE/wn+O0RINUXMZH+6yESMx25t3gim+7hO0pMDBQZPBn5rya5StieqZPYv9CYOvlNIk/PBUu 0IoGlPTBTSV/iY36KyuYFzlaHYBZMxIUv4w/f1Zh2GCMQ3SZYbLSIC6pbYgMaRZ1ucvdSdXIF8V /6JlYI08gzClpGBAFLOkfgP8OzfJjm7ddlX0DThy89YDEiFrBUJslQFIqbzKUtH5sGQ6rxgKM6X 3knro1Z+ofejQ9X/wgK4WX6vyWiPxGNQOBJEeLBWfRja1lJI7/GqvEhJ/uTfkwRSiS8NGuwiJ5l 1hbjHUQrtUPrJNVzKUh+WIsXtGzpaOkcO7eREv2c6NnhCTQ== X-Received: by 2002:a05:620a:4609:b0:939:8d65:fa9b with SMTP id af79cd13be357-9398d65faa8mr934150185a.31.1788651021124; Sat, 05 Sep 2026 16:30:21 -0700 (PDT) X-Received: by 2002:a05:620a:4609:b0:939:8d65:fa9b with SMTP id af79cd13be357-9398d65faa8mr934144685a.31.1788651020480; Sat, 05 Sep 2026 16:30:20 -0700 (PDT) Received: from [127.0.1.1] (nat-128-59-179-57.net.columbia.edu. [128.59.179.57]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9397fb303b8sm559334185a.20.2026.09.05.16.30.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 05 Sep 2026 16:30:19 -0700 (PDT) From: Tal Zussman Date: Sat, 05 Sep 2026 19:30:16 -0400 Subject: [PATCH] ceph: use iov_iter_extract_bvecs() for direct I/O Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260905-b4-ceph-extract-bvecs-v1-1-b1cf2c92b671@columbia.edu> X-B4-Tracking: v=1; b=H4sIAAemnGoC/yXMQQ6CMBBG4auQWTtJIRWtVzEu6PAj4wJJpxISw t2tsvwW721kSAqjW7VRwqKm76mgPlUkYzc9wdoXU+Oa1gV35uhZMI+MNadOMscFYowgg7/UrZd wpdLOCYOu/+/9cdg+8QXJvxnt+xfKJiYbeQAAAA== X-Change-ID: 20260905-b4-ceph-extract-bvecs-e9cf47164c98 To: Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko Cc: David Howells , Christoph Hellwig , ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org, Tal Zussman X-Mailer: b4 0.17-dev-db0b7 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788651019; l=8980; i=tz2294@columbia.edu; s=20250528; h=from:subject:message-id; bh=9WdIrSvi2Dd9/cHdtNtBKG51gzHcNlt3FXz2tP6eqRQ=; b=II5bIK7NS983Upd9194ITOueXpAW59VB6rSFvaJMDvmucHL17W1ZSp4kx01n816BWULQEqXh6 ZsCVjnsEao7AbsCznApg4pDRkrq7Wj+QrJdUNmlHr7/XzIOcnEJe5+O X-Developer-Key: i=tz2294@columbia.edu; a=ed25519; pk=BIj5KdACscEOyAC0oIkeZqLB3L94fzBnDccEooxeM5Y= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA1MDI2MSBTYWx0ZWRfX5tl7zjDyGOkH eF2FlCM3J9ODwoW6e4ZYEBOWdQmAwsDw8Hk1kYQJY9Sfr62TiBrsVIw6fhpP93I3mrpEgh4DP9X FOMz1rCqhpzba4SxgSMy5PoqKHLuA3NjSbaE5bi6KEbOe5i25BV2WCss6OGrv3UPIVZsGcgk0s7 hqMv/jeDxENy5NTBRQBpZCn6H65OotI99fD2jcGOdCtxIL+GUWfc8N90eoG2OsZV+7pO+pvrY0A fSyhu5ec118LpJsABzvdMDpVkmU53kZMhM7GK69mVcRH3yq6Efz/34lqsz2F6qrJFt+SpPs7Rx3 XCWRoBcuDaOXn9o2CvWrnZtc6Mx3nagj8BAl/cgrPANTeG38Xuz3pO+0Hqf7l/zVQV/dJrCsmrh YHE9QLGZWlD1mlN0q0ZXDutYJjgkJbYEE4/1ToeKqlX/lQ3B2ot9ry+9j3TPZfB1zil2Pva8sNo tvTTOKcr6Lm6uZL5Kzg== X-Proofpoint-ORIG-GUID: P4Z2kiBIgqSPtaVq4MdDBmzqZFQBv8CB X-Proofpoint-Spam-Info: AW1haW4tMjYwOTA1MDI2MSBTYWx0ZWRfX+Jy7pQLZO9/5 TDw/3suk85uFMRDefMm+uZ1THOOeJZAC6KJ1YfX3drbiA5aBKEsAuFqAvLbwGwGL3TB7bvSbMwR Zz5Za2rl6cloPFUSv3belQmKFD0SC9m5S4JMuHIUxglj+UvCxspu X-Proofpoint-GUID: P4Z2kiBIgqSPtaVq4MdDBmzqZFQBv8CB X-Authority-Analysis: v=2.4 cv=KMdqylFo c=1 sm=1 tr=0 ts=6a9ca60d cx=c_pps a=hnmNkyzTK/kJ09Xio7VxxA==:117 a=Qh9WKzuy3vK2roC+qB/eOQ==:17 a=IkcTkHD0fZMA:10 a=VdqzKS8jKosA:10 a=x7bEGLp0ZPQA:10 a=A0y_DWxS2BwA:10 a=VkNPw1HP01LnGYTKEx00:22 a=Da8U98TiO7q1upZEImrf:22 a=HpS3TJQ9O3Ob1ozEcmik:22 a=OIAt_Amlr7pWAP3joXgA:9 a=QEXdDO2ut3YA:10 a=PEH46H7Ffwr30OY-TuGO:22 X-Proofpoint-Virus-Version: vendor=nai engine=6900 definitions=11897 signatures=596817 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=10 malwarescore=0 adultscore=0 bulkscore=10 impostorscore=10 clxscore=1015 priorityscore=1501 suspectscore=0 phishscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2609050261 ceph_direct_read_write() builds its bio_vec array with iov_iter_get_pages2(), which takes a reference on each page rather than pinning it. As the page is not pinned, fork() does not copy it early for the child and page migration is free to move it. If a process forks while a direct read is in flight and the parent then writes to the page, the parent gets a fresh copy while the read completes into the original, which now belongs to the child. The read reports success and the parent never sees the data. Switch to iov_iter_extract_bvecs(), which pins user pages with FOLL_PIN and borrows kernel pages without taking a reference. This is the same conversion the block layer did in commit a7e689dd1c06 ("block: Convert bio_iov_iter_get_pages to use iov_iter_extract_pages") and fuse did in commit 738adade96b2 ("fuse: Fix missing FOLL_PIN for direct-io"). Since iov_iter_extract_bvecs() coalesces contiguous ranges within a folio into a single bio_vec, release per folio in put_bvecs() with unpin_user_folio(). Unpinning is done based on iov_iter_extract_will_pin(). The bio_vec array no longer needs to be zeroed. put_bvecs() used to walk all npages entries and skip those with a NULL bv_page. iov_iter_extract_bvecs() counts the entries it fills, so return that count instead and don't go past it. The array is still sized by npages, as that is the worst case of one bio_vec per page. Cap npages at USHRT_MAX to match the type taken by iov_iter_extract_bvecs(). This also replaces the deprecated set_page_dirty_lock() with folio_mark_dirty_lock() and drops the on-stack page array. Tested against a Ceph 19.2.3 cluster with KASAN, lockdep and DEBUG_VM enabled. A reproducer issues an 8 MiB O_DIRECT read (libaio and blocking pread, with and without THP), forks while the read is held in flight by pausing the OSDs, has the parent write to every page of the buffer, and verifies the result. Without this change the parent loses the read data in every variant, and with it the data is intact. The AIO and direct I/O xfstests in the generic group pass as well. Signed-off-by: Tal Zussman --- fs/ceph/file.c | 81 ++++++++++++++++++++++++------------------------------= ---- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index dafaa59aea67..06023233ecb2 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -95,52 +95,32 @@ static __le32 ceph_flags_sys2wire(struct ceph_mds_clien= t *mdsc, u32 flags) * need to wait for MDS acknowledgement. */ =20 -/* - * How many pages to get in one call to iov_iter_get_pages(). This - * determines the size of the on-stack array used as a buffer. - */ -#define ITER_GET_BVECS_PAGES 64 - static ssize_t __iter_get_bvecs(struct iov_iter *iter, size_t maxsize, - struct bio_vec *bvecs) + struct bio_vec *bvecs, unsigned short max_vecs, + unsigned short *nr_vecs) { size_t size =3D 0; - int bvec_idx =3D 0; =20 if (maxsize > iov_iter_count(iter)) maxsize =3D iov_iter_count(iter); =20 + /* iov_iter_extract_bvecs() only handles one iov_iter segment per call */ while (size < maxsize) { - struct page *pages[ITER_GET_BVECS_PAGES]; ssize_t bytes; - size_t start; - int idx =3D 0; =20 - bytes =3D iov_iter_get_pages2(iter, pages, maxsize - size, - ITER_GET_BVECS_PAGES, &start); - if (bytes < 0) + bytes =3D iov_iter_extract_bvecs(iter, bvecs, maxsize - size, + nr_vecs, max_vecs, 0, 0); + if (bytes <=3D 0) return size ?: bytes; =20 size +=3D bytes; - - for ( ; bytes; idx++, bvec_idx++) { - int len =3D min_t(int, bytes, PAGE_SIZE - start); - - bvec_set_page(&bvecs[bvec_idx], pages[idx], len, start); - bytes -=3D len; - start =3D 0; - } } =20 return size; } =20 /* - * iov_iter_get_pages() only considers one iov_iter segment, no matter - * what maxsize or maxpages are given. For ITER_BVEC that is a single - * page. - * - * Attempt to get up to @maxsize bytes worth of pages from @iter. + * Attempt to extract up to @maxsize bytes worth of pages from @iter. * Return the number of bytes in the created bio_vec array, or an error. */ static ssize_t iter_get_bvecs_alloc(struct iov_iter *iter, size_t maxsize, @@ -148,22 +128,20 @@ static ssize_t iter_get_bvecs_alloc(struct iov_iter *= iter, size_t maxsize, { struct bio_vec *bv; size_t orig_count =3D iov_iter_count(iter); + unsigned short nr_vecs =3D 0; ssize_t bytes; int npages; =20 iov_iter_truncate(iter, maxsize); - npages =3D iov_iter_npages(iter, INT_MAX); + npages =3D iov_iter_npages(iter, USHRT_MAX); iov_iter_reexpand(iter, orig_count); =20 - /* - * __iter_get_bvecs() may populate only part of the array -- zero it - * out. - */ - bv =3D kvmalloc_objs(*bv, npages, GFP_KERNEL | __GFP_ZERO); + /* Worst case is one bio_vec per page */ + bv =3D kvmalloc_objs(*bv, npages, GFP_KERNEL); if (!bv) return -ENOMEM; =20 - bytes =3D __iter_get_bvecs(iter, maxsize, bv); + bytes =3D __iter_get_bvecs(iter, maxsize, bv, npages, &nr_vecs); if (bytes < 0) { /* * No pages were pinned -- just free the array. @@ -173,20 +151,24 @@ static ssize_t iter_get_bvecs_alloc(struct iov_iter *= iter, size_t maxsize, } =20 *bvecs =3D bv; - *num_bvecs =3D npages; + *num_bvecs =3D nr_vecs; return bytes; } =20 -static void put_bvecs(struct bio_vec *bvecs, int num_bvecs, bool should_di= rty) +static void put_bvecs(struct bio_vec *bvecs, int num_bvecs, bool should_di= rty, + bool pinned) { int i; =20 for (i =3D 0; i < num_bvecs; i++) { - if (bvecs[i].bv_page) { - if (should_dirty) - set_page_dirty_lock(bvecs[i].bv_page); - put_page(bvecs[i].bv_page); - } + struct folio *folio =3D bvec_folio(&bvecs[i]); + unsigned int nr_pages =3D DIV_ROUND_UP(bvecs[i].bv_offset + + bvecs[i].bv_len, PAGE_SIZE); + + if (should_dirty) + folio_mark_dirty_lock(folio); + if (pinned) + unpin_user_folio(folio, nr_pages); } kvfree(bvecs); } @@ -1325,6 +1307,7 @@ struct ceph_aio_request { size_t total_len; bool write; bool should_dirty; + bool pinned; int error; struct list_head osd_reqs; unsigned num_reqs; @@ -1469,7 +1452,7 @@ static void ceph_aio_complete_req(struct ceph_osd_req= uest *req) } =20 put_bvecs(osd_data->bvec_pos.bvecs, osd_data->num_bvecs, - aio_req->should_dirty); + aio_req->should_dirty, aio_req->pinned); ceph_osdc_put_request(req); =20 if (rc < 0) @@ -1560,14 +1543,15 @@ ceph_direct_read_write(struct kiocb *iocb, struct i= ov_iter *iter, struct ceph_osd_request *req; struct bio_vec *bvecs; struct ceph_aio_request *aio_req =3D NULL; - int num_pages =3D 0; + int num_bvecs =3D 0; int flags; int ret =3D 0; struct timespec64 mtime =3D current_time(inode); size_t count =3D iov_iter_count(iter); loff_t pos =3D iocb->ki_pos; bool write =3D iov_iter_rw(iter) =3D=3D WRITE; - bool should_dirty =3D !write && user_backed_iter(iter); + bool pinned =3D iov_iter_extract_will_pin(iter); + bool should_dirty =3D !write && pinned; bool sparse =3D ceph_test_mount_opt(fsc, SPARSEREAD); =20 if (write && ceph_in_snap(file_inode(file))) @@ -1630,7 +1614,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov= _iter *iter, } } =20 - len =3D iter_get_bvecs_alloc(iter, size, &bvecs, &num_pages); + len =3D iter_get_bvecs_alloc(iter, size, &bvecs, &num_bvecs); if (len < 0) { ceph_osdc_put_request(req); ret =3D len; @@ -1639,7 +1623,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov= _iter *iter, if (len !=3D size) osd_req_op_extent_update(req, 0, len); =20 - osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len); + osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_bvecs, len); =20 /* * To simplify error handling, allow AIO when IO within i_size @@ -1652,6 +1636,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov= _iter *iter, aio_req->iocb =3D iocb; aio_req->write =3D write; aio_req->should_dirty =3D should_dirty; + aio_req->pinned =3D pinned; INIT_LIST_HEAD(&aio_req->osd_reqs); if (write) { aio_req->mtime =3D mtime; @@ -1719,7 +1704,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov= _iter *iter, int zlen =3D min_t(size_t, len - ret, size - pos - ret); =20 - iov_iter_bvec(&i, ITER_DEST, bvecs, num_pages, len); + iov_iter_bvec(&i, ITER_DEST, bvecs, num_bvecs, len); iov_iter_advance(&i, ret); iov_iter_zero(zlen, &i); ret +=3D zlen; @@ -1728,7 +1713,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov= _iter *iter, len =3D ret; } =20 - put_bvecs(bvecs, num_pages, should_dirty); + put_bvecs(bvecs, num_bvecs, should_dirty, pinned); ceph_osdc_put_request(req); if (ret < 0) break; --- base-commit: 190736464f4572bfb360fd3747fb827493e02e09 change-id: 20260905-b4-ceph-extract-bvecs-e9cf47164c98 Best regards, -- =20 Tal Zussman