From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AC7840DB31 for ; Mon, 17 Aug 2026 11:56:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.176 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786967779; cv=none; b=FQ5GKG4bnKtMY0xX7v/LaR8apumt+ww4Cx+CZObrwHNnzsyufU64Q3JrqEXKldqwa24KVCfelTyKH6YePo1xS680Pg4gsnBkCQwW4yvJBicv4kviHXH8YD7Tetx3dNfIKlglfbQR7FYodqJt+c618MdvZnG1Ih0g4OWwaVSV5tU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786967779; c=relaxed/simple; bh=dTf0Tz0X4VVHgkG9msuKEzTghe8BHrC1N9I4A1dE7dg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SU8N+XMIsX4JtgzhPBFzCLdayO73zRAPKxLCoCHs/6klBLnZ7imgyl0o9FHvekykA+eOCDYOWrPzSJVqERf9F1+OBgqVFg2DIjkyyx8yq1Ur9PufMLieMYFK3EZvmVF0cdE9Z329Q2Nc7yDN39poN6pxOJ9fKeTq6/eQYN2XHVw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WfFCXAta; arc=none smtp.client-ip=209.85.210.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WfFCXAta" Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-84faf0fa17eso3255434b3a.2 for ; Mon, 17 Aug 2026 04:56:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786967777; x=1787572577; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=yavRK7ZC/YlJzzUQXee9HV5ifkhoLGmP6A7lwIfErD0=; b=WfFCXAtaLRZoLbPTDmhhyMvwIHX31JNzTevjuRuQ9yqHs61X3SVhbXv4IWNIk8WuxX 3SFWHibaSPEJ8Aywc2VA8eSzHwyvlbdnpVUf40dEpdixqEgKUisJDlJOXGSnBafibsrD dzSiWG2qnmLvQCeGNkEMoIrzWpdza/CVLsa8cF/xq4xGZmDpOq8Gej3vCpncEjzV/hYs qrxULH/spZM9oQ4TuwgZQ0pX6VS27yBB7gD09YHoSQCRrPHO191+Sqd1hP7Jzd5NlhZA ARNn2NVOhXzBFddgqJTsitkQWh0pAUZhWnbRAnDW3la+ip6H523uxRpM1JaJ2mo2sG7u xljw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786967777; x=1787572577; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=yavRK7ZC/YlJzzUQXee9HV5ifkhoLGmP6A7lwIfErD0=; b=ItvoU+oLPZ0KrDS3PbLw/2j2cmR9PU8+T7yXshXEf7D8bLPYvVMnmtSSxZswMJv3It VbB4jl4Fb5/oqQSoo1ekXjhM6nTDf5qAh0wH4DoQ5joZVaJxGzK9FCFKfm8FX+aoWAsZ CqDgTqmb86Vtl/XOxiPW147lYmxMsSHM1H9RsJBAZd2VWCQLdn+EfF/7ndHrtI9QOAOt PJ5AyXl3wtbEjR6wpDI7mIg15g2aO05Zb9jmdQlD9hXoIBgymwfJY1ADuOr11Kwhs2H0 wOh9numPu2WH8bOsFpBerACiK/pM4EAQIuc6a6yqdEARYGpnxuih6nyn5wnzmWgOWIhX enDw== X-Forwarded-Encrypted: i=1; AHgh+RpdlR2UqUyu+XP4KXivsz0RRCc9+qRZA5XhzadND7pQ9OqHF+lANlFEMQwwOrF+5UkJKhgMzW4RY+MCDTM=@vger.kernel.org X-Gm-Message-State: AOJu0YzEv2DNo5nQl4d7NYAtxnV9xaggktPfJZrBv4+BIbOf3HinqEtQ rCceYL8vX2uQBwYtV9+uG5Grb0XdnsJH5/1ontcpAAk+Wp1Pb4dk2iyF X-Gm-Gg: AR+sD10uZoN2jUObSdJ27KEPNhaxogAKTfAytBJJg7IUMQUUJ8GQ88p7YvJgKyn0S0/ U+6uoG+qXEqUwsN1JYoMGIzY6WSao72vQc5lEKyiiCkDRH+CJlR/fIueBudVKqWgImqvJQMQ4kY 4LJuzQPDBqgmNTSuuhCTdAW9BafNKoOwZxWJL8ISPmVTbyZs+4KHVy7WbXbdllm6FCzwB35buG8 kjxWVsRkf/GS5x0GNXT4KaxwZNxtdDPfsjg3IW+ikuvU8NjOdqgAjSvYFEsZzQM1pKRS+M/R/cD 9AxBo6ZY/3VBX8WiEAKne/uwy54SJT4OIv6Y5QV8W4GZgvJX2F3gN5+BPlzj+bERq47S1P04pDp lmiCEOPQI3vZvK9wo4EgGME2ffblLwXQ5V/bghceVEUEdr5+nzSNIiYbTrKGkEGJedOrz4R08rV KJi1PNjXZzBhi4gZeMoKiqNwVwvIjbOGn1M9iVxsNaEwQ/kzq8qQo44AEi033StP9r2dToSRSOA dUCnUTqnxCX+osqY/r+xDIwmMVld6qBYHPARAa8VjphulnuJTsX42HGJXdzIHnP2+aEUrbIhUKU jmN72jnXdwTPy/Ed6juHQMM6K0G4WqMJ3royUXH+RFzcRYEdpZ4R X-Received: by 2002:a05:6a00:f8b:b0:84a:2e5f:d69c with SMTP id d2e1a72fcca58-84fde396e23mr26704239b3a.32.1786967776615; Mon, 17 Aug 2026 04:56:16 -0700 (PDT) Received: from spider.bream-herring.ts.net ([103.252.203.158]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-851b6f8cdd1sm161099b3a.36.2026.08.17.04.56.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Aug 2026 04:56:16 -0700 (PDT) From: Matthias Goergens To: linux-fsdevel@vger.kernel.org Cc: viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, linux-kernel@vger.kernel.org, ansgar.loesser@kom.tu-darmstadt.de, djwong@kernel.org, david@fromorbit.com, amir73il@gmail.com Subject: [PATCH v3] vfs: add FILE_DEDUPE_RANGE_REPORT_PROGRESS flag to FIDEDUPERANGE Date: Mon, 17 Aug 2026 19:56:09 +0800 Message-ID: <20260817115609.3586664-2-matthias.goergens@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260817115609.3586664-1-matthias.goergens@gmail.com> References: <20260814082326.3756669-1-matthias.goergens@gmail.com> <20260817115609.3586664-1-matthias.goergens@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit On success FIDEDUPERANGE reports the requested length in bytes_deduped even when the filesystem shortens a destination range and deduplicates fewer bytes. This predates the VFS hoisting of the ioctl (the btrfs ioctl behaved the same way), and changing the default would change an ABI that deployed consumers such as duperemove depend on: they advance their offsets by bytes_deduped and expect the historical semantics. Add a flag to opt into the truthful behaviour. With FILE_DEDUPE_RANGE_REPORT_PROGRESS set, bytes_deduped in each destination's info is an advance hint for the next call on that destination: - if status is an error, bytes_deduped is 0; - if status is FILE_DEDUPE_RANGE_DIFFERS, bytes_deduped is a safe advance step: one filesystem block, capped to the requested length so a sub-block request ending at EOF cannot be advanced past its end, and falling back to the requested length when the top-level inode reports a degenerate block size (stacked filesystems); - if status is FILE_DEDUPE_RANGE_SAME, bytes_deduped is the number of bytes actually deduplicated; - in both success cases a zero value means no further work is possible. Unknown flag bits are rejected. The flags field shares an anonymous union with the old reserved2 name, so existing source keeps compiling and the binary layout is unchanged; old kernels require the field to be zero, so new callers setting the flag on old kernels get -EINVAL rather than silently the old semantics. Suggested-by: Darrick J. Wong Link: https://lore.kernel.org/linux-fsdevel/20260805071414.3414870-1-matthias.goergens@gmail.com/ Signed-off-by: Matthias Goergens --- fs/remap_range.c | 25 +++++++++++++++++++++---- include/uapi/linux/fs.h | 5 ++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/fs/remap_range.c b/fs/remap_range.c index 26afbbbfb10c2..ac88a81c12739 100644 --- a/fs/remap_range.c +++ b/fs/remap_range.c @@ -503,7 +503,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (same->reserved1 || same->reserved2) + if (same->reserved1 || (same->flags & ~FILE_DEDUPE_RANGE_REPORT_PROGRESS)) return -EINVAL; off = same->src_offset; @@ -551,12 +551,29 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) deduped = vfs_dedupe_file_range_one(file, off, fd_file(dst_fd), info->dest_offset, len, REMAP_FILE_CAN_SHORTEN); - if (deduped == -EBADE) + if (deduped == -EBADE) { info->status = FILE_DEDUPE_RANGE_DIFFERS; - else if (deduped < 0) + if (same->flags & FILE_DEDUPE_RANGE_REPORT_PROGRESS) { + u64 step = i_blocksize(src); + + /* + * Stacked filesystems (e.g. overlayfs) can + * report a degenerate block size here; a + * one-byte step would only misalign the + * next call, so advance past the whole + * request instead. + */ + if (step <= 1) + step = len; + info->bytes_deduped = min_t(u64, step, len); + } + } else if (deduped < 0) { info->status = deduped; - else + } else if (same->flags & FILE_DEDUPE_RANGE_REPORT_PROGRESS) { + info->bytes_deduped = deduped; + } else { info->bytes_deduped = len; + } next_loop: if (fatal_signal_pending(current)) diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index bd87262f2e349..471f698beaa93 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -178,13 +178,16 @@ struct file_dedupe_range_info { __u32 reserved; /* must be zero */ }; +/* flags for struct file_dedupe_range */ +#define FILE_DEDUPE_RANGE_REPORT_PROGRESS (1U << 0) + /* from struct btrfs_ioctl_file_extent_same_args */ struct file_dedupe_range { __u64 src_offset; /* in - start of extent in source */ __u64 src_length; /* in - length of extent */ __u16 dest_count; /* in - total elements in info array */ __u16 reserved1; /* must be zero */ - __u32 reserved2; /* must be zero */ + __u32 flags; /* in - FILE_DEDUPE_RANGE_* flags */ struct file_dedupe_range_info info[]; }; -- 2.55.0