JDK-8313368 : (fc) FileChannel.size returns 0 on block special files
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 20,21
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: generic
  • Submitted: 2023-07-27
  • Updated: 2023-10-02
  • Resolved: 2023-08-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 22
22 b09Fixed
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
OS Fedora 34
Java 20.0.1+9 (temurin build) (but issue seems to be relevant for 20.0.2 also)

A DESCRIPTION OF THE PROBLEM :
The implementation of FileChannel.size should use ioctl(BLKGETSIZE64) for block special devices.
For java 20 it's never called (checked with strace)

Looks like a regression from https://github.com/openjdk/jdk20/commit/48cc15602b62e81bb179ca9570a1e7d8bbf4d6df

Java 19 (https://github.com/openjdk/jdk19/blob/master/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c) imports  `<linux/fs.h>` which includes definition of `BLKGETSIZE64`
Java 20 (https://github.com/openjdk/jdk20/blob/master/src/java.base/unix/native/libnio/ch/UnixFileDispatcherImpl.c) doesn't import, so BLKGETSIZE64 is never defined and ioctl is never called

REGRESSION : Last worked in version 20

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- create block device with non-empty size
- check `blockdev --getsize64 /dev/sample.block` has size not 0
- run `java  SizeError.java`

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Prints size
ACTUAL -
Prints zero and "WRONG"

---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Path;

public class SizeError {
	public static void main(String[] args) throws IOException {
		var ch = FileChannel.open(Path.of("/dev/sample.block"));
		var size = ch.size();
		System.out.println(size);
		if (size == 0L) System.out.println("WRONG");
	}
}
---------- END SOURCE ----------


Comments
Changeset: 4ba81f63 Author: Brian Burkhalter <bpb@openjdk.org> Date: 2023-08-02 15:25:59 +0000 URL: https://git.openjdk.org/jdk/commit/4ba81f631f572d870d0f2c96fefe0cabc55e1841
02-08-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/15092 Date: 2023-07-31 18:16:49 +0000
31-07-2023

The observations on Ubuntu: JDK 20ea+16: Passed. JDK 20ea+17: Failed, 0 WRONG returned. JDK 21ea+20: Failed.
29-07-2023

Additional information from the submitter: There are 2 options: - you can use any existing block device (something like `/dev/sda`) and call java with `sudo` - create new one ``` fallocate -l 10M /var/tmp/test.img sudo losetup --find --show /var/tmp/test.img sudo chmod 444 /dev/loop0 ➜ /usr/bin/java SizeError.java 10485760 ➜ /home/evanslo/.jdks/openjdk-20.0.2/bin/java SizeError.java 0 WRONG
29-07-2023

Probably not a main stream usage to have a FileChannel to a block special device but the issue is a remainder that the JDK needs a lot more tests in this area to ensure that any changes catch issues like this.
29-07-2023

Requested more details of creating block device with non-empty size from the submitter.
28-07-2023