removeDirectory :: HalfsCapable b t r l m =>
                   Maybe String -- ^ name to remove from parent
                                -- directory's content map (when Nothing,
                                -- leaves the the parent directory's
                                -- content map alone)
                -> InodeRef     -- ^ inr of directory to remove
                -> HalfsM b r l m ()
removeDirectory mdname inr = do
  -- TODO: Perms check (write perms on parent directory, etc.)
  dhMap <- hasks hsDHMap

  -- We lock the dirhandle map so (a) there's no contention for
  -- dirhandle lookup/creation for the directory we're removing and (b)
  -- so we can ensure that the directory is empty.

  withLockedRscRef dhMap $ \dhMapRef -> do
    dh <- lookupRM inr dhMapRef >>= maybe (newDirHandle inr) return
    withDHLock dh $ do
      -- begin dirhandle critical section
      contents <- readRef (dhContents dh)
      unless (M.null contents) $ HE_DirectoryNotEmpty `annErrno` eNOTEMPTY

      -- When we've been given a directory name, purge this dir's dirent from
      -- the parent directory.
      case mdname of
        Nothing    -> return ()
        Just dname ->
          withLockedInode inr $ do
            pinr <- inoParent `fmap` drefInode inr
            pdh  <- lookupRM pinr dhMapRef >>= maybe (newDirHandle pinr) return
            rmDirEnt pdh dname

      -- Invalidate dh so that all subsequent DH-mediated access fails
      writeRef (dhInode dh) Nothing
      deleteRM inr dhMapRef
      freeInode inr
      -- end dirhandle critical section

-- | Syncs directory contents to disk
removeDirectory :: HalfsCapable b t r l m =>
                   Maybe String -- ^ name to remove from parent
                                -- directory's content map (when Nothing,
                                -- leaves the the parent directory's
                                -- content map alone)
                -> InodeRef     -- ^ inr of directory to remove
                -> HalfsM b r l m ()
removeDirectory mdname inr = do
  -- TODO: Perms check (write perms on parent directory, etc.)
  dhMap <- hasks hsDHMap

  -- We lock the dirhandle map so (a) there's no contention for
  -- dirhandle lookup/creation for the directory we're removing and (b)
  -- so we can ensure that the directory is empty.

  withLockedRscRef dhMap $ \dhMapRef -> do
    dh <- lookupRM inr dhMapRef >>= maybe (newDirHandle inr) return
    withDHLock dh $ do
      -- begin dirhandle critical section
      contents <- readRef (dhContents dh)
      unless (M.null contents) $ HE_DirectoryNotEmpty `annErrno` eNOTEMPTY

      -- When we've been given a directory name, purge this dir's dirent from
      -- the parent directory.
      case mdname of
        Nothing    -> return ()
        Just dname ->
          withLockedInode inr $ do
            pinr <- inoParent `fmap` drefInode inr
            pdh  <- lookupRM pinr dhMapRef >>= maybe (newDirHandle pinr) return
            rmDirEnt pdh dname

      -- Invalidate dh so that all subsequent DH-mediated access fails
      writeRef (dhInode dh) Nothing
      deleteRM inr dhMapRef
      freeInode inr
      -- end dirhandle critical section

-- | Syncs directory contents to disk
removeDirectory mdname inr = do
  -- TODO: Perms check (write perms on parent directory, etc.)
  dhMap <- hasks hsDHMap

  -- We lock the dirhandle map so (a) there's no contention for
  -- dirhandle lookup/creation for the directory we're removing and (b)
  -- so we can ensure that the directory is empty.

  withLockedRscRef dhMap $ \dhMapRef -> do
    dh <- lookupRM inr dhMapRef >>= maybe (newDirHandle inr) return
    withDHLock dh $ do
      -- begin dirhandle critical section
      contents <- readRef (dhContents dh)
      unless (M.null contents) $ HE_DirectoryNotEmpty `annErrno` eNOTEMPTY

      -- When we've been given a directory name, purge this dir's dirent from
      -- the parent directory.
      case mdname of
        Nothing    -> return ()
        Just dname ->
          withLockedInode inr $ do
            pinr <- inoParent `fmap` drefInode inr
            pdh  <- lookupRM pinr dhMapRef >>= maybe (newDirHandle pinr) return
            rmDirEnt pdh dname

      -- Invalidate dh so that all subsequent DH-mediated access fails
      writeRef (dhInode dh) Nothing
      deleteRM inr dhMapRef
      freeInode inr
      -- end dirhandle critical section

-- | Syncs directory contents to disk