From patchwork Wed Nov 25 01:08:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shichangkuo X-Patchwork-Id: 7694651 Return-Path: X-Original-To: patchwork-ocfs2-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 835C39F4F5 for ; Wed, 25 Nov 2015 01:10:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CC3F620893 for ; Wed, 25 Nov 2015 01:09:58 +0000 (UTC) Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BA25A2084E for ; Wed, 25 Nov 2015 01:09:56 +0000 (UTC) Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id tAP193EY007918 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 25 Nov 2015 01:09:04 GMT Received: from oss.oracle.com (oss-old-reserved.oracle.com [137.254.22.2]) by userv0022.oracle.com (8.13.8/8.13.8) with ESMTP id tAP191wC028424 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 25 Nov 2015 01:09:02 GMT Received: from localhost ([127.0.0.1] helo=lb-oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1a1OZx-0005Nh-Nb; Tue, 24 Nov 2015 17:09:01 -0800 Received: from aserv0021.oracle.com ([141.146.126.233]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1a1OZv-0005NX-7J for ocfs2-devel@oss.oracle.com; Tue, 24 Nov 2015 17:08:59 -0800 Received: from aserp1020.oracle.com (aserp1020.oracle.com [141.146.126.67]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id tAP18wdr032513 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 25 Nov 2015 01:08:58 GMT Received: from userp2040.oracle.com (userp2040.oracle.com [156.151.31.90]) by aserp1020.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id tAP18vTW017872 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 25 Nov 2015 01:08:58 GMT Received: from pps.filterd (userp2040.oracle.com [127.0.0.1]) by userp2040.oracle.com (8.15.0.59/8.15.0.59) with SMTP id tAP18vhR009425 for ; Wed, 25 Nov 2015 01:08:57 GMT Received: from h3cmg01-ex.h3c.com (smtp.h3c.com [221.12.31.13] (may be forged)) by userp2040.oracle.com with ESMTP id 1yc6jn5v1j-1 for ; Wed, 25 Nov 2015 01:08:57 +0000 Received: from H3CHUB03-EX.srv.huawei-3com.com (unknown [10.63.20.169]) by h3cmg01-ex.h3c.com with smtp id 692b_01ad_2d8f03c3_80e3_4aff_b639_5ece14ee2815; Wed, 25 Nov 2015 09:08:30 +0800 Received: from H3CMLB12-EX.srv.huawei-3com.com ([fe80::f091:bd11:f0a9:5cbe]) by H3CHUB03-EX.srv.huawei-3com.com ([fe80::ec6c:67e6:67f8:ce53%15]) with mapi id 14.01.0355.002; Wed, 25 Nov 2015 09:08:19 +0800 From: Shichangkuo To: Joseph Qi , Andrew Morton Thread-Topic: [Ocfs2-devel] [PATCH] ocfs2: fix BUG due to uncleaned localalloc during mount Thread-Index: AdEnHZJjmO9f5egvTN2lKfdJINTrXg== Date: Wed, 25 Nov 2015 01:08:19 +0000 Message-ID: Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.153.28.132] MIME-Version: 1.0 X-Proofpoint-SPF-Result: None X-ServerName: [221.12.31.13] X-Proofpoint-Virus-Version: vendor=nai engine=5700 definitions=7995 signatures=670662 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1507310000 definitions=main-1511250021 Cc: Mark Fasheh , "ocfs2-devel@oss.oracle.com" Subject: Re: [Ocfs2-devel] [PATCH] ocfs2: fix BUG due to uncleaned localalloc during mount X-BeenThere: ocfs2-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ocfs2-devel-bounces@oss.oracle.com Errors-To: ocfs2-devel-bounces@oss.oracle.com X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Spam-Status: No, score=-2.9 required=5.0 tests=BAYES_20, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hi?Joseph Qi In this situation, ocfs2_begin_local_alloc_recovery will be called, and finally call ocfs2_clear_local_alloc, which direct clear la bitmap, like: alloc->id1.bitmap1.i_total = 0; alloc->id1.bitmap1.i_used = 0; la->la_bm_off = 0; for(i = 0; i < le16_to_cpu(la->la_size); i++) la->la_bitmap[i] = 0; It's different from fsck.ocfs2, also called function ocfs2_clear_local_alloc, but this function does more than direct clear la bitmap. Global bitmap will also be cleared. So, does this patch data-safe? -----????----- ???: ocfs2-devel-bounces@oss.oracle.com [mailto:ocfs2-devel-bounces@oss.oracle.com] ?? Joseph Qi ????: 2015?11?24? 21:38 ???: Andrew Morton ??: Mark Fasheh; ocfs2-devel@oss.oracle.com ??: [Ocfs2-devel] [PATCH] ocfs2: fix BUG due to uncleaned localalloc during mount Tariq has reported a BUG before and posted a fix at: https://oss.oracle.com/pipermail/ocfs2-devel/2015-April/010696.html This is because during umount, localalloc shutdown relies on journal shutdown. But during journal shutdown, it just stops commit thread without checking its result. So it may happen that localalloc shutdown uncleaned during I/O error and after that, journal then has been marked clean if I/O restores. Then during mount, localalloc won't be recovered because of clean journal and then trigger BUG when claiming clusters from localalloc. In Tariq's fix, we have to run fsck offline and a separate fix to fsck is needed because it currently does not support clearing out localalloc inode. And my way to fix this issue is checking localalloc before actually loading it during mount. And this is somewhat online. Signed-off-by: Joseph Qi --- fs/ocfs2/localalloc.c | 19 ++++++++++++------- fs/ocfs2/localalloc.h | 2 +- fs/ocfs2/super.c | 17 ++++++++++++++--- 3 files changed, 27 insertions(+), 11 deletions(-) -- 1.8.4.3 _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel@oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel ------------------------------------------------------------------------------------------------------------------------------------- ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ??? This e-mail and its attachments contain confidential information from H3C, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it! diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 0a4457f..ceebaef 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -281,7 +281,7 @@ bail: return ret; } -int ocfs2_load_local_alloc(struct ocfs2_super *osb) +int ocfs2_load_local_alloc(struct ocfs2_super *osb, int check, int +*recovery) { int status = 0; struct ocfs2_dinode *alloc = NULL; @@ -345,21 +345,26 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb) if (num_used || alloc->id1.bitmap1.i_used || alloc->id1.bitmap1.i_total - || la->la_bm_off) + || la->la_bm_off) { mlog(ML_ERROR, "Local alloc hasn't been recovered!\n" "found = %u, set = %u, taken = %u, off = %u\n", num_used, le32_to_cpu(alloc->id1.bitmap1.i_used), le32_to_cpu(alloc->id1.bitmap1.i_total), OCFS2_LOCAL_ALLOC(alloc)->la_bm_off); + status = -EINVAL; + *recovery = 1; + goto bail; + } - osb->local_alloc_bh = alloc_bh; - osb->local_alloc_state = OCFS2_LA_ENABLED; + if (!check) { + osb->local_alloc_bh = alloc_bh; + osb->local_alloc_state = OCFS2_LA_ENABLED; + } bail: - if (status < 0) + if (status < 0 || check) brelse(alloc_bh); - if (inode) - iput(inode); + iput(inode); trace_ocfs2_load_local_alloc(osb->local_alloc_bits); diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h index 44a7d1f..a913841 100644 --- a/fs/ocfs2/localalloc.h +++ b/fs/ocfs2/localalloc.h @@ -26,7 +26,7 @@ #ifndef OCFS2_LOCALALLOC_H #define OCFS2_LOCALALLOC_H -int ocfs2_load_local_alloc(struct ocfs2_super *osb); +int ocfs2_load_local_alloc(struct ocfs2_super *osb, int check, int +*recovery); void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 2de4c8a..4004b29 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -2428,6 +2428,7 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) int status; int dirty; int local; + int la_dirty = 0, recovery = 0; struct ocfs2_dinode *local_alloc = NULL; /* only used if we * recover * ourselves. */ @@ -2449,6 +2450,16 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) * recover anything. Otherwise, journal_load will do that * dirty work for us :) */ if (!dirty) { + /* It may happen that local alloc is unclean shutdown, but + * journal has been marked clean, so check it here and do + * recovery if needed */ + status = ocfs2_load_local_alloc(osb, 1, &recovery); + if (recovery) { + printk(KERN_NOTICE "ocfs2: local alloc needs recovery " + "on device (%s).\n", osb->dev_str); + la_dirty = 1; + } + status = ocfs2_journal_wipe(osb->journal, 0); if (status < 0) { mlog_errno(status); @@ -2477,7 +2488,7 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) JBD2_FEATURE_COMPAT_CHECKSUM, 0, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); - if (dirty) { + if (dirty || la_dirty) { /* recover my local alloc if we didn't unmount cleanly. */ status = ocfs2_begin_local_alloc_recovery(osb, osb->slot_num, @@ -2490,13 +2501,13 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) * ourselves as mounted. */ } - status = ocfs2_load_local_alloc(osb); + status = ocfs2_load_local_alloc(osb, 0, &recovery); if (status < 0) { mlog_errno(status); goto finally; } - if (dirty) { + if (dirty || la_dirty) { /* Recovery will be completed after we've mounted the * rest of the volume. */ osb->dirty = 1;