From patchwork Tue Oct 1 01:27:14 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Darrick Wong X-Patchwork-Id: 279284 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 DFC212C0097 for ; Tue, 1 Oct 2013 11:27:20 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755380Ab3JAB1U (ORCPT ); Mon, 30 Sep 2013 21:27:20 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:22379 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755345Ab3JAB1T (ORCPT ); Mon, 30 Sep 2013 21:27:19 -0400 Received: from acsinet21.oracle.com (acsinet21.oracle.com [141.146.126.237]) by aserp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r911RIIp021621 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 1 Oct 2013 01:27:18 GMT Received: from userz7022.oracle.com (userz7022.oracle.com [156.151.31.86]) by acsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r911RHr5002715 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 1 Oct 2013 01:27:17 GMT Received: from abhmt118.oracle.com (abhmt118.oracle.com [141.146.116.70]) by userz7022.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r911RG24005878; Tue, 1 Oct 2013 01:27:16 GMT Received: from localhost (/10.137.226.112) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 30 Sep 2013 18:27:16 -0700 Subject: [PATCH 05/31] libext2fs: Add space for metadata checksum when unconverting a hashed directory block To: tytso@mit.edu, darrick.wong@oracle.com From: "Darrick J. Wong" Cc: linux-ext4@vger.kernel.org Date: Mon, 30 Sep 2013 18:27:14 -0700 Message-ID: <20131001012714.28415.87579.stgit@birch.djwong.org> In-Reply-To: <20131001012642.28415.89353.stgit@birch.djwong.org> References: <20131001012642.28415.89353.stgit@birch.djwong.org> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Source-IP: acsinet21.oracle.com [141.146.126.237] Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org The ext2fs_link function has the unfortunate habit of converting hashed directories into unhashed directories. It doesn't notice that it's slicing and dicing directory entries from a former dx_{root,node} block, and therefore doesn't write a protective dirent into the end of the block to store the checksum. Teach it to do this. Signed-off-by: Darrick J. Wong --- lib/ext2fs/link.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c index e3ff450..24fa083 100644 --- a/lib/ext2fs/link.c +++ b/lib/ext2fs/link.c @@ -42,6 +42,7 @@ static int link_proc(struct ext2_dir_entry *dirent, unsigned int rec_len, min_rec_len, curr_rec_len; int ret = 0; int csum_size = 0; + struct ext2_dir_entry_tail *t; if (ls->done) return 0; @@ -71,6 +72,40 @@ static int link_proc(struct ext2_dir_entry *dirent, } /* + * Since ext2fs_link blows away htree data, we need to be careful -- + * if metadata_csum is enabled and we're passed in a dirent that + * contains htree data, we need to create the fake entry at the end + * of the block that hides the checksum. + */ + + /* De-convert a dx_node block */ + if (csum_size && + curr_rec_len == ls->fs->blocksize && + !dirent->inode) { + curr_rec_len -= csum_size; + ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent); + if (ls->err) + return DIRENT_ABORT; + t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize); + ext2fs_initialize_dirent_tail(ls->fs, t); + ret = DIRENT_CHANGED; + } + + /* De-convert a dx_root block */ + if (csum_size && + curr_rec_len == ls->fs->blocksize - EXT2_DIR_REC_LEN(1) && + offset == EXT2_DIR_REC_LEN(1) && + dirent->name[0] == '.' && dirent->name[1] == '.') { + curr_rec_len -= csum_size; + ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent); + if (ls->err) + return DIRENT_ABORT; + t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize); + ext2fs_initialize_dirent_tail(ls->fs, t); + ret = DIRENT_CHANGED; + } + + /* * If the directory entry is used, see if we can split the * directory entry to make room for the new name. If so, * truncate it and return. @@ -152,6 +187,11 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) return retval; + /* + * If this function changes to preserve the htree, remove the two + * hunks in link_proc that shove checksum tails into the former + * dx_root/dx_node blocks. + */ if (inode.i_flags & EXT2_INDEX_FL) { inode.i_flags &= ~EXT2_INDEX_FL; if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)