{"record":{"id":"5a9f1b24d2a93b0b","repo":"apache/hadoop","slug":"disk-mount-mount-already-has-volume-when-trying","errorCode":null,"errorMessage":"Disk mount {mount} already has volume, when trying to add {location}. Please try removing mounts first or restart datanode.","messagePattern":"Disk mount (.+?) already has volume, when trying to add (.+?)\\. Please try removing mounts first or restart datanode\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java","lineNumber":1271,"sourceCode":"        if (StorageType.allowSameDiskTiering(location.getStorageType())) {\n          File dir = new File(location.getUri());\n          // Get the first parent dir that exists to check disk mount point.\n          while (!dir.exists()) {\n            dir = dir.getParentFile();\n            if (dir == null) {\n              throw new IOException(\"Invalid path: \"\n                  + location + \": directory does not exist\");\n            }\n          }\n          DF df = new DF(dir, dnConf.getConf());\n          String mount = df.getMount();\n          if (data.getMountVolumeMap().hasMount(mount)) {\n            String errMsg = \"Disk mount \" + mount\n                + \" already has volume, when trying to add \"\n                + location + \". Please try removing mounts first\"\n                + \" or restart datanode.\";\n            LOG.error(errMsg);\n            throw new IOException(errMsg);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Attempts to reload data volumes with new configuration.\n   * @param newVolumes a comma separated string that specifies the data volumes.\n   * @throws IOException on error. If an IOException is thrown, some new volumes\n   * may have been successfully added and removed.\n   */\n  private void refreshVolumes(String newVolumes) throws IOException {\n    // Add volumes for each Namespace\n    final List<NamespaceInfo> nsInfos = Lists.newArrayList();\n    for (BPOfferService bpos : blockPoolManager.getAllNamenodeThreads()) {\n      nsInfos.add(bpos.getNamespaceInfo());\n    }","sourceCodeStart":1253,"sourceCodeEnd":1289,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java#L1253-L1289","documentation":"With dfs.datanode.allow.same.disk.tiering enabled, refreshVolumes resolves each new location's mount point with DF and rejects the add when data.getMountVolumeMap() already has a volume on that mount — one volume per mount is enforced for tierable storage types. The IOException is explicit about the remedy: remove the existing volume on that mount first, or restart the DataNode.","triggerScenarios":"Adding [DISK]file:///mnt/disk2/dn1 when /mnt/disk2 already backs an active volume such as /mnt/disk2/dn0; bind mounts or symlinked paths making two directories resolve to the same device; partitions of one disk exposed under two mount paths.","commonSituations":"Operators splitting one big disk into multiple DN dirs for scan parallelism; containers with shared hostPath devices; SAN LUNs presented under two mount points; adding a 'spare' dir on the root disk.","solutions":["Remove the existing volume on that mount first: reconfig with it omitted from dfs.datanode.data.dir, let it deactivate, then add the new location in a second reconfig","If two dirs on one physical disk is intentional, review whether dfs.datanode.allow.same.disk.tiering should be enabled at all for this layout","Verify which volume owns the mount: findmnt/lsblk on the host plus the DN's 'Volume' JMX beans"],"exampleFix":"# before: both dirs on mount /mnt/disk2 -> rejected\n[DISK]file:///mnt/disk2/dn0,[DISK]file:///mnt/disk2/dn1\n# after: one volume per mount\n[DISK]file:///mnt/disk2/dn0,[DISK]file:///mnt/disk3/dn1","handlingStrategy":"validation","validationCode":"Set<String> usedMounts = new HashSet<>();\nfor (StorageLocation l : currentLocations) usedMounts.add(new DF(new File(l.getUri()), conf).getMount());\nfor (StorageLocation l : newLocations) {\n  String m = new DF(new File(l.getUri()), conf).getMount();\n  if (usedMounts.contains(m)) throw new IllegalArgumentException(\"mount \" + m + \" already has a volume\");\n}","typeGuard":null,"tryCatchPattern":"catch (ReconfigurationException e) {\n  if (String.valueOf(e.getCause()).contains(\"already has volume\")) {\n    // drop the old volume on that mount first, then re-add in a second reconfig\n  }\n}","preventionTips":["One DN volume per disk mount when same-disk tiering is enabled","Map every candidate dir to its device (findmnt/lsblk) before adding volumes","Watch for bind mounts and symlinks resolving two paths to one device"],"tags":["hadoop","hdfs","datanode","volume-management","mount","disk-tiering"],"backgroundTag":"mount-conflict","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}