Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)

# macOS specific settings
if(APPLE)
# Detect architecture
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
set(CMAKE_OSX_ARCHITECTURES "arm64")
message(STATUS "Building for macOS ARM64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64")
message(STATUS "Building for macOS x86_64")
endif()

# Set minimum macOS version that supports ARM64
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")

# Enable Objective-C++ support for .mm files
enable_language(OBJCXX)
set(CMAKE_OBJCXX_STANDARD 17)
endif()

option(ZFSW_BUILD_SHARED_LIBRARY "Build the ZFSWrapper as shared library" OFF)

option(ZFSW_HAS_ZPOOL_STATUS_COMPATIBILITY_ERR "ZFS has symbol ZPOOL_STATUS_COMPATIBILITY_ERR" OFF)
Expand All @@ -24,6 +43,19 @@ option(ZFSW_HAS_ZPOOL_STATUS_INCOMPATIBLE_FEAT "ZFS has symbol ZPOOL_STATUS_INCO

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

# macOS specific library paths for ARM64
if(APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
# Add Homebrew ARM64 paths to search
list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew")
list(APPEND CMAKE_LIBRARY_PATH "/opt/homebrew/lib")
list(APPEND CMAKE_INCLUDE_PATH "/opt/homebrew/include")
elseif(APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
# Add Homebrew x86_64 paths to search
list(APPEND CMAKE_PREFIX_PATH "/usr/local")
list(APPEND CMAKE_LIBRARY_PATH "/usr/local/lib")
list(APPEND CMAKE_INCLUDE_PATH "/usr/local/include")
endif()

find_package(ZFS REQUIRED)

################################################################################
Expand All @@ -34,11 +66,18 @@ set(ZFS_WRAPPER_SOURCES
include/ZFSNVList.hpp
include/ZFSStrings.hpp
include/ZFSUtils.hpp
include/ZFSManager.hpp
src/ZFSNVList.cpp
src/ZFSStrings.cpp
src/ZFSUtils.cpp
src/ZFSManager.cpp
)

# Add Objective-C++ source files for macOS
if(APPLE)
list(APPEND ZFS_WRAPPER_SOURCES src/ZFSStrings.mm)
endif()

if(ZFSW_BUILD_SHARED_LIBRARY)
set(ZFSW_LIBRARY_TYPE SHARED)
else()
Expand All @@ -63,6 +102,13 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
Threads::Threads
)

# macOS specific linking
if(APPLE)
target_link_libraries(${PROJECT_NAME} PRIVATE
"-framework Foundation"
)
endif()

target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
Expand All @@ -76,4 +122,4 @@ target_compile_options(${PROJECT_NAME} PRIVATE
)

# Organization in Xcode and Co
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${QN_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${ZFS_WRAPPER_SOURCES})
218 changes: 218 additions & 0 deletions OPENZFS_2_3_0_FEATURES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# OpenZFS 2.3.0 Features in ZFSWrapper

This document describes the new OpenZFS 2.3.0 features that have been added to the ZFSWrapper library.

## Overview

OpenZFS 2.3.0 introduced several significant features that enhance performance, flexibility, and functionality:

- **RAIDZ Expansion**: Add devices to existing RAIDZ vdevs without downtime
- **Direct I/O**: Bypass ARC for better performance with fast storage devices
- **Enhanced Deduplication**: Better management of deduplication with quotas and statistics
- **Long Filename Support**: Support for filenames up to 1023 characters
- **Wait Operations**: Wait for pool operations to complete

## API Reference

### ZFSManager Class (High-Level API)

#### RAIDZ Expansion
```cpp
// Expand a RAIDZ vdev by adding a new device
bool expandRaidz(const std::string& poolName, const std::string& raidzName, const std::string& newDevice);

// Check if a pool is currently expanding RAIDZ
bool isPoolRaidzExpanding(const std::string& poolName);
```

#### Direct I/O Support
```cpp
// Set Direct I/O mode for a filesystem
bool setDirectIO(const std::string& filesystemName, bool enabled);
```

#### Enhanced Deduplication
```cpp
// Get deduplication statistics for a pool
bool getDedupStats(const std::string& poolName, std::uint64_t& tableSize, std::uint64_t& tableCached);

// Set deduplication table quota for a pool
bool setDedupQuota(const std::string& poolName, std::uint64_t quota);
```

### ZPool Class (Low-Level API)

#### RAIDZ Expansion
```cpp
// Add devices to an existing RAIDZ vdev
int raidzExpand(const std::string& raidz_name, const std::string& new_device);

// Get RAIDZ expansion statistics
struct RaidzExpandStat {
uint64_t res_state; // Current state of expansion
uint64_t res_start_time; // Start time of expansion
uint64_t res_end_time; // End time of expansion
uint64_t res_to_reflow; // Total bytes to reflow
uint64_t res_reflowed; // Bytes already reflowed
uint64_t res_waiting_for_resilver; // Waiting for resilver
};

bool getRaidzExpandStats(RaidzExpandStat& stats) const;
bool isRaidzExpanding() const;
```

#### Enhanced Deduplication
```cpp
// Get deduplication table size for this pool
std::uint64_t getDedupTableSize() const;

// Get deduplication table quota for this pool
std::uint64_t getDedupTableQuota() const;

// Get cached deduplication data amount for this pool
std::uint64_t getDedupCached() const;

// Set deduplication table quota for this pool
int setDedupTableQuota(std::uint64_t quota);
```

#### Wait Operations
```cpp
// Wait for RAIDZ expansion to complete
int waitForRaidzExpansion();

// Wait for scrub to complete
int waitForScrub();
```

### ZFileSystem Class (Low-Level API)

#### Direct I/O Support
```cpp
enum class DirectIOMode {
disabled = 0, // Direct I/O disabled (default)
standard = 1, // Direct I/O enabled for large I/O
always = 2 // Direct I/O always enabled
};

// Set Direct I/O mode for this filesystem
int setDirectIOMode(DirectIOMode mode);

// Get Direct I/O mode for this filesystem
DirectIOMode getDirectIOMode() const;

// Check if Direct I/O is supported for this filesystem
bool isDirectIOSupported() const;
```

#### Long Filename Support
```cpp
// Check if long filenames (up to 1023 chars) are supported
bool isLongNameSupported() const;
```

## Usage Examples

### Example 1: RAIDZ Expansion
```cpp
zfs::ZFSManager manager;

// Check if expansion is in progress
if (manager.isPoolRaidzExpanding("mypool")) {
std::cout << "Pool is currently expanding" << std::endl;
}

// Add a device to expand RAIDZ
if (manager.expandRaidz("mypool", "raidz-0", "/dev/disk3")) {
std::cout << "RAIDZ expansion initiated" << std::endl;
}
```

### Example 2: Direct I/O for NVMe Performance
```cpp
zfs::ZFSManager manager;

// Enable Direct I/O for better NVMe performance
if (manager.setDirectIO("mypool/dataset", true)) {
std::cout << "Direct I/O enabled" << std::endl;
}
```

### Example 3: Deduplication Management
```cpp
zfs::ZFSManager manager;

// Get deduplication statistics
std::uint64_t tableSize, tableCached;
if (manager.getDedupStats("mypool", tableSize, tableCached)) {
std::cout << "Dedup table: " << tableSize << " bytes" << std::endl;
std::cout << "Cached: " << tableCached << " bytes" << std::endl;
}

// Set 1GB deduplication quota
manager.setDedupQuota("mypool", 1024ULL * 1024 * 1024);
```

### Example 4: Wait for Operations
```cpp
zfs::LibZFSHandle lib;
auto pool = lib.pool("mypool");

// Start a scrub and wait for completion
pool.scrub();
pool.waitForScrub();
std::cout << "Scrub completed" << std::endl;

// Wait for RAIDZ expansion if in progress
if (pool.isRaidzExpanding()) {
pool.waitForRaidzExpansion();
std::cout << "RAIDZ expansion completed" << std::endl;
}
```

## Compilation Requirements

To use these features, ensure you have:

1. **OpenZFS 2.3.0 or later** installed
2. **macOS 11.0 or later** (for ARM64 support)
3. **CMake 3.10 or later**
4. **C++17 compatible compiler**

The features are automatically detected at compile time and enabled via CMake options:

```bash
cmake .. -DZFSW_HAS_ZPOOL_STATUS_COMPATIBILITY_ERR=ON \
-DZFSW_HAS_ZPOOL_STATUS_INCOMPATIBLE_FEAT=ON
```

## Notes and Limitations

1. **RAIDZ Expansion**: This is a long-running operation. Use `waitForRaidzExpansion()` carefully in production code.

2. **Direct I/O**: Best suited for fast storage devices like NVMe. May not provide benefits on slower devices.

3. **Deduplication**: Monitor memory usage when enabling deduplication, especially with quotas.

4. **Long Filenames**: While supported, very long filenames may impact performance.

5. **Platform Support**: These features are tested on macOS ARM64. Linux and other platforms should work but may require additional testing.

## Building the Examples

```bash
cd examples
mkdir build && cd build
cmake ..
make openzfs_2_3_0_demo
./openzfs_2_3_0_demo
```

## Error Handling

All functions follow the existing ZFSWrapper error handling patterns:

- **High-level API** (ZFSManager): Returns `bool` for success/failure, prints errors to stderr
- **Low-level API** (ZPool/ZFileSystem): Returns `int` error codes (0 = success) or throws exceptions

Always check return values and handle exceptions appropriately in production code.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ For Developers
Dependencies
------------

On MacOS, OpenZFS 2.0.1 is tested. The following OpenZFS needs to be installed:
- [OpenZFS 2.0.1](https://openzfsonosx.org/forum/viewtopic.php?f=20&t=3569&p=11206#p11206)
On MacOS, OpenZFS 2.3.0 is tested. The following OpenZFS needs to be installed:
- [OpenZFS 2.3.0](https://github.com/openzfsonosx/openzfs-fork/releases/tag/zfs-macOS-2.3.0)

On Ubuntu 21.04, OpenZFS 2.0.2 is tested. The following apt packages need to be installed:
- `libzfslinux-dev`
Expand All @@ -25,7 +25,6 @@ Building
--------

Building works as usual with CMake.
On MacOS, pass `-DZFSW_HAS_ZPOOL_STATUS_COMPATIBILITY_ERR` to CMake.

```
mkdir build
Expand Down
Loading