From patchwork Sat Mar 10 18:17:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andiry Xu X-Patchwork-Id: 10273811 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E4DB3602BD for ; Sat, 10 Mar 2018 18:20:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D380E28BAE for ; Sat, 10 Mar 2018 18:20:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C511329106; Sat, 10 Mar 2018 18:20:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_NONE,T_DKIM_INVALID autolearn=no version=3.3.1 Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 30AEE299D0 for ; Sat, 10 Mar 2018 18:20:30 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D95CA2258AF05; Sat, 10 Mar 2018 10:14:10 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:400e:c05::244; helo=mail-pg0-x244.google.com; envelope-from=jix024@eng.ucsd.edu; receiver=linux-nvdimm@lists.01.org Received: from mail-pg0-x244.google.com (mail-pg0-x244.google.com [IPv6:2607:f8b0:400e:c05::244]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 73A222258AEFC for ; Sat, 10 Mar 2018 10:14:09 -0800 (PST) Received: by mail-pg0-x244.google.com with SMTP id l4so4831519pgp.11 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=eMzPT5hT3C2txyRpAN6QWue7JGqY5cGPFHGgw/ZQbuKwTZN/roAEctuxDfip6RRJmi 7En3Jsmpi0ylLtpG+Lha+7YbKp//d8x1a5gNrqhwV07HKHQpF5+xZtUgNGzSFCPgZYPu 9tqjW/gY4m7/WbW78pS0ylu6Rf/nbpqEIOojZEjq6NghZ9WElppFVuArOOQybNXBo0FD LOpjM9AvTJFeCsgYkInYx7bA3o1fOG53DMMigZKe+Cag470V2BSww7sDsaMObiG8S8FV 1cEe/8qKYUMImzJw23mJHN7dsp/x9iESj3laOCi8cihsW6KuDN7ysUG5VcVTvXL3mdtF FQtQ== X-Gm-Message-State: AElRT7HMUslauj+d9+BlU9iePBpXPeRlxUC3Bj1t/KbFPdMKZoAJ/afl xDHCbws+tujeZc+r21W6wtH7ng== X-Google-Smtp-Source: AG47ELuW02Mrq/qLv/j12PINGXh58/vKyXi/4H54qKcC80oKYgBIEXOp0bQBCJbCY+pUcktJGy1TAg== 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 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> X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: coughlan@redhat.com, miklos@szeredi.hu, Andiry Xu , david@fromorbit.com, jack@suse.com, swanson@cs.ucsd.edu, swhiteho@redhat.com, andiry.xu@gmail.com MIME-Version: 1.0 Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Virus-Scanned: ClamAV using ClamSMTP 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;