From patchwork Sat Nov 19 09:34:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yongqiang Yang X-Patchwork-Id: 126551 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id C5426B723B for ; Sat, 19 Nov 2011 23:08:09 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751197Ab1KSMIH (ORCPT ); Sat, 19 Nov 2011 07:08:07 -0500 Received: from mail-iy0-f174.google.com ([209.85.210.174]:35322 "EHLO mail-iy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750994Ab1KSMIG (ORCPT ); Sat, 19 Nov 2011 07:08:06 -0500 Received: by iage36 with SMTP id e36so4841730iag.19 for ; Sat, 19 Nov 2011 04:08:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; bh=wWM2Ybdl0wbyTrS4LTyfAJCR8rllGHIdEPkC84BEpVU=; b=Ba+CDPWpFEAii+j6lddakYPnis6cR31Ihkdt0aLxpM451HJzrrGgU2zJ4xxMllSjpd QMlvUnPcgpnKHBNydiJ1MiJOvqNiuVESGgGIZz3BT7BqMQh6Yl5y9epetUEte04wDi1o 1APv4XWLAv60KPr/wEPQ+42GnP0TRKfF5voNI= Received: by 10.50.47.168 with SMTP id e8mr7100929ign.15.1321704485269; Sat, 19 Nov 2011 04:08:05 -0800 (PST) Received: from localhost.localdomain ([159.226.43.42]) by mx.google.com with ESMTPS id ft1sm9040664igc.3.2011.11.19.04.08.03 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 19 Nov 2011 04:08:04 -0800 (PST) From: Yongqiang Yang To: jack@suse.cz Cc: linux-ext4@vger.kernel.org, Yongqiang Yang Subject: [PATCH v2] jbd: clear revoked flag on buffers before a new transaction started Date: Sat, 19 Nov 2011 17:34:29 +0800 Message-Id: <1321695269-3319-1-git-send-email-xiaoqiangnk@gmail.com> X-Mailer: git-send-email 1.7.5.1 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Currently, we clear revoked flag only when a block is reused. However, this can tigger a false journal error. Consider a situation when a block is used as a meta block and is deleted(revoked) in ordered mode, then the block is allocated as a data block to a file. At this moment, user changes the file's journal mode from ordered to journaled and truncates the file. The block will be considered re-revoked by journal because it has revoked flag still pending from the last transaction and an assertion triggers. We fix the problem by keeping the revoked status more uptodate - we clear revoked flag when switching revoke tables to reflect there is no revoked buffers in current transaction any more. Signed-off-by: Yongqiang Yang --- fs/jbd/commit.c | 6 ++++++ fs/jbd/revoke.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/jbd.h | 1 + 3 files changed, 41 insertions(+), 0 deletions(-) diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 8799207..f2b9a57 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -392,6 +392,12 @@ void journal_commit_transaction(journal_t *journal) jbd_debug (3, "JBD: commit phase 1\n"); /* + * Clear revoked flag to reflect there is no revoked buffers + * in the next transaction which is going to be started. + */ + journal_clear_buffer_revoked_flags(journal); + + /* * Switch to a new revoke table. */ journal_switch_revoke_table(journal); diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index 034eb82..501d363 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c @@ -47,6 +47,10 @@ * overwriting the new data. We don't even need to clear the revoke * bit here. * + * We cache revoke status of a buffer in the current transaction in b_states + * bits. As the name says, revokevalid flag indicates that the cached revoke + * status of a buffer is valid and we can rely on the cached status. + * * Revoke information on buffers is a tri-state value: * * RevokeValid clear: no cached revoke status, need to look it up @@ -474,6 +478,36 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) return did_revoke; } +/* + * journal_clear_revoked_flag clears revoked flag of buffers in + * revoke table to reflect there is no revoked buffers in the next + * transaction which is going to be started. + */ +void journal_clear_buffer_revoked_flags(journal_t *journal) +{ + struct jbd_revoke_table_s *revoke = journal->j_revoke; + int i = 0; + + for (i = 0; i < revoke->hash_size; i++) { + struct list_head *hash_list; + struct list_head *list_entry; + hash_list = &revoke->hash_table[i]; + + list_for_each(list_entry, hash_list) { + struct jbd_revoke_record_s *record; + struct buffer_head *bh; + record = (struct jbd_revoke_record_s *)list_entry; + bh = __find_get_block(journal->j_fs_dev, + record->blocknr, + journal->j_blocksize); + if (bh) { + clear_buffer_revoked(bh); + __brelse(bh); + } + } + } +} + /* journal_switch_revoke table select j_revoke for next transaction * we do not want to suspend any processing until all revokes are * written -bzzz diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 0f9f0b6..5aa964e 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -918,6 +918,7 @@ extern int journal_set_revoke(journal_t *, unsigned int, tid_t); extern int journal_test_revoke(journal_t *, unsigned int, tid_t); extern void journal_clear_revoke(journal_t *); extern void journal_switch_revoke_table(journal_t *journal); +extern void journal_clear_buffer_revoked_flags(journal_t *journal); /* * The log thread user interface: