Beispiel #1
0
            private int GetSelfSnapshot(int prior)
            {
                INodeReference.WithCount wc = (INodeReference.WithCount)GetReferredINode().AsReference
                                                  ();
                INode referred     = wc.GetReferredINode();
                int   lastSnapshot = Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId;

                if (referred.IsFile() && referred.AsFile().IsWithSnapshot())
                {
                    lastSnapshot = referred.AsFile().GetDiffs().GetLastSnapshotId();
                }
                else
                {
                    if (referred.IsDirectory())
                    {
                        DirectoryWithSnapshotFeature sf = referred.AsDirectory().GetDirectoryWithSnapshotFeature
                                                              ();
                        if (sf != null)
                        {
                            lastSnapshot = sf.GetLastSnapshotId();
                        }
                    }
                }
                if (lastSnapshot != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId &&
                    lastSnapshot != prior)
                {
                    return(lastSnapshot);
                }
                else
                {
                    return(Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.CurrentStateId);
                }
            }
        /// <summary>Create FileStatus by file INode</summary>
        /// <exception cref="System.IO.IOException"/>
        internal static HdfsFileStatus CreateFileStatus(FSDirectory fsd, string fullPath,
                                                        byte[] path, INode node, byte storagePolicy, int snapshot, bool isRawPath, INodesInPath
                                                        iip)
        {
            long size = 0;
            // length is zero for directories
            short replication = 0;
            long  blocksize   = 0;
            bool  isEncrypted;
            FileEncryptionInfo feInfo = isRawPath ? null : fsd.GetFileEncryptionInfo(node, snapshot
                                                                                     , iip);

            if (node.IsFile())
            {
                INodeFile fileNode = node.AsFile();
                size        = fileNode.ComputeFileSize(snapshot);
                replication = fileNode.GetFileReplication(snapshot);
                blocksize   = fileNode.GetPreferredBlockSize();
                isEncrypted = (feInfo != null) || (isRawPath && fsd.IsInAnEZ(INodesInPath.FromINode
                                                                                 (node)));
            }
            else
            {
                isEncrypted = fsd.IsInAnEZ(INodesInPath.FromINode(node));
            }
            int childrenNum = node.IsDirectory() ? node.AsDirectory().GetChildrenNum(snapshot
                                                                                     ) : 0;
            INodeAttributes nodeAttrs = fsd.GetAttributes(fullPath, path, node, snapshot);

            return(new HdfsFileStatus(size, node.IsDirectory(), replication, blocksize, node.
                                      GetModificationTime(snapshot), node.GetAccessTime(snapshot), GetPermissionForFileStatus
                                          (nodeAttrs, isEncrypted), nodeAttrs.GetUserName(), nodeAttrs.GetGroupName(), node
                                      .IsSymlink() ? node.AsSymlink().GetSymlink() : null, path, node.GetId(), childrenNum
                                      , feInfo, storagePolicy));
        }
 /// <summary>Save one inode's attributes to the image.</summary>
 /// <exception cref="System.IO.IOException"/>
 public static void SaveINode2Image(INode node, DataOutput @out, bool writeUnderConstruction
                                    , SnapshotFSImageFormat.ReferenceMap referenceMap)
 {
     if (node.IsReference())
     {
         WriteINodeReference(node.AsReference(), @out, writeUnderConstruction, referenceMap
                             );
     }
     else
     {
         if (node.IsDirectory())
         {
             WriteINodeDirectory(node.AsDirectory(), @out);
         }
         else
         {
             if (node.IsSymlink())
             {
                 WriteINodeSymlink(node.AsSymlink(), @out);
             }
             else
             {
                 if (node.IsFile())
                 {
                     WriteINodeFile(node.AsFile(), @out, writeUnderConstruction);
                 }
             }
         }
     }
 }
        /// <summary>Create FileStatus with location info by file INode</summary>
        /// <exception cref="System.IO.IOException"/>
        private static HdfsLocatedFileStatus CreateLocatedFileStatus(FSDirectory fsd, string
                                                                     fullPath, byte[] path, INode node, byte storagePolicy, int snapshot, bool isRawPath
                                                                     , INodesInPath iip)
        {
            System.Diagnostics.Debug.Assert(fsd.HasReadLock());
            long size = 0;
            // length is zero for directories
            short              replication = 0;
            long               blocksize   = 0;
            LocatedBlocks      loc         = null;
            bool               isEncrypted;
            FileEncryptionInfo feInfo = isRawPath ? null : fsd.GetFileEncryptionInfo(node, snapshot
                                                                                     , iip);

            if (node.IsFile())
            {
                INodeFile fileNode = node.AsFile();
                size        = fileNode.ComputeFileSize(snapshot);
                replication = fileNode.GetFileReplication(snapshot);
                blocksize   = fileNode.GetPreferredBlockSize();
                bool inSnapshot = snapshot != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                  .CurrentStateId;
                bool isUc     = !inSnapshot && fileNode.IsUnderConstruction();
                long fileSize = !inSnapshot && isUc?fileNode.ComputeFileSizeNotIncludingLastUcBlock
                                    () : size;

                loc = fsd.GetFSNamesystem().GetBlockManager().CreateLocatedBlocks(fileNode.GetBlocks
                                                                                      (snapshot), fileSize, isUc, 0L, size, false, inSnapshot, feInfo);
                if (loc == null)
                {
                    loc = new LocatedBlocks();
                }
                isEncrypted = (feInfo != null) || (isRawPath && fsd.IsInAnEZ(INodesInPath.FromINode
                                                                                 (node)));
            }
            else
            {
                isEncrypted = fsd.IsInAnEZ(INodesInPath.FromINode(node));
            }
            int childrenNum = node.IsDirectory() ? node.AsDirectory().GetChildrenNum(snapshot
                                                                                     ) : 0;
            INodeAttributes       nodeAttrs = fsd.GetAttributes(fullPath, path, node, snapshot);
            HdfsLocatedFileStatus status    = new HdfsLocatedFileStatus(size, node.IsDirectory()
                                                                        , replication, blocksize, node.GetModificationTime(snapshot), node.GetAccessTime
                                                                            (snapshot), GetPermissionForFileStatus(nodeAttrs, isEncrypted), nodeAttrs.GetUserName
                                                                            (), nodeAttrs.GetGroupName(), node.IsSymlink() ? node.AsSymlink().GetSymlink() :
                                                                        null, path, node.GetId(), loc, childrenNum, feInfo, storagePolicy);

            // Set caching information for the located blocks.
            if (loc != null)
            {
                CacheManager cacheManager = fsd.GetFSNamesystem().GetCacheManager();
                foreach (LocatedBlock lb in loc.GetLocatedBlocks())
                {
                    cacheManager.SetCachedLocations(lb);
                }
            }
            return(status);
        }
Beispiel #5
0
 /// <summary>
 /// <inheritDoc/>
 /// <br/>
 /// To destroy a DstReference node, we first remove its link with the
 /// referred node. If the reference number of the referred node is &lt;= 0, we
 /// destroy the subtree of the referred node. Otherwise, we clean the
 /// referred node's subtree and delete everything created after the last
 /// rename operation, i.e., everything outside of the scope of the prior
 /// WithName nodes.
 /// </summary>
 public override void DestroyAndCollectBlocks(BlockStoragePolicySuite bsps, INode.BlocksMapUpdateInfo
                                              collectedBlocks, IList <INode> removedINodes)
 {
     if (RemoveReference(this) <= 0)
     {
         GetReferredINode().DestroyAndCollectBlocks(bsps, collectedBlocks, removedINodes);
     }
     else
     {
         // we will clean everything, including files, directories, and
         // snapshots, that were created after this prior snapshot
         int prior = GetPriorSnapshot(this);
         // prior must be non-null, otherwise we do not have any previous
         // WithName nodes, and the reference number will be 0.
         Preconditions.CheckState(prior != Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot
                                  .NoSnapshotId);
         // identify the snapshot created after prior
         int   snapshot = GetSelfSnapshot(prior);
         INode referred = GetReferredINode().AsReference().GetReferredINode();
         if (referred.IsFile())
         {
             // if referred is a file, it must be a file with snapshot since we did
             // recordModification before the rename
             INodeFile file = referred.AsFile();
             Preconditions.CheckState(file.IsWithSnapshot());
             // make sure we mark the file as deleted
             file.GetFileWithSnapshotFeature().DeleteCurrentFile();
             // when calling cleanSubtree of the referred node, since we
             // compute quota usage updates before calling this destroy
             // function, we use true for countDiffChange
             referred.CleanSubtree(bsps, snapshot, prior, collectedBlocks, removedINodes);
         }
         else
         {
             if (referred.IsDirectory())
             {
                 // similarly, if referred is a directory, it must be an
                 // INodeDirectory with snapshot
                 INodeDirectory dir = referred.AsDirectory();
                 Preconditions.CheckState(dir.IsWithSnapshot());
                 try
                 {
                     DirectoryWithSnapshotFeature.DestroyDstSubtree(bsps, dir, snapshot, prior, collectedBlocks
                                                                    , removedINodes);
                 }
                 catch (QuotaExceededException e)
                 {
                     Log.Error("should not exceed quota while snapshot deletion", e);
                 }
             }
         }
     }
 }
Beispiel #6
0
 private void AddToParent(INodeDirectory parent, INode child)
 {
     if (parent == dir.rootDir && FSDirectory.IsReservedName(child))
     {
         throw new HadoopIllegalArgumentException("File name \"" + child.GetLocalName() +
                                                  "\" is reserved. Please " + " change the name of the existing file or directory to another "
                                                  + "name before upgrading to this release.");
     }
     // NOTE: This does not update space counts for parents
     if (!parent.AddChild(child))
     {
         return;
     }
     dir.CacheName(child);
     if (child.IsFile())
     {
         UpdateBlocksMap(child.AsFile(), fsn.GetBlockManager());
     }
 }
Beispiel #7
0
        /// <exception cref="System.IO.IOException"/>
        internal static void UnprotectedSetStoragePolicy(FSDirectory fsd, BlockManager bm
                                                         , INodesInPath iip, byte policyId)
        {
            System.Diagnostics.Debug.Assert(fsd.HasWriteLock());
            INode inode = iip.GetLastINode();

            if (inode == null)
            {
                throw new FileNotFoundException("File/Directory does not exist: " + iip.GetPath()
                                                );
            }
            int snapshotId = iip.GetLatestSnapshotId();

            if (inode.IsFile())
            {
                BlockStoragePolicy newPolicy = bm.GetStoragePolicy(policyId);
                if (newPolicy.IsCopyOnCreateFile())
                {
                    throw new HadoopIllegalArgumentException("Policy " + newPolicy + " cannot be set after file creation."
                                                             );
                }
                BlockStoragePolicy currentPolicy = bm.GetStoragePolicy(inode.GetLocalStoragePolicyID
                                                                           ());
                if (currentPolicy != null && currentPolicy.IsCopyOnCreateFile())
                {
                    throw new HadoopIllegalArgumentException("Existing policy " + currentPolicy.GetName
                                                                 () + " cannot be changed after file creation.");
                }
                inode.AsFile().SetStoragePolicyID(policyId, snapshotId);
            }
            else
            {
                if (inode.IsDirectory())
                {
                    SetDirStoragePolicy(fsd, inode.AsDirectory(), policyId, snapshotId);
                }
                else
                {
                    throw new FileNotFoundException(iip.GetPath() + " is not a file or directory");
                }
            }
        }
Beispiel #8
0
 /// <summary>Cast INode to INodeFile.</summary>
 /// <exception cref="System.IO.FileNotFoundException"/>
 public static Org.Apache.Hadoop.Hdfs.Server.Namenode.INodeFile ValueOf(INode inode
                                                                        , string path, bool acceptNull)
 {
     if (inode == null)
     {
         if (acceptNull)
         {
             return(null);
         }
         else
         {
             throw new FileNotFoundException("File does not exist: " + path);
         }
     }
     if (!inode.IsFile())
     {
         throw new FileNotFoundException("Path is not a file: " + path);
     }
     return(inode.AsFile());
 }
Beispiel #9
0
 /// <exception cref="System.IO.IOException"/>
 private void Save(OutputStream @out, INode n)
 {
     if (n.IsDirectory())
     {
         Save(@out, n.AsDirectory());
     }
     else
     {
         if (n.IsFile())
         {
             Save(@out, n.AsFile());
         }
         else
         {
             if (n.IsSymlink())
             {
                 Save(@out, n.AsSymlink());
             }
         }
     }
 }
Beispiel #10
0
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.QuotaExceededException"/>
        /// <exception cref="Org.Apache.Hadoop.FS.UnresolvedLinkException"/>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.SnapshotAccessControlException"/
        ///     >
        internal static Block[] UnprotectedSetReplication(FSDirectory fsd, string src, short
                                                          replication, short[] blockRepls)
        {
            System.Diagnostics.Debug.Assert(fsd.HasWriteLock());
            INodesInPath iip   = fsd.GetINodesInPath4Write(src, true);
            INode        inode = iip.GetLastINode();

            if (inode == null || !inode.IsFile())
            {
                return(null);
            }
            INodeFile file  = inode.AsFile();
            short     oldBR = file.GetBlockReplication();

            // before setFileReplication, check for increasing block replication.
            // if replication > oldBR, then newBR == replication.
            // if replication < oldBR, we don't know newBR yet.
            if (replication > oldBR)
            {
                long dsDelta = file.StoragespaceConsumed() / oldBR;
                fsd.UpdateCount(iip, 0L, dsDelta, oldBR, replication, true);
            }
            file.SetFileReplication(replication, iip.GetLatestSnapshotId());
            short newBR = file.GetBlockReplication();

            // check newBR < oldBR case.
            if (newBR < oldBR)
            {
                long dsDelta = file.StoragespaceConsumed() / newBR;
                fsd.UpdateCount(iip, 0L, dsDelta, oldBR, newBR, true);
            }
            if (blockRepls != null)
            {
                blockRepls[0] = oldBR;
                blockRepls[1] = newBR;
            }
            return(file.GetBlocks());
        }
Beispiel #11
0
 /// <summary>
 /// When destroying a reference node (WithName or DstReference), we call this
 /// method to identify the snapshot which is the latest snapshot before the
 /// reference node's creation.
 /// </summary>
 internal static int GetPriorSnapshot(Org.Apache.Hadoop.Hdfs.Server.Namenode.INodeReference
                                      @ref)
 {
     INodeReference.WithCount wc = (INodeReference.WithCount)@ref.GetReferredINode();
     INodeReference.WithName  wn = null;
     if (@ref is INodeReference.DstReference)
     {
         wn = wc.GetLastWithName();
     }
     else
     {
         if (@ref is INodeReference.WithName)
         {
             wn = wc.GetPriorWithName((INodeReference.WithName)@ref);
         }
     }
     if (wn != null)
     {
         INode referred = wc.GetReferredINode();
         if (referred.IsFile() && referred.AsFile().IsWithSnapshot())
         {
             return(referred.AsFile().GetDiffs().GetPrior(wn.lastSnapshotId));
         }
         else
         {
             if (referred.IsDirectory())
             {
                 DirectoryWithSnapshotFeature sf = referred.AsDirectory().GetDirectoryWithSnapshotFeature
                                                       ();
                 if (sf != null)
                 {
                     return(sf.GetDiffs().GetPrior(wn.lastSnapshotId));
                 }
             }
         }
     }
     return(Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.NoSnapshotId);
 }
Beispiel #12
0
            private int GetSelfSnapshot()
            {
                INode referred = GetReferredINode().AsReference().GetReferredINode();
                int   snapshot = Org.Apache.Hadoop.Hdfs.Server.Namenode.Snapshot.Snapshot.NoSnapshotId;

                if (referred.IsFile() && referred.AsFile().IsWithSnapshot())
                {
                    snapshot = referred.AsFile().GetDiffs().GetPrior(lastSnapshotId);
                }
                else
                {
                    if (referred.IsDirectory())
                    {
                        DirectoryWithSnapshotFeature sf = referred.AsDirectory().GetDirectoryWithSnapshotFeature
                                                              ();
                        if (sf != null)
                        {
                            snapshot = sf.GetDiffs().GetPrior(lastSnapshotId);
                        }
                    }
                }
                return(snapshot);
            }
Beispiel #13
0
        /// <exception cref="System.IO.IOException"/>
        internal static INode UnprotectedSetXAttrs(FSDirectory fsd, string src, IList <XAttr
                                                                                       > xAttrs, EnumSet <XAttrSetFlag> flag)
        {
            System.Diagnostics.Debug.Assert(fsd.HasWriteLock());
            INodesInPath iip = fsd.GetINodesInPath4Write(FSDirectory.NormalizePath(src), true
                                                         );
            INode         inode          = FSDirectory.ResolveLastINode(iip);
            int           snapshotId     = iip.GetLatestSnapshotId();
            IList <XAttr> existingXAttrs = XAttrStorage.ReadINodeXAttrs(inode);
            IList <XAttr> newXAttrs      = SetINodeXAttrs(fsd, existingXAttrs, xAttrs, flag);
            bool          isFile         = inode.IsFile();

            foreach (XAttr xattr in newXAttrs)
            {
                string xaName = XAttrHelper.GetPrefixName(xattr);

                /*
                 * If we're adding the encryption zone xattr, then add src to the list
                 * of encryption zones.
                 */
                if (HdfsServerConstants.CryptoXattrEncryptionZone.Equals(xaName))
                {
                    HdfsProtos.ZoneEncryptionInfoProto ezProto = HdfsProtos.ZoneEncryptionInfoProto.ParseFrom
                                                                     (xattr.GetValue());
                    fsd.ezManager.AddEncryptionZone(inode.GetId(), PBHelper.Convert(ezProto.GetSuite(
                                                                                        )), PBHelper.Convert(ezProto.GetCryptoProtocolVersion()), ezProto.GetKeyName());
                }
                if (!isFile && HdfsServerConstants.SecurityXattrUnreadableBySuperuser.Equals(xaName
                                                                                             ))
                {
                    throw new IOException("Can only set '" + HdfsServerConstants.SecurityXattrUnreadableBySuperuser
                                          + "' on a file.");
                }
            }
            XAttrStorage.UpdateINodeXAttrs(inode, newXAttrs, snapshotId);
            return(inode);
        }
Beispiel #14
0
        /// <exception cref="System.IO.IOException"/>
        internal static HdfsFileStatus Mkdirs(FSNamesystem fsn, string src, PermissionStatus
                                              permissions, bool createParent)
        {
            FSDirectory fsd = fsn.GetFSDirectory();

            if (NameNode.stateChangeLog.IsDebugEnabled())
            {
                NameNode.stateChangeLog.Debug("DIR* NameSystem.mkdirs: " + src);
            }
            if (!DFSUtil.IsValidName(src))
            {
                throw new InvalidPathException(src);
            }
            FSPermissionChecker pc = fsd.GetPermissionChecker();

            byte[][] pathComponents = FSDirectory.GetPathComponentsForReservedPath(src);
            fsd.WriteLock();
            try
            {
                src = fsd.ResolvePath(pc, src, pathComponents);
                INodesInPath iip = fsd.GetINodesInPath4Write(src);
                if (fsd.IsPermissionEnabled())
                {
                    fsd.CheckTraverse(pc, iip);
                }
                INode lastINode = iip.GetLastINode();
                if (lastINode != null && lastINode.IsFile())
                {
                    throw new FileAlreadyExistsException("Path is not a directory: " + src);
                }
                INodesInPath existing = lastINode != null ? iip : iip.GetExistingINodes();
                if (lastINode == null)
                {
                    if (fsd.IsPermissionEnabled())
                    {
                        fsd.CheckAncestorAccess(pc, iip, FsAction.Write);
                    }
                    if (!createParent)
                    {
                        fsd.VerifyParentDir(iip, src);
                    }
                    // validate that we have enough inodes. This is, at best, a
                    // heuristic because the mkdirs() operation might need to
                    // create multiple inodes.
                    fsn.CheckFsObjectLimit();
                    IList <string> nonExisting = iip.GetPath(existing.Length(), iip.Length() - existing
                                                             .Length());
                    int length = nonExisting.Count;
                    if (length > 1)
                    {
                        IList <string> ancestors = nonExisting.SubList(0, length - 1);
                        // Ensure that the user can traversal the path by adding implicit
                        // u+wx permission to all ancestor directories
                        existing = CreateChildrenDirectories(fsd, existing, ancestors, AddImplicitUwx(permissions
                                                                                                      , permissions));
                        if (existing == null)
                        {
                            throw new IOException("Failed to create directory: " + src);
                        }
                    }
                    if ((existing = CreateChildrenDirectories(fsd, existing, nonExisting.SubList(length
                                                                                                 - 1, length), permissions)) == null)
                    {
                        throw new IOException("Failed to create directory: " + src);
                    }
                }
                return(fsd.GetAuditFileInfo(existing));
            }
            finally
            {
                fsd.WriteUnlock();
            }
        }
Beispiel #15
0
        /// <summary>
        /// If a default ACL is defined on a parent directory, then copies that default
        /// ACL to a newly created child file or directory.
        /// </summary>
        /// <param name="child">INode newly created child</param>
        public static void CopyINodeDefaultAcl(INode child)
        {
            INodeDirectory parent           = child.GetParent();
            AclFeature     parentAclFeature = parent.GetAclFeature();

            if (parentAclFeature == null || !(child.IsFile() || child.IsDirectory()))
            {
                return;
            }
            // Split parent's entries into access vs. default.
            IList <AclEntry> featureEntries       = GetEntriesFromAclFeature(parent.GetAclFeature());
            ScopedAclEntries scopedEntries        = new ScopedAclEntries(featureEntries);
            IList <AclEntry> parentDefaultEntries = scopedEntries.GetDefaultEntries();

            // The parent may have an access ACL but no default ACL.  If so, exit.
            if (parentDefaultEntries.IsEmpty())
            {
                return;
            }
            // Pre-allocate list size for access entries to copy from parent.
            IList <AclEntry> accessEntries = Lists.NewArrayListWithCapacity(parentDefaultEntries
                                                                            .Count);
            FsPermission childPerm = child.GetFsPermission();
            // Copy each default ACL entry from parent to new child's access ACL.
            bool parentDefaultIsMinimal = AclUtil.IsMinimalAcl(parentDefaultEntries);

            foreach (AclEntry entry in parentDefaultEntries)
            {
                AclEntryType     type    = entry.GetType();
                string           name    = entry.GetName();
                AclEntry.Builder builder = new AclEntry.Builder().SetScope(AclEntryScope.Access).
                                           SetType(type).SetName(name);
                // The child's initial permission bits are treated as the mode parameter,
                // which can filter copied permission values for owner, mask and other.
                FsAction permission;
                if (type == AclEntryType.User && name == null)
                {
                    permission = entry.GetPermission().And(childPerm.GetUserAction());
                }
                else
                {
                    if (type == AclEntryType.Group && parentDefaultIsMinimal)
                    {
                        // This only happens if the default ACL is a minimal ACL: exactly 3
                        // entries corresponding to owner, group and other.  In this case,
                        // filter the group permissions.
                        permission = entry.GetPermission().And(childPerm.GetGroupAction());
                    }
                    else
                    {
                        if (type == AclEntryType.Mask)
                        {
                            // Group bits from mode parameter filter permission of mask entry.
                            permission = entry.GetPermission().And(childPerm.GetGroupAction());
                        }
                        else
                        {
                            if (type == AclEntryType.Other)
                            {
                                permission = entry.GetPermission().And(childPerm.GetOtherAction());
                            }
                            else
                            {
                                permission = entry.GetPermission();
                            }
                        }
                    }
                }
                builder.SetPermission(permission);
                accessEntries.AddItem(builder.Build());
            }
            // A new directory also receives a copy of the parent's default ACL.
            IList <AclEntry> defaultEntries = child.IsDirectory() ? parentDefaultEntries : Sharpen.Collections
                                              .EmptyList <AclEntry>();
            FsPermission newPerm;

            if (!AclUtil.IsMinimalAcl(accessEntries) || !defaultEntries.IsEmpty())
            {
                // Save the new ACL to the child.
                child.AddAclFeature(CreateAclFeature(accessEntries, defaultEntries));
                newPerm = CreateFsPermissionForExtendedAcl(accessEntries, childPerm);
            }
            else
            {
                // The child is receiving a minimal ACL.
                newPerm = CreateFsPermissionForMinimalAcl(accessEntries, childPerm);
            }
            child.SetPermission(newPerm);
        }