From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1lOh78-00050z-SG for mharc-grub-devel@gnu.org; Tue, 23 Mar 2021 09:30:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58592) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lOh73-0004zT-A0 for grub-devel@gnu.org; Tue, 23 Mar 2021 09:30:26 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:31492) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1lOh6z-0008S4-TH for grub-devel@gnu.org; Tue, 23 Mar 2021 09:30:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1616506221; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5rwTgBzi3VTgdaOx4WndNcOUmoi+XyVhsbOFVnx//kg=; b=Cj4tOHdQVkXusLk8KaoWIS43o4WgHYMbnynMZia+zGDABQXiD1ZdUDgkCbE1TkDH+MOmLg HmbWXHMflC5s7Skz7pF0wzdzhczPBTni8JJjmxjEcc3sPUUGcqgk9TrTZTJeg0NWYRuPCe foGUrDvL7QcBFyVS6jctdTZllfkbeo0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-537-64tw3uXyMoGWRaP66Hv86Q-1; Tue, 23 Mar 2021 09:30:18 -0400 X-MC-Unique: 64tw3uXyMoGWRaP66Hv86Q-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2952E881D79; Tue, 23 Mar 2021 13:30:17 +0000 (UTC) Received: from andromeda.redhat.com (unknown [10.40.193.225]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4FDC02AC83; Tue, 23 Mar 2021 13:30:11 +0000 (UTC) From: Carlos Maiolino To: grub-devel@gnu.org Cc: daniel.kiper@oracle.com, javierm@redhat.com Subject: [PATCH 1/2] Add bigtime support for xfs driver Date: Tue, 23 Mar 2021 14:29:58 +0100 Message-Id: <20210323132959.1594989-2-cmaiolino@redhat.com> In-Reply-To: <20210323132959.1594989-1-cmaiolino@redhat.com> References: <20210323132959.1594989-1-cmaiolino@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=cmaiolino@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII" Received-SPF: pass client-ip=216.205.24.124; envelope-from=cmaiolino@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Mar 2021 13:30:27 -0000 XFS filesystem now supports bigtime feature, to overcome y2038 problem. This patch makes grub able to support xfs filesystems with this feature enabled. xfs counter for bigtime enable timestamps starts on 0, which translates to INT32_MIN (Dec 31 20:45:52 UTC 1901) in the legacy timestamps. The conversion to unix timestamps is made before passing the value to grub-core. For this to work properly, grub requires to access flags2 field in the xfs ondisk inode, so, the grub_xfs_inode structure has been updated to the full ondisk inode size. This patch is enough to make grub work properly with files with timestamps up to INT32_MAX (y2038), any file with timestamps bigger than this will overflow the counter, causing grub to show wrong timestamps (not really much difference on current situation). Signed-off-by: Carlos Maiolino --- grub-core/fs/xfs.c | 69 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 43023e03f..2ce76ec70 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -75,10 +75,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); XFS_SB_VERSION2_PROJID32BIT | \ XFS_SB_VERSION2_FTYPE) +/* Inode flags2 flags */ +#define XFS_DIFLAG2_BIGTIME_BIT 3 +#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) + /* incompat feature flags */ -#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ -#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ -#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ +#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ +#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ +#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ +#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ /* * Directory entries with ftype are explicitly handled by GRUB code. @@ -92,7 +97,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ (XFS_SB_FEAT_INCOMPAT_FTYPE | \ XFS_SB_FEAT_INCOMPAT_SPINODES | \ - XFS_SB_FEAT_INCOMPAT_META_UUID) + XFS_SB_FEAT_INCOMPAT_META_UUID | \ + XFS_SB_FEAT_INCOMPAT_BIGTIME) struct grub_xfs_sblock { @@ -177,7 +183,7 @@ struct grub_xfs_btree_root grub_uint64_t keys[1]; } GRUB_PACKED; -struct grub_xfs_time +struct grub_xfs_time_legacy { grub_uint32_t sec; grub_uint32_t nanosec; @@ -190,20 +196,23 @@ struct grub_xfs_inode grub_uint8_t version; grub_uint8_t format; grub_uint8_t unused2[26]; - struct grub_xfs_time atime; - struct grub_xfs_time mtime; - struct grub_xfs_time ctime; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; grub_uint64_t size; grub_uint64_t nblocks; grub_uint32_t extsize; grub_uint32_t nextents; grub_uint16_t unused3; grub_uint8_t fork_offset; - grub_uint8_t unused4[17]; + grub_uint8_t unused4[37]; + grub_uint64_t flags2; + grub_uint8_t unused5[48]; } GRUB_PACKED; -#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode) -#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76) +#define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) +/* Size of struct grub_xfs_inode until fork_offset (included)*/ +#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) struct grub_xfs_dirblock_tail { @@ -233,8 +242,6 @@ struct grub_xfs_data static grub_dl_t my_mod; - - static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) { return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == @@ -950,7 +957,6 @@ grub_xfs_mount (grub_disk_t disk) return 0; } - /* Context for grub_xfs_dir. */ struct grub_xfs_dir_ctx { @@ -958,6 +964,39 @@ struct grub_xfs_dir_ctx void *hook_data; }; +/* Bigtime inodes helpers */ + +#define NSEC_PER_SEC 1000000000L +#define XFS_BIGTIME_EPOCH_OFFSET (-(grub_int64_t)GRUB_INT32_MIN) + +static int grub_xfs_inode_has_bigtime(const struct grub_xfs_inode *inode) +{ + return inode->version >= 3 && + (inode->flags2 & grub_cpu_to_be64_compile_time(XFS_DIFLAG2_BIGTIME)); +} + +static grub_int64_t +grub_xfs_bigtime_to_unix(grub_uint64_t time) +{ + grub_uint64_t rem; + grub_int64_t nsec = NSEC_PER_SEC; + grub_int64_t seconds = grub_divmod64((grub_int64_t)time, nsec, &rem); + + return seconds - XFS_BIGTIME_EPOCH_OFFSET; +} + +static grub_int64_t +grub_xfs_get_inode_time(struct grub_xfs_inode *inode) +{ + struct grub_xfs_time_legacy *lts; + + if (grub_xfs_inode_has_bigtime(inode)) + return grub_xfs_bigtime_to_unix(grub_be_to_cpu64(inode->mtime)); + + lts = (struct grub_xfs_time_legacy *)&inode->mtime; + return grub_be_to_cpu32(lts->sec); +} + /* Helper for grub_xfs_dir. */ static int grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, @@ -970,7 +1009,7 @@ grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, if (node->inode_read) { info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); + info.mtime = grub_xfs_get_inode_time(&node->inode); } info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); grub_free (node); -- 2.29.2