From nobody Tue Jun 16 01:37:39 2026 Received: from mail-pj1-f45.google.com (mail-pj1-f45.google.com [209.85.216.45]) (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 4CF6534028D for ; Fri, 17 Apr 2026 03:51:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776397893; cv=none; b=kG+vb1fGONczvUlsdLwFjPWdm79hM8K7FwzLB3XlbddtZbjBOthGEcKQE11Rk1zdJHealUY9fTZ86FjUL77emyumgijq+mAqaj9FsU23nxhyMjs+2LwhgqCizPLPxBf8QjZBs0cLzC7A79JJ3+E9M/04ptjuQaf53LSN2VD0MYw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776397893; c=relaxed/simple; bh=PvYxjNz7FrD3i9sCUWfMMynK4IBMO9q2uwZudK3DFpo=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=YQhgjO0Oc6M2S+k6ECJz95jkUGojC0Vc5phmVbI1INa475ZjkSjxh59L59S/Ar0fc5F1AYdarbY4l+Fklv3FHkDRvqzloVugJgEw1cpwmsJXCvR6ofy78SYmCUEy++LOP8K6wPYpP14pyCztyOTWJ8nrKb/E71CBbR8u71/A4kM= 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=buHRPXVh; arc=none smtp.client-ip=209.85.216.45 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="buHRPXVh" Received: by mail-pj1-f45.google.com with SMTP id 98e67ed59e1d1-35fc0d7c310so175507a91.1 for ; Thu, 16 Apr 2026 20:51:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776397892; x=1777002692; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=uiMoYM6dbl34o9SsLqCiISFnk0Jr//K7m705ROB9B8w=; b=buHRPXVhQ0WiDmE/CPryqswoRA1e7u0nET9ZbOo5d6e1KZisjw9P46bKUtw2rLdvXV sKZ8+h/fuhaVmkt/Gk9zPBQMyhmZ3B4Y4ATuoDdkXbzsWKLHiqT1ljxgp3CuwZXn2Qov +90v/YlqMjxKzgr4iXlyHSKryDX3kIDz/pQQvXbYoJDTnoqnHXABo66u8lJDWus4tuVB +rCh4WBUfxYh9C5Yz0S7xrrriFMy595TofpxyN8Xyv3USm8XuFBUfHp7BDFVRukRxoAN I65063iAhNh8xjqE/we+BkjG1j4p1zcV4KcfzrpDzdz73CenPgFZzBYpmVE9ilLkgjM2 QxsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776397892; x=1777002692; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=uiMoYM6dbl34o9SsLqCiISFnk0Jr//K7m705ROB9B8w=; b=s7qupt9Qq04CLmDD/boYfFt35yCh/yZinnyRmd3xj8n2WOvKnP0RPHl0dBehkIAO3T z1LlHc9kpBjf9PAYKDH7/YlAAg0L2/QdnflaNbtxVw6V8lODU8SyFL861NJh/Kekj4ZU 62MHoQJeMDlurvYVkSZupi9RXl00jEwU26uWwON3EIpnFD8zhcitDHZS388tZl13lOYZ iGmuKvZ2ffUoV1xwek7Os1miPC7ca72K99JMuJzOHvwuBgUj1l/ugQPSfvSS3Yi33If5 ohi4CF1dJxn54NKmYiwJ2xfb/i2Z5MQWYIVQNGplgD27fhWOsKM+kELSeE8yEPae7di8 UnHA== X-Forwarded-Encrypted: i=1; AFNElJ+tIO1H4SKE7tr4WAHmbgFZD4pDkf1ohlqe0AJxJ5+5MqWiFl68QsWcFLwrT/BPeWEWkoRWKJeBikSH0mo=@vger.kernel.org X-Gm-Message-State: AOJu0YxwE9blrH1dmKO4Ifvv/+x78ljQO1PWIJFWD7LIOtzLrdmq72yK r4WLy2NUTswtapEiwgYTs3pxyZcXjgVPFojhQaQU/MwQuELuO6Ojiey7kMmEAA== X-Gm-Gg: AeBDietx3dZTlhfLUDNjYqHPGu/wAPSu2I02MaafrCaJ6sGslMPWC1lgNwcXj1R7KFI Fqywn+jaU28G71Xl4taSKUD1gAykODlHZJl1LTvHunHbOUz6eeJypoRUO31JXP9rtWGsEjN4axz 4mPYrcdgBJJHamTPgOBbT/IUNEuC93TSHWrXSD8UgsVvLdcQx+BP33kQyOhRUvzDQL9jxUysAuH tycbfwpAthI16JnGuama5ccdNkdUqubilmO5rtKZ3fxfkyEU3rpFBrOnqgwSrzOHo3L9yUr/q7r mkFQZc4bcfZimeDZ7OWpxrv4XLCtGjZVjfZqh0c/QTiLuLr64I0QVPNNhx/mrEz9DR73c6vgZjz 2PQA36XJRwtHsaf7CvcnI556eLRYyCvLtBIHj+QWNYAxx2Uqi6LNMDy+FcYeAAYJPOY3vbO3bwu pa6Cc5V/DIhNMsys2BZKtsnGUWdaDuFlJKQ+nCF/kHocgtGumKas3hPKa761qZ0US1k7FkUA== X-Received: by 2002:a17:90b:278f:b0:35b:e4f8:7cc5 with SMTP id 98e67ed59e1d1-361404a5988mr1014628a91.25.1776397891553; Thu, 16 Apr 2026 20:51:31 -0700 (PDT) Received: from qiwenjie-ThinkCentre-M760t.mioffice.cn ([43.224.245.179]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5faa176e9sm4266965ad.20.2026.04.16.20.51.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Apr 2026 20:51:31 -0700 (PDT) From: Wenjie Qi X-Google-Original-From: Wenjie Qi To: jaegeuk@kernel.org, chao@kernel.org Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, qiwenjie@xiaomi.com, qwjhust@gmail.com Subject: [RFC PATCH v2] f2fs: map data writes to FDP streams Date: Fri, 17 Apr 2026 11:51:26 +0800 Message-ID: <20260417035126.3886702-1-qiwenjie@xiaomi.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Wenjie Qi From: Wenjie Qi F2FS already classifies DATA writes using its existing hot, warm and cold temperature policy, but it only passes that intent down as a write hint. That hint alone is not sufficient for NVMe FDP placement, because the current NVMe command path consumes `bio->bi_write_stream` rather than `bio->bi_write_hint` when selecting a placement ID. When the target block device exposes write streams, map the existing F2FS DATA temperature classes onto stream IDs and set `bio->bi_write_stream` for both buffered and direct writes. If the device exposes no write streams, keep the current behavior by leaving the stream unset. The stream mapping is evaluated against the target block device of each bio, so the existing per-device fallback behavior stays unchanged for multi-device filesystems. Existing blkzoned restrictions also remain in place. The mapping is intentionally small and deterministic: - 1 stream: hot, warm and cold all use stream 1 - 2 streams: hot/warm use 1, cold uses 2 - 3+ streams: hot uses 1, warm uses 2, cold uses 3 Signed-off-by: Wenjie Qi Reviewed-by: Chao Yu --- v1 -> v2: - document the default active_logs=3D6 DATA stream mapping and non-FDP fall= back - replace open-coded stream mapping values with existing F2FS symbols where= possible RFC notes: - Scope is intentionally limited to DATA writes only. - Validation used stock QEMU 8.2.2 NVMe FDP emulation with a 16G namespace. - FDP enabled: buffered and direct writes each produced 3 dominant NVMe placement tuples. - FDP disabled: buffered and direct writes each collapsed to 1 dominant tuple. Documentation/filesystems/f2fs.rst | 9 +++++++++ fs/f2fs/data.c | 2 ++ fs/f2fs/f2fs.h | 2 ++ fs/f2fs/file.c | 2 ++ fs/f2fs/segment.c | 13 +++++++++++++ 5 files changed, 28 insertions(+) diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems= /f2fs.rst index 7e4031631..8c4a14ae4 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -137,6 +137,15 @@ noacl Disable POSIX Access Control List. Note: acl = is enabled active_logs=3D%u Support configuring the number of active logs. In the current design, f2fs supports only 2, 4, and 6 logs. Default number is 6. + When the underlying block device exposes write + streams, the default active_logs=3D6 configuration + maps hot, warm, and cold DATA writes to streams 1, + 2, and 3, respectively. If only one or two write + streams are available, f2fs falls back to mapping + all DATA writes to stream 1 or mapping hot/warm + to stream 1 and cold to stream 2. If no write + streams are exposed, f2fs leaves the stream + unset. disable_ext_identify Disable the extension list configured by mkfs, so f2= fs is not aware of cold files such as media files. inline_xattr Enable the inline xattrs feature. diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 338df7a2a..df9f4a230 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -508,6 +508,8 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio= , int npages) bio->bi_private =3D sbi; bio->bi_write_hint =3D f2fs_io_type_to_rw_hint(sbi, fio->type, fio->temp); + bio->bi_write_stream =3D f2fs_io_type_to_write_stream(bdev, fio->type, + fio->temp); } iostat_alloc_and_bind_ctx(sbi, bio, NULL); =20 diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index bb34e864d..2f0777478 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4056,6 +4056,8 @@ void f2fs_destroy_segment_manager_caches(void); int f2fs_rw_hint_to_seg_type(struct f2fs_sb_info *sbi, enum rw_hint hint); enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi, enum page_type type, enum temp_type temp); +u8 f2fs_io_type_to_write_stream(struct block_device *bdev, + enum page_type type, enum temp_type temp); unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi); unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, unsigned int segno); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index c8a2f17a8..a3186cfc9 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -5064,6 +5064,8 @@ static void f2fs_dio_write_submit_io(const struct iom= ap_iter *iter, enum temp_type temp =3D f2fs_get_segment_temp(sbi, type); =20 bio->bi_write_hint =3D f2fs_io_type_to_rw_hint(sbi, DATA, temp); + bio->bi_write_stream =3D + f2fs_io_type_to_write_stream(bio->bi_bdev, DATA, temp); blk_crypto_submit_bio(bio); } =20 diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 6a97fe767..902fc654d 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3626,6 +3626,19 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_= info *sbi, } } =20 +u8 f2fs_io_type_to_write_stream(struct block_device *bdev, + enum page_type type, enum temp_type temp) +{ + unsigned short nr =3D bdev_max_write_streams(bdev); + + if (type !=3D DATA || !nr) + return 0; + if (nr < NR_TEMP_TYPE) + return temp =3D=3D COLD ? nr : HOT + 1; + + return temp + 1; +} + static int __get_segment_type_2(struct f2fs_io_info *fio) { if (fio->type =3D=3D DATA) --=20 2.43.0