[ 
https://issues.apache.org/jira/browse/HDFS-3981?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Konstantin Shvachko updated HDFS-3981:
--------------------------------------

          Description: Incorrect condition in 
{{FSNamesystem.getBlockLocatoins()}} can lead to updating times without write 
lock. In most cases this condition will force 
{{FSNamesystem.getBlockLocatoins()}} to hold write lock, even if times do not 
need to be updated.  (was: If now > inode.getAccessTime() + 
getAccessTimePrecision() when attempt == 0, we will call dir.setTimes(src, 
inode, -1, now, false) without writelock. So there will be races and an ealier 
access time might overwrite a later access time. Looks like we need to change 
the code to 
{code}

        if (doAccessTime && isAccessTimeSupported()) {
          if (now > inode.getAccessTime() + getAccessTimePrecision()) {
            // if we have to set access time but we only have the readlock, then
            // restart this entire operation with the writeLock.
            if (attempt == 0) {
              continue;
            }
            dir.setTimes(src, inode, -1, now, false);
          }
        }
{code}

Also, seems we need to release readlock before trying to acquire writelock. 
Otherwise, we might end up with still holding readlock after the function call. 
Or we could simply remove the condition "if (attempt == 0)" for readUnlock(), 
i.e. readUnlock() should be called even if attempt is 1.

The following code is from branch-2.0.1-alpha
{code:title=FSNamesystem.java|borderStyle=solid}
  private LocatedBlocks getBlockLocationsUpdateTimes(String src,
                                                       long offset, 
                                                       long length,
                                                       boolean doAccessTime, 
                                                       boolean needBlockToken)
      throws FileNotFoundException, UnresolvedLinkException, IOException {

    for (int attempt = 0; attempt < 2; attempt++) {
      if (attempt == 0) { // first attempt is with readlock
        readLock();
      }  else { // second attempt is with  write lock
        writeLock(); // writelock is needed to set accesstime
      }
      try {
        checkOperation(OperationCategory.READ);

        // if the namenode is in safemode, then do not update access time
        if (isInSafeMode()) {
          doAccessTime = false;
        }

        long now = now();
        INodeFile inode = dir.getFileINode(src);
        if (inode == null) {
          throw new FileNotFoundException("File does not exist: " + src);
        }
        assert !inode.isLink();
        if (doAccessTime && isAccessTimeSupported()) {
          if (now <= inode.getAccessTime() + getAccessTimePrecision()) {
            // if we have to set access time but we only have the readlock, then
            // restart this entire operation with the writeLock.
            if (attempt == 0) {
              continue;
            }
          }
          dir.setTimes(src, inode, -1, now, false);
        }
        return blockManager.createLocatedBlocks(inode.getBlocks(),
            inode.computeFileSize(false), inode.isUnderConstruction(),
            offset, length, needBlockToken);
      } finally {
        if (attempt == 0) {
          readUnlock();
        } else {
          writeUnlock();
        }
      }
    }
    return null; // can never reach here
  }
{code})
     Target Version/s: 0.23.4
    Affects Version/s:     (was: 2.0.1-alpha)
                       0.23.3
    
> access time is set without holding writelock in FSNamesystem
> ------------------------------------------------------------
>
>                 Key: HDFS-3981
>                 URL: https://issues.apache.org/jira/browse/HDFS-3981
>             Project: Hadoop HDFS
>          Issue Type: Bug
>          Components: name-node
>    Affects Versions: 0.23.3
>            Reporter: Xiaobo Peng
>            Assignee: Xiaobo Peng
>            Priority: Minor
>
> Incorrect condition in {{FSNamesystem.getBlockLocatoins()}} can lead to 
> updating times without write lock. In most cases this condition will force 
> {{FSNamesystem.getBlockLocatoins()}} to hold write lock, even if times do not 
> need to be updated.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to