From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f174.google.com (mail-oi1-f174.google.com [209.85.167.174]) (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 8F826381B18 for ; Sun, 5 Apr 2026 19:50:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.174 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775418643; cv=none; b=ViS/YXdH5YygrrvUkmCcYQEkHXoxFKEESGS1TNRgGdZ5laGRErbf0KC84TbCK5AyMC4eOIcytWQPkmkmNuT1YZvGhKC544h54zE9nAdogq9T92QoaKI+u2WDrcq7e0xdB6YFnHmOK/eXIH9V8Qrlp7BX78ZD07z2HCRO35pSLA4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775418643; c=relaxed/simple; bh=M3Pjhbze6h8AbWBgQKGzzirkBeW7ABl2/2UM8BAwgDs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BMHfp9dIj99m/0D2Qj1xROfFXiHr5HpLv1iJTIONi+lIO5lxAw5VymT7Ju9R87YzvOHvvdc89dK9R5g/5TdkYo/2NncPhkKQhGZv1ufzkZc1rmEHycS80vh+4+/dQvFXZ1wGoTg47Lis0S4C9P44k2IA1mla1laJhbTfEiossio= 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=MFGd3Z38; arc=none smtp.client-ip=209.85.167.174 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="MFGd3Z38" Received: by mail-oi1-f174.google.com with SMTP id 5614622812f47-46aa216a65aso1857673b6e.1 for ; Sun, 05 Apr 2026 12:50:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775418641; x=1776023441; 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; bh=NEusXoSwED78w0vyJyU5i030iDxdLxYwqTLGcdoyW1Q=; b=MFGd3Z38AU/J7a2O6oIPMttJmmmN9rttQChMC6sOmnGQshaIseiIvJ0AU67UDhSlWb I2RLPiBpqVWhTTFZWGDBzI8bqhEMtCIQROjUWIzUmDBPFcThCyNEbelT0+5u4KDc+cfD YPc+JDCf9vTKTz3xjyUo7PW6X2t5EaTjRTQzH6qVgMRlwVbzeN0VBepiCNUzHB46JwcJ ppFBSMKNPLNXCO0oA5mRNinVThyOYF9vELDMQjmBEyWPP1edyOiz0O/UB4QX5xu5nrUJ UJOVxxzjQzd2P+1kH80hFE2RummrWZoczwBNN3kBsXLRepADMjd5XARKmyBA6DZgY5MC CWtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775418641; x=1776023441; 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; bh=NEusXoSwED78w0vyJyU5i030iDxdLxYwqTLGcdoyW1Q=; b=AKBtIdLTwBrJrkf2rAciHSZDnPe5SXSmKMXY0jQ3BHDq0IssXa1cAxBVMQFBsRfdZc vI7sPhHlbMl3+ZyWcvX/HCy71kceihzR+Km/xaAglhumxh2zX3jiVOfJ9jwXqhKxmgxM sPzjWLGeW+c4aeP4H/FJHgwl51BUk23JQIrTJKG1L3kfJPVSGLbqsr0kryv+uIf2lESh 9rZfnnWvef6jnDmSBlf99a7Vlursf5gV86nyAe3hLTfyGX5Ij2VbkKYep/YkU19XQe5U LZ4sxLU0w7eAb2fPUqEm9cs2CMY3pgwqNFU84uUkXmDRt+INTjFdhIWnHF17oxo32v+z XR4w== X-Gm-Message-State: AOJu0YwVhfDiiqB0Miz3rgbpaJva/sVsxVENrPlkRxEHse0qSeyoCCNI ySndtKzrI79xm38v9PTi4rqkej2oNzhtOCYhykShzYZtt8Eya/k+84fAdn5r8OUe X-Gm-Gg: AeBDiettWflBTro6FtuE0CYfyO7RCGMfUR/c76e5gDaZY2visXPOMmRECfAI7PE9eTa fKvlrKHvj8l4sFq567K5QcyWYsTImXfpFb/dyWvYtrTa+OQOkgHuc5CGkTTE/dmVTJr8l+B74hD nywKX/6x8Tv+I6s5piXqpLPb05MgIorHtOG5payR/rdDnW+PiV375E9vrnSmZoqpHqtMTa7r9fY 97yNQcsXil+IBP2X2lz6gzwhaKGgRhUxLvIsRk+m/EdPc9YsNZDClKdIpVacs2bSIhJTvMMYtL0 USCV596iR/lfnLIitiTBmuVE22A6JHb+oWZ2zIg+tCTIuCvn6C+ggzuyCkkhEaJg5W6MH24rg6B sY5aEubo9ShT0nHP4NqeaDEQ/CaSGLkC39lQq/kRq49doDmBFzLrG2S3NOSzQFirG4iK9B5zqLD EX698TZJ8qXoSLSjZxJ9J6wfcJKpA6QYWp8QexEKXeqLWpzru3AScDckOUbZWHg9tQ2v0i9j7wB CNt71Hq5pWnp8n8ni0PEn+PZA== X-Received: by 2002:a05:6808:5088:b0:468:1574:4cc1 with SMTP id 5614622812f47-46ef8d5bf29mr5189492b6e.3.1775418641053; Sun, 05 Apr 2026 12:50:41 -0700 (PDT) Received: from localhost.localdomain (c-73-5-99-191.hsd1.la.comcast.net. [73.5.99.191]) by smtp.gmail.com with ESMTPSA id 5614622812f47-46f46160155sm4547428b6e.17.2026.04.05.12.50.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Apr 2026 12:50:39 -0700 (PDT) From: Sean Smith X-Google-Original-From: Sean Smith To: linux-fsdevel@vger.kernel.org Cc: linux-ext4@vger.kernel.org, linux-btrfs@vger.kernel.org, tytso@mit.edu, dsterba@suse.com, david@fromorbit.com, brauner@kernel.org, osandov@osandov.com, almaz@kernel.org, hirofumi@mail.parknet.co.jp, linkinjeon@kernel.org, Sean Smith Subject: [PATCH 4/6] ext4: add dedicated ptime field alongside i_crtime Date: Sun, 5 Apr 2026 14:50:00 -0500 Message-ID: <20260405195007.1306-5-DefendTheDisabled@gmail.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: <20260405195007.1306-1-DefendTheDisabled@gmail.com> References: <20260405195007.1306-1-DefendTheDisabled@gmail.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add i_ptime (__le32) and i_ptime_extra (__le32) to the ext4 on-disk inode structure after i_projid. Total: 8 bytes in the extended inode area. i_crtime remains untouched as immutable birth time. This is a native-ptime implementation: ptime and btime are separate fields. On 256-byte inodes (modern default), both fit easily. On 128-byte inodes, ptime is silently unavailable (same graceful degradation as i_crtime via EXT4_FITS_IN_INODE). Uses existing EXT4_EINODE_GET_XTIME/SET_XTIME macros for read/write. Rename-over: when a file with ptime=0 replaces a file with ptime set, inherit target ptime (same zero-sentinel logic as Btrfs). Signed-off-by: Sean Smith --- fs/ext4/ext4.h | 3 +++ fs/ext4/inode.c | 14 ++++++++++++++ fs/ext4/namei.c | 13 +++++++++++++ 3 files changed, 30 insertions(+) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f1c476303..5c2812637 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -860,6 +860,8 @@ struct ext4_inode { __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ __le32 i_version_hi; /* high 32 bits for 64-bit version */ __le32 i_projid; /* Project ID */ + __le32 i_ptime; /* Provenance time */ + __le32 i_ptime_extra; /* extra Provenance time (nsec << 2 | epoch) */ }; #define EXT4_EPOCH_BITS 2 @@ -1136,6 +1138,7 @@ struct ext4_inode_info { * struct timespec64 i_{a,c,m}time in the generic inode. */ struct timespec64 i_crtime; + struct timespec64 i_ptime; /* mballoc */ atomic_t i_prealloc_active; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 625cfbf61..15b6b6dc6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4753,6 +4753,7 @@ static int ext4_fill_raw_inode(struct inode *inode, struct ext4_inode *raw_inode EXT4_INODE_SET_MTIME(inode, raw_inode); EXT4_INODE_SET_ATIME(inode, raw_inode); EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); + EXT4_EINODE_SET_XTIME(i_ptime, ei, raw_inode); raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); raw_inode->i_flags = cpu_to_le32(ei->i_flags & 0xFFFFFFFF); @@ -5409,6 +5410,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, EXT4_INODE_GET_ATIME(inode, raw_inode); EXT4_INODE_GET_MTIME(inode, raw_inode); EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode); + EXT4_EINODE_GET_XTIME(i_ptime, ei, raw_inode); if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) { u64 ivers = le32_to_cpu(raw_inode->i_disk_version); @@ -6061,6 +6063,9 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry, if (!error) { if (inc_ivers) inode_inc_iversion(inode); + if (attr->ia_valid & ATTR_PTIME) + EXT4_I(inode)->i_ptime = attr->ia_ptime; + setattr_copy(idmap, inode, attr); mark_inode_dirty(inode); } @@ -6114,6 +6119,15 @@ int ext4_getattr(struct mnt_idmap *idmap, const struct path *path, stat->btime.tv_nsec = ei->i_crtime.tv_nsec; } + /* Report ptime from dedicated field, not crtime */ + if ((request_mask & STATX_PTIME) && + EXT4_FITS_IN_INODE(raw_inode, ei, i_ptime) && + (ei->i_ptime.tv_sec || ei->i_ptime.tv_nsec)) { + stat->result_mask |= STATX_PTIME; + stat->ptime.tv_sec = ei->i_ptime.tv_sec; + stat->ptime.tv_nsec = ei->i_ptime.tv_nsec; + } + /* * Return the DIO alignment restrictions if requested. We only return * this information when requested, since on encrypted files it might diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index c4b5e252a..1bfe4df24 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -3942,6 +3942,19 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir, * rename. */ inode_set_ctime_current(old.inode); + + /* ptime rename-over: preserve ptime across atomic saves */ + if (new.inode && S_ISREG(old.inode->i_mode) && + S_ISREG(new.inode->i_mode) && old.inode->i_nlink == 1 && + !(flags & RENAME_WHITEOUT)) { + struct ext4_inode_info *old_ei = EXT4_I(old.inode); + struct ext4_inode_info *new_ei = EXT4_I(new.inode); + + if (!old_ei->i_ptime.tv_sec && !old_ei->i_ptime.tv_nsec && + (new_ei->i_ptime.tv_sec || new_ei->i_ptime.tv_nsec)) + old_ei->i_ptime = new_ei->i_ptime; + } + retval = ext4_mark_inode_dirty(handle, old.inode); if (unlikely(retval)) goto end_rename; -- 2.53.0