Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2220008/?format=api
{ "id": 2220008, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2220008/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-ext4/patch/20260405195007.1306-2-DefendTheDisabled@gmail.com/", "project": { "id": 8, "url": "http://patchwork.ozlabs.org/api/1.2/projects/8/?format=api", "name": "Linux ext4 filesystem development", "link_name": "linux-ext4", "list_id": "linux-ext4.vger.kernel.org", "list_email": "linux-ext4@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260405195007.1306-2-DefendTheDisabled@gmail.com>", "list_archive_url": null, "date": "2026-04-05T19:49:57", "name": "[1/6] vfs: add provenance_time (ptime) infrastructure", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "abd12337e8c5c4e1bbfc5a9d733f0a44719febc6", "submitter": { "id": 93064, "url": "http://patchwork.ozlabs.org/api/1.2/people/93064/?format=api", "name": "Sean Smith", "email": "defendthedisabled@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-ext4/patch/20260405195007.1306-2-DefendTheDisabled@gmail.com/mbox/", "series": [ { "id": 498804, "url": "http://patchwork.ozlabs.org/api/1.2/series/498804/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-ext4/list/?series=498804", "date": "2026-04-05T19:49:56", "name": "provenance_time (ptime): a new settable timestamp for cross-filesystem provenance", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/498804/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2220008/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2220008/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <SRS0=UmLJ=CE=vger.kernel.org=linux-ext4+bounces-15643-patchwork-incoming=ozlabs.org@ozlabs.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-ext4@vger.kernel.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "patchwork-incoming@ozlabs.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=gf6h+E7X;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=2404:9400:2221:ea00::3; helo=mail.ozlabs.org;\n envelope-from=srs0=umlj=ce=vger.kernel.org=linux-ext4+bounces-15643-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)", "gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=104.64.211.4 arc.chain=subspace.kernel.org", "gandalf.ozlabs.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "gandalf.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=gf6h+E7X;\n\tdkim-atps=neutral", "gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=104.64.211.4; helo=sin.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15643-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"gf6h+E7X\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.167.177", "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com" ], "Received": [ "from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fpjkJ5jB2z1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 06 Apr 2026 05:50:48 +1000 (AEST)", "from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4fpjkJ5FHlz4wCm\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 06 Apr 2026 05:50:48 +1000 (AEST)", "by gandalf.ozlabs.org (Postfix)\n\tid 4fpjkJ59r1z4wF0; Mon, 06 Apr 2026 05:50:48 +1000 (AEST)", "from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby gandalf.ozlabs.org (Postfix) with ESMTPS id 4fpjkF1X7Pz4wCm\n\tfor <patchwork-incoming@ozlabs.org>; Mon, 06 Apr 2026 05:50:45 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sin.lore.kernel.org (Postfix) with ESMTP id 20C5A3001FB7\n\tfor <patchwork-incoming@ozlabs.org>; Sun, 5 Apr 2026 19:50:36 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id A0A0A37F740;\n\tSun, 5 Apr 2026 19:50:33 +0000 (UTC)", "from mail-oi1-f177.google.com (mail-oi1-f177.google.com\n [209.85.167.177])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EA0137B010\n\tfor <linux-ext4@vger.kernel.org>; Sun, 5 Apr 2026 19:50:30 +0000 (UTC)", "by mail-oi1-f177.google.com with SMTP id\n 5614622812f47-470145d7e07so846174b6e.1\n for <linux-ext4@vger.kernel.org>;\n Sun, 05 Apr 2026 12:50:30 -0700 (PDT)", "from localhost.localdomain (c-73-5-99-191.hsd1.la.comcast.net.\n [73.5.99.191])\n by smtp.gmail.com with ESMTPSA id\n 5614622812f47-46f46160155sm4547428b6e.17.2026.04.05.12.50.26\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sun, 05 Apr 2026 12:50:27 -0700 (PDT)" ], "ARC-Seal": [ "i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1775418648; cv=pass;\n\tb=eUgUWEGfnjBzkIAIYn7WGrt5hsJNbof8P9KdrFaryt7qaWHvuf4RTkqqG9kT44UDAe09ZovB8Rpr2OLT/PqOCEI43lix7f5utRYHrcnejViFIQSdBNLc4rv6uqlH2VPkr8NXrBevK3Ni1RQt7VGoqOXviyllHXs47Z9NmA7uObCQ8WBsorWUtNkT/lF1T6Bsmm+p0Xy/+kNxFX/bTm4ru67tJR0cBKBdcmg1vOBIk5lIJLrb73aCCYJHLmh0Q0yGb3KOBCuFMw0MxA4RoPnmv8qzGz+tXPhWNDIMqP5uo7WVpbe1L097yJsImocFGaJ55zaErsDvgg1eFrymaCiclw==", "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775418633; cv=none;\n b=NLGE/P82awYTL3gXLR1+GZpqCyzNjvaOqDSSBwupOpmdyOMMOb/aVlu+kvxsZtBHZ5apelvnhmntf3Oq7BhLMW2eaoCcQCY1Q2CQWy0+x6P4aNmRqFReb/p1W/2i6FtIRQVgo3k/NCr3oqSpnYZMxhmjZ9JQn44mMPY2YNztGFY=" ], "ARC-Message-Signature": [ "i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1775418648; c=relaxed/relaxed;\n\tbh=2ZQ0VkPeOJ/If+th1ogC495oRb3mBG/Wl1YVzp5b6bI=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=yglfINmD2dRUa5Z+YCXakkQLDvdo6bqgQoA9kWsL/vnGXXU4vTIAhrH/XFu6Wc9EGpjzmZtmX8Y84+yH2Prq8/0ZCQIeXQgNAmt5jSy2q33NlYNxYs/DagG2Kc65/EP+hMPXt3zHy5AqnxTI9qRJlibsgzcUD4Z8OYoUZ7TieQ2/6VgiWVXfH4JO07+cTznG6iy3f1+m6I33BkbMNOiLyXeotLTmBP1H5ILYqqTEFtUX8EUi0N9hdMWcnoJJWF9/mD9LKhvDo4ugnbXtLAslNhtwu99JQX6YA63bcnA7tHSNpnwZdz6cAO6wdaJWyHIA6uTUPs4wZQDJJ+ftZE9cPw==", "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775418633; c=relaxed/simple;\n\tbh=eAS0CC0y+ljGDQRKHJmotWjYqP7vy5Qg1wjW0SfPpNo=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=R214Dm9IZyzuDQDlrAGXAV4ZW3SQapwxnDRPNhSnLsECKb1oCLahfwW89wDssSckOSlLKtDanlbt04cEjqZ6NHBMiYDXlJPwYBE+d0RAVIPy2OoJEz4bJlPBjUlXyykjymJX291yj7u4l91WqYJnRRiTDo9AmNvKCVhSqSil7PM=" ], "ARC-Authentication-Results": [ "i=2; gandalf.ozlabs.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com; dkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=gf6h+E7X; dkim-atps=neutral;\n spf=pass (client-ip=104.64.211.4; helo=sin.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15643-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org", "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=gf6h+E7X; arc=none smtp.client-ip=209.85.167.177" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1775418629; x=1776023429;\n darn=vger.kernel.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=2ZQ0VkPeOJ/If+th1ogC495oRb3mBG/Wl1YVzp5b6bI=;\n b=gf6h+E7XmOIC0RSWsYfFX7CSaxEP6YAk0sBGFr/dVcS2HJm2pP2Q3Rb+2ozmIdX9Eu\n kWTSFaE17u/iwGgV7sQdlN6deke/RDr+a4Od6wfaXwu5XBMZvUy24NYfHxF2hy+Ktzs3\n am6NV81wd5aTymHXUoyqbBAGzOCIn75J3FvQmwW60XUnlXfbaYZ8jr8KF77UbL9j7Yb9\n xcjelQQ0VH2J5iSvl5v1pJ99nn1vHTyrHWU8l6X0Hcyd4EGCqvKgr/+7vj1Do8nVkxCj\n ODsBYy4I6i0tEPqemCjFpxmKXmnbzMbfywkAyLa1lhBB5s0VBxrXIOyMuVl6ejXUCmkV\n N50g==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775418629; x=1776023429;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=2ZQ0VkPeOJ/If+th1ogC495oRb3mBG/Wl1YVzp5b6bI=;\n b=V+okqFkK7ifBPVTF3HsMsnHHeuts8qNyvEbNshDc8LGq2w7LjQLsHR8dFiZiT5TrH1\n Ukjc6skazqON6aldwOmi01hwn0jmFh6ugfb2nU3aZ3yRMC76TSsWpKehrtB4/u/LqKxv\n /SObDBW1hVazRQYd+CZ/FyQNLyCpyN9f3w6gZGfISiFEOolBsGZM3+mukwX/N2RX7QW8\n 8ojW2X7ELymnIqW6SqmU7n9+gpJ8Fst6jO7ma5N22wXHtG4Orc9zQOhOw7IS6Xm3RZ3e\n FHomS09QXSnlvREWda0ElVBBvhkoR305J1cgIMw0kSS9JxUJ/Tw/57R1bfbOYRy1rw4j\n EQmA==", "X-Gm-Message-State": "AOJu0YyxvkMoIdlex4VZUIbhDBFmv/uh1KqtTUCtXhRi4ki14nT+6X9s\n\tRhPMP5c0yxjD+L9lAyFHQXNNlblq8rg4ncaa/NQSUrF/OWUorExyNrV1", "X-Gm-Gg": "AeBDiesXiDEvuIn0EEC+cpxx7Pt4C31HO06b3KVhgNU1ABEmbGlW90ogLpXNj+WIjiM\n\tECa5b+8DHWoEvMpJ6ZvE7iJjkj3LRwjilJ3RqGx2oItSKmzrP5svVFuItiL+g9nVGpqqpD/D6cK\n\tdz+atjAD3Q29tnwmrUZVs7coHnpxIu91hjFLn1hFzMwmIw2UguwcVQauGxNVcmfJNZZGTbrEH2j\n\takRHh284yl5mo8Dr2YKaXCD/E16/De6C58Tj5I9Nm7U1SGAtkmQVoJwYCyx7CU/Bssw6sLgbOyG\n\tUyE3NecgrRKAXgJcU0XP6BGAb+bjldCILbxvtuX2rV7JbnNvDvxFfW9d5Xw0mS+eBedx4okH1sy\n\thWXKC7r9GaFl99iI8RkpDs8q7tMGoLjwxCs1+vk/GDR+Ahs4mEwnnZ4JpGbPZlo/OWadsFDhG2q\n\tgBF4L8jrwuMR2ATneFU2Jg8ApeXcgmJGnY5xxH4MzwMtapfruRCGCKJroNNF4FJGTmFOPBdXilL\n\tNlDCMsAYyUsFMA116ZEtLwYAg==", "X-Received": "by 2002:a05:6808:5088:b0:46a:cb96:d2b7 with SMTP id\n 5614622812f47-46ef7e16ea0mr5583483b6e.35.1775418629222;\n Sun, 05 Apr 2026 12:50:29 -0700 (PDT)", "From": "Sean Smith <defendthedisabled@gmail.com>", "X-Google-Original-From": "Sean Smith <DefendTheDisabled@gmail.com>", "To": "linux-fsdevel@vger.kernel.org", "Cc": "linux-ext4@vger.kernel.org,\n\tlinux-btrfs@vger.kernel.org,\n\ttytso@mit.edu,\n\tdsterba@suse.com,\n\tdavid@fromorbit.com,\n\tbrauner@kernel.org,\n\tosandov@osandov.com,\n\talmaz@kernel.org,\n\thirofumi@mail.parknet.co.jp,\n\tlinkinjeon@kernel.org,\n\tSean Smith <DefendTheDisabled@gmail.com>", "Subject": "[PATCH 1/6] vfs: add provenance_time (ptime) infrastructure", "Date": "Sun, 5 Apr 2026 14:49:57 -0500", "Message-ID": "<20260405195007.1306-2-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-ext4@vger.kernel.org", "List-Id": "<linux-ext4.vger.kernel.org>", "List-Subscribe": "<mailto:linux-ext4+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-ext4+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Spam-Status": "No, score=-1.2 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DMARC_PASS,\n\tFREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,\n\tMAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=disabled\n\tversion=4.0.1", "X-Spam-Checker-Version": "SpamAssassin 4.0.1 (2024-03-25) on gandalf.ozlabs.org" }, "content": "Add a new settable inode timestamp, provenance_time (ptime), for tracking\nthe original creation date of file content across filesystem boundaries.\n\nptime is distinct from btime (forensic, immutable): it records when file\ncontent first came into existence on any filesystem, and is designed to\nbe set during cross-filesystem migration and preserved through copies.\n\nVFS changes:\n- ATTR_PTIME (bit 19) and ATTR_PTIME_SET (bit 20) in struct iattr\n- STATX_PTIME (0x00040000) in struct statx at offset 0xC0\n- AT_UTIME_PTIME (0x20000) flag for utimensat()\n- ptime field in struct kstat\n- Permission model matches mtime (owner or CAP_FOWNER)\n- UTIME_NOW and UTIME_OMIT supported for ptime element\n- All existing vfs_utimes() callers updated for new flags parameter\n\nSigned-off-by: Sean Smith <DefendTheDisabled@gmail.com>\n---\n fs/attr.c | 6 +++-\n fs/btrfs/volumes.c | 2 +-\n fs/init.c | 2 +-\n fs/stat.c | 2 ++\n fs/utimes.c | 56 +++++++++++++++++++++++++++++---------\n include/linux/fs.h | 5 +++-\n include/linux/stat.h | 1 +\n include/uapi/linux/fcntl.h | 3 ++\n include/uapi/linux/stat.h | 4 ++-\n init/initramfs.c | 2 +-\n 10 files changed, 64 insertions(+), 19 deletions(-)", "diff": "diff --git a/fs/attr.c b/fs/attr.c\nindex b9ec6b47b..7fa9c01d1 100644\n--- a/fs/attr.c\n+++ b/fs/attr.c\n@@ -206,7 +206,7 @@ int setattr_prepare(struct mnt_idmap *idmap, struct dentry *dentry,\n \t}\n \n \t/* Check for setting the inode time. */\n-\tif (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) {\n+\tif (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_PTIME_SET | ATTR_TIMES_SET)) {\n \t\tif (!inode_owner_or_capable(idmap, inode))\n \t\t\treturn -EPERM;\n \t}\n@@ -466,6 +466,10 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,\n \t\tattr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode);\n \telse\n \t\tattr->ia_mtime = now;\n+\tif (ia_valid & ATTR_PTIME_SET)\n+\t\tattr->ia_ptime = timestamp_truncate(attr->ia_ptime, inode);\n+\telse if (ia_valid & ATTR_PTIME)\n+\t\tattr->ia_ptime = now;\n \n \tif (ia_valid & ATTR_KILL_PRIV) {\n \t\terror = security_inode_need_killpriv(dentry);\ndiff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c\nindex 052b830a0..0e81f2cc9 100644\n--- a/fs/btrfs/volumes.c\n+++ b/fs/btrfs/volumes.c\n@@ -2117,7 +2117,7 @@ static void update_dev_time(const char *device_path)\n \tstruct path path;\n \n \tif (!kern_path(device_path, LOOKUP_FOLLOW, &path)) {\n-\t\tvfs_utimes(&path, NULL);\n+\t\tvfs_utimes(&path, NULL, 0);\n \t\tpath_put(&path);\n \t}\n }\ndiff --git a/fs/init.c b/fs/init.c\nindex e0f5429c0..e9a9f4d93 100644\n--- a/fs/init.c\n+++ b/fs/init.c\n@@ -254,7 +254,7 @@ int __init init_utimes(char *filename, struct timespec64 *ts)\n \terror = kern_path(filename, 0, &path);\n \tif (error)\n \t\treturn error;\n-\terror = vfs_utimes(&path, ts);\n+\terror = vfs_utimes(&path, ts, 0);\n \tpath_put(&path);\n \treturn error;\n }\ndiff --git a/fs/stat.c b/fs/stat.c\nindex 6c79661e1..9284bb753 100644\n--- a/fs/stat.c\n+++ b/fs/stat.c\n@@ -728,6 +728,8 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)\n \ttmp.stx_atime.tv_nsec = stat->atime.tv_nsec;\n \ttmp.stx_btime.tv_sec = stat->btime.tv_sec;\n \ttmp.stx_btime.tv_nsec = stat->btime.tv_nsec;\n+\ttmp.stx_ptime.tv_sec = stat->ptime.tv_sec;\n+\ttmp.stx_ptime.tv_nsec = stat->ptime.tv_nsec;\n \ttmp.stx_ctime.tv_sec = stat->ctime.tv_sec;\n \ttmp.stx_ctime.tv_nsec = stat->ctime.tv_nsec;\n \ttmp.stx_mtime.tv_sec = stat->mtime.tv_sec;\ndiff --git a/fs/utimes.c b/fs/utimes.c\nindex 86f8ce8cd..50b5ad296 100644\n--- a/fs/utimes.c\n+++ b/fs/utimes.c\n@@ -17,10 +17,10 @@ static bool nsec_valid(long nsec)\n \treturn nsec >= 0 && nsec <= 999999999;\n }\n \n-int vfs_utimes(const struct path *path, struct timespec64 *times)\n+int vfs_utimes(const struct path *path, struct timespec64 *times, int flags)\n {\n \tint error;\n-\tstruct iattr newattrs;\n+\tstruct iattr newattrs = {};\n \tstruct inode *inode = path->dentry->d_inode;\n \tstruct delegated_inode delegated_inode = { };\n \n@@ -28,7 +28,11 @@ int vfs_utimes(const struct path *path, struct timespec64 *times)\n \t\tif (!nsec_valid(times[0].tv_nsec) ||\n \t\t !nsec_valid(times[1].tv_nsec))\n \t\t\treturn -EINVAL;\n-\t\tif (times[0].tv_nsec == UTIME_NOW &&\n+\t\tif ((flags & AT_UTIME_PTIME) &&\n+\t\t !nsec_valid(times[2].tv_nsec))\n+\t\t\treturn -EINVAL;\n+\t\tif (!(flags & AT_UTIME_PTIME) &&\n+\t\t times[0].tv_nsec == UTIME_NOW &&\n \t\t times[1].tv_nsec == UTIME_NOW)\n \t\t\ttimes = NULL;\n \t}\n@@ -52,6 +56,15 @@ int vfs_utimes(const struct path *path, struct timespec64 *times)\n \t\t\tnewattrs.ia_mtime = times[1];\n \t\t\tnewattrs.ia_valid |= ATTR_MTIME_SET;\n \t\t}\n+\t\tif (flags & AT_UTIME_PTIME) {\n+\t\t\tif (times[2].tv_nsec != UTIME_OMIT) {\n+\t\t\t\tnewattrs.ia_valid |= ATTR_PTIME;\n+\t\t\t\tif (times[2].tv_nsec != UTIME_NOW) {\n+\t\t\t\t\tnewattrs.ia_ptime = times[2];\n+\t\t\t\t\tnewattrs.ia_valid |= ATTR_PTIME_SET;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n \t\t/*\n \t\t * Tell setattr_prepare(), that this is an explicit time\n \t\t * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET\n@@ -84,7 +97,7 @@ static int do_utimes_path(int dfd, const char __user *filename,\n \tstruct path path;\n \tint lookup_flags = 0, error;\n \n-\tif (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH))\n+\tif (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH | AT_UTIME_PTIME))\n \t\treturn -EINVAL;\n \n \tif (!(flags & AT_SYMLINK_NOFOLLOW))\n@@ -97,7 +110,7 @@ static int do_utimes_path(int dfd, const char __user *filename,\n \tif (error)\n \t\treturn error;\n \n-\terror = vfs_utimes(&path, times);\n+\terror = vfs_utimes(&path, times, flags);\n \tpath_put(&path);\n \tif (retry_estale(error, lookup_flags)) {\n \t\tlookup_flags |= LOOKUP_REVAL;\n@@ -109,13 +122,13 @@ static int do_utimes_path(int dfd, const char __user *filename,\n \n static int do_utimes_fd(int fd, struct timespec64 *times, int flags)\n {\n-\tif (flags)\n+\tif (flags & ~AT_UTIME_PTIME)\n \t\treturn -EINVAL;\n \n \tCLASS(fd, f)(fd);\n \tif (fd_empty(f))\n \t\treturn -EBADF;\n-\treturn vfs_utimes(&fd_file(f)->f_path, times);\n+\treturn vfs_utimes(&fd_file(f)->f_path, times, flags);\n }\n \n /*\n@@ -144,16 +157,24 @@ long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,\n SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,\n \t\tstruct __kernel_timespec __user *, utimes, int, flags)\n {\n-\tstruct timespec64 tstimes[2];\n+\tstruct timespec64 tstimes[3];\n+\n+\tif ((flags & AT_UTIME_PTIME) && !utimes)\n+\t\treturn -EINVAL;\n \n \tif (utimes) {\n \t\tif ((get_timespec64(&tstimes[0], &utimes[0]) ||\n-\t\t\tget_timespec64(&tstimes[1], &utimes[1])))\n+\t\t get_timespec64(&tstimes[1], &utimes[1])))\n+\t\t\treturn -EFAULT;\n+\t\tif ((flags & AT_UTIME_PTIME) &&\n+\t\t get_timespec64(&tstimes[2], &utimes[2]))\n \t\t\treturn -EFAULT;\n \n \t\t/* Nothing to do, we must not even check the path. */\n \t\tif (tstimes[0].tv_nsec == UTIME_OMIT &&\n-\t\t tstimes[1].tv_nsec == UTIME_OMIT)\n+\t\t tstimes[1].tv_nsec == UTIME_OMIT &&\n+\t\t (!(flags & AT_UTIME_PTIME) ||\n+\t\t tstimes[2].tv_nsec == UTIME_OMIT))\n \t\t\treturn 0;\n \t}\n \n@@ -247,14 +268,23 @@ SYSCALL_DEFINE2(utime32, const char __user *, filename,\n \n SYSCALL_DEFINE4(utimensat_time32, unsigned int, dfd, const char __user *, filename, struct old_timespec32 __user *, t, int, flags)\n {\n-\tstruct timespec64 tv[2];\n+\tstruct timespec64 tv[3];\n+\n+\tif ((flags & AT_UTIME_PTIME) && !t)\n+\t\treturn -EINVAL;\n \n-\tif (t) {\n+\tif (t) {\n \t\tif (get_old_timespec32(&tv[0], &t[0]) ||\n \t\t get_old_timespec32(&tv[1], &t[1]))\n \t\t\treturn -EFAULT;\n+\t\tif ((flags & AT_UTIME_PTIME) &&\n+\t\t get_old_timespec32(&tv[2], &t[2]))\n+\t\t\treturn -EFAULT;\n \n-\t\tif (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)\n+\t\tif (tv[0].tv_nsec == UTIME_OMIT &&\n+\t\t tv[1].tv_nsec == UTIME_OMIT &&\n+\t\t (!(flags & AT_UTIME_PTIME) ||\n+\t\t tv[2].tv_nsec == UTIME_OMIT))\n \t\t\treturn 0;\n \t}\n \treturn do_utimes(dfd, filename, t ? tv : NULL, flags);\ndiff --git a/include/linux/fs.h b/include/linux/fs.h\nindex a01621fa6..07719e216 100644\n--- a/include/linux/fs.h\n+++ b/include/linux/fs.h\n@@ -239,6 +239,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,\n #define ATTR_TIMES_SET\t(1 << 16)\n #define ATTR_TOUCH\t(1 << 17)\n #define ATTR_DELEG\t(1 << 18) /* Delegated attrs. Don't break write delegations */\n+#define ATTR_PTIME\t(1 << 19) /* Set provenance time */\n+#define ATTR_PTIME_SET\t(1 << 20) /* Set provenance time to specific value */\n \n /*\n * Whiteout is represented by a char device. The following constants define the\n@@ -283,6 +285,7 @@ struct iattr {\n \tstruct timespec64 ia_atime;\n \tstruct timespec64 ia_mtime;\n \tstruct timespec64 ia_ctime;\n+\tstruct timespec64 ia_ptime;\n \n \t/*\n \t * Not an attribute, but an auxiliary info for filesystems wanting to\n@@ -1814,7 +1817,7 @@ int vfs_mkobj(struct dentry *, umode_t,\n \n int vfs_fchown(struct file *file, uid_t user, gid_t group);\n int vfs_fchmod(struct file *file, umode_t mode);\n-int vfs_utimes(const struct path *path, struct timespec64 *times);\n+int vfs_utimes(const struct path *path, struct timespec64 *times, int flags);\n \n #ifdef CONFIG_COMPAT\n extern long compat_ptr_ioctl(struct file *file, unsigned int cmd,\ndiff --git a/include/linux/stat.h b/include/linux/stat.h\nindex e3d00e7bb..52272000c 100644\n--- a/include/linux/stat.h\n+++ b/include/linux/stat.h\n@@ -48,6 +48,7 @@ struct kstat {\n \tstruct timespec64 mtime;\n \tstruct timespec64 ctime;\n \tstruct timespec64 btime;\t\t\t/* File creation time */\n+\tstruct timespec64 ptime;\t\t\t/* Provenance time */\n \tu64\t\tblocks;\n \tu64\t\tmnt_id;\n \tu64\t\tchange_cookie;\ndiff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h\nindex aadfbf6e0..f80ce0295 100644\n--- a/include/uapi/linux/fcntl.h\n+++ b/include/uapi/linux/fcntl.h\n@@ -190,4 +190,7 @@ struct delegation {\n #define AT_EXECVE_CHECK\t\t0x10000\t/* Only perform a check if execution\n \t\t\t\t\t would be allowed. */\n \n+/* Flag for utimensat(2): times[2] carries provenance time */\n+#define AT_UTIME_PTIME\t\t0x20000\n+\n #endif /* _UAPI_LINUX_FCNTL_H */\ndiff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h\nindex 1686861aa..0c8db3715 100644\n--- a/include/uapi/linux/stat.h\n+++ b/include/uapi/linux/stat.h\n@@ -187,7 +187,8 @@ struct statx {\n \t__u32\t__spare2[1];\n \n \t/* 0xc0 */\n-\t__u64\t__spare3[8];\t/* Spare space for future expansion */\n+\tstruct statx_timestamp\tstx_ptime;\t/* File provenance time */\n+\t__u64\t__spare3[6];\t\t/* Spare space for future expansion */\n \n \t/* 0x100 */\n };\n@@ -219,6 +220,7 @@ struct statx {\n #define STATX_SUBVOL\t\t0x00008000U\t/* Want/got stx_subvol */\n #define STATX_WRITE_ATOMIC\t0x00010000U\t/* Want/got atomic_write_* fields */\n #define STATX_DIO_READ_ALIGN\t0x00020000U\t/* Want/got dio read alignment info */\n+#define STATX_PTIME\t\t0x00040000U\t/* Want/got stx_ptime */\n \n #define STATX__RESERVED\t\t0x80000000U\t/* Reserved for future struct statx expansion */\n \ndiff --git a/init/initramfs.c b/init/initramfs.c\nindex 6ddbfb17f..e066b1fee 100644\n--- a/init/initramfs.c\n+++ b/init/initramfs.c\n@@ -139,7 +139,7 @@ static void __init do_utime(char *filename, time64_t mtime)\n static void __init do_utime_path(const struct path *path, time64_t mtime)\n {\n \tstruct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } };\n-\tvfs_utimes(path, t);\n+\tvfs_utimes(path, t, 0);\n }\n \n static __initdata LIST_HEAD(dir_list);\n", "prefixes": [ "1/6" ] }