Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Disk::new() may leak file descriptors (openzfs#459)
= Problem If you try to add a disk that already exists in the ZettaCache we’ll end up getting to this point: ``` fn add_disk(&mut self, path: &Path) -> Result<()> { ... let disk_id = self.block_access.add_disk(Disk::new(path, false)?)?; ``` At that point, `Disk::new()` has succeeded (opening a file descriptor with a static lifetime to the dev device) but we are failing in `BlockAccess.add_disk()` (which make us leak the file descriptor). Here is a test where we can see how the file descriptor to the device file is leaked: ``` ~$ sudo lsof -p $(pgrep zfs_o) | grep "/dev/sdb" | wc -l 58 ~$ for i in {0..20}; do sudo zcache add /dev/sdb; done Error: disk "/dev/sdb" ("/dev/sdb") is already part of the zettacache .. 20 error messages ... ~$ sudo lsof -p $(pgrep zfs_o) | grep "/dev/sdb" | wc -l 79 ``` = Patch The file descriptor is kept behind an `Arc` so when the read/write threads terminate (they do so when all the Senders are dropped and their `recv()` calls return an error) and the "main" thread drops `Disk`, the file descriptor is automatically closed. = Testing I made sure that the file descriptor count stayed the same performing the above test: ``` ~$ sudo lsof -p $(pgrep zfs_o) | grep "/dev/sdb" | wc -l 1 ~$ for i in {0..20}; do sudo zcache add /dev/sdb; done Error: disk "/dev/sdb" ("/dev/sdb") is already part of the zettacache ... 20 error messages ... ~$ sudo lsof -p $(pgrep zfs_o) | grep "/dev/sdb" | wc -l 1 ```
- Loading branch information