From patchwork Wed Aug 26 22:12:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 7080431 Return-Path: X-Original-To: patchwork-ocfs2-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B8A28BEEC1 for ; Wed, 26 Aug 2015 22:12:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C577A208DE for ; Wed, 26 Aug 2015 22:12:49 +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 665E8208D7 for ; Wed, 26 Aug 2015 22:12:48 +0000 (UTC) Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id t7QMCfYB012891 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 26 Aug 2015 22:12:42 GMT Received: from oss.oracle.com (oss-old-reserved.oracle.com [137.254.22.2]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id t7QMCfBH007973 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 26 Aug 2015 22:12:41 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 1ZUivx-00072g-32; Wed, 26 Aug 2015 15:12:41 -0700 Received: from aserv0022.oracle.com ([141.146.126.234]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1ZUivu-00072J-MH for ocfs2-devel@oss.oracle.com; Wed, 26 Aug 2015 15:12:38 -0700 Received: from aserp1020.oracle.com (aserp1020.oracle.com [141.146.126.67]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id t7QMCcvK013029 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 26 Aug 2015 22:12:38 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 t7QMCbV0010354 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 26 Aug 2015 22:12:38 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 t7QM8h0l041966 for ; Wed, 26 Aug 2015 22:12:37 GMT Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) by userp2040.oracle.com with ESMTP id 1whb7wgwks-1 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 26 Aug 2015 22:12:37 +0000 Received: from akpm3.mtv.corp.google.com (unknown [216.239.45.65]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 936C9E47; Wed, 26 Aug 2015 22:12:36 +0000 (UTC) Date: Wed, 26 Aug 2015 15:12:36 -0700 From: akpm@linux-foundation.org To: ocfs2-devel@oss.oracle.com, akpm@linux-foundation.org, ghe@suse.com, jlbec@evilplan.org, mfasheh@suse.com, rgoldwyn@suse.de Message-ID: <55de39d4.hW5RHoJSnnEelK16%akpm@linux-foundation.org> User-Agent: Heirloom mailx 12.5 6/20/10 MIME-Version: 1.0 X-Proofpoint-SPF-Result: pass X-Proofpoint-SPF-Record: v=spf1 ip4:140.211.169.12/30 include:_spf.google.com ~all X-ServerName: mail.linuxfoundation.org X-Proofpoint-Virus-Version: vendor=nai engine=5700 definitions=7905 signatures=670626 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1507310000 definitions=main-1508260346 Subject: [Ocfs2-devel] [patch 28/28] ocfs2: add file extent block check 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: userv0021.oracle.com [156.151.31.71] X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, 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 From: Gang He Subject: ocfs2: add file extent block check Add file extent block online check, besides inode block online check, we will add more kinds of meta block online check/repair. Signed-off-by: Gang He Cc: Mark Fasheh Cc: Joel Becker Cc: Goldwyn Rodrigues Signed-off-by: Andrew Morton --- fs/ocfs2/filecheck.c | 247 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 239 insertions(+), 8 deletions(-) diff -puN fs/ocfs2/filecheck.c~ocfs2-add-file-extent-block-check fs/ocfs2/filecheck.c --- a/fs/ocfs2/filecheck.c~ocfs2-add-file-extent-block-check +++ a/fs/ocfs2/filecheck.c @@ -462,38 +462,269 @@ ocfs2_filecheck_done_entry(struct ocfs2_ spin_unlock(&ent->fs_fcheck->fc_lock); } +static int +ocfs2_filecheck_inode_block(struct super_block *sb, unsigned long ino, + unsigned int flags, struct inode **ret) +{ + int rc = 0; + struct inode *inode; + + if (flags == OCFS2_FILECHECK_TYPE_CHK) + flags = OCFS2_FI_FLAG_FILECHECK_CHK; + else + flags = OCFS2_FI_FLAG_FILECHECK_FIX; + + inode = ocfs2_iget(OCFS2_SB(sb), ino, flags, 0); + if (IS_ERR(inode)) + rc = (int)(long)inode; + else + *ret = inode; + + return rc; +} + +static int +ocfs2_filecheck_extent_list(handle_t *handle, struct inode *inode, + unsigned int flags, struct ocfs2_extent_list *el) +{ + int i, rc = 0; + u64 blkno; + struct buffer_head *bh = NULL; + struct ocfs2_extent_block *eb; + struct ocfs2_extent_list *ell; + + if (!el || !el->l_tree_depth) + return 0; + + mlog(ML_NOTICE, "ocfs2_filecheck_extent_list: inode %llu tree_depth " + "%u count %u next_free_rec %u\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + le16_to_cpu(el->l_tree_depth), + le16_to_cpu(el->l_count), + le16_to_cpu(el->l_next_free_rec)); + + if (le16_to_cpu(el->l_next_free_rec) == 0) { + mlog(ML_ERROR, + "Inode %llu has empty extent list at depth %u\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + le16_to_cpu(el->l_tree_depth)); + rc = -EROFS; + goto out; + } + + if (le16_to_cpu(el->l_next_free_rec) > le16_to_cpu(el->l_count)) { + mlog(ML_ERROR, + "Inode %llu has bad count in extent list " + "at depth %u (next free=%u, count=%u)\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + le16_to_cpu(el->l_tree_depth), + le16_to_cpu(el->l_next_free_rec), + le16_to_cpu(el->l_count)); + rc = -EROFS; + goto out; + } + + for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { + blkno = le64_to_cpu(el->l_recs[i].e_blkno); + if (blkno == 0) { + mlog(ML_ERROR, + "Inode %llu has bad blkno in extent list " + "at depth %u (index %d)\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + le16_to_cpu(el->l_tree_depth), i); + rc = -EROFS; + goto out; + } + + mlog(ML_NOTICE, "ocfs2_filecheck_extent_list: inode %llu " + "rec[%d]: cpos %u clusters %u blkno %llu\n ", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + i, + le32_to_cpu(el->l_recs[i].e_cpos), + le32_to_cpu(el->l_recs[i].e_int_clusters), + le64_to_cpu(el->l_recs[i].e_blkno)); + + brelse(bh); + bh = NULL; + + rc = ocfs2_filecheck_read_extent_block(INODE_CACHE(inode), + blkno, &bh, flags); + if (rc) { + mlog_errno(rc); + goto out; + } + + if (flags && buffer_dirty(bh)) { + /* Dirty buffer means that filecheck just repaired + * this buffer during reading it from disk. + */ + clear_buffer_dirty(bh); + + rc = ocfs2_extend_trans(handle, + OCFS2_EXTENT_BLOCK_UPDATE_CREDITS); + if (rc) { + mlog_errno(rc); + goto out; + } + + rc = ocfs2_journal_access_eb(handle, + INODE_CACHE(inode), bh, + OCFS2_JOURNAL_ACCESS_WRITE); + if (rc < 0) { + mlog_errno(rc); + goto out; + } + + ocfs2_journal_dirty(handle, bh); + } + + eb = (struct ocfs2_extent_block *)bh->b_data; + ell = &eb->h_list; + rc = ocfs2_filecheck_extent_list(handle, inode, flags, ell); + if (rc) + goto out; + } + +out: + brelse(bh); + return rc; +} + +static int +ocfs2_filecheck_extent_block(struct inode *inode, struct buffer_head *di_bh, + unsigned int flags) +{ + int rc = 0; + handle_t *handle = NULL; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + struct ocfs2_dinode *di; + struct ocfs2_extent_list *el; + + if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) + return 0; + + if (flags) { + handle = ocfs2_start_trans(osb, + OCFS2_EXTENT_BLOCK_UPDATE_CREDITS); + if (IS_ERR(handle)) { + rc = PTR_ERR(handle); + mlog_errno(rc); + goto out; + } + } + + di = (struct ocfs2_dinode *)di_bh->b_data; + el = &di->id2.i_list; + rc = ocfs2_filecheck_extent_list(handle, inode, flags, el); + + if (flags) + ocfs2_commit_trans(osb, handle); + +out: + return rc; +} + +static int +ocfs2_filecheck_file_block(struct inode *inode, unsigned int flags) +{ + int rc; + struct buffer_head *di_bh = NULL; + + mutex_lock(&inode->i_mutex); + + rc = ocfs2_rw_lock(inode, 1); + if (rc) { + mlog_errno(rc); + goto out; + } + + rc = ocfs2_inode_lock(inode, &di_bh, 1); + if (rc) { + mlog_errno(rc); + goto out_rw_unlock; + } + + do { + down_write(&OCFS2_I(inode)->ip_alloc_sem); + rc = ocfs2_filecheck_extent_block(inode, di_bh, flags); + up_write(&OCFS2_I(inode)->ip_alloc_sem); + if (rc) + break; + + /* TODO: Add check/fix for xattr/refcount blocks */ + + } while (0); + + brelse(di_bh); + ocfs2_inode_unlock(inode, 1); +out_rw_unlock: + ocfs2_rw_unlock(inode, 1); +out: + mutex_unlock(&inode->i_mutex); + + return rc; +} + +static int +ocfs2_filecheck_other_block(struct inode *inode, unsigned int flags) +{ + int rc = 0; + + switch (inode->i_mode & S_IFMT) { + case S_IFREG: + rc = ocfs2_filecheck_file_block(inode, flags); + break; + case S_IFDIR: + /* TODO: Add check/fix for directory blocks */ + break; + default: + break; + } + + return rc; +} + static unsigned short ocfs2_filecheck_handle(struct super_block *sb, unsigned long ino, unsigned int flags) { + int rc; unsigned short ret = OCFS2_FILECHECK_ERR_SUCCESS; struct inode *inode = NULL; - int rc; - inode = ocfs2_iget(OCFS2_SB(sb), ino, flags, 0); - if (IS_ERR(inode)) { - rc = (int)(-(long)inode); + do { + rc = ocfs2_filecheck_inode_block(sb, ino, flags, &inode); + if (rc) + break; + + rc = ocfs2_filecheck_other_block(inode, flags); + } while (0); + + if (rc) { + rc = (-rc); if (rc >= OCFS2_FILECHECK_ERR_START && rc < OCFS2_FILECHECK_ERR_END) ret = rc; else ret = OCFS2_FILECHECK_ERR_FAILED; - } else + } + + if (inode) iput(inode); return ret; } -static void +static inline void ocfs2_filecheck_handle_entry(struct ocfs2_filecheck_sysfs_entry *ent, struct ocfs2_filecheck_entry *entry) { if (entry->fe_type == OCFS2_FILECHECK_TYPE_CHK) entry->fe_status = ocfs2_filecheck_handle(ent->fs_sb, - entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_CHK); + entry->fe_ino, OCFS2_FILECHECK_TYPE_CHK); else if (entry->fe_type == OCFS2_FILECHECK_TYPE_FIX) entry->fe_status = ocfs2_filecheck_handle(ent->fs_sb, - entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_FIX); + entry->fe_ino, OCFS2_FILECHECK_TYPE_FIX); else entry->fe_status = OCFS2_FILECHECK_ERR_UNSUPPORTED;