Received: by 10.223.185.111 with SMTP id b44csp1654920wrg; Sat, 10 Mar 2018 10:43:29 -0800 (PST) X-Google-Smtp-Source: AG47ELvpTcZ4L4qDkNgWqtAKPayCiLdZN3nrpCNZsk4yIRDeYvgMmoDhriNouetIp4ICTYQZfz4T X-Received: by 2002:a17:902:8d90:: with SMTP id v16-v6mr2766722plo.168.1520707409835; Sat, 10 Mar 2018 10:43:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520707409; cv=none; d=google.com; s=arc-20160816; b=f10k+Zv9cAlGiL1qo7BOBXEy0CQShuCCv6xKopjWsx025UcsdIq2b/u4LC4vNsTK6F /o6rWa4qlaNF45oTRDYzgGY8jQLtqKdfjX972jQO7x9Of7SuRJEav8bInAE6hDdpyeQh FGtKAa4nCdcH+QEwQIRGFy3HdmyzGRMlxvPmd5So1oM8Xc54X50RGzGhIwV9QiTPgEiv BqwNqbRCw8wHM58V7VmeRIAuaWsuilPShNhEshJwOaKURsXvlHa97SPW1q7KfqU7N3sz cR8UDfr0vsq0aFMv78l4ep9KGQ83ygORUsvvAhLK0N5xhtrTB0wRSgf6qWwv1x3o79EM RY2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=SsEqAe5TVG0L/78YJNxj2g83ptJHPC3IA0cR166vL5o=; b=RC4pRknWDr3J8gY6cTcguQNQJcE7PK/z5JGqKdH2B4vp+JCN8YIdqG1H1NXrhzC2Ie qU/qzLX9M9/gSbFSOB/KIgk2n8xoEoemc+XeFO5e7GxP74DmeANWnKc/JtwCYqV/2VtH YammgUS0kP24ZhAJ1crKB2Bnagom3on/RHdGLcZ6xS6Olnl9CnZnt6V/tv+lFCfclnKR vVwZFjbBDBQB4KulNRZyTyoDo3zZAPAIxzWKQYIkllDhX0xCXpHPxJWupLo9umji4W1J MCA3ypegDtYWNbN3u10HJxhMWYP+iNvQfA8aCVu4/okP4RCKeMquf35IUYWLKXh9q7zx LciA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@eng.ucsd.edu header.s=google header.b=WUdBZmSG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q9si2642993pgc.401.2018.03.10.10.43.15; Sat, 10 Mar 2018 10:43:29 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@eng.ucsd.edu header.s=google header.b=WUdBZmSG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932308AbeCJSUc (ORCPT + 99 others); Sat, 10 Mar 2018 13:20:32 -0500 Received: from mail-pg0-f68.google.com ([74.125.83.68]:39517 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932269AbeCJSU2 (ORCPT ); Sat, 10 Mar 2018 13:20:28 -0500 Received: by mail-pg0-f68.google.com with SMTP id e3so4833191pga.6 for ; Sat, 10 Mar 2018 10:20:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eng.ucsd.edu; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SsEqAe5TVG0L/78YJNxj2g83ptJHPC3IA0cR166vL5o=; b=WUdBZmSGHO5ZWI9EpdPA3w90FRyMHmuU9nUBohxVl6s9KSMoZTxBWVpY6z00AAC1bD +9TaqoWFro9ZYOAZlFtpgdUhKXexEAu15jkJG2p7htCQBQRYS50m7NOQfNr6CfBaEJjf Zu1r4ih6U5ITxsuavdXdUwcLZpvP4WCleGnp0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SsEqAe5TVG0L/78YJNxj2g83ptJHPC3IA0cR166vL5o=; b=hEuytNKqfc5jA4CPK7Z/6DTOfOWl2SerOkbIBjq+nf9M79Zw0VuDVdkH0gMzO0gTvx uAMCCjfZ34ttEQzC5aZq3nnnFLEnaGdiHu86/8owr5MI6K5fodX2BHqB7prSfN3JXRqD oPnOov3rDGR20A0aoAIx1Grsnyd1ulOc7S7wUkxTu3oM8tqL1P7V+7/uPcqrNFIXGaR6 m6aU0uvmBxkhTSG1XBdihO8SoyQhVteT5hUYyAGtWka6snvqbmG4tHCxGntXaY05xEk6 wIPFLShgIppNf26dQvDzN6VcuBCecywHX/+e7POxVn0aWrDxyH7SpKb3zBj45G9l74lW bnLQ== X-Gm-Message-State: AElRT7F7AdnAoj+xtkejhqrMTSmYFCtClFpsObqMuA8gdReriYSzzEmD 5G493Up0GUd8QAXZPLzXJbJi4w== X-Received: by 10.101.93.134 with SMTP id f6mr2203397pgt.293.1520706027842; Sat, 10 Mar 2018 10:20:27 -0800 (PST) Received: from brienza-desktop.8.8.4.4 (andxu.ucsd.edu. [132.239.17.134]) by smtp.gmail.com with ESMTPSA id h80sm9210167pfj.181.2018.03.10.10.20.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 10 Mar 2018 10:20:27 -0800 (PST) From: Andiry Xu To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nvdimm@lists.01.org Cc: dan.j.williams@intel.com, andy.rudoff@intel.com, coughlan@redhat.com, swanson@cs.ucsd.edu, david@fromorbit.com, jack@suse.com, swhiteho@redhat.com, miklos@szeredi.hu, andiry.xu@gmail.com, Andiry Xu Subject: [RFC v2 10/83] Add superblock integrity check. Date: Sat, 10 Mar 2018 10:17:51 -0800 Message-Id: <1520705944-6723-11-git-send-email-jix024@eng.ucsd.edu> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> References: <1520705944-6723-1-git-send-email-jix024@eng.ucsd.edu> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andiry Xu Repair broken primary superblock with redundant superblock. Signed-off-by: Andiry Xu --- fs/nova/super.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/fs/nova/super.c b/fs/nova/super.c index 552fe5d..e0e38ab 100644 --- a/fs/nova/super.c +++ b/fs/nova/super.c @@ -276,6 +276,21 @@ static bool nova_check_size(struct super_block *sb, unsigned long size) return true; } +static inline int nova_check_super_checksum(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + u32 crc = 0; + + // Check CRC but skip c_sum, which is the 4 bytes at the beginning + crc = nova_crc32c(~0, (__u8 *)sbi->nova_sb + sizeof(__le32), + sizeof(struct nova_super_block) - sizeof(__le32)); + + if (sbi->nova_sb->s_sum == cpu_to_le32(crc)) + return 0; + else + return 1; +} + static inline void nova_sync_super(struct super_block *sb) { struct nova_sb_info *sbi = NOVA_SB(sb); @@ -293,6 +308,34 @@ static inline void nova_sync_super(struct super_block *sb) PERSISTENT_BARRIER(); } +/* Update checksum for the DRAM copy */ +static inline void nova_update_super_crc(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + u32 crc = 0; + + sbi->nova_sb->s_wtime = cpu_to_le32(get_seconds()); + sbi->nova_sb->s_sum = 0; + crc = nova_crc32c(~0, (__u8 *)sbi->nova_sb + sizeof(__le32), + sizeof(struct nova_super_block) - sizeof(__le32)); + sbi->nova_sb->s_sum = cpu_to_le32(crc); +} + + +static inline void nova_update_mount_time(struct super_block *sb) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + u64 mnt_write_time; + + mnt_write_time = (get_seconds() & 0xFFFFFFFF); + mnt_write_time = mnt_write_time | (mnt_write_time << 32); + + sbi->nova_sb->s_mtime = cpu_to_le64(mnt_write_time); + nova_update_super_crc(sb); + + nova_sync_super(sb); +} + static struct nova_inode *nova_init(struct super_block *sb, unsigned long size) { @@ -328,6 +371,7 @@ static struct nova_inode *nova_init(struct super_block *sb, sbi->nova_sb->s_blocksize = cpu_to_le32(blocksize); sbi->nova_sb->s_magic = cpu_to_le32(NOVA_SUPER_MAGIC); sbi->nova_sb->s_epoch_id = 0; + nova_update_super_crc(sb); nova_sync_super(sb); @@ -369,6 +413,54 @@ static void nova_root_check(struct super_block *sb, struct nova_inode *root_pi) nova_warn("root is not a directory!\n"); } +/* Check super block magic and checksum */ +static int nova_check_super(struct super_block *sb, + struct nova_super_block *ps) +{ + struct nova_sb_info *sbi = NOVA_SB(sb); + int rc; + + rc = memcpy_mcsafe(sbi->nova_sb, ps, + sizeof(struct nova_super_block)); + + if (rc < 0) + return rc; + + if (le32_to_cpu(sbi->nova_sb->s_magic) != NOVA_SUPER_MAGIC) + return -EIO; + + if (nova_check_super_checksum(sb)) + return -EIO; + + return 0; +} + +static int nova_check_integrity(struct super_block *sb) +{ + struct nova_super_block *super = nova_get_super(sb); + struct nova_super_block *super_redund; + int rc; + + super_redund = nova_get_redund_super(sb); + + /* Do sanity checks on the superblock */ + rc = nova_check_super(sb, super); + if (rc < 0) { + rc = nova_check_super(sb, super_redund); + if (rc < 0) { + nova_err(sb, "Can't find a valid nova partition\n"); + return rc; + } else { + nova_warn("Error in super block: try to repair it with the other copy\n"); + memcpy_to_pmem_nocache((void *)super, (void *)super_redund, + sizeof(struct nova_super_block)); + PERSISTENT_BARRIER(); + } + } + + return 0; +} + static int nova_fill_super(struct super_block *sb, void *data, int silent) { struct nova_sb_info *sbi = NULL; @@ -446,6 +538,13 @@ static int nova_fill_super(struct super_block *sb, void *data, int silent) goto setup_sb; } + if (nova_check_integrity(sb) < 0) { + retval = -EINVAL; + nova_dbg("Memory contains invalid nova %x:%x\n", + le32_to_cpu(sbi->nova_sb->s_magic), NOVA_SUPER_MAGIC); + goto out; + } + blocksize = le32_to_cpu(sbi->nova_sb->s_blocksize); nova_set_blocksize(sb, blocksize); @@ -482,6 +581,9 @@ static int nova_fill_super(struct super_block *sb, void *data, int silent) goto out; } + if (!(sb->s_flags & MS_RDONLY)) + nova_update_mount_time(sb); + retval = 0; return retval; -- 2.7.4