Return-Path: X-Original-To: apmail-hadoop-hdfs-commits-archive@minotaur.apache.org Delivered-To: apmail-hadoop-hdfs-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 991B611231 for ; Fri, 20 Jun 2014 19:40:54 +0000 (UTC) Received: (qmail 50144 invoked by uid 500); 20 Jun 2014 19:40:54 -0000 Delivered-To: apmail-hadoop-hdfs-commits-archive@hadoop.apache.org Received: (qmail 50092 invoked by uid 500); 20 Jun 2014 19:40:54 -0000 Mailing-List: contact hdfs-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: hdfs-dev@hadoop.apache.org Delivered-To: mailing list hdfs-commits@hadoop.apache.org Received: (qmail 50081 invoked by uid 99); 20 Jun 2014 19:40:54 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 20 Jun 2014 19:40:54 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 20 Jun 2014 19:40:52 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 538BB2388831; Fri, 20 Jun 2014 19:40:32 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1604258 - in /hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs: CHANGES.txt src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java Date: Fri, 20 Jun 2014 19:40:32 -0000 To: hdfs-commits@hadoop.apache.org From: kihwal@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140620194032.538BB2388831@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kihwal Date: Fri Jun 20 19:40:31 2014 New Revision: 1604258 URL: http://svn.apache.org/r1604258 Log: HDFS-6527. Edit log corruption due to defered INode removal. Contributed by Jing Zhao and Kihwal Lee. Added: hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java (with props) Modified: hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java Modified: hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt?rev=1604258&r1=1604257&r2=1604258&view=diff ============================================================================== --- hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt (original) +++ hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt Fri Jun 20 19:40:31 2014 @@ -89,6 +89,9 @@ Release 2.4.1 - 2014-06-23 HDFS-6411. nfs-hdfs-gateway mount raises I/O error and hangs when a unauthorized user attempts to access it (brandonli) + HDFS-6527. Edit log corruption due to defered INode removal. (kihwal and + jing9 via jing9) + Release 2.4.0 - 2014-04-07 INCOMPATIBLE CHANGES Modified: hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java?rev=1604258&r1=1604257&r2=1604258&view=diff ============================================================================== --- hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java (original) +++ hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java Fri Jun 20 19:40:31 2014 @@ -2962,6 +2962,13 @@ public class FSNamesystem implements Nam + (lease != null ? lease.toString() : "Holder " + holder + " does not have any open files.")); } + // No further modification is allowed on a deleted file. + // A file is considered deleted, if it has no parent or is marked + // as deleted in the snapshot feature. + if (file.getParent() == null || (file.isWithSnapshot() && + file.getFileWithSnapshotFeature().isCurrentFileDeleted())) { + throw new FileNotFoundException(src); + } String clientName = file.getFileUnderConstructionFeature().getClientName(); if (holder != null && !clientName.equals(holder)) { throw new LeaseExpiredException("Lease mismatch on " + src + " owned by " @@ -3371,6 +3378,7 @@ public class FSNamesystem implements Nam getEditLog().logSync(); removeBlocks(collectedBlocks); // Incremental deletion of blocks collectedBlocks.clear(); + dir.writeLock(); try { dir.removeFromInodeMap(removedINodes); Added: hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java?rev=1604258&view=auto ============================================================================== --- hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java (added) +++ hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java Fri Jun 20 19:40:31 2014 @@ -0,0 +1,149 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hdfs.server.namenode; + +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FSDataOutputStream; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hdfs.DFSConfigKeys; +import org.apache.hadoop.hdfs.DistributedFileSystem; +import org.apache.hadoop.hdfs.HdfsConfiguration; +import org.apache.hadoop.hdfs.MiniDFSCluster; +import org.apache.hadoop.hdfs.StorageType; +import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicy; +import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyDefault; +import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStorageInfo; +import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotTestHelper; +import org.apache.hadoop.net.Node; +import org.apache.hadoop.test.GenericTestUtils; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.internal.util.reflection.Whitebox; + + +/** + * Test race between delete and other operations. For now only addBlock() + * is tested since all others are acquiring FSNamesystem lock for the + * whole duration. + */ +public class TestDeleteRace { + private static final Log LOG = LogFactory.getLog(TestDeleteRace.class); + private static final Configuration conf = new HdfsConfiguration(); + private MiniDFSCluster cluster; + + @Test + public void testDeleteAddBlockRace() throws Exception { + testDeleteAddBlockRace(false); + } + + @Test + public void testDeleteAddBlockRaceWithSnapshot() throws Exception { + testDeleteAddBlockRace(true); + } + + private void testDeleteAddBlockRace(boolean hasSnapshot) throws Exception { + try { + conf.setClass(DFSConfigKeys.DFS_BLOCK_REPLICATOR_CLASSNAME_KEY, + SlowBlockPlacementPolicy.class, BlockPlacementPolicy.class); + cluster = new MiniDFSCluster.Builder(conf).build(); + FileSystem fs = cluster.getFileSystem(); + final String fileName = "/testDeleteAddBlockRace"; + Path filePath = new Path(fileName); + + FSDataOutputStream out = null; + out = fs.create(filePath); + if (hasSnapshot) { + SnapshotTestHelper.createSnapshot((DistributedFileSystem) fs, new Path( + "/"), "s1"); + } + + Thread deleteThread = new DeleteThread(fs, filePath); + deleteThread.start(); + + try { + // write data and syn to make sure a block is allocated. + out.write(new byte[32], 0, 32); + out.hsync(); + Assert.fail("Should have failed."); + } catch (Exception e) { + GenericTestUtils.assertExceptionContains(filePath.getName(), e); + } + } finally { + if (cluster != null) { + cluster.shutdown(); + } + } + } + + private static class SlowBlockPlacementPolicy extends + BlockPlacementPolicyDefault { + @Override + public DatanodeStorageInfo[] chooseTarget(String srcPath, + int numOfReplicas, + Node writer, + List chosenNodes, + boolean returnChosenNodes, + Set excludedNodes, + long blocksize, + StorageType storageType) { + DatanodeStorageInfo[] results = super.chooseTarget(srcPath, + numOfReplicas, writer, chosenNodes, returnChosenNodes, excludedNodes, + blocksize, storageType); + try { + Thread.sleep(3000); + } catch (InterruptedException e) {} + return results; + } + } + + private class DeleteThread extends Thread { + private FileSystem fs; + private Path path; + + DeleteThread(FileSystem fs, Path path) { + this.fs = fs; + this.path = path; + } + + @Override + public void run() { + try { + Thread.sleep(1000); + LOG.info("Deleting" + path); + final FSDirectory fsdir = cluster.getNamesystem().dir; + INode fileINode = fsdir.getINode4Write(path.toString()); + INodeMap inodeMap = (INodeMap) Whitebox.getInternalState(fsdir, + "inodeMap"); + + fs.delete(path, false); + // after deletion, add the inode back to the inodeMap + inodeMap.put(fileINode); + LOG.info("Deleted" + path); + } catch (Exception e) { + LOG.info(e); + } + } + } +} Propchange: hadoop/common/branches/branch-2.4.1/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestDeleteRace.java ------------------------------------------------------------------------------ svn:eol-style = native