From patchwork Wed Mar 8 02:41:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9610235 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 A54D9604DD for ; Wed, 8 Mar 2017 02:43:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 984DD2857C for ; Wed, 8 Mar 2017 02:43:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8CF7C285AE; Wed, 8 Mar 2017 02:43: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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1EB5A28593 for ; Wed, 8 Mar 2017 02:43:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933626AbdCHCnX (ORCPT ); Tue, 7 Mar 2017 21:43:23 -0500 Received: from cn.fujitsu.com ([59.151.112.132]:15282 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S933529AbdCHCnU (ORCPT ); Tue, 7 Mar 2017 21:43:20 -0500 X-IronPort-AV: E=Sophos;i="5.22,518,1449504000"; d="scan'208";a="16316952" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 08 Mar 2017 10:41:54 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id 130C0481857C; Wed, 8 Mar 2017 10:41:50 +0800 (CST) Received: from localhost.localdomain (10.167.226.34) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 8 Mar 2017 10:41:50 +0800 From: Qu Wenruo To: , , , Subject: [PATCH v3 4/7] btrfs: Introduce extra_rw_degrade_errors parameter for btrfs_check_rw_degradable Date: Wed, 8 Mar 2017 10:41:21 +0800 Message-ID: <20170308024124.16899-5-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170308024124.16899-1-quwenruo@cn.fujitsu.com> References: <20170308024124.16899-1-quwenruo@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.226.34] X-yoursite-MailScanner-ID: 130C0481857C.AA2F7 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: quwenruo@cn.fujitsu.com Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Introduce a new structure, extra_rw_degrade_errors, to record devid<->error mapping. This strucutre will have a array to record runtime error, which affects degraded mount, like failure to flush or wait one device. Also allow btrfs_check_rw_degradable() to accept such structure as another error source other than btrfs_device->missing. Signed-off-by: Qu Wenruo --- fs/btrfs/disk-io.c | 3 ++- fs/btrfs/super.c | 2 +- fs/btrfs/volumes.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/btrfs/volumes.h | 36 ++++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3de89283d400..658b8fab1d39 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3058,7 +3058,8 @@ int open_ctree(struct super_block *sb, goto fail_sysfs; } - if (!(sb->s_flags & MS_RDONLY) && !btrfs_check_rw_degradable(fs_info)) { + if (!(sb->s_flags & MS_RDONLY) && + !btrfs_check_rw_degradable(fs_info, NULL)) { btrfs_warn(fs_info, "writeable mount is not allowed due to too many missing devices"); goto fail_sysfs; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1f5772501c92..06bd9b332e18 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1785,7 +1785,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) } if (!(*flags & MS_RDONLY) && - !btrfs_check_rw_degradable(fs_info)) { + !btrfs_check_rw_degradable(fs_info, NULL)) { btrfs_warn(fs_info, "too many missing devices, writeable remount is not allowed"); ret = -EACCES; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 3fb760cd5bad..f44f7f428848 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6765,13 +6765,72 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info) return -EIO; } +void record_extra_rw_degrade_error(struct extra_rw_degrade_errors *errors, + u64 devid) +{ + int i; + bool inserted = false; + + if (!errors) + return; + + spin_lock(&errors->lock); + for (i = 0; i < errors->nr_devs; i++) { + struct rw_degrade_error *error = &errors->errors[i]; + + if (!error->initialized) { + error->devid = devid; + error->initialized = true; + error->err = true; + inserted = true; + break; + } + if (error->devid == devid) { + error->err = true; + inserted = true; + break; + } + } + spin_unlock(&errors->lock); + /* + * We iterate all the error records but still found no empty slot + * This means errors->nr_devs is not correct. + */ + WARN_ON(!inserted); +} + +static bool device_has_rw_degrade_error(struct extra_rw_degrade_errors *errors, + u64 devid) +{ + int i; + bool ret = false; + + if (!errors) + return ret; + + spin_lock(&errors->lock); + for (i = 0; i < errors->nr_devs; i++) { + struct rw_degrade_error *error = &errors->errors[i]; + + if (!error->initialized) + break; + if (error->devid == devid) { + ret = true; + break; + } + } + spin_unlock(&errors->lock); + return ret; +} + /* * Check if all chunks in the fs is OK for read-write degraded mount * * Return true if the fs is OK to be mounted degraded read-write * Return false if the fs is not OK to be mounted degraded */ -bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info) +bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info, + struct extra_rw_degrade_errors *errors) { struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; struct extent_map *em; @@ -6796,7 +6855,10 @@ bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info) btrfs_get_num_tolerated_disk_barrier_failures( map->type); for (i = 0; i < map->num_stripes; i++) { - if (map->stripes[i].dev->missing) + struct btrfs_device *device = map->stripes[i].dev; + + if (device->missing || + device_has_rw_degrade_error(errors, device->devid)) missing++; } if (missing > max_tolerated) { diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index db1b5ef479cf..67d7474e42a3 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -538,5 +538,39 @@ struct list_head *btrfs_get_fs_uuids(void); void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info); void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info); -bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info); +/* + * For btrfs_check_rw_degradable() to check extra error from + * barrier_all_devices() + */ +struct rw_degrade_error { + u64 devid; + bool initialized; + bool err; +}; + +struct extra_rw_degrade_errors { + int nr_devs; + spinlock_t lock; + struct rw_degrade_error errors[]; +}; + +static inline struct extra_rw_degrade_errors *alloc_extra_rw_degrade_errors( + int nr_devs) +{ + struct extra_rw_degrade_errors *ret; + + ret = kzalloc(sizeof(struct extra_rw_degrade_errors) + nr_devs * + sizeof(struct rw_degrade_error), GFP_NOFS); + if (!ret) + return ret; + spin_lock_init(&ret->lock); + ret->nr_devs = nr_devs; + return ret; +} + +void record_extra_rw_degrade_error(struct extra_rw_degrade_errors *errors, + u64 devid); + +bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info, + struct extra_rw_degrade_errors *errors); #endif