NAS HW 오프로드
NAS(Network Attached Storage) H/W 오프로드 종합 가이드 — HW RAID, Intel DSA/IOAT 데이터 이동 가속, Copy Offload(XCOPY/ODX/NVMe Copy), dm-crypt/blk-crypto/SED 암호화 3경로, TSO/RDMA/TOE 네트워크 가속, NVMe-oF/iSCSI HBA/FC HBA 스토리지 프로토콜 오프로드, QAT 압축, GPU/NPU 미디어 가속, P2P DMA, 상용 NAS 아키텍처 비교, Linux 커널 빌딩 블록 매핑, 오프로드 결정 트리
핵심 요약
- 한 줄 정의: NAS H/W 오프로드란 스토리지 I/O 경로의 데이터 처리(RAID 패리티 연산, 암호화, 압축, 네트워크 프로토콜 등)를 CPU 대신 전용 하드웨어(RAID 컨트롤러, DSA, QAT, RDMA NIC, SED 등)에서 수행하여 처리량을 극대화하는 기술입니다.
- 핵심 역할: 멀티 유저 NAS에서 동시 파일 서비스(SMB/NFS), iSCSI 블록 서비스, 미디어 트랜스코딩, 백업/복제가 동시에 발생하면 CPU가 병목이 됩니다. 7대 오프로드(RAID, 데이터 이동, 복사, 암호화, 네트워크, 프로토콜, 압축)를 적절히 조합하면 CPU 부하를 극적으로 줄일 수 있습니다.
- 사용 이유: 10GbE 이상의 고속 네트워크 환경에서 소프트웨어 RAID + dm-crypt + TCP 체크섬 연산만으로도 CPU 코어가 포화되어 NAS 처리량이 네트워크 대역폭에 미치지 못하는 현상이 발생합니다. HW 오프로드로 CPU를 데이터 경로에서 제거하면 라인 레이트(Line Rate) 달성이 가능합니다.
- Linux 구현: md/dm(RAID) + DMA Engine/DSA(데이터 이동) + blk-crypto/SED(암호화) + crypto API/QAT(압축) + RDMA/TOE(네트워크) + LIO/NVMe target(프로토콜)을 커널 서브시스템 조합으로 구현합니다.
- 핵심 수치: HW RAID 6 vs SW RAID 6(CPU 사용률 80%→5%), QAT deflate(CPU 200MB/s→QAT 10GB/s), SED 암호화(성능 손실 0%), RDMA SMB Direct(CPU 50%↓, 지연 10×↓)
단계별 이해
- 애플리케이션 I/O 요청
NAS 클라이언트(SMB/NFS/iSCSI)로부터 I/O 요청이 도착하면, 커널의 VFS(Virtual File System) 계층을 통해 해당 파일시스템(ext4, Btrfs, XFS 등)에 전달됩니다. 이 단계에서 네트워크 프로토콜 오프로드(RDMA, TSO)가 CPU 부하를 줄입니다. - Block 레이어와 I/O 스케줄러
파일시스템이 블록 I/O를 생성하면 블록 레이어(Block Layer)의 blk-mq를 통해 I/O 스케줄러에 전달됩니다. 이 단계에서blk-crypto인라인 암호화나REQ_OP_COPY_OFFLOAD복사 오프로드가 적용될 수 있습니다. - RAID/DM 변환 + 암호화/압축 오프로드
MD(Multiple Devices) 또는 Device Mapper 레이어에서 RAID 변환이 수행됩니다. HW RAID 컨트롤러(MegaRAID, SmartPQI)는 이 과정 전체를 하드웨어에서 처리합니다. dm-crypt는 CPU에서, blk-crypto는 인라인 HW에서, SED/OPAL은 드라이브 내부에서 암호화합니다. - 스토리지 프로토콜 HBA 오프로드
SCSI/NVMe 드라이버가 디스크에 명령을 전달합니다. HW iSCSI HBA(Chelsio T6, QLogic)는 TCP/iSCSI 처리를 하드웨어에서 수행하고, FC HBA(lpfc, qla2xxx)는 Fibre Channel 프로토콜을 처리합니다. NVMe-oF RNIC는 RDMA 기반 원격 NVMe 접근을 가속합니다. - 네트워크 전송 오프로드
NAS가 클라이언트에 데이터를 전송할 때, NIC의 TSO/GSO/GRO/체크섬 오프로드가 TCP 세그먼테이션을 가속합니다. RDMA(RoCE/iWARP)를 사용하면 커널 TCP/IP 스택을 완전히 우회하여 zero-copy 전송이 가능합니다. QAT는 전송 전 데이터 압축을, kTLS은 TLS 암호화를 오프로드합니다.
선수 지식 수준 가이드
| 지식 영역 | 필수/권장 | 수준 | 학습 자료 |
|---|---|---|---|
| Linux 블록 I/O 기초 | 필수 | bio, request, blk-mq 개념 | Block I/O |
| RAID 개념 | 필수 | RAID 0/1/5/6/10 차이, 패리티 계산 | Device Mapper |
| SCSI/iSCSI | 권장 | SCSI 명령, iSCSI 프로토콜 | SCSI / iSCSI |
| 암호화 기초 | 권장 | AES, dm-crypt, LUKS 개념 | Crypto Framework |
| 네트워크 오프로드 | 권장 | TSO, GRO, RDMA 개념 | GSO/GRO |
NAS H/W 오프로드 개요 — I/O 경로와 오프로드 포인트
NAS는 일반 서버와 달리 다수의 동시 클라이언트가 혼합 워크로드(순차 대용량 읽기 + 랜덤 소규모 쓰기 + 메타데이터 연산)를 동시에 요청합니다. 이로 인해 CPU가 I/O 경로의 각 단계에서 데이터를 처리하느라 병목이 발생하며, 네트워크 대역폭을 100% 활용하지 못하는 상황이 흔합니다.
NAS가 일반 서버와 다른 I/O 특성
| 특성 | 일반 서버 | NAS |
|---|---|---|
| 동시 클라이언트 | 1~10 | 수십~수백 |
| 워크로드 패턴 | 단일 애플리케이션 | 혼합 (파일/블록/미디어) |
| I/O 크기 분포 | 비교적 균일 | 4KB~수MB 혼합 |
| 데이터 보호 | 선택적 | RAID + 암호화 + 스냅샷 필수 |
| 네트워크 대역폭 | 1~10 Gbps | 10~100 Gbps (다중 NIC) |
| CPU 부하 패턴 | 연산 중심 | I/O 경로 처리 중심 |
CPU-bound vs I/O-bound 분석
NAS 워크로드에서 CPU가 병목이 되는 대표적인 상황:
- SW RAID 5/6 패리티 계산: XOR/P+Q 연산이 모든 쓰기에 발생. 8-디스크 RAID 6에서 1GB 쓰기 시 ~3GB의 추가 연산량
- dm-crypt AES-XTS 암호화: AES-NI가 있어도 대역폭 3-5GB/s 수준에서 CPU 코어 포화
- TCP 체크섬 + 세그먼테이션: 10GbE 라인 레이트에서 TCP 처리만으로 2-3 코어 소모
- SW 압축 (gzip/lz4): 단일 코어 기준 200-800MB/s, 고속 NVMe 대비 병목
- 미디어 트랜스코딩: 4K H.265 실시간 변환 시 12코어 이상 필요
오프로드 없는 NAS의 CPU 사용률 분석
10GbE NAS에서 동시 워크로드를 실행했을 때, 오프로드 없이 CPU만으로 처리하면 어떤 분포를 보이는지 분석합니다. Xeon E-2388G(8코어 16스레드) 기준입니다.
| 처리 단계 | CPU 코어 소모 | CPU 비율 | 오프로드 가능 HW |
|---|---|---|---|
| SW RAID 6 XOR/PQ 연산 | 2~3 코어 | 25~38% | HW RAID, IOAT DMA |
| dm-crypt AES-XTS 암/복호화 | 1~2 코어 | 12~25% | SED, blk-crypto |
| TCP/IP 프로토콜 처리 | 1~2 코어 | 12~25% | RDMA, TSO/GRO |
| SMB3/NFS 프로토콜 처리 | 1~2 코어 | 12~25% | ksmbd 커널 서버 |
| gzip 압축 (백업 동시) | 1~2 코어 | 12~25% | QAT |
| 미디어 트랜스코딩 (동시) | 4~8 코어 | 50~100% | QSV, dGPU |
| memcpy (버퍼 복사) | 0.5~1 코어 | 6~12% | DSA |
perf로 오프로드 효과 측정하는 방법
# 1단계: 오프로드 전 CPU 프로파일링
perf record -g -a -- sleep 30 # 30초간 시스템 전체 프로파일
perf report --sort=comm,dso,symbol --stdio | head -50
# 결과 예시:
# 35.2% md0_raid6 [kernel] raid5_compute_sector
# 22.1% kcryptd [kernel] aesni_ctr_enc
# 15.3% ksoftirqd [kernel] tcp_v4_rcv
# 8.7% kworker [kernel] memcpy_orig
# 2단계: HW RAID 적용 후 프로파일링
# raid5_compute_sector가 사라지고 CPU 여유 확인
perf stat -e cycles,instructions,cache-misses -- fio ...
# 3단계: SED 적용 후 프로파일링
# aesni_ctr_enc가 사라짐
# 4단계: RDMA 적용 후 프로파일링
# tcp_v4_rcv가 사라지고 mlx5_ib 하드웨어 처리
# CPU 사용률 변화 요약 (mpstat)
mpstat -P ALL 5 3 # 5초 간격, 3회 측정
오프로드 적용 전후 성능 비교 예시
| 지표 | 오프로드 없음 | 부분 오프로드 | 전체 오프로드 |
|---|---|---|---|
| 순차 쓰기 (RAID 6) | ~1.5 GB/s | ~5 GB/s (HW RAID) | ~8 GB/s (HW RAID + SED) |
| CPU 사용률 (순차 쓰기) | 90% | 40% | 10% |
| SMB 동시 클라이언트 4K IOPS | ~50K | ~150K | ~400K (RDMA) |
| CPU 사용률 (SMB 서비스) | 85% | 35% | 15% |
| 백업 압축 처리량 | ~200 MB/s (gzip SW) | ~2 GB/s (lz4 SW) | ~10 GB/s (QAT deflate) |
| 4K 트랜스코딩 동시 스트림 | 1개 (CPU) | 15개 (QSV) | 30개 (dGPU) |
| rebuild 중 서비스 성능 유지율 | 50% | 80% | 95% |
오프로드 7대 분류 체계
HW RAID 오프로드 — MegaRAID, async_tx, BBU/FBWC
HW RAID 컨트롤러는 NAS에서 가장 전통적이고 효과적인 오프로드 수단입니다. XOR/P+Q 패리티 연산, 캐시 관리, 디스크 장애 복구를 모두 컨트롤러 펌웨어와 전용 프로세서에서 처리하므로, 호스트 CPU는 RAID의 존재를 인식하지 못합니다.
주요 HW RAID 드라이버 비교
| 드라이버 | 벤더 | 대표 제품 | RAID 레벨 | 최대 디스크 | 캐시 보호 |
|---|---|---|---|---|---|
megaraid_sas | Broadcom (LSI) | MegaRAID 9560, 9670 | 0/1/5/6/10/50/60 | 240+ | BBU, FBWC (CacheVault) |
smartpqi | Microchip (Adaptec) | SmartRAID 3200 | 0/1/5/6/10/50/60 | 256 | ZMCP, maxCache |
hpsa → smartpqi | HPE | Smart Array P816i-a | 0/1/5/6/10/50/60 | 68 | FBWC |
커널 소스 분석: megaraid_sas 명령 제출 경로
/* drivers/scsi/megaraid/megaraid_sas_fusion.c (간략화) */
static int
megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
struct scsi_cmnd *scmd)
{
struct megasas_cmd_fusion *cmd;
struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
cmd = megasas_get_cmd_fusion(instance, scmd->request->tag);
io_request = cmd->io_request;
/* SCSI CDB를 MPI2 RAID 요청으로 변환 */
memcpy(io_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
io_request->DevHandle = cpu_to_le16(device_id);
/* RAID 가속 경로: 컨트롤러가 직접 디스크에 접근 */
if (megasas_is_ldio(scmd))
megasas_build_ldio_fusion(instance, scmd, cmd);
/* 도어벨 레지스터를 통해 컨트롤러에 명령 전달 */
instance->instancet->fire_cmd(instance,
cmd->request_desc_phys, 0, instance->reg_set);
return 0;
}
코드 설명
- 핵심megasas_build_and_issue_cmd_fusion() — SCSI mid-layer에서 받은 명령을 MPI2(Message Passing Interface 2) 프레임으로 변환하여 HW RAID 컨트롤러에 전달합니다. 컨트롤러는 내부 XOR/P+Q 엔진으로 패리티를 계산하고, DDR 캐시를 통해 쓰기를 가속합니다. 호스트 CPU는 프레임 구성과 도어벨(doorbell) 알림만 수행하며, 실제 RAID 연산에는 관여하지 않습니다.
BBU/FBWC 모니터링과 캐시 정책
HW RAID의 성능은 Write-back 캐시에 크게 의존합니다. Write-back은 데이터를 컨트롤러 캐시에만 기록하고 즉시 완료를 반환하므로 쓰기 지연이 극적으로 줄어듭니다. 단, BBU(Battery Backup Unit) 또는 FBWC(Flash-Backed Write Cache)가 정상이어야 정전 시 데이터를 보호할 수 있습니다.
# storcli BBU 상태 확인 (MegaRAID)
storcli /c0/bbu show all
# 주요 확인 항목:
# Battery State : Optimal
# Charging Status : None
# Temperature : 23 C
# Design Capacity : 1400 mAh
# Full Charge Capacity: 1350 mAh (95% 이상 권장)
# Write Policy 확인
storcli /c0/v0 show | grep "Cache Policy"
# WriteBack → 정상 (BBU OK)
# WriteThrough → BBU 불량 시 자동 전환 (성능 급락!)
# smartpqi (Adaptec) BBU 확인
arcconf getconfig 1 | grep -A5 "Battery"
async_tx API — 커널 XOR/PQ 연산 오프로드 프레임워크
Linux 커널의 async_tx API는 RAID 5/6의 XOR 패리티 연산 및 PQ(P+Q) 이중 패리티 연산을 DMA 엔진으로 오프로드하는 프레임워크입니다. HW RAID 컨트롤러 없이도 SW RAID(md)에서 XOR 가속을 활용할 수 있으며, HW RAID와 결합하면 rebuild 성능을 더욱 향상시킬 수 있습니다. async_tx는 drivers/dma/ 디렉토리의 DMA 엔진 드라이버와 연동하며, DMA 엔진이 없으면 자동으로 CPU 기반 소프트웨어 폴백을 수행합니다.
커널 소스 분석: async_xor() — XOR 패리티 연산 오프로드
/* crypto/async_tx/async_xor.c */
struct dma_async_tx_descriptor *
async_xor(struct page *dest, struct page **src_list,
unsigned int offset, int src_cnt, size_t len,
struct async_submit_ctl *submit)
{
struct dma_chan *chan = async_tx_find_channel(submit,
DMA_XOR, &dest, 1, src_list,
src_cnt, len);
struct dma_device *device = chan ? chan->device : NULL;
struct dmaengine_unmap_data *unmap = NULL;
BUG_ON(src_cnt <= 1);
if (device && src_cnt <= device->max_xor) {
/* DMA 엔진이 XOR을 지원하고 소스 수가 범위 내 */
unmap = dmaengine_get_unmap_data(device->dev,
src_cnt + 1, GFP_NOWAIT);
if (likely(unmap)) {
struct dma_async_tx_descriptor *tx;
/* DMA 엔진에 XOR 작업 제출 */
tx = device->device_prep_dma_xor(chan,
dma_dest, dma_src, src_cnt, len,
dma_flags);
if (likely(tx)) {
async_tx_submit(chan, tx, submit);
return tx;
}
}
}
/* DMA 엔진 사용 불가 시 CPU 소프트웨어 폴백 */
xor_blocks(src_cnt, len, dest_buf, srcs);
return NULL;
}
코드 설명
- 핵심async_xor()는 RAID 5/6 패리티 계산의 핵심 경로입니다. 먼저
async_tx_find_channel()로 XOR 기능을 지원하는 DMA 채널을 탐색합니다. Intel IOAT, Marvell XOR 엔진 등이 등록되어 있으면device_prep_dma_xor()로 하드웨어 XOR 연산을 준비하고,async_tx_submit()으로 비동기 제출합니다. DMA 엔진이 없거나 제출에 실패하면xor_blocks()소프트웨어 폴백이 실행됩니다. 이 투명한 폴백 설계 덕분에 md RAID는 HW XOR 엔진 유무에 관계없이 동일한 코드 경로를 사용합니다.
RAID Rebuild 과정과 HW 가속 효과
RAID 어레이에서 디스크가 교체되면 rebuild(재구성) 프로세스가 시작됩니다. 이 과정은 나머지 디스크의 데이터와 패리티로부터 교체된 디스크의 데이터를 복원하는 것으로, 대규모 NAS에서는 수 시간에서 수일이 소요될 수 있습니다.
- RAID 5 rebuild: (N-1)개 디스크의 동일 스트라이프를 XOR하여 누락 디스크 데이터를 복원합니다. XOR 연산량이 전체 디스크 용량에 비례합니다.
- RAID 6 rebuild: PQ(Reed-Solomon) 연산으로 2개 디스크 장애까지 복구 가능하며, GF(Galois Field) 곱셈이 추가되어 CPU 부하가 RAID 5 대비 2~3배 증가합니다.
- HW RAID rebuild: 컨트롤러의 XOR/PQ 전용 ASIC이 처리하므로 호스트 CPU 사용률이 1~5% 수준에 머무릅니다. NAS 서비스 성능 영향이 최소화됩니다.
- SW RAID rebuild:
md_do_sync()→sync_request()→async_xor()경로를 통해 CPU 또는 DMA 엔진이 처리합니다./proc/sys/dev/raid/speed_limit_min과speed_limit_max로 rebuild 속도를 제어하여 서비스 영향을 조절합니다.
# SW RAID rebuild 속도 제한 설정
echo 200000 > /proc/sys/dev/raid/speed_limit_min # 최소 200 MB/s
echo 500000 > /proc/sys/dev/raid/speed_limit_max # 최대 500 MB/s
# rebuild 진행 상황 확인
cat /proc/mdstat
# md0 : active raid6 sda1[0] sdb1[1] sdc1[2] sdd1[3] sde1[4] sdf1[5]
# 19531776 blocks super 1.2 level 6, 512k chunk
# [6/5] [UUUUU_]
# [====>................] recovery = 23.4% (1143040/4883072)
# finish=12.3min speed=508120K/sec
HW RAID vs SW RAID 성능 비교
| 항목 | HW RAID (MegaRAID 9560) | SW RAID (md + AES-NI XOR) | SW RAID (md + IOAT DMA) |
|---|---|---|---|
| 순차 읽기 (RAID 6, 8×SSD) | ~12 GB/s | ~10 GB/s | ~11 GB/s |
| 순차 쓰기 (RAID 6, 8×SSD) | ~8 GB/s | ~4 GB/s | ~6 GB/s |
| 랜덤 4K 읽기 IOPS | ~900K | ~600K | ~700K |
| 랜덤 4K 쓰기 IOPS | ~250K | ~80K | ~120K |
| Rebuild 중 CPU 사용률 | 1~5% | 60~80% | 15~25% |
| Rebuild 중 서비스 성능 저하 | 5~10% | 30~50% | 15~25% |
| 패리티 연산 대역폭 | 24 GB/s (전용 ASIC) | ~15 GB/s (AVX-512) | ~20 GB/s (DMA XOR) |
| 쓰기 캐시 | 4 GB FBWC | 페이지 캐시 의존 | 페이지 캐시 의존 |
| 장점 | CPU 완전 해방, 캐시 보호 | 투명성, 유연성, 무료 | CPU 부분 해방 |
| 단점 | 높은 비용, 벤더 종속 | 높은 CPU 부하 | Xeon 서버 전용 |
JBOD Passthrough 모드와 HBA 모드 (IT Firmware)
HW RAID 컨트롤러를 사용하지 않고 디스크를 OS에 직접 노출하려면 JBOD(Just a Bunch of Disks) 모드 또는 IT(Initiator Target) 모드 펌웨어를 사용합니다. ZFS, Btrfs 같은 소프트웨어 RAID/볼륨 관리자는 디스크에 직접 접근해야 최적의 성능과 기능(자가 복구, 스크럽, 스냅샷 등)을 제공할 수 있으므로, HBA 모드가 권장됩니다.
| 모드 | RAID 처리 | 디스크 노출 | 대표 컨트롤러 | 적합 시나리오 |
|---|---|---|---|---|
| IR 모드 (HW RAID) | 컨트롤러 ASIC | 가상 디스크 (VD) | MegaRAID 9560, SmartRAID 3254 | 전통적 NAS, 하드웨어 캐시 필요 시 |
| IT 모드 (HBA) | 없음 (패스스루) | 개별 물리 디스크 | 9500-16i (IT), HBA 9400 | ZFS/Btrfs NAS, TrueNAS |
| JBOD 모드 | RAID 가능 + 개별 노출 | 혼합 가능 | MegaRAID (JBOD 설정) | 유연한 혼합 구성 |
# LSI/Broadcom 컨트롤러 IT 모드 확인
sas3flash -list
# Firmware Product ID: IT (Initiator Target)
# JBOD 모드 설정 (storcli)
storcli /c0 set jbod=on
# 개별 디스크를 JBOD으로 전환
storcli /c0/e252/s0 set jbod
# 디스크가 OS에 직접 노출되는지 확인
lsblk -d -o NAME,MODEL,SIZE,TRAN
# sda ST16000NM001G 14.6T sas
# sdb ST16000NM001G 14.6T sas
Intel DSA/IOAT 데이터 이동 가속 — idxd, work queue
Intel DSA(Data Streaming Accelerator)는 4세대 Xeon Scalable(Sapphire Rapids)부터 내장된 데이터 이동 가속기입니다. 기존 IOAT(I/O Acceleration Technology, Crystal Beach DMA)의 후속으로, 대용량 메모리 복사(memcpy), 0-fill, CRC 계산, 데이터 비교 등을 CPU 없이 수행합니다.
DSA vs IOAT 비교
| 항목 | IOAT (Crystal Beach DMA) | DSA (Data Streaming Accelerator) |
|---|---|---|
| 도입 세대 | Nehalem~Ice Lake | Sapphire Rapids~ |
| 커널 드라이버 | ioatdma | idxd |
| 제출 방식 | MMIO descriptor ring | ENQCMD/ENQCMDS (CPU 명령어) |
| Work Queue | 단일 채널 | Shared WQ + Dedicated WQ |
| 지원 연산 | memcpy, XOR | memcpy, memfill, compare, CRC, DIF, drain, batch |
| 가상화 | SR-IOV (제한적) | mdev (SIOV, 유연한 할당) |
| 배치 처리 | 미지원 | batch descriptor로 다수 연산 묶어 제출 |
커널 소스 분석: idxd descriptor 제출
/* drivers/dma/idxd/submit.c (간략화) */
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc,
enum idxd_submit_flags flags)
{
struct idxd_device *idxd = wq->idxd;
void __iomem *portal;
portal = idxd_wq_portal_addr(wq);
/*
* Shared WQ: ENQCMDS 명령어로 제출 (실패 시 재시도)
* Dedicated WQ: MOVDIR64B로 제출 (항상 성공)
*/
if (wq_dedicated(wq)) {
movdir64b(portal, desc->hw);
} else {
/* ENQCMDS는 WQ가 꽉 찬 경우 실패할 수 있음 */
rc = enqcmds(portal, desc->hw);
if (rc)
return -EAGAIN;
}
return 0;
}
코드 설명
- 핵심idxd_submit_desc() — DSA의 Work Queue에 작업 descriptor를 제출합니다. Dedicated WQ는 단일 드라이버가 독점하므로
MOVDIR64B명령어로 무조건 성공합니다. Shared WQ는 다중 사용자(VM 포함)가 공유하므로ENQCMDS명령어를 사용하며, 큐가 꽉 차면-EAGAIN을 반환합니다. NAS 환경에서는 RAID rebuild, 대용량 복사 등의 memcpy 작업을 DSA에 위임하여 CPU 코어를 클라이언트 요청 처리에 집중시킬 수 있습니다.
NAS RAID Rebuild에서 DSA memcpy 활용
RAID rebuild는 디스크에서 읽은 데이터 블록을 메모리에서 XOR 연산한 뒤 교체 디스크에 기록하는 과정입니다. 이 과정에서 대량의 memcpy 작업이 발생하며, DSA를 활용하면 CPU를 데이터 이동에서 완전히 해방할 수 있습니다.
- 읽기 단계: N-1개 디스크에서 스트라이프를 DMA로 메모리에 적재 — DSA
memmove연산으로 버퍼 정렬 - 연산 단계: XOR/PQ 연산은 async_tx 또는 RAID 컨트롤러가 처리
- 쓰기 단계: 복원된 데이터를 교체 디스크로 전송 — DSA
memcpy로 DMA 버퍼 준비 - 검증 단계: 복원 데이터의 CRC 검증 — DSA
crc_gen연산 활용 가능
특히 NAS가 rebuild 중에도 클라이언트 요청을 처리해야 하는 경우, DSA로 memcpy를 오프로드하면 CPU 코어를 SMB/NFS 프로토콜 처리에 집중시킬 수 있습니다. 8TB RAID 6 어레이의 rebuild 시 약 8TB의 읽기 + 8TB의 쓰기 + 지속적인 XOR 연산이 필요하며, memcpy 오프로드만으로도 CPU 사용률을 20~30% 절감할 수 있습니다.
Batch Descriptor 활용법
DSA는 단일 descriptor 제출뿐 아니라 Batch descriptor를 지원합니다. 여러 개의 작업을 하나의 batch로 묶어 제출하면 descriptor 제출 오버헤드를 줄이고 DSA 내부 파이프라인을 효율적으로 활용할 수 있습니다.
/* Batch descriptor 구성 예시 (사용자 공간 DSA 라이브러리) */
struct dsa_hw_desc batch_desc;
struct dsa_hw_desc sub_descs[MAX_BATCH_SIZE];
/* 서브 descriptor 배열 준비 */
for (int i = 0; i < batch_size; i++) {
sub_descs[i].opcode = DSA_OPCODE_MEMMOVE;
sub_descs[i].src_addr = src_buffers[i];
sub_descs[i].dst_addr = dst_buffers[i];
sub_descs[i].xfer_size = block_size;
sub_descs[i].flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
}
/* Batch descriptor 설정 */
batch_desc.opcode = DSA_OPCODE_BATCH;
batch_desc.desc_list_addr = (uintptr_t)sub_descs;
batch_desc.desc_count = batch_size;
batch_desc.flags = IDXD_OP_FLAG_CRAV | IDXD_OP_FLAG_RCR;
batch_desc.completion_addr = (uintptr_t)&completion;
/* 단일 MOVDIR64B/ENQCMDS로 전체 batch 제출 */
movdir64b(wq_portal, &batch_desc);
DSA vs CPU memcpy 벤치마크
| 블록 크기 | CPU memcpy (단일 코어) | DSA Dedicated WQ | DSA Shared WQ | CPU 사용률 (DSA) |
|---|---|---|---|---|
| 4 KB | ~12 GB/s | ~3 GB/s | ~2.5 GB/s | <1% |
| 64 KB | ~15 GB/s | ~25 GB/s | ~20 GB/s | <1% |
| 256 KB | ~16 GB/s | ~35 GB/s | ~30 GB/s | <1% |
| 1 MB | ~17 GB/s | ~40 GB/s | ~35 GB/s | <1% |
| 4 MB | ~17 GB/s | ~42 GB/s | ~38 GB/s | <1% |
accel-config 도구 사용법
accel-config는 Intel DSA/IAX 장치를 사용자 공간에서 설정하고 관리하는 공식 도구입니다. Work Queue 생성, 엔진 바인딩, 디바이스 활성화 등을 수행합니다.
# DSA 장치 열거
accel-config list
# DSA 장치 설정 (dsa0)
# 1. 그룹 생성 및 엔진 할당
accel-config config-group dsa0/group0.0 \
--read-buffers-reserved=8 \
--read-buffers-allowed=8
accel-config config-engine dsa0/engine0.0 --group-id=0
# 2. Dedicated Work Queue 생성
accel-config config-wq dsa0/wq0.0 \
--group-id=0 \
--mode=dedicated \
--wq-size=128 \
--priority=10 \
--type=kernel \
--name=nas_raid_wq \
--driver-name=dmaengine \
--block-on-fault=1
# 3. 장치 및 WQ 활성화
accel-config enable-device dsa0
accel-config enable-wq dsa0/wq0.0
# 4. 상태 확인
accel-config list -i
# [
# {
# "dev": "dsa0",
# "state": "enabled",
# "max_groups": 4,
# "max_work_queues": 8,
# "max_engines": 4,
# ...
# }
# ]
# Shared WQ 설정 (VM/컨테이너 공유용)
accel-config config-wq dsa0/wq0.1 \
--group-id=0 \
--mode=shared \
--wq-size=64 \
--priority=5 \
--type=user \
--name=nas_shared_wq \
--threshold=32
# DMA 엔진으로 등록되었는지 확인
ls /sys/class/dma/
# dma0chan0 dma0chan1 ...
# 성능 모니터링
cat /sys/bus/dsa/devices/dsa0/clients
cat /sys/bus/dsa/devices/wq0.0/state
accel-config 설정은 재부팅 시 초기화됩니다. accel-config save-config -s nas-dsa.conf로 저장하고, systemd 서비스 또는 /etc/accel-config/accel-config.conf.d/에 배치하여 부팅 시 자동 적용할 수 있습니다. NAS 환경에서는 type=kernel과 driver-name=dmaengine을 사용하여 커널 DMA 서브시스템에 자동 등록하는 것이 일반적입니다.
Copy Offload — XCOPY, ODX, NVMe Copy
Copy Offload는 데이터 복사 시 호스트 CPU와 메모리를 경유하지 않고, 스토리지 장치 내부 또는 서버 측에서 직접 복사를 수행하는 기술입니다. NAS에서 VM 클론, 스냅샷 복사, 백업 등 대용량 데이터 이동 시 네트워크 대역폭과 CPU를 극적으로 절약합니다.
커널 소스 분석: NVMe Copy Command 설정
/* drivers/nvme/host/core.c (간략화) */
static void nvme_setup_copy(struct nvme_ns *ns,
struct nvme_command *cmd,
struct nvme_copy_range *ranges,
u16 nr_ranges, u64 dst_lba)
{
cmd->copy.opcode = nvme_cmd_copy;
cmd->copy.nsid = cpu_to_le32(ns->head->ns_id);
cmd->copy.sdlba = cpu_to_le64(dst_lba); /* 대상 시작 LBA */
cmd->copy.nr = cpu_to_le16(nr_ranges - 1);
/* 소스 LBA 범위들은 PRP/SGL로 전달 */
/* 컨트롤러가 NAND 내부에서 직접 복사 수행 */
}
코드 설명
- 핵심NVMe Copy Command — TP 4065 사양으로 정의된 NVMe Simple Copy 명령입니다. 소스 LBA와 대상 LBA를 지정하면 컨트롤러가 NAND 플래시 내부에서 직접 데이터를 복사합니다. 호스트 메모리를 전혀 경유하지 않으므로 CPU 부하 0%, PCIe 대역폭 미소모의 이상적인 복사가 가능합니다. 단, 동일 네임스페이스(NS) 내에서만 복사 가능하며, 컨트롤러별 최대 복사 크기(MSSRL/MCL) 제한이 있습니다.
XCOPY 실전 활용과 LIO 타겟 설정
SCSI XCOPY(Extended Copy, SPC-4)는 iSCSI/FC 환경에서 서버 측 데이터 복사를 수행합니다. NAS가 LIO 타겟으로 블록 서비스를 제공할 때, 클라이언트의 복사 요청을 서버 내부에서 처리하여 네트워크 트래픽을 제거합니다.
# LIO 타겟에서 XCOPY 지원 확인
targetcli
/> /backstores/block/nas-lun0 get attribute max_xcopy_target_sectors
# 2048 (기본값, 8MB)
# XCOPY 최대 크기 설정 (대용량 VM 클론용)
/> /backstores/block/nas-lun0 set attribute max_xcopy_target_sectors=8192
# 클라이언트에서 XCOPY 복사 (sg3_utils)
sg_xcopy --src=/dev/sda --dst=/dev/sdb --bs=512 --count=204800
# 100MB 복사 — 호스트 메모리 미경유, CPU 부하 최소
# dd 대비 XCOPY 성능
# dd: 호스트 read(source) → 메모리 → write(dest) = CPU+메모리 경유
# XCOPY: 호스트가 XCOPY 명령만 전송 → 타겟이 내부 복사
# 대용량 LUN 복제 시 XCOPY가 3~5배 빠름
SMB ODX(Offloaded Data Transfer) NAS 적용
SMB ODX는 Windows 클라이언트가 SMB 공유 간 파일을 복사할 때, 실제 데이터를 네트워크로 전송하지 않고 토큰 기반으로 서버 측에서 복사를 수행합니다. NAS에서 대용량 파일/폴더 복사 시 네트워크 부하를 제거합니다.
- 동작 원리: 클라이언트가 FSCTL_OFFLOAD_READ로 소스 파일의 토큰을 획득하고, FSCTL_OFFLOAD_WRITE로 대상 위치에 토큰을 전달합니다. 서버(ksmbd/Samba)가 내부적으로 데이터를 복사합니다.
- ksmbd 지원: Linux 6.x의 ksmbd는 SMB3 Copy Offload를 지원합니다. 동일 서버의 다른 공유 간 복사도 서버 내부에서 처리됩니다.
- Samba 지원: Samba 4.1+에서
vfs_copy_chunk()를 통해 server-side copy를 구현합니다.copy chunk = yes설정이 필요합니다. - 제한사항: 서로 다른 NAS 서버 간 ODX는 토큰 호환성 문제로 실질적으로 동작하지 않습니다. 동일 서버 내 공유 간 복사에서만 효과가 있습니다.
NVMe Copy와 파일시스템 연동
NVMe Copy 명령은 블록 레이어에서 동작하므로, 파일시스템이 이를 활용하려면 copy_file_range() 시스템콜과의 연동이 필요합니다.
| 파일시스템 | NVMe Copy 활용 | 메커니즘 | 상태 |
|---|---|---|---|
| XFS | reflink + copy | CoW reflink 후 블록 복사 시 NVMe Copy 가능 | 개발 중 |
| Btrfs | reflink (CoW) | 메타데이터만 복사, 실제 블록 복사 불필요 | 네이티브 CoW |
| ext4 | 미지원 | reflink 미지원 | - |
| ZFS | 간접적 | ZFS CoW + send/receive | 블록 레이어 미경유 |
암호화 오프로드 — dm-crypt/blk-crypto/SED 3경로
NAS에서 디스크 암호화는 규제 준수(GDPR, HIPAA)와 물리적 도난 대비를 위해 필수입니다. Linux는 세 가지 암호화 경로를 제공하며, 각각 성능 특성이 크게 다릅니다.
3경로 성능 비교
| 방식 | 암호화 위치 | CPU 부하 | 성능 영향 | 키 관리 | 사용 사례 |
|---|---|---|---|---|---|
| dm-crypt (AES-NI) | 블록 레이어 (CPU) | 중~높음 | 10-30% 감소 | LUKS1/LUKS2 | 범용 NAS, 유연한 키 관리 필요 시 |
| blk-crypto | 스토리지 컨트롤러 HW | 없음 | 0-2% 감소 | blk-crypto framework | UFS/NVMe 인라인 암호화 지원 장치 |
| SED/OPAL | 드라이브 내부 | 없음 | 0% (투명) | TCG Opal (sedutil) | 최고 성능, 물리 보안 중심 NAS |
blk_crypto_submit_bio() — 인라인 암호화 경로
커널 소스 분석: blk_crypto_submit_bio() — 블록 레이어 인라인 암호화
/* block/blk-crypto.c */
bool blk_crypto_submit_bio(struct bio **bio_ptr)
{
struct bio *bio = *bio_ptr;
struct bio_crypt_ctx *bc = bio->bi_crypt_context;
struct blk_crypto_keyslot *keyslot;
if (!bc)
return true; /* 암호화 컨텍스트 없으면 통과 */
/*
* 하드웨어가 이 암호화 프로파일을 지원하는지 확인
* — 지원하면 인라인 HW 암호화 사용
* — 미지원이면 blk-crypto-fallback (SW) 경로
*/
if (!blk_crypto_config_supported_natively(
bio->bi_bdev, &bc->bc_key->crypto_cfg)) {
/* SW 폴백: dm-crypt 유사 방식으로 CPU 암호화 */
return blk_crypto_fallback_submit_bio(bio_ptr);
}
/* 키슬롯 할당: HW 컨트롤러의 키 테이블에 키 프로그래밍 */
keyslot = blk_crypto_get_keyslot(bc->bc_key,
bio->bi_bdev);
if (IS_ERR(keyslot)) {
bio->bi_status = BLK_STS_IOERR;
return false;
}
/* bio에 키슬롯 번호를 설정하여 HW 컨트롤러에 전달 */
bio_crypt_set_keyslot(bio, keyslot);
return true; /* 정상 I/O 경로 계속 */
}
코드 설명
- 핵심blk_crypto_submit_bio()는 블록 I/O가 제출될 때 호출되어 인라인 암호화를 처리합니다.
bi_crypt_context가 설정된 bio에 대해, 먼저 HW 컨트롤러가 해당 암호화 알고리즘(AES-256-XTS 등)을 지원하는지 확인합니다. 지원하면 키를 HW 키슬롯에 프로그래밍하고 bio에 키슬롯 번호를 설정하여 컨트롤러가 데이터 경로에서 투명하게 암/복호화를 수행합니다. UFS/eMMC 인라인 암호화 엔진이나 NVMe 컨트롤러의 암호화 기능이 이 경로를 사용합니다. HW 미지원 시blk_crypto_fallback이 CPU에서 암호화를 수행합니다.
dm-crypt 워커 스레드 아키텍처 (kcryptd)
dm-crypt는 Device Mapper 기반의 블록 레이어 암호화로, NAS에서 가장 널리 사용되는 전체 디스크 암호화 솔루션입니다. 내부적으로 여러 워커 스레드를 사용하여 암호화/복호화를 병렬 처리합니다.
- kcryptd: 암호화 요청을 처리하는 메인 워커 스레드입니다. I/O 요청을 받아 crypto API로 전달합니다.
- kcryptd_io: 암/복호화가 완료된 bio를 하위 디바이스에 제출하거나 상위로 완료를 전달합니다.
- kcryptd_crypt: 실제 AES-XTS 연산을 수행하는 워커입니다. CPU 코어별로 독립적으로 실행되어 멀티코어 병렬 처리를 활용합니다.
# dm-crypt 워커 스레드 확인
ps aux | grep kcrypt
# root kcryptd
# root kcryptd_io
# root kcryptd_crypt/0
# root kcryptd_crypt/1
# root kcryptd_crypt/2
# root kcryptd_crypt/3
# dm-crypt 성능 튜닝
# 동시 I/O 요청 수 (기본값: 적절한 값 자동 설정)
dmsetup table --showkeys /dev/mapper/nas-crypt
# 0 976773168 crypt aes-xts-plain64 0 /dev/sda2 0
# submit_from_crypt_cpus 옵션으로 I/O 제출 스레드 분리
# → 암호화 스레드가 I/O 완료 대기를 하지 않아 처리량 향상
echo 1 > /sys/block/dm-0/dm/submit_from_crypt_cpus
# no_read_workqueue / no_write_workqueue (5.9+)
# → 워크큐 없이 직접 처리하여 지연시간 감소 (NVMe SSD 권장)
cryptsetup open --perf-no_read_workqueue --perf-no_write_workqueue \
/dev/nvme0n1p2 nas-crypt
per-file Encryption (fscrypt) vs Full-disk Encryption 비교
NAS에서는 전체 디스크 암호화(FDE)와 파일 단위 암호화(fscrypt) 중 선택해야 합니다. 각 방식의 특성이 NAS 워크로드에 미치는 영향을 비교합니다.
| 항목 | dm-crypt (FDE) | fscrypt (per-file) | SED (FDE) |
|---|---|---|---|
| 암호화 단위 | 블록 디바이스 전체 | 파일/디렉토리 단위 | 드라이브 전체 |
| 메타데이터 보호 | 전체 (파일명 포함) | 파일명 암호화 선택적 | 전체 (투명) |
| 성능 영향 | 10~30% (AES-NI) | 5~15% (AES-NI) | 0% (투명) |
| 키 관리 | LUKS1/LUKS2 (단일 키) | 파일별/디렉토리별 키 | TCG Opal (드라이브 키) |
| 멀티 유저 격리 | 불가 (단일 키) | 가능 (유저별 키) | 불가 (단일 키) |
| NAS 공유 폴더 적합성 | 높음 (전체 볼륨) | 높음 (폴더별 키) | 최고 (성능 무손실) |
| 지원 파일시스템 | 모든 파일시스템 | ext4, F2FS, UBIFS | 모든 파일시스템 |
| HW 가속 | AES-NI / blk-crypto | AES-NI / blk-crypto | 드라이브 내장 AES |
LUKS2 vs LUKS1 — NAS 적합성 비교
LUKS(Linux Unified Key Setup)는 dm-crypt의 표준 키 관리 형식입니다. LUKS2는 LUKS1의 후속 버전으로 NAS 환경에서 상당한 장점을 제공합니다.
| 항목 | LUKS1 | LUKS2 |
|---|---|---|
| 헤더 형식 | 바이너리 | JSON 메타데이터 |
| 최대 키슬롯 | 8개 | 32개 |
| 키 유도 함수 | PBKDF2 | Argon2id (메모리 하드) |
| 무결성 보호 | 없음 | dm-integrity 연동 (AEAD) |
| 온라인 재암호화 | 불가 | 가능 (cryptsetup reencrypt) |
| 토큰 지원 | 없음 | FIDO2, TPM2, systemd-cryptenroll |
| 헤더 크기 | 2 MB (고정) | 16 MB (가변, 확장 가능) |
| NAS 권장 | 레거시 호환 | 신규 설치 기본값 |
# LUKS2 볼륨 생성 (NAS 최적화 설정)
cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha256 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--sector-size 4096 \
/dev/md0
# LUKS2 무결성 보호 활성화 (AEAD 모드)
cryptsetup luksFormat --type luks2 \
--cipher aes-gcm-random \
--integrity aead \
/dev/md0
# 온라인 재암호화 (서비스 중단 없이 키 변경)
cryptsetup reencrypt /dev/mapper/nas-crypt \
--cipher aes-xts-plain64 --key-size 512
# TPM2 자동 잠금해제 설정 (NAS 자동 부팅)
systemd-cryptenroll /dev/md0 --tpm2-device=auto --tpm2-pcrs=7
--pbkdf-memory를 512MB 이하로 설정하세요. 메모리 부족 시 잠금해제가 실패하거나 OOM이 발생할 수 있습니다.
네트워크 프로토콜 오프로드 — TSO/RDMA/TOE/iSER
NAS는 네트워크를 통해 클라이언트에 데이터를 전달하므로, 네트워크 프로토콜 처리가 전체 CPU 부하의 상당 부분을 차지합니다. 10GbE 이상 환경에서는 TCP 처리만으로 CPU 코어가 포화될 수 있습니다.
RDMA 프로토콜 비교
| 프로토콜 | 전송 계층 | Lossless 필요 | 대표 NIC | NAS 사용 사례 |
|---|---|---|---|---|
| RoCE v2 | UDP/IP | PFC/ECN 필수 | ConnectX-6/7, BCM57508 | SMB Direct, NFS/RDMA |
| iWARP | TCP/IP | 불필요 | Chelsio T6, Intel E810 | 기존 네트워크 호환 RDMA |
| InfiniBand | IB Native | 자체 Flow Control | ConnectX-7 (IB) | HPC 스토리지, 대규모 클러스터 |
RDMA Queue Pair — 커널 QP 생성 경로
커널 소스 분석: rdma_create_qp() — RDMA Queue Pair 생성
/* drivers/infiniband/core/cma.c */
int rdma_create_qp(struct rdma_cm_id *id,
struct ib_pd *pd,
struct ib_qp_init_attr *qp_init_attr)
{
struct rdma_id_private *id_priv;
struct ib_qp *qp;
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
/*
* Queue Pair 생성:
* - Send Queue (SQ): RDMA Write/Send 요청 게시
* - Receive Queue (RQ): 수신 버퍼 사전 등록
* - Completion Queue (CQ): 완료 이벤트 수신
*/
qp = ib_create_qp(pd, qp_init_attr);
if (IS_ERR(qp))
return PTR_ERR(qp);
/* QP를 RDMA CM ID에 연결 */
id->qp = qp;
id_priv->qp_num = qp->qp_num;
/* QP를 INIT 상태로 전환 */
ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
if (ret)
goto err;
ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
if (ret)
goto err;
return 0;
err:
ib_destroy_qp(qp);
return ret;
}
코드 설명
- 핵심rdma_create_qp()는 RDMA 통신의 핵심 자료구조인 Queue Pair(QP)를 생성합니다. QP는 Send Queue(SQ)와 Receive Queue(RQ)로 구성되며, 각 큐에 Work Request(WR)를 게시하여 제로카피(zero-copy) 데이터 전송을 수행합니다. NAS에서 SMB Direct나 NFS/RDMA를 사용할 때 이 경로를 통해 QP가 생성됩니다.
ib_create_qp()는 HW 드라이버(mlx5, bnxt_re 등)의create_qp콜백을 호출하여 NIC의 하드웨어 QP 자원을 할당합니다. QP는 INIT → RTR(Ready to Receive) → RTS(Ready to Send) 상태 전환을 거쳐 데이터 전송이 가능해집니다.
SMB Direct 프로토콜 흐름
SMB Direct는 SMB3 프로토콜을 RDMA 전송 계층 위에서 실행하는 Windows/Linux 호환 프로토콜입니다. ksmbd(커널 SMB 서버) 또는 Samba가 RDMA NIC을 통해 클라이언트와 직접 메모리 전송을 수행하여, TCP 대비 지연시간을 10배 이상 단축하고 CPU 부하를 50% 이상 절감합니다.
- 연결 설정: TCP 5445 포트로 SMB 협상 후, RDMA 가용 시 SMB Direct로 전환합니다. RDMA CM(Connection Manager)이 QP를 생성하고 연결을 수립합니다.
- 크레딧 기반 흐름 제어: 수신측이 RDMA Read/Write 크레딧을 부여하고, 송신측은 크레딧 범위 내에서 데이터를 전송합니다. TCP의 윈도우 제어와 유사하지만 HW 레벨에서 동작합니다.
- 대용량 파일 전송: 파일 데이터는 RDMA Write로 직접 전송되어 커널 버퍼 복사 없이 NIC에서 클라이언트 메모리로 DMA됩니다.
- 멀티채널 RDMA: SMB3 멀티채널과 결합하면 여러 RDMA QP를 동시에 사용하여 NIC 대역폭을 완전히 활용합니다 (예: 100GbE × 2 = 200Gbps).
# ksmbd SMB Direct 설정
# 1. RDMA NIC 확인
rdma link show
# link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev enp1s0f0
# 2. ksmbd SMB Direct 활성화
cat /etc/ksmbd/ksmbd.conf
# [global]
# server string = NAS-RDMA
# smb2 max read = 8388608
# smb2 max write = 8388608
# smbd max io size = 1048576
# interfaces = enp1s0f0
# 3. SMB Direct 연결 확인
smbstatus --shares
# PID Username Group Machine Protocol Encryption Signing Transport
# 1234 user1 users client1 SMB3_11 - AES-128 RDMA
NFS over RDMA 설정과 성능
NFS/RDMA(RFC 8267)는 NFS 프로토콜의 RPC 전송 계층을 TCP 대신 RDMA로 교체하는 기술입니다. 커널 NFS 서버(nfsd)와 NFS 클라이언트 모두 RDMA를 지원하며, 특히 대용량 순차 I/O 워크로드에서 TCP 대비 현저한 성능 향상을 보입니다.
# NFS 서버: RDMA 전송 활성화
# 1. 필요 모듈 로드
modprobe svcrdma # 서버측 RDMA 전송
modprobe xprtrdma # 클라이언트측 RDMA 전송
# 2. NFS 서버 RDMA 포트 활성화 (기본 20049)
echo "rdma 20049" > /proc/fs/nfsd/portlist
# 3. NFS export 설정 (일반 NFS와 동일)
cat /etc/exports
# /srv/nas 10.0.0.0/24(rw,sync,no_subtree_check)
# NFS 클라이언트: RDMA 마운트
mount -t nfs -o rdma,port=20049,vers=4.2 \
nas-server:/srv/nas /mnt/nas-rdma
# 성능 확인
nfsstat -c # 클라이언트 RPC 통계
nfsiostat # NFS I/O 통계
| 워크로드 | NFS/TCP (25GbE) | NFS/RDMA (25GbE RoCEv2) | 성능 향상 |
|---|---|---|---|
| 순차 읽기 (1MB) | ~2.8 GB/s | ~3.1 GB/s | +11% |
| 순차 쓰기 (1MB) | ~2.2 GB/s | ~2.9 GB/s | +32% |
| 랜덤 4K 읽기 IOPS | ~180K | ~280K | +56% |
| 랜덤 4K 쓰기 IOPS | ~90K | ~150K | +67% |
| CPU 사용률 (서버) | ~65% | ~30% | -54% |
| 평균 지연시간 (4K) | ~120us | ~45us | -63% |
iSER — iSCSI Extensions for RDMA
iSER(iSCSI Extensions for RDMA, RFC 7145)는 iSCSI 프로토콜의 데이터 전송 계층을 RDMA로 교체합니다. iSCSI의 TCP 오버헤드(헤더 다이제스트, 데이터 다이제스트, 버퍼 복사)를 제거하여 NAS의 블록 스토리지 서비스 성능을 극대화합니다.
- 아키텍처: iSCSI 제어 PDU는 RDMA Send/Receive로 전송하고, 데이터 PDU는 RDMA Read/Write로 제로카피 전송합니다. iSCSI 프로토콜 의미론은 유지하면서 전송 효율만 개선합니다.
- LIO 타겟 연동: Linux LIO(TCM) iSCSI 타겟은 iSER 백엔드를 기본 지원합니다.
ib_isert모듈이 RDMA 전송을 담당합니다. - 이니시에이터: open-iscsi의
iscsi_tcp대신ib_iser전송 모듈을 사용합니다.
# iSER 타겟 설정 (LIO)
modprobe ib_isert
targetcli
/> /iscsi create iqn.2024-01.com.nas:storage
/> /iscsi/iqn.2024-01.com.nas:storage/tpg1/portals create 0.0.0.0 3260
# iSER은 동일한 포트에서 자동 협상됨
# iSER 이니시에이터 설정
modprobe ib_iser
iscsiadm -m discovery -t st -p nas-server:3260
iscsiadm -m node -T iqn.2024-01.com.nas:storage \
-o update -n iface.transport_name -v iser
iscsiadm -m node -T iqn.2024-01.com.nas:storage --login
# iSER 연결 확인
iscsiadm -m session -P 3 | grep Transport
# iface.transport_name = iser
RoCEv2 네트워크 설정 가이드
RoCEv2(RDMA over Converged Ethernet v2)는 UDP/IP 위에서 RDMA를 제공하며, NAS RDMA 배포에서 가장 널리 사용됩니다. Lossless fabric 설정이 핵심이며, 잘못 구성하면 TCP보다 나쁜 성능을 보일 수 있습니다.
# 1. PFC(Priority Flow Control) 설정
# NIC 측 설정 (mlx5)
mlnx_qos -i enp1s0f0 --pfc 0,0,0,1,0,0,0,0
# → 우선순위 3에 PFC 활성화
# 2. ECN(Explicit Congestion Notification) 활성화
echo 1 > /sys/class/net/enp1s0f0/ecn/enable/3
# 3. DSCP/PCP 매핑
mlnx_qos -i enp1s0f0 --trust=dscp
# RDMA 트래픽에 DSCP 26 (CS4) 할당
# 4. MTU 설정 (Jumbo Frame)
ip link set enp1s0f0 mtu 9000
# 모든 경로(NIC, 스위치)에서 동일한 MTU 필수!
# 5. RoCEv2 모드 확인 및 설정
cma_roce_mode -d mlx5_0 -p 1 -m 2 # 모드 2 = RoCEv2
cat /sys/class/infiniband/mlx5_0/ports/1/gid_attrs/types/0
# RoCE v2
# 6. RDMA 연결 테스트
rdma link show
# link mlx5_0/1 state ACTIVE physical_state LINK_UP netdev enp1s0f0
rping -c -a nas-server -v # RDMA ping 테스트
# 7. 스위치 설정 (Cisco Nexus 예시)
# interface Ethernet1/1
# priority-flow-control mode on
# priority-flow-control priority 3 no-drop
# mtu 9216
# no shutdown
스토리지 프로토콜 HW 가속 — NVMe-oF/iSCSI HBA/FC HBA
NAS가 백엔드 스토리지에 접근하거나 블록 서비스를 제공할 때, 스토리지 프로토콜 처리를 전용 HBA(Host Bus Adapter)로 오프로드할 수 있습니다.
NVMe-oF 전송 계층 비교
NVMe over Fabrics(NVMe-oF)는 NVMe 프로토콜을 네트워크로 확장하여 원격 NVMe SSD에 로컬과 동일한 지연시간으로 접근합니다. NAS의 스토리지 확장과 disaggregated storage 아키텍처에 핵심적입니다.
| 전송 계층 | 대역폭 | 지연시간 | CPU 부하 | 필요 HW | NAS 적합성 |
|---|---|---|---|---|---|
| NVMe-oF/RDMA | 100+ Gbps | ~10μs | 최소 | RDMA NIC (ConnectX-7) | 최고 (고성능 NAS) |
| NVMe-oF/TCP | 100 Gbps | ~50μs | 중간 | 일반 NIC | 높음 (범용) |
| NVMe-oF/FC | 64 Gbps | ~15μs | 최소 | FC HBA | SAN 환경 |
# NVMe-oF/RDMA 타겟 상세 설정
modprobe nvmet
modprobe nvmet-rdma
# 서브시스템 생성
mkdir -p /sys/kernel/config/nvmet/subsystems/nqn.nas-storage
cd /sys/kernel/config/nvmet/subsystems/nqn.nas-storage
echo 1 > attr_allow_any_host
# NVMe 네임스페이스 추가
mkdir namespaces/1
echo -n /dev/nvme0n1 > namespaces/1/device_path
echo 1 > namespaces/1/enable
# RDMA 포트 바인딩
mkdir -p /sys/kernel/config/nvmet/ports/1
echo "rdma" > /sys/kernel/config/nvmet/ports/1/addr_trtype
echo "10.0.0.1" > /sys/kernel/config/nvmet/ports/1/addr_traddr
echo "4420" > /sys/kernel/config/nvmet/ports/1/addr_trsvcid
echo "ipv4" > /sys/kernel/config/nvmet/ports/1/addr_adrfam
ln -s /sys/kernel/config/nvmet/subsystems/nqn.nas-storage \
/sys/kernel/config/nvmet/ports/1/subsystems/
# 이니시에이터 연결
nvme discover -t rdma -a 10.0.0.1 -s 4420
nvme connect -t rdma -a 10.0.0.1 -s 4420 \
-n nqn.nas-storage --nr-io-queues=16
iSCSI HBA vs SW iSCSI 성능 비교
| 항목 | SW iSCSI (open-iscsi) | HW iSCSI (Chelsio T6) | NVMe-oF/RDMA |
|---|---|---|---|
| 순차 읽기 | ~2 GB/s (25GbE) | ~2.8 GB/s (25GbE) | ~3.1 GB/s (25GbE) |
| 랜덤 4K IOPS | ~150K | ~250K | ~400K |
| CPU 사용률 | 60~80% | 10~20% | 5~10% |
| 지연시간 | ~200μs | ~80μs | ~15μs |
| TCP 오프로드 | 커널 TCP | Full TOE | RDMA (TCP 없음) |
| I/O 큐 | 단일 세션 큐 | 다중 HW 큐 | NVMe 멀티큐 |
FC HBA NAS 백엔드 연결
엔터프라이즈 NAS는 클라이언트에 NFS/SMB를 제공하면서, 백엔드 스토리지에는 FC(Fibre Channel) SAN으로 연결합니다. FC HBA는 FCP(Fibre Channel Protocol) 처리를 전용 ASIC에서 수행하여 CPU를 파일 서비스에 집중시킵니다.
- FC HBA 드라이버:
lpfc(Emulex/Broadcom),qla2xxx(Marvell/QLogic)가 주요 드라이버입니다. 양쪽 모두 LIO 타겟과 이니시에이터 모드를 지원합니다. - NPIV(N-Port ID Virtualization): 단일 FC HBA에서 여러 가상 포트를 생성하여 VM별로 독립적인 FC 연결을 제공합니다.
- 멀티패스:
dm-multipath와 FC HBA를 결합하여 이중화된 SAN 경로를 구성합니다. 한 경로 장애 시 자동 절체되어 NAS 서비스 중단을 방지합니다.
# FC HBA 확인
lspci | grep Fibre
# 81:00.0 Fibre Channel: Broadcom LPe35002 32Gb 2-port
# FC 포트 상태 확인
cat /sys/class/fc_host/host0/port_state
# Online
# WWPN 확인 (SAN 조닝에 필요)
cat /sys/class/fc_host/host0/port_name
# 0x100000109b1234ab
# 멀티패스 설정
multipath -ll
# mpath0 (3600508b4000...) dm-2 LSI,INF-01-00
# size=1.0T features='1 queue_if_no_path' hwhandler='1 rdac'
# |-+- policy='service-time 0' prio=14 status=active
# | `- 0:0:0:0 sda 8:0 active ready running
# `-+- policy='service-time 0' prio=9 status=enabled
# `- 1:0:0:0 sdb 8:16 active ready running
압축 HW 가속 — QAT deflate/lz4, crypto_comp API
NAS에서 백업 데이터 압축, 파일시스템 투명 압축(Btrfs, ZFS), 네트워크 전송 압축 등에 하드웨어 압축 가속기를 활용하면 CPU 부하를 극적으로 줄일 수 있습니다.
crypto_acomp API — 비동기 압축 인터페이스
커널 소스 분석: crypto_acomp_compress() — 비동기 HW 압축 API
/* include/crypto/acompress.h */
static inline int crypto_acomp_compress(
struct acomp_req *req)
{
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
struct crypto_alg *alg = tfm->base.__crt_alg;
struct comp_alg_common *calg;
calg = container_of(alg, struct comp_alg_common, base);
/*
* 비동기 압축 요청:
* - req->src: 원본 데이터 (scatterlist)
* - req->dst: 압축 결과 버퍼 (scatterlist)
* - req->slen: 원본 길이
* - req->dlen: 결과 버퍼 크기
*
* QAT 드라이버의 경우:
* qat_comp_alg_compress() → adf_send_message()
* → QAT HW 엔진에 DMA 전송 → 완료 콜백
*/
return calg->compress(req);
}
/* 사용 예시: QAT 압축 요청 */
struct crypto_acomp *acomp;
struct acomp_req *req;
acomp = crypto_alloc_acomp("deflate", 0, 0);
req = acomp_request_alloc(acomp);
/* 콜백 설정 (비동기 완료 통지) */
acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
compress_done_callback, &wait);
/* 소스/대상 버퍼 설정 */
acomp_request_set_params(req, src_sg, dst_sg,
src_len, dst_len);
/* 비동기 압축 제출 */
ret = crypto_acomp_compress(req);
if (ret == -EINPROGRESS || ret == -EBUSY)
wait_for_completion(&wait); /* HW 완료 대기 */
코드 설명
- 핵심crypto_acomp_compress()는 커널의 비동기 압축(acomp) API 진입점입니다. 동기식
crypto_comp와 달리 비동기로 동작하여 HW 가속기의 병렬 처리를 활용합니다. QAT 드라이버가 등록되어 있으면qat_comp_alg_compress()가 호출되어 데이터를 QAT 엔진으로 DMA 전송하고, 압축 완료 시 콜백을 호출합니다. 이 비동기 모델 덕분에 CPU는 압축 대기 없이 다른 NAS 요청을 처리할 수 있습니다. scatterlist 기반이므로 비연속 페이지에 대해서도 추가 복사 없이 압축이 가능합니다.
QAT 인스턴스 관리와 동시 요청
QAT 장치는 여러 개의 인스턴스(instance)를 제공하며, 각 인스턴스는 독립적인 링 버퍼(ring pair)를 가집니다. NAS에서 다수의 동시 압축 요청을 효율적으로 처리하려면 인스턴스 할당과 부하 분산을 적절히 구성해야 합니다.
- 인스턴스 수: QAT C62x는 장치당 최대 18개 압축 인스턴스를 지원하며, QAT 4xxx(Sapphire Rapids 내장)는 최대 4개의 압축 인스턴스를 제공합니다.
- 커널 vs 사용자 공간: 인스턴스는 커널(cy/dc)과 사용자 공간(user)으로 분리 할당할 수 있습니다. NAS 파일시스템 압축은 커널 인스턴스, 백업 SW 압축은 사용자 공간 인스턴스를 사용합니다.
- NUMA 인식: QAT 장치는 특정 NUMA 노드에 연결되므로, 해당 노드의 CPU에서 요청을 제출해야 최적 성능을 달성합니다.
# QAT 장치 및 인스턴스 상태 확인
adf_ctl status
# qat_dev0 - type: 4xxx, bsf: 0000:6b:00.0, state: up
# qat_dev1 - type: 4xxx, bsf: 0000:70:00.0, state: up
# 인스턴스 설정 파일
cat /etc/4xxx_dev0.conf
# [GENERAL]
# ServicesEnabled = dc # dc=압축, cy=암호화, sym=대칭, asym=비대칭
#
# [KERNEL]
# NumberDcInstances = 2
# NumConcurrentSymRequests = 512
# NumConcurrentAsymRequests = 64
#
# [SHIM]
# NumberDcInstances = 2 # 사용자 공간 인스턴스
# QAT 서비스 재시작
adf_ctl restart
# 성능 카운터 확인
cat /sys/kernel/debug/qat_4xxx_0000:6b:00.0/fw_counters
Btrfs/ZFS QAT 연동 상태
NAS 파일시스템의 투명 압축 기능과 QAT HW 가속의 연동 상태는 파일시스템마다 다릅니다.
| 파일시스템 | QAT 지원 | 지원 알고리즘 | 구현 방식 | 비고 |
|---|---|---|---|---|
| ZFS (OpenZFS) | 지원 | gzip, lz4 | qat_compress / qat_checksum 모듈 | zfs set compression=gzip + QAT 자동 사용 |
| Btrfs | 미지원 | - | SW 전용 (zstd/lzo/zlib) | 커널 crypto API 연동 미구현 |
| dm-VDO | 간접 지원 | lz4 | 커널 crypto API 경유 | QAT lz4 드라이버 등록 시 자동 사용 |
| SquashFS | 간접 지원 | zlib, lz4, zstd | 커널 crypto API 경유 | 읽기 전용, 압축 해제만 |
# ZFS QAT 압축 활성화
# 1. QAT 모듈 로드
modprobe qat_4xxx # QAT 장치 드라이버
modprobe qat_common # QAT 공통 프레임워크
# 2. ZFS QAT 모듈 활성화
echo 1 > /sys/module/zfs/parameters/zfs_qat_compress_disable
# 0 = QAT 활성화, 1 = QAT 비활성화 (기본값은 설치에 따라 다름)
# 3. ZFS 풀에 gzip 압축 설정 (QAT 자동 사용)
zfs set compression=gzip-6 tank/nas-data
# 4. QAT 압축 동작 확인
zpool iostat -v tank
cat /proc/spl/kstat/zfs/qat
# qat_comp_requests: 1234567
# qat_comp_total_in: 500 GB
# qat_comp_total_out: 200 GB (60% 압축률)
압축 알고리즘 선택 가이드
NAS 워크로드에 따라 최적의 압축 알고리즘이 달라집니다. CPU 사용률, 압축률, 지연시간의 트레이드오프를 고려해야 합니다.
| 알고리즘 | 압축률 | 압축 속도 (SW) | 해제 속도 | CPU 부하 | QAT 가속 | 적합 워크로드 |
|---|---|---|---|---|---|---|
| lz4 | 낮음 (~2:1) | ~800 MB/s | ~4 GB/s | 낮음 | 지원 | 실시간 파일 서비스, NVMe SSD |
| zstd (level 1-3) | 중간 (~3:1) | ~500 MB/s | ~1.5 GB/s | 중간 | 미지원 | 범용 NAS 스토리지 |
| zstd (level 10+) | 높음 (~4:1) | ~50 MB/s | ~1.5 GB/s | 높음 | 미지원 | 콜드 아카이브 |
| deflate/gzip | 중간 (~3:1) | ~200 MB/s | ~400 MB/s | 높음 | 지원 | QAT 가속 시 대용량 백업 |
| lzo | 낮음 (~2:1) | ~600 MB/s | ~900 MB/s | 낮음 | 미지원 | 레거시 Btrfs |
- NVMe 전용 NAS: lz4 (지연시간 최소화, SSD 수명 절약)
- HDD 기반 대용량 NAS: zstd level 3 (최적의 압축률/속도 균형)
- QAT 장착 NAS: deflate/gzip (QAT HW 가속으로 CPU 무부하 고압축)
- 백업/아카이브: zstd level 15+ 또는 QAT deflate (저장 공간 최소화)
중복제거와 HW 가속 — VDO, SHA-256 HW
VDO(Virtual Data Optimizer)는 Linux 커널에 통합된 인라인 중복제거 + 압축 솔루션입니다. 블록 단위로 SHA-256 해시를 계산하여 중복 데이터를 탐지하며, CPU의 SHA Extensions(Intel SHA-NI, ARM CE)를 활용하면 해시 계산 속도가 ~3배 향상됩니다.
- VDO 아키텍처: UDS(Universal Deduplication Service) 인덱스 → 해시 룩업 → 중복 시 참조 카운트 증가, 비중복 시 압축 후 저장
- SHA-256 HW 가속:
sha256-ni(x86),sha256-ce(ARM),sha256-avx2— Crypto API가 자동 선택 - NAS 시나리오: 백업 스토리지에서 VDO 적용 시 3:1~5:1 공간 절약, SHA Extensions로 CPU 오버헤드 최소화
- dm-vdo (커널 9.0+): RHEL 9에서 VDO는 Device Mapper 타겟(
dm-vdo)으로 커널에 완전 통합. 별도 사용자 공간 데몬 불필요
VDO 구성과 성능 튜닝
# VDO 볼륨 생성 (1TB 물리 → 3TB 논리)
vdo create --name=nas-dedup \
--device=/dev/md0 \
--vdoLogicalSize=3T \
--vdoSlabSize=32G \
--writePolicy=auto
# VDO 위에 파일시스템 생성
mkfs.xfs -K /dev/mapper/nas-dedup
mount /dev/mapper/nas-dedup /srv/nas-backup
# VDO 통계 확인
vdostats --human-readable
# Device 1K-blocks Used Available Use% Space saving%
# nas-dedup 1073741824 214748 858993459 20% 68%
# SHA-256 HW 가속 확인
grep -i sha /proc/cpuinfo | head -1
# flags : ... sha_ni ...
# 커널 crypto API에서 사용 중인 SHA 구현 확인
cat /proc/crypto | grep -A4 "name.*sha256"
# name : sha256
# driver : sha256-ni
# module : sha256_ssse3
# priority : 250
VDO 데이터 경로와 HW 가속 포인트
- 1단계 — 해시 계산: 들어오는 4KB 블록마다 SHA-256 해시를 계산합니다. SHA-NI 확장이 있으면 자동으로 HW 가속됩니다. 이 단계가 VDO CPU 사용률의 약 40%를 차지합니다.
- 2단계 — UDS 인덱스 조회: 해시를 UDS(Universal Deduplication Service) 인덱스에서 검색합니다. 인덱스는 메모리에 상주하며, NAS에서는 VDO가 관리하는 TB당 약 1GB RAM이 필요합니다.
- 3단계 — 중복 처리: 해시가 일치하면 기존 블록에 대한 참조만 추가합니다. 일치하지 않으면 데이터를 압축(lz4/zlib)한 후 저장합니다.
- 4단계 — 쓰기: 압축된 블록을 물리 장치에 기록합니다. QAT가 있으면 압축 단계에서 HW 가속을 활용할 수 있습니다.
VDO 커널 내부 — dm_vdo_target 구조
dm-vdo는 Device Mapper 타겟으로 커널에 통합되어, vdo_map_bio()가 BIO를 수신하면 해시 계산 → UDS 조회 → 중복/비중복 분기를 수행합니다. 핵심 자료구조와 흐름을 살펴봅니다.
/* drivers/md/dm-vdo/vdo.c (커널 6.9+) */
/* VDO의 BIO 처리 핵심 경로 */
static int vdo_map_bio(struct dm_target *ti, struct bio *bio)
{
struct vdo *vdo = get_vdo_for_target(ti);
struct data_vio *data_vio;
/* data_vio: VDO의 I/O 추적 단위 (4KB 블록 1개에 대응) */
data_vio = allocate_data_vio(vdo, bio);
if (IS_ERR(data_vio))
return DM_MAPIO_KILL;
/*
* 쓰기 경로: hash → UDS dedupe 조회 → 압축 → 물리 쓰기
* 읽기 경로: Block Map에서 LBN→PBN 변환 → 물리 읽기 → 압축해제
*/
if (bio_data_dir(bio) == WRITE)
launch_write_data_vio(data_vio); /* 비동기 파이프라인 시작 */
else
launch_read_data_vio(data_vio);
return DM_MAPIO_SUBMITTED;
}
코드 설명
vdo_map_bio()는 Device Mapper의 map 콜백으로, 상위 파일시스템에서 내려오는 BIO를 가로채 VDO 파이프라인에 넣습니다. 각 4KB 블록은 data_vio라는 추적 구조체로 래핑되어, 해시 → 중복검사 → 압축 → 쓰기 단계를 비동기로 진행합니다. DM_MAPIO_SUBMITTED를 반환하면 DM은 BIO 완료를 VDO에게 위임합니다.
UDS 인덱스 — 해시 조회와 Sparse/Dense 모드
UDS(Universal Deduplication Service)는 SHA-256 해시를 키로 사용하여 블록의 물리 위치(PBN)를 조회합니다. 두 가지 인덱스 모드를 제공합니다.
| 인덱스 모드 | RAM 사용 | 조회 속도 | 커버리지 | NAS 권장 시나리오 |
|---|---|---|---|---|
| Dense | TB당 ~1GB | 빠름 (메모리 기반) | 전체 해시 | 백업 NAS (높은 중복률) |
| Sparse | TB당 ~250MB | 보통 (디스크 참조) | 최근 + 빈번 해시 | 범용 NAS (메모리 제한) |
/* drivers/md/dm-vdo/indexer/index-session.c */
/*
* UDS 해시 조회 API: 블록의 SHA-256 해시로 중복 여부 확인
* 반환: UDS_SUCCESS + found=true → 중복, found=false → 신규
*/
int uds_index_session_lookup(struct uds_index_session *session,
const struct uds_record_name *name,
const struct uds_record_data *old_metadata,
struct uds_record_data *new_metadata,
bool *found)
{
/* 1. Sparse Volume Index에서 빠른 조회 (LRU 캐시) */
/* 2. 실패 시 Dense Index 디스크 참조 */
/* 3. 해시 collision 방지: 전체 32바이트 SHA-256 비교 */
...
}
코드 설명
UDS의 해시 조회는 2단계로 진행됩니다. 먼저 Sparse Index의 LRU 캐시(메모리 상주)에서 빠른 조회를 시도하고, 미스 시 Dense Index(디스크 기반)를 참조합니다. found가 true이면 old_metadata에 기존 블록의 PBN이 담기고, VDO는 데이터 쓰기를 건너뛰고 참조 카운트만 증가시킵니다. NAS 백업 워크로드에서 중복률이 높으면 물리 I/O가 크게 줄어듭니다.
SHA-256 HW 가속 — Crypto API와 SHA-NI 내부
VDO의 해시 계산은 Linux Crypto API를 통해 수행됩니다. SHA-NI(Intel)나 SHA-CE(ARM) 확장이 있으면 자동으로 하드웨어 가속이 적용되며, priority 값이 높은 구현이 선택됩니다.
/* arch/x86/crypto/sha256_ssse3_glue.c */
static struct shash_alg sha256_ni_alg = {
.digestsize = SHA256_DIGEST_SIZE, /* 32 bytes */
.init = sha256_ni_init,
.update = sha256_ni_update, /* SHA-NI 명령어 사용 */
.final = sha256_ni_final,
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-ni",
.cra_priority = 250, /* SW(100)보다 높아 자동 선택 */
.cra_blocksize = SHA256_BLOCK_SIZE, /* 64 bytes */
.cra_module = THIS_MODULE,
}
};
/*
* SHA-NI 명령어: sha256rnds2, sha256msg1, sha256msg2
* 4KB 블록 해시: SW ~180 cycles/byte → NI ~7 cycles/byte (~25× 가속)
* VDO가 초당 처리하는 4KB 블록: SW ~100K → NI ~400K
*/
코드 설명
SHA-NI 구현은 cra_priority가 250으로 SW 구현(100)보다 높아, Crypto API가 자동으로 SHA-NI를 선택합니다. VDO는 들어오는 모든 4KB 블록에 대해 crypto_shash_digest()를 호출하며, SHA-NI가 있으면 sha256rnds2 등 전용 x86 명령어로 해시를 계산합니다. NAS에서 1GB/s 쓰기 시 초당 약 256K 블록의 해시를 계산해야 하므로, SHA-NI 가속이 VDO 성능에 결정적인 영향을 미칩니다.
| VDO 워크로드 | SW SHA-256 | SHA-NI (HW) | SHA-NI + QAT 압축 |
|---|---|---|---|
| 순차 쓰기 처리량 | ~400 MB/s | ~800 MB/s | ~1.2 GB/s |
| CPU 사용률 (4코어) | ~90% | ~45% | ~20% |
| 중복제거 오버헤드 | 높음 | 중간 | 낮음 |
| 4K 랜덤 쓰기 IOPS | ~15K | ~35K | ~50K |
| 해시 계산 지연 (4KB) | ~4.5 μs | ~0.18 μs | ~0.18 μs |
VDO 모니터링과 튜닝 실전
# VDO 상세 통계 — 중복제거 효율 확인
vdostats --verbose nas-dedup
# data blocks used : 52428800
# overhead blocks used : 1048576
# logical blocks : 157286400
# savings percent : 67% ← 중복제거 + 압축 절약률
# VDO sysfs 실시간 모니터링
cat /sys/kvdo/nas-dedup/statistics/dedupe_advice_valid
# 중복으로 판정된 블록 수 (UDS 히트)
cat /sys/kvdo/nas-dedup/statistics/dedupe_advice_stale
# 스테일 어드바이스 (PBN 재활용 후 해시 충돌)
cat /sys/kvdo/nas-dedup/statistics/compressed_fragments_written
# 압축되어 저장된 프래그먼트 수
# VDO 스레드 튜닝 (NAS 코어 수에 맞춤)
# 해시 스레드: SHA-256 해시 계산 전담
# 논리 스레드: Block Map 관리
# 물리 스레드: Slab 할당/해제
vdo modify --name=nas-dedup \
--vdoHashZoneThreads=2 \
--vdoLogicalThreads=2 \
--vdoPhysicalThreads=1
# VDO + dm-crypt 스택 (암호화 + 중복제거)
# 순서 중요: dm-crypt 아래에 VDO 배치 (암호화 전 중복제거)
# 잘못: 디스크 → VDO → dm-crypt → FS (암호화된 데이터는 중복제거 불가)
# 올바름: 디스크 → dm-crypt → VDO → FS (평문 블록 중복제거 후 암호화)
# ※ 단, 이 경우 dm-crypt가 VDO 아래이므로 물리적으로 이 구성 불가
# → 실제로는 SED + VDO 조합이 최적 (HW 암호화 + SW 중복제거)
dm-vdo Device Mapper 타겟으로 커널에 완전 통합되었습니다. 기존의 vdo 사용자 공간 도구 대신 lvcreate --type vdo로 LVM에서 직접 VDO 볼륨을 생성합니다. 커널 통합 버전은 사용자 공간 데몬이 불필요하여 부팅 의존성이 줄고, 커널 BIO 경로에서 직접 동작하므로 컨텍스트 스위칭 오버헤드도 감소합니다.
GPU/NPU 미디어 가속 — QSV, V4L2, NPU 커널 경로
미디어 NAS(Synology, QNAP 등)에서 실시간 트랜스코딩은 CPU 부하가 매우 높은 작업입니다. GPU/NPU 가속을 통해 CPU를 파일 서비스에 집중시킬 수 있습니다.
Intel QSV 설정과 NAS 트랜스코딩
Intel Quick Sync Video(QSV)는 Intel CPU의 내장 GPU(iGPU)를 활용한 하드웨어 비디오 인코딩/디코딩 기술입니다. Celeron J4125, N5105부터 Core i3/i5까지 대부분의 Intel 프로세서가 QSV를 지원하며, NAS의 실시간 미디어 트랜스코딩에 핵심적인 역할을 합니다.
# Intel iGPU 확인
lspci | grep -i vga
# 00:02.0 VGA compatible controller: Intel Corporation Alder Lake-N [UHD Graphics]
# i915 드라이버 및 VAAPI 확인
ls /dev/dri/render*
# /dev/dri/renderD128
# VAAPI 지원 코덱 확인
vainfo --display drm --device /dev/dri/renderD128
# vainfo: Supported profile and target:
# VAProfileH264Main : VAEntrypointVLD
# VAProfileH264Main : VAEntrypointEncSlice
# VAProfileHEVCMain : VAEntrypointVLD
# VAProfileHEVCMain : VAEntrypointEncSlice
# VAProfileAV1Profile0 : VAEntrypointVLD # 12세대+
# FFmpeg QSV 트랜스코딩 (Plex/Jellyfin 내부 사용)
ffmpeg -hwaccel qsv -hwaccel_device /dev/dri/renderD128 \
-i input.mkv \
-c:v hevc_qsv -preset medium -global_quality 25 \
-c:a copy output.mp4
# Docker 컨테이너에 GPU 패스스루
docker run -d --device=/dev/dri:/dev/dri \
jellyfin/jellyfin:latest
NAS 미디어 가속 비교
| 가속기 | 4K HEVC 트랜스코딩 | 동시 1080p 스트림 | CPU 사용률 | 전력 소비 | NAS 적합성 |
|---|---|---|---|---|---|
| SW (x264, 4코어) | ~5 fps | 1~2개 | 100% | +65W | 낮음 |
| Intel QSV (N5105) | ~30 fps | 8~12개 | <5% | +5W | 높음 |
| Intel QSV (i3-1215U) | ~60 fps | 15~20개 | <5% | +10W | 최고 |
| NVIDIA T400 (dGPU) | ~90 fps | 20~30개 | <2% | +30W | 전문용 |
| ARM V4L2 (RK3588) | ~30 fps | 8~12개 | <10% | +3W | 임베디드 |
V4L2 M2M 커널 내부 — 임베디드 NAS HW 코덱
ARM 기반 NAS(Synology DS224+, QNAP TS-264 등)에서 비디오 트랜스코딩은 SoC 내장 코덱 IP를 V4L2 M2M(Memory-to-Memory) 인터페이스로 노출합니다. V4L2 M2M은 입력 큐(OUTPUT)와 출력 큐(CAPTURE)를 가진 비동기 파이프라인으로, 커널의 v4l2_m2m_ctx가 프레임 스케줄링을 관리합니다.
/* drivers/media/v4l2-core/v4l2-mem2mem.c */
/*
* V4L2 M2M 디바이스 실행 — OUTPUT 큐에 인코딩할 프레임이 있고
* CAPTURE 큐에 빈 버퍼가 있으면 HW 코덱 작업을 시작
*/
static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
struct v4l2_m2m_ctx *m2m_ctx)
{
/* OUTPUT 큐(원본 프레임)와 CAPTURE 큐(결과 버퍼) 확인 */
if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) ||
list_empty(&m2m_ctx->cap_q_ctx.rdy_queue))
return;
/*
* 드라이버의 device_run 콜백 호출 → HW 코덱 시작
* 예: rk3588_vpu_run(), hantro_run(), cedrus_run()
*/
m2m_dev->m2m_ops->device_run(m2m_ctx->priv);
/*
* HW 코덱이 완료되면 인터럽트 핸들러에서
* v4l2_m2m_buf_done()을 호출하여 CAPTURE 버퍼를
* 사용자 공간에 반환 → 폴링으로 수신
*/
}
/* 코덱 세션당 처리량:
* RK3588 Rkvdec2: 8K30/4K120 H.265 디코드
* Hantro H1: 1080p60 H.264 인코드
* Cedrus (Allwinner): 4K30 H.265 디코드
*/
코드 설명
__v4l2_m2m_try_queue()는 V4L2 M2M 프레임워크의 핵심 스케줄러입니다. OUTPUT 큐에 원본 프레임이 있고 CAPTURE 큐에 빈 버퍼가 있으면, 드라이버의 device_run() 콜백을 호출하여 SoC 코덱 IP에 작업을 제출합니다. ARM NAS에서 Plex/Jellyfin이 FFmpeg의 V4L2 M2M 백엔드를 사용하면, 이 경로를 통해 CPU 대신 SoC 코덱이 트랜스코딩을 처리합니다. RK3588 기반 NAS에서 CPU 사용률이 100%에서 10% 이하로 떨어집니다.
NPU 기반 AI 비디오 분석
최신 NAS는 단순 트랜스코딩을 넘어 AI 기반 비디오 분석(사물 인식, 얼굴 인식, 모션 감지)을 수행합니다. NPU(Neural Processing Unit)는 이러한 추론 워크로드를 CPU에서 분리합니다.
- Intel NPU (Meteor Lake VPU): OpenVINO 프레임워크를 통해 커널 드라이버(
intel_vpu)와 연동합니다. Synology DSM의 Surveillance Station이 이를 활용합니다. - Hailo-8 (PCIe/M.2): 26 TOPS 성능의 외장 NPU로, QNAP NAS에 M.2 슬롯으로 장착 가능합니다. QVR Pro 감시 시스템에서 AI 분석에 사용됩니다.
- Google Coral TPU (USB/M.2): 4 TOPS TensorFlow Lite 추론 가속기로, Frigate NVR 같은 오픈소스 감시 시스템에서 사용됩니다.
- 커널 연동: NPU 장치는
/dev/accel*또는 V4L2 M2M 인터페이스로 노출됩니다. DMA-BUF를 통해 GPU/NIC과 제로카피 버퍼 공유가 가능합니다.
DMA-BUF 제로카피 파이프라인 — GPU 디코드 → NPU 추론
NAS의 감시 시스템에서 최적의 성능을 얻으려면 GPU 디코더 출력을 시스템 메모리에 복사하지 않고 DMA-BUF를 통해 NPU에 직접 전달해야 합니다. 이 제로카피 파이프라인은 V4L2 M2M, VAAPI, DRM의 DMA-BUF 익스포트/임포트로 구현됩니다.
/* V4L2 M2M + DMA-BUF 제로카피 예시 (사용자 공간) */
#include <linux/videodev2.h>
#include <linux/dma-buf.h>
/* 1. V4L2 디코더: CAPTURE 버퍼를 DMA-BUF로 내보내기 */
struct v4l2_exportbuffer expbuf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
.index = buf_idx,
.flags = O_RDONLY,
};
ioctl(decoder_fd, VIDIOC_EXPBUF, &expbuf);
int dmabuf_fd = expbuf.fd; /* DMA-BUF 파일 디스크립터 */
/*
* 2. NPU에 DMA-BUF 전달 (제로카피)
* - Hailo: hailo_import_dmabuf(dmabuf_fd)
* - Coral: gasket_import_dmabuf(dmabuf_fd)
* - Intel NPU: VPU 드라이버 DMA-BUF 임포트
*
* 커널 내부 경로:
* V4L2 CAPTURE → dma_buf_export() → struct dma_buf
* NPU 드라이버 → dma_buf_attach() → dma_buf_map_attachment()
* → sg_table의 물리 주소를 NPU DMA 엔진에 프로그래밍
* → CPU 복사 없이 GPU 디코드 출력 → NPU 추론 입력
*/
코드 설명
V4L2 디코더의 CAPTURE 버퍼를 VIDIOC_EXPBUF로 DMA-BUF 파일 디스크립터로 내보냅니다. NPU 드라이버는 이 fd를 임포트하여 dma_buf_attach() + dma_buf_map_attachment()으로 SG 테이블을 얻고, 해당 물리 주소에서 직접 DMA로 데이터를 읽습니다. GPU → 시스템 메모리 → NPU의 2회 복사가 GPU → NPU 직접 전송으로 바뀌어, 16채널 감시 카메라 NAS에서 메모리 대역폭 병목을 제거합니다.
NAS 감시 시스템 NPU 설정 실전
# Google Coral TPU 설치 (Frigate NVR용)
# 1. PCIe M.2 Coral 드라이버 설치
apt install gasket-dkms
modprobe apex
ls /dev/apex_0 # Coral TPU 장치 확인
# 2. Docker에 Coral 패스스루
docker run -d --name frigate \
--device /dev/apex_0:/dev/apex_0 \
--device /dev/dri/renderD128:/dev/dri/renderD128 \
-v /srv/nas/frigate:/media/frigate \
ghcr.io/blakeblackshear/frigate:stable
# 3. Frigate 설정 (config.yml) — QSV 디코드 + Coral 추론
# detectors:
# coral:
# type: edgetpu
# device: pci
# ffmpeg:
# hwaccel_args: preset-vaapi # Intel QSV HW 디코드
# Hailo-8 NPU 상태 확인
hailortcli fw-control identify
# Board Name: HAILO-8
# FW Version: 4.17.0
# Serial: xxxx
# Hailo-8 추론 벤치마크
hailortcli benchmark --hef yolov8s.hef
# FPS: 280 (YOLOv8s, 640×640, batch 8)
# Latency: 8.5ms (single frame)
# Power: ~2.5W
# Intel NPU 확인 (Meteor Lake+)
ls /dev/accel/accel0
cat /sys/class/accel/accel0/device/power/runtime_status
# active (추론 중) / suspended (유휴)
P2P DMA와 GPU Direct Storage
P2P(Peer-to-Peer) DMA는 NVMe SSD에서 GPU 메모리로 데이터를 CPU와 시스템 메모리를 경유하지 않고 직접 전송하는 기술입니다. AI/ML 학습 데이터 로딩이나 HPC 스크래치 파일시스템에서 활용됩니다.
- PCI P2P DMA:
pci_p2pdma_distance_many()로 P2P 전송 가능 여부와 성능을 확인. 같은 PCIe 스위치 하위에 있어야 최적 - GPU Direct Storage (GDS): NVIDIA cuFile API를 통해 NVMe → GPU VRAM 직접 DMA.
nvidia-fs커널 모듈 필요 - NAS 시나리오: AI 학습용 대규모 데이터셋 NAS에서 GPU 직접 로딩, 전통적 read() 대비 대역폭 2-3배, CPU 부하 제거
- NVMe CMB (Controller Memory Buffer): NVMe 컨트롤러의 온보드 메모리를 P2P 전송의 바운스 버퍼로 활용하여 호스트 메모리 경유를 회피
P2P DMA 커널 인터페이스
/* drivers/pci/p2pdma.c */
/* P2P DMA 가능 여부 확인 */
int distance = pci_p2pdma_distance_many(storage_dev,
&gpu_clients, 1, verbose);
/*
* 반환값:
* > 0: P2P 가능 (값이 작을수록 최적)
* -1: P2P 불가능 (다른 PCIe 호스트 브리지)
*
* 같은 PCIe 스위치 하위 → distance = 2 (최적)
* 같은 root complex 하위 → distance = 4 (가능)
* 다른 NUMA 노드 → distance = -1 또는 높은 값
*/
P2P DMA 커널 내부 — pci_p2pdma_map_sg()
P2P DMA의 핵심은 DMA 매핑 과정에서 시스템 메모리 대신 피어 장치의 BAR(Base Address Register) 영역을 직접 참조하는 것입니다. NVMe 드라이버가 BIO를 처리할 때 SGL(Scatter-Gather List)에 GPU VRAM의 물리 주소를 넣어 NVMe 컨트롤러가 직접 데이터를 전송합니다.
/* drivers/pci/p2pdma.c */
/*
* P2P DMA용 SG 리스트 매핑 — 피어 장치의 BAR 주소를 SGL에 배치
* NVMe → GPU 전송 시: NVMe 드라이버가 이 함수로 GPU VRAM 주소를 SGL에 등록
*/
int pci_p2pdma_map_sg_attrs(struct device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction dir,
unsigned long attrs)
{
struct scatterlist *s;
int i;
for_each_sg(sg, s, nents, i) {
/* SG 엔트리가 P2P 메모리인지 확인 */
if (is_pci_p2pdma_page(sg_page(s))) {
/* 시스템 메모리 DMA 매핑 대신
* 피어 장치의 PCI BAR 물리 주소를 직접 사용 */
s->dma_address = pci_p2pdma_bus_addr(sg_page(s))
+ s->offset;
sg_dma_len(s) = s->length;
sg_dma_mark_bus_address(s); /* P2P 주소 마킹 */
}
}
return nents;
}
코드 설명
pci_p2pdma_map_sg_attrs()는 일반 DMA 매핑(dma_map_sg())을 대체하여, P2P 메모리 페이지의 경우 시스템 IOMMU 변환 대신 피어 PCI 장치의 BAR 주소를 직접 사용합니다. NVMe 드라이버가 읽기 명령의 SGL에 이 주소를 넣으면, NVMe 컨트롤러는 DMA 엔진으로 해당 BAR 주소(= GPU VRAM)에 직접 데이터를 써넣습니다. CPU와 시스템 메모리는 전혀 관여하지 않습니다.
GPU Direct Storage — nvidia-fs와 cuFile API
NVIDIA GPU Direct Storage(GDS)는 nvidia-fs 커널 모듈을 통해 NVMe SSD와 GPU VRAM 간 P2P DMA를 파일시스템 수준에서 투명하게 지원합니다. cuFile API는 POSIX의 read()/write()를 대체하여 GPU 버퍼에 직접 I/O를 수행합니다.
/* NVIDIA cuFile API 사용 예시 (사용자 공간) */
#include <cufile.h>
/* 1. cuFile 드라이버 초기화 */
CUfileError_t status = cuFileDriverOpen();
/* 2. 파일 열기 + cuFile 핸들 등록 */
int fd = open("/mnt/nas-nvme/dataset/imagenet.tar", O_RDONLY | O_DIRECT);
CUfileDescr_t desc = { .type = CU_FILE_HANDLE_TYPE_OPAQUE_FD };
desc.handle.fd = fd;
CUfileHandle_t fh;
cuFileHandleRegister(&fh, &desc);
/* 3. GPU 메모리 할당 + cuFile 버퍼 등록 */
void *gpu_buf;
cudaMalloc(&gpu_buf, BUFFER_SIZE);
cuFileBufRegister(gpu_buf, BUFFER_SIZE, 0);
/* 4. NVMe → GPU VRAM 직접 읽기 (P2P DMA) */
ssize_t bytes = cuFileRead(fh, gpu_buf, BUFFER_SIZE,
file_offset, gpu_offset);
/*
* 내부 경로: cuFileRead() → nvidia-fs 커널 모듈
* → NVMe 드라이버에 P2P SGL 제출
* → NVMe 컨트롤러가 GPU BAR 주소에 직접 DMA
* → CPU/시스템 메모리 미경유
*
* 성능: PCIe Gen4 x4 NVMe 기준 ~6.5 GB/s
* read()+cudaMemcpy() 대비 2~3× 처리량 향상
*/
코드 설명
cuFile API는 GPU 메모리에 대한 직접 파일 I/O를 제공합니다. cuFileBufRegister()로 GPU 버퍼를 등록하면 nvidia-fs 모듈이 해당 GPU VRAM의 BAR 주소를 파악하고, cuFileRead() 호출 시 NVMe 드라이버에 P2P SGL을 제출합니다. NVMe 컨트롤러는 이 SGL의 주소가 시스템 메모리가 아닌 GPU BAR임을 인지하고, PCIe 패브릭을 통해 GPU에 직접 데이터를 전송합니다. AI/ML NAS에서 학습 데이터 로딩 시 CPU 오버헤드를 완전히 제거합니다.
P2P DMA 성능과 토폴로지 요구사항
| PCIe 토폴로지 | P2P 가능 | 대역폭 | 지연시간 | 권장 |
|---|---|---|---|---|
| 같은 PCIe 스위치 하위 | 최적 | PCIe 링크 속도 | 최소 | 강력 권장 |
| 같은 Root Complex | 가능 | RC 대역폭 제한 | 중간 | 사용 가능 |
| 다른 Root Complex (같은 NUMA) | 플랫폼 의존 | 제한적 | 높음 | 비권장 |
| 다른 NUMA 노드 | 대부분 불가 | - | - | 사용 불가 |
NVMe CMB P2P 메모리 할당
일부 NVMe 컨트롤러는 CMB(Controller Memory Buffer)를 제공하여 P2P DMA의 바운스 버퍼로 사용합니다. 이를 통해 피어 장치 간 직접 통신이 불가능한 토폴로지에서도 NVMe 컨트롤러의 온보드 메모리를 경유하여 P2P 전송을 수행할 수 있습니다.
/* drivers/nvme/host/pci.c */
/*
* NVMe CMB(Controller Memory Buffer)를 P2P DMA용으로 등록
* CMB는 NVMe 컨트롤러의 BAR에 매핑된 온보드 SRAM/DRAM
*/
static void nvme_map_cmb(struct nvme_dev *dev)
{
u64 size = nvme_cmb_size(dev);
if (!size)
return;
/* CMB BAR 영역을 P2P 메모리로 등록 */
if (pci_p2pdma_add_resource(dev->pci_dev,
dev->cmb_bar, size, 0)) {
dev_warn(dev->ctrl.device,
"failed to register CMB for P2P\n");
return;
}
/*
* 등록 후 다른 PCIe 장치(GPU, NIC)가
* pci_p2pdma_alloc_pages()로 CMB 메모리를 할당하여
* P2P DMA의 중간 버퍼로 사용 가능
*/
}
코드 설명
nvme_map_cmb()는 NVMe 컨트롤러의 CMB 영역을 pci_p2pdma_add_resource()로 커널 P2P 프레임워크에 등록합니다. 등록된 CMB 메모리는 struct page로 관리되며, 다른 PCIe 장치가 DMA 대상으로 사용할 수 있습니다. AI NAS에서 NVMe SSD의 CMB를 GPU DMA 버퍼로 활용하면, 같은 PCIe 스위치 아래가 아니어도 시스템 메모리를 경유하지 않는 P2P 전송이 가능합니다.
# PCIe 토폴로지 확인
lspci -tv
# -[0000:00]-+-00.0 Intel Device
# +-01.0-[01-02]----00.0 NVIDIA A2000
# +-02.0-[03-04]----00.0 Samsung NVMe SSD
# # → 같은 root complex → P2P 가능
# NVIDIA GPU Direct Storage 설정
modprobe nvidia-fs
# cuFile API로 NVMe → GPU 직접 읽기
# cuFileRead(file_handle, gpu_buffer, size, file_offset, gpu_offset);
# P2P DMA 활성화 확인
cat /sys/bus/pci/devices/0000:01:00.0/p2pmem/size
# 268435456 (256MB P2P 메모리 영역)
# NVMe CMB P2P 지원 확인
cat /sys/bus/pci/devices/0000:03:00.0/p2pmem/size
# CMB 크기 (0이면 CMB 미지원)
# GDS 상태 확인
cat /proc/driver/nvidia-fs/stats
# Reads : 1234567
# Writes : 567890
# P2P Reads: 1234567 ← P2P DMA로 처리된 읽기
# P2P Fail : 0 ← P2P 불가 시 폴백 횟수
# gdsio 벤치마크 (NVIDIA GDS 도구)
gdsio -f /mnt/nas-nvme/testfile -d 0 -w 4 -s 1G -x 0 -I 1
# IoType: READ, Threads: 4, Bandwidth: 6.2 GiB/s
# GPU Util: 0%, CPU Util: 0.3%
P2P DMA와 IOMMU 상호작용
| IOMMU 설정 | P2P DMA | 성능 영향 | NAS 권장 |
|---|---|---|---|
| IOMMU 비활성 | 직접 P2P (물리 주소) | 최고 성능 | 전용 GPU NAS |
| IOMMU passthrough | 1:1 매핑, P2P 가능 | 무시할 수준 | 범용 권장 |
| IOMMU strict | ATS(Address Translation Service) 필요 | 지연 증가 (~5%) | 보안 요구 시 |
| IOMMU + ACS 활성 | P2P 차단 가능 | P2P 불가 | ACS override 패치 필요 |
# IOMMU passthrough 모드 설정 (P2P DMA 최적)
# /etc/default/grub에 추가:
# GRUB_CMDLINE_LINUX="iommu=pt intel_iommu=on"
# ACS 확인 — P2P를 차단하는 ACS가 있는지 확인
setpci -s 01:00.0 ECAP_ACS+6.w
# 0000 → ACS 미활성 (P2P 허용)
# P2P DMA 가능 여부를 커널 로그에서 확인
dmesg | grep -i p2pdma
# nvme 0000:03:00.0: registered 256MB of P2P memory
# nvidia-fs: P2P DMA enabled for GPU 0000:01:00.0
상용 NAS 아키텍처 비교 — Synology/QNAP/TrueNAS/NetApp
상용 NAS 오프로드 구현 상세
각 상용 NAS 플랫폼이 하드웨어 오프로드를 어떻게 구현하는지 상세히 비교합니다.
Synology DSM
- RAID: SHR(Synology Hybrid RAID)는 md RAID 기반 소프트웨어 RAID입니다. XOR 연산은 CPU에서 처리하며, AES-NI로 암호화를 가속합니다.
- 암호화: 공유 폴더 암호화(eCryptfs) 또는 볼륨 암호화(dm-crypt/LUKS2)를 선택할 수 있습니다. AES-NI 지원 CPU에서만 허용 가능한 성능을 보입니다.
- 미디어: Intel QSV(i915 드라이버)를 Surveillance Station과 Video Station에서 활용합니다. 적합한 CPU(J4125, N5105, Celeron 7305 등)가 탑재된 모델에서만 지원됩니다.
- 네트워크: 10GbE 옵션 카드(E10G18-T1 등) 지원. RDMA/SMB Direct는 미지원이며, TSO/GRO 기본 오프로드만 사용합니다.
- 제한사항: 커널 버전이 구형(DSM 7.x는 Linux 4.4 기반)이므로 DSA, blk-crypto 등 최신 오프로드 기능은 사용할 수 없습니다.
QNAP QTS/QuTS hero
- RAID: QTS는 SW RAID(md), QuTS hero는 ZFS RAID-Z를 사용합니다. 일부 고급 모델은 HW RAID 카드를 지원합니다.
- 네트워크: 25GbE 내장 모델(TS-h2490FU)이 있으며, 10GbE PCIe 카드를 다양하게 지원합니다.
- GPU: PCIe 슬롯이 있는 모델에서 NVIDIA dGPU를 장착하여 Plex/Jellyfin 트랜스코딩에 활용할 수 있습니다.
- NPU: M.2 슬롯에 Hailo-8 NPU를 장착하여 QVR Pro 감시 카메라의 AI 분석을 가속합니다.
- 압축: QuTS hero(ZFS)는 lz4/zstd 투명 압축을 지원하지만, QAT HW 가속은 미지원입니다.
TrueNAS (iXsystems)
- RAID: OpenZFS RAID-Z1/Z2/Z3을 사용합니다. IT 모드 HBA가 필수이며, HW RAID 컨트롤러 사용은 강력히 비권장됩니다.
- 암호화: ZFS 네이티브 암호화와 SED를 모두 지원합니다. ZFS 암호화는 AES-256-GCM을 사용하며, AES-NI로 가속됩니다.
- 네트워크: TrueNAS Enterprise는 100GbE와 iSER을 지원합니다. SCALE 에디션은 Linux 기반으로 RDMA 구성이 가능합니다.
- 압축: ZFS의 lz4/zstd 투명 압축 기본 활성화. QAT HW 가속은 OpenZFS 2.x에서 실험적으로 지원됩니다.
- NVMe-oF: TrueNAS Enterprise(CORE+)에서 NVMe-oF 타겟 기능을 제공합니다.
NetApp ONTAP
- RAID: RAID-DP(이중 패리티, RAID 6 유사)와 RAID-TEC(삼중 패리티)를 전용 HW ASIC으로 처리합니다. CPU 오버헤드가 거의 없습니다.
- 암호화: NSE(NetApp Storage Encryption, SED)와 NVE(NetApp Volume Encryption, SW)를 제공합니다. 엔터프라이즈 키 관리(KMIP)와 완전 통합됩니다.
- 네트워크: 25/100GbE, NFS/RDMA, FC 32Gbps를 기본 지원합니다. RDMA는 NFS와 네이티브로 통합되어 있습니다.
- 중복제거/압축: 인라인 중복제거와 압축을 전용 하드웨어(AFF 시리즈)로 가속합니다. 공간 절약률이 3:1~5:1에 달하며 성능 영향이 최소화됩니다.
- FlexClone: WAFL의 CoW 메커니즘을 활용한 즉시 복제 기능으로, 데이터 복사 없이 메타데이터만 복제합니다.
Linux 커널 NAS 빌딩 블록 매핑
오프로드 결정 트리 (워크로드별 선택 가이드)
성능 벤치마크 방법론 — fio, iperf3, perf
스토리지 오프로드 효과 측정 (fio)
# 기준선: SW RAID 6 + dm-crypt
fio --name=baseline --ioengine=libaio --direct=1 --bs=1M \
--rw=write --size=10G --numjobs=4 --iodepth=32 \
--filename=/dev/mapper/crypt-raid6
# 비교: HW RAID + SED (동일 디스크 구성)
fio --name=hw-offload --ioengine=libaio --direct=1 --bs=1M \
--rw=write --size=10G --numjobs=4 --iodepth=32 \
--filename=/dev/sdX # HW RAID 가상 디스크
# CPU 사용률 동시 모니터링
mpstat -P ALL 1 # 별도 터미널에서 실행
네트워크 오프로드 효과 측정 (iperf3)
# TCP 기본 (TSO 활성화 상태)
iperf3 -c nas-server -t 30 -P 8
# RDMA 대역폭 (perftest)
ib_write_bw -d mlx5_0 -s 1048576 nas-server
# CPU 사용률 비교
perf stat -e cycles,instructions -- iperf3 -c nas-server -t 10
오프로드 효과 검증 (perf)
# dm-crypt CPU 핫스팟 확인
perf top -g -p $(pgrep -d, kcryptd)
# RAID 패리티 연산 CPU 점유율
perf record -g -a -- sleep 10
perf report --sort=dso,symbol | grep -E "xor|raid|pq"
# DSA offload 확인
cat /sys/bus/dsa/devices/dsa0/state
cat /sys/bus/dsa/devices/wq0.0/state
RDMA 성능 벤치마크
# RDMA 대역폭 테스트 (서버측)
ib_write_bw -d mlx5_0 --report_gbits
# RDMA 대역폭 테스트 (클라이언트측)
ib_write_bw -d mlx5_0 --report_gbits nas-server
# RDMA 지연시간 테스트
ib_write_lat -d mlx5_0 nas-server
# SMB Direct 실제 파일 전송 벤치마크
smbclient //nas-server/share -U user%pass -c \
"put /dev/zero testfile 10737418240" # 10GB 쓰기
# NFS/RDMA vs NFS/TCP 비교
# TCP 마운트 → fio 실행 → 결과 기록
mount -t nfs -o tcp,vers=4.2 nas:/data /mnt/tcp
fio --name=nfs-tcp --directory=/mnt/tcp --rw=randread \
--bs=4k --numjobs=16 --iodepth=32 --size=4G \
--group_reporting --output=tcp-result.txt
# RDMA 마운트 → fio 실행 → 결과 기록
mount -t nfs -o rdma,port=20049,vers=4.2 nas:/data /mnt/rdma
fio --name=nfs-rdma --directory=/mnt/rdma --rw=randread \
--bs=4k --numjobs=16 --iodepth=32 --size=4G \
--group_reporting --output=rdma-result.txt
QAT 압축 벤치마크
# QAT 압축 성능 테스트 (qatzip 도구)
qzip -A deflate -O gzip -L 6 --hw-buff-sz 65536 \
-i testdata-1GB.bin -o /dev/null
# 커널 crypto API 벤치마크
modprobe tcrypt
# dmesg 로그에서 QAT deflate 성능 확인
dmesg | grep -i "deflate.*qat"
# SW vs HW 비교 스크립트
for algo in deflate lz4; do
echo "=== $algo SW ==="
time openssl speed -evp $algo
echo "=== $algo HW (QAT) ==="
QAT_POLICY=1 time openssl speed -engine qatengine -evp $algo
done
종합 벤치마크 체크리스트
| 테스트 항목 | 도구 | 핵심 지표 | 비교 대상 |
|---|---|---|---|
| 블록 I/O 성능 | fio | IOPS, BW, lat | HW RAID vs SW RAID |
| 암호화 오버헤드 | fio + perf | CPU%, BW 감소율 | SED vs dm-crypt vs plain |
| RAID rebuild 영향 | fio + mdstat | rebuild 중 서비스 IOPS | HW vs SW rebuild |
| 네트워크 대역폭 | iperf3, perftest | Gbps, CPU% | TCP vs RDMA |
| 파일 서비스 성능 | smbclient, nfsiostat | MB/s, 동시 사용자 | SMB/TCP vs SMB Direct |
| 압축 처리량 | qzip, openssl speed | MB/s, CPU% | SW vs QAT |
| 트랜스코딩 | ffmpeg, MediaInfo | fps, 동시 스트림 | SW vs QSV |
| memcpy 오프로드 | dsa_perf_micros | GB/s, CPU% | CPU vs DSA |
커널 설정 (Kconfig)
| 분류 | Kconfig 옵션 | 설명 |
|---|---|---|
| HW RAID | CONFIG_MEGARAID_SAS | Broadcom MegaRAID SAS 드라이버 |
CONFIG_SCSI_SMARTPQI | Microchip SmartPQI 드라이버 | |
| DSA | CONFIG_INTEL_IDXD | Intel DSA/IAA 드라이버 |
CONFIG_INTEL_IDXD_SVM | DSA SVM(Shared Virtual Memory) 지원 | |
| 암호화 | CONFIG_BLK_INLINE_ENCRYPTION | 블록 레이어 인라인 암호화 |
CONFIG_BLK_SED_OPAL | SED/OPAL 커널 지원 | |
CONFIG_CRYPTO_DEV_QAT_* | Intel QAT 암호화/압축 드라이버 | |
| RDMA | CONFIG_INFINIBAND | InfiniBand/RDMA 코어 |
CONFIG_MLX5_INFINIBAND | ConnectX RDMA 드라이버 | |
CONFIG_SMB_SERVER_RDMA | ksmbd SMB Direct 지원 | |
| NVMe-oF | CONFIG_NVME_TARGET | NVMe 타겟 프레임워크 |
CONFIG_NVME_TARGET_RDMA | NVMe-oF/RDMA 타겟 | |
| iSCSI HBA | CONFIG_SCSI_CXGB4_ISCSI | Chelsio T6 iSCSI HW 오프로드 |
| async_tx | CONFIG_ASYNC_TX_DMA | async_tx DMA 엔진 연동 활성화 |
CONFIG_ASYNC_XOR | 비동기 XOR 연산 (RAID 5/6 필수) | |
| DMA 엔진 | CONFIG_DMADEVICES | DMA 엔진 서브시스템 |
CONFIG_INTEL_IOATDMA | Intel IOAT DMA (Crystal Beach) | |
| P2P DMA | CONFIG_PCI_P2PDMA | PCIe P2P DMA 지원 |
CONFIG_DMABUF_MOVE_NOTIFY | DMA-BUF 이동 알림 (GPU 연동) | |
| 스토리지 프로토콜 | CONFIG_NVME_TARGET_TCP | NVMe-oF/TCP 타겟 |
CONFIG_ISCSI_TARGET | LIO iSCSI 타겟 | |
CONFIG_TARGET_CORE | LIO 타겟 코어 (XCOPY 지원) | |
| VDO | CONFIG_DM_VDO | VDO 중복제거/압축 (6.9+) |
CONFIG_CRYPTO_SHA256_NI | SHA-256 HW 가속 (SHA-NI) | |
| 파일시스템 | CONFIG_BTRFS_FS | Btrfs (CoW, 스냅샷, 압축) |
CONFIG_FS_ENCRYPTION | fscrypt (파일 단위 암호화) | |
| 네트워크 | CONFIG_TLS_DEVICE | kTLS HW 오프로드 |
CONFIG_SUNRPC_XPRT_RDMA | NFS/RDMA 전송 지원 |
NAS 오프로드별 Kconfig 의존성
각 오프로드 기능은 여러 Kconfig 옵션이 조합되어 동작합니다. 하나라도 빠지면 오프로드가 활성화되지 않으므로, 커널 빌드 시 다음 의존성을 확인하세요.
# RAID XOR HW 가속 의존성 체인
CONFIG_DMADEVICES=y # DMA 서브시스템
CONFIG_INTEL_IOATDMA=m # IOAT DMA 드라이버 (또는 mv_xor 등)
CONFIG_ASYNC_TX_DMA=y # async_tx → DMA 연동
CONFIG_ASYNC_XOR=y # XOR 비동기 연산
CONFIG_MD_RAID456=m # md RAID 5/6
# blk-crypto 인라인 암호화 의존성
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y # HW 미지원 시 SW 폴백
CONFIG_FS_ENCRYPTION=y # fscrypt (선택적)
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y # fscrypt → blk-crypto 연동
# SMB Direct (ksmbd RDMA) 의존성
CONFIG_SMB_SERVER=m # ksmbd
CONFIG_SMB_SERVER_RDMA=y # RDMA 전송 활성화
CONFIG_INFINIBAND=m # RDMA 코어
CONFIG_MLX5_INFINIBAND=m # ConnectX 드라이버 (예시)
CONFIG_INFINIBAND_ADDR_TRANS=y
# QAT 압축 의존성
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ACOMP2=y # 비동기 압축 프레임워크
CONFIG_CRYPTO_DEV_QAT=m # QAT 공통
CONFIG_CRYPTO_DEV_QAT_4XXX=m # QAT 4xxx (Sapphire Rapids)
CONFIG_CRYPTO_DEV_QAT_DH895xCC=m # QAT DH895xCC (선택)
# NFS/RDMA 의존성
CONFIG_NFSD=m # 커널 NFS 서버
CONFIG_NFSD_V4=y # NFSv4 지원
CONFIG_SUNRPC_XPRT_RDMA=m # RPC RDMA 전송
CONFIG_SVCRDMA=m # 서버측 RDMA
#!/bin/bash
# NAS 오프로드 Kconfig 확인 스크립트
CONFIGS="BLK_INLINE_ENCRYPTION INTEL_IDXD ASYNC_TX_DMA ASYNC_XOR
INFINIBAND MLX5_INFINIBAND SMB_SERVER_RDMA
NVME_TARGET NVME_TARGET_RDMA CRYPTO_DEV_QAT
SUNRPC_XPRT_RDMA PCI_P2PDMA DM_VDO
CRYPTO_SHA256_NI TLS_DEVICE"
for cfg in $CONFIGS; do
val=$(grep "CONFIG_${cfg}=" /boot/config-$(uname -r) 2>/dev/null || echo "not set")
printf "%-35s %s\n" "CONFIG_${cfg}" "$val"
done
실전 구성 예제
예제 1: 4-Bay NAS — HW RAID + dm-crypt + SMB3
# HW RAID 6 구성 (storcli)
storcli /c0 add vd r6 drives=252:0-3 wb ra cached
# dm-crypt LUKS2 설정
cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 \
--key-size 512 /dev/sda # HW RAID 가상 디스크
cryptsetup open /dev/sda crypt-nas
# ext4 + SMB3 공유
mkfs.ext4 /dev/mapper/crypt-nas
mount /dev/mapper/crypt-nas /srv/nas
# ksmbd 또는 Samba 설정
예제 2: 10GbE NAS — RDMA + NFS
# RoCE v2 설정
modprobe mlx5_ib
rdma link show # RDMA 디바이스 확인
# NFS over RDMA 서버
cat >> /etc/nfs.conf << 'EOF'
[nfsd]
rdma=y
rdma-port=20049
EOF
systemctl restart nfs-server
# 클라이언트 마운트
mount -t nfs -o rdma,port=20049 nas-server:/export /mnt/nas
예제 3: All-Flash NAS — NVMe-oF + QAT 압축
# NVMe-oF/RDMA 타겟 설정
modprobe nvmet-rdma
mkdir -p /sys/kernel/config/nvmet/subsystems/nqn.nas
echo 1 > /sys/kernel/config/nvmet/subsystems/nqn.nas/attr_allow_any_host
# QAT 압축 활성화
modprobe qat_4xxx
modprobe intel_qat
# Btrfs + QAT (ZFS의 경우 qat_compress 모듈)
mkfs.btrfs -m raid1 -d raid6 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1
mount -o compress=zstd /dev/nvme0n1 /srv/nas
예제 4: 고가용성 NAS — ZFS + iSER + SED
# ZFS 풀 구성 (IT 모드 HBA 필수)
zpool create -o ashift=12 tank \
raidz2 /dev/sd{a,b,c,d,e,f} \
log mirror /dev/nvme0n1p1 /dev/nvme1n1p1 \
cache /dev/nvme2n1
# SED 잠금 설정
sedutil-cli --initialSetup debug /dev/sda
sedutil-cli --enableLockingRange 0 password /dev/sda
# 모든 디스크에 반복...
# iSER 타겟 구성 (LIO)
modprobe ib_isert
targetcli /iscsi create iqn.2024-01.com.nas:ha-zfs
targetcli /iscsi/.../tpg1/luns create /backstores/block/tank-zvol
# iSER은 TCP 포트 3260에서 자동 협상
# ZFS 스냅샷 자동화 (랜섬웨어 방어)
zfs set snapdir=visible tank
zfs snapshot -r tank@daily-$(date +%Y%m%d)
zfs hold anti-ransom tank@daily-$(date +%Y%m%d)
예제 5: Hyper-Converged NAS — DSA + RDMA + QAT
# 4세대 Xeon Sapphire Rapids 전용 구성
# DSA 설정 (RAID rebuild + 데이터 이동 가속)
accel-config config-wq dsa0/wq0.0 --mode=dedicated \
--type=kernel --driver-name=dmaengine --wq-size=128
accel-config enable-device dsa0
accel-config enable-wq dsa0/wq0.0
# QAT 압축 활성화 (내장 QAT 4xxx)
modprobe qat_4xxx
adf_ctl restart
# RDMA + SMB Direct (ConnectX-7 100GbE)
modprobe mlx5_ib
rdma link show
# ksmbd SMB Direct 서비스 시작
ksmbd.mountd -s /etc/ksmbd/ksmbd.conf
# VDO 중복제거 + QAT 압축
vdo create --name=hci-dedup --device=/dev/md0 \
--vdoLogicalSize=10T --vdoSlabSize=32G
# 시스템 모니터링 대시보드
# DSA 상태, QAT 카운터, RDMA 통계를 종합 확인
watch -n 5 'echo "=== DSA ===" && cat /sys/bus/dsa/devices/dsa0/clients && \
echo "=== QAT ===" && adf_ctl status && \
echo "=== RDMA ===" && rdma statistic show'
구성별 총 비용 대비 성능 비교
| 구성 | 예상 비용 (USD) | 순차 쓰기 | 랜덤 4K IOPS | 동시 사용자 | 적합 규모 |
|---|---|---|---|---|---|
| 4-Bay HDD + SW RAID | $500~800 | ~400 MB/s | ~1K | 5~10명 | 소규모 사무실 |
| 4-Bay HDD + HW RAID | $800~1,500 | ~500 MB/s | ~2K | 10~20명 | 중소기업 |
| 8-Bay SSD + RDMA | $3,000~6,000 | ~5 GB/s | ~500K | 50~100명 | 중견기업 |
| All-NVMe + QAT + DSA | $8,000~15,000 | ~12 GB/s | ~1M | 100~500명 | 데이터센터 |
| HA Cluster + NVMe-oF | $20,000+ | ~25 GB/s | ~2M+ | 500명+ | 엔터프라이즈 |
흔한 실수와 안티패턴
HW RAID의 BBU가 방전되면 자동으로 Write-through 모드로 전환되어 쓰기 성능이 5-10배 저하됩니다. 정기적인 BBU 상태 점검과 SNMP/이메일 알림을 설정하세요.
dm-crypt는 데이터를 암호화한 후 HW RAID에 전달합니다. HW RAID의 Write-back 캐시에 암호화된 데이터가 있는 상태에서 정전이 발생하면, BBU/FBWC가 없으면 데이터 손실이 발생합니다. 반드시 BBU/FBWC가 정상인지 확인 후 Write-back을 활성화하세요.
RoCE v2는 lossless fabric이 필수입니다. PFC(Priority Flow Control)를 설정하지 않으면 네트워크 혼잡 시 대량 패킷 손실이 발생하여 RDMA 성능이 TCP보다 나빠질 수 있습니다. iWARP는 TCP 기반이므로 PFC 없이도 동작합니다.
SED/OPAL 드라이브의 비밀번호를 분실하면 데이터 복구가 절대 불가능합니다. PSID revert(공장 초기화)만 가능하며 모든 데이터가 삭제됩니다.
현재 Linux 커널의 Btrfs는 QAT 압축을 직접 지원하지 않습니다(zstd/lzo/zlib SW 전용). ZFS는
qat_compress 모듈로 QAT gzip/lz4 가속이 가능합니다. 파일시스템 선택 전 QAT 호환성을 확인하세요.
DSA는 4KB 이하의 소규모 memcpy에서 CPU보다 느립니다. descriptor 제출 오버헤드(~1μs)가 작은 전송에서 병목이 되기 때문입니다. DSA는 64KB 이상의 대규모 전송에만 사용하세요. 소규모 전송은 CPU의 REP MOVSB가 더 효율적입니다.
NFS/RDMA는 NFSv4 이상에서만 안정적으로 지원됩니다. NFSv3 over RDMA는 실험적이며 프로덕션 환경에서 권장되지 않습니다. 또한 NFSv4.1+의 세션/트렁킹 기능을 활용해야 RDMA 멀티채널 성능을 최대화할 수 있습니다.
ZFS RAID-Z나 Btrfs RAID는 디스크에 직접 접근해야 합니다. HW RAID 컨트롤러가 가상 디스크를 노출하면 ZFS의 자가 복구, 스크럽, 체크섬 검증이 무력화됩니다. ZFS/Btrfs NAS에서는 반드시 IT 모드(HBA) 컨트롤러를 사용하세요.
LUKS2의 기본 Argon2id KDF는 잠금해제 시 1GB 메모리를 사용합니다. RAM이 2GB 이하인 임베디드 NAS에서 부팅 시 잠금해제에 실패하거나 OOM이 발생할 수 있습니다.
--pbkdf-memory 524288으로 512MB 이하로 설정하세요.
RDMA(특히 RoCEv2)는 엔드투엔드 MTU가 일치해야 합니다. 스위치의 MTU가 NIC의 MTU보다 작으면 PMTU discovery 실패로 연결이 끊기거나 성능이 급락합니다. 모든 경로(NIC, 스위치, 라우터)에서 Jumbo Frame(MTU 9000)을 일관되게 설정하세요.
트러블슈팅 가이드
| 증상 | 가능한 원인 | 진단 방법 | 해결책 |
|---|---|---|---|
| RAID rebuild 중 NAS 응답 없음 | SW RAID CPU 과부하 | top에서 md worker 확인 | speed_limit_max 낮추기 또는 HW RAID 전환 |
| dm-crypt 쓰기 성능 저하 | BBU 방전 → Write-through | storcli /c0/bbu show | BBU 교체 또는 FBWC 업그레이드 |
| RDMA 연결 실패 | PFC 미설정, MTU 불일치 | rdma res show qp, ethtool -S | PFC/ECN 설정, MTU 통일 |
| QAT 압축 미작동 | 인스턴스 미할당 | adf_ctl status | 설정 파일 확인 후 adf_ctl restart |
| DSA 작업 실패 (EAGAIN) | Shared WQ 포화 | cat /sys/bus/dsa/devices/wq0.0/state | WQ 크기 증가 또는 Dedicated WQ 사용 |
| SMB Direct 미활성 | RDMA NIC 미인식 | rdma link show | mlx5_ib 모듈 로드, 펌웨어 업데이트 |
| SED 잠금해제 실패 | 비밀번호 오류, PBA 손상 | sedutil-cli --query /dev/sdX | PSID revert (데이터 손실 주의) |
| NFS/RDMA 마운트 실패 | svcrdma 모듈 미로드 | cat /proc/fs/nfsd/portlist | modprobe svcrdma, portlist에 rdma 추가 |
NAS 워크로드별 오프로드 조합 권장
NAS 워크로드는 매우 다양하며, 각 워크로드에 최적인 오프로드 조합이 다릅니다. 아래에서 주요 NAS 워크로드 유형별 권장 오프로드 전략을 제시합니다.
파일 서버 (SMB/NFS)
가장 일반적인 NAS 워크로드로, 다수 사용자가 동시에 문서, 이미지, 스프레드시트 등을 읽고 씁니다. 소규모 랜덤 I/O가 주를 이루며, 동시 접속자 수에 따라 CPU 부하가 증가합니다.
| 구성 요소 | 소규모 (5~20명) | 중규모 (20~100명) | 대규모 (100명+) |
|---|---|---|---|
| RAID | SW RAID 5/6 (md) | HW RAID 6 + FBWC | HW RAID 6 + 대용량 캐시 |
| 암호화 | dm-crypt + AES-NI | SED + dm-crypt | SED 단독 |
| 네트워크 | 1GbE TSO/GRO | 10GbE + kTLS | 25GbE RDMA + SMB Direct |
| 프로토콜 | SMB3 (ksmbd) | SMB3 멀티채널 | SMB Direct + 멀티채널 |
| 스토리지 | HDD SATA | HDD + SSD 캐시 | All-SSD 또는 NVMe |
| CPU 여유율 목표 | >50% | >40% | >60% (오프로드 덕분) |
백업 및 아카이브
대용량 순차 쓰기가 주 워크로드로, 압축과 중복제거가 저장 공간 효율에 핵심입니다.
- 필수 오프로드: QAT 압축 (deflate/lz4), VDO 중복제거 + SHA-NI
- 권장 오프로드: HW RAID 6 (rebuild 중 서비스 영향 최소화), DSA memcpy (대용량 버퍼 복사)
- 암호화: dm-crypt LUKS2 (백업 데이터 보호), Argon2id KDF
- 네트워크: 10GbE 이상 (백업 윈도우 단축), NFS/RDMA 또는 SMB Direct
- 스토리지: HDD RAID 6/Z2 (용량 우선), SSD 로그 장치 (동기 쓰기 가속)
# 백업 NAS 최적화 설정 예시
# 1. VDO 중복제거 + 압축
vdo create --name=backup-store --device=/dev/md0 \
--vdoLogicalSize=20T --writePolicy=auto
# 2. ZFS + QAT 압축 (대안)
zpool create backup raidz2 /dev/sd{a..h}
zfs set compression=gzip-6 backup # QAT 가속 자동 사용
zfs set dedup=on backup # RAM 충분 시에만
# 3. rsync/borg 백업 시 대역폭 확인
iotop -ao -d 30 # 30초간 프로세스별 I/O 확인
가상화 스토리지 (iSCSI/NVMe-oF)
VM 스토리지는 랜덤 4K I/O가 대부분이며, 지연시간이 VM 성능에 직접적인 영향을 줍니다.
- 필수 오프로드: NVMe-oF/RDMA 또는 iSER (최소 지연시간), SED 암호화 (성능 무손실)
- 권장 오프로드: All-NVMe + HW RAID (또는 ZFS mirror), DSA (VM 라이브 마이그레이션 시 memcpy 가속)
- Copy Offload: XCOPY (VM 클론 가속), NVMe Copy (스냅샷)
- 네트워크: 25GbE+ RDMA, PFC/ECN 설정 필수 (RoCEv2)
- 핵심 지표: 4K 랜덤 IOPS > 500K, P99 지연시간 < 100μs
미디어 서비스 (Plex/Jellyfin/감시)
미디어 트랜스코딩과 감시 카메라 녹화/AI 분석은 CPU 집약적 워크로드입니다.
- 필수 오프로드: Intel QSV 또는 dGPU (트랜스코딩), NPU/TPU (AI 분석)
- 권장 오프로드: SW RAID 5/6 + AES-NI (비용 절감), 10GbE (다중 4K 스트림)
- 스토리지: HDD RAID 5 (미디어 저장 + 순차 읽기), NVMe 캐시 (썸네일/메타데이터)
- CPU 선택: Intel QSV 지원 CPU 필수 (Celeron J4125 이상, AV1 디코딩은 12세대+)
AI/ML 데이터 레이크
대규모 학습 데이터셋을 저장하고 GPU 클러스터에 제공하는 NAS입니다.
- 필수 오프로드: P2P DMA + GPU Direct Storage, NVMe-oF/RDMA, 100GbE
- 권장 오프로드: All-NVMe (순차 읽기 대역폭), DSA (데이터 전처리 memcpy)
- 파일시스템: XFS 또는 Lustre/GPFS (대규모 병렬 I/O)
- 핵심 지표: 순차 읽기 > 20 GB/s, GPU 로딩 대역폭 > 10 GB/s
워크로드별 오프로드 우선순위 매트릭스
| 오프로드 | 파일 서버 | 백업/아카이브 | 가상화 | 미디어 | AI/ML |
|---|---|---|---|---|---|
| HW RAID / XOR 가속 | 중간 | 높음 | 높음 | 낮음 | 낮음 |
| DSA memcpy | 낮음 | 중간 | 높음 | 낮음 | 높음 |
| Copy Offload | 낮음 | 중간 | 높음 | 낮음 | 낮음 |
| SED / dm-crypt | 높음 | 높음 | 높음 | 중간 | 낮음 |
| RDMA / SMB Direct | 높음 | 중간 | 높음 | 낮음 | 필수 |
| NVMe-oF | 낮음 | 낮음 | 필수 | 낮음 | 필수 |
| QAT 압축 | 낮음 | 필수 | 낮음 | 낮음 | 낮음 |
| GPU QSV | 낮음 | 낮음 | 낮음 | 필수 | 낮음 |
| P2P DMA | 없음 | 없음 | 낮음 | 낮음 | 필수 |
오프로드 도입 단계별 권장
NAS 오프로드를 한 번에 전부 도입하는 것은 비현실적입니다. 비용 효율이 높은 순서대로 단계적으로 도입하는 것을 권장합니다.
- 1단계 (무비용): TSO/GRO 활성화 확인, AES-NI 암호화 가속 확인, SHA-NI VDO 가속. 소프트웨어 설정만으로 즉시 효과.
- 2단계 (저비용): SED 드라이브 도입 (추가 비용 10~20%), 10GbE NIC 업그레이드, SSD 캐시 추가.
- 3단계 (중비용): HW RAID 컨트롤러 (FBWC 포함), 25GbE RDMA NIC, Intel QSV CPU 선택.
- 4단계 (고비용): QAT 가속기, DSA 지원 Xeon, 100GbE 인프라, NVMe-oF 확장.
- 5단계 (엔터프라이즈): P2P DMA + GPU Direct, FC SAN 백엔드, HA 클러스터 구성.
async_tx XOR/PQ 오프로드 프레임워크
async_tx는 Linux 커널의 비동기 트랜잭션 프레임워크로, RAID 5/6에서 사용하는 XOR 및 PQ(Reed-Solomon) 연산을 DMA 엔진 또는 CPU에서 투명하게 실행합니다. md RAID의 쓰기 경로에서 핵심적인 역할을 하며, DMA 엔진이 있으면 자동으로 하드웨어 가속을 활용합니다.
async_tx_submit() 구조와 DMA 엔진 연동
async_tx_submit()은 비동기 작업의 제출과 완료 추적을 관리합니다. DMA 엔진의 트랜잭션 descriptor를 채널에 제출하고, 완료 콜백을 등록하여 비동기 파이프라인을 구성합니다.
/* crypto/async_tx/async_tx.c */
void async_tx_submit(struct dma_chan *chan,
struct dma_async_tx_descriptor *tx,
struct async_submit_ctl *submit)
{
struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;
/* 의존 관계 설정: 이전 연산 완료 후 실행 */
if (depend_tx) {
tx->parent = depend_tx;
spin_lock_bh(&depend_tx->lock);
list_add_tail(&tx->parent_node, &depend_tx->tx_list);
spin_unlock_bh(&depend_tx->lock);
}
/* 완료 콜백 설정 */
tx->callback = submit->cb_fn;
tx->callback_param = submit->cb_param;
/* DMA 엔진 채널에 작업 제출 */
dmaengine_submit(tx);
/* 보류된 작업 시작 (실제 HW 전송 트리거) */
dma_async_issue_pending(chan);
}
async_tx의 의존 관계 체인은 RAID 5/6의 read-modify-write 또는 reconstruct-write 패턴에서 연산 순서를 보장합니다. 예를 들어, RAID 6 쓰기 시 "P 패리티 XOR" → "Q 패리티 PQ" → "디스크 쓰기" 순서가 콜백 체인으로 자동 보장됩니다.
XOR/PQ 가속 지원 DMA 엔진 목록
| DMA 엔진 | XOR | PQ | memcpy | 플랫폼 | 커널 드라이버 |
|---|---|---|---|---|---|
| Intel IOAT (CB DMA) | 지원 | 지원 | 지원 | Xeon (Sandy Bridge~) | ioatdma |
| Intel DSA | 미지원 | 미지원 | 지원 | Xeon (Sapphire Rapids~) | idxd |
| Marvell XOR v2 | 지원 | 지원 | 지원 | Armada 7K/8K, CN9xxx | mv_xor_v2 |
| Marvell XOR v1 | 지원 | 미지원 | 지원 | Armada 370/XP/38x | mv_xor |
| Freescale RAID Engine | 지원 | 지원 | 지원 | QorIQ P/T 시리즈 | fsl-raideng |
| Microchip PolarFire | 지원 | 미지원 | 지원 | PolarFire SoC FPGA | mpfs-dma |
| Hisilicon SEC | 미지원 | 미지원 | 지원 | Kunpeng 920 | hisi_sec2 |
async_xor() 핵심 경로 상세
커널 소스 분석: async_xor() — RAID 5 패리티 연산 내부
/* crypto/async_tx/async_xor.c (상세 분석) */
struct dma_async_tx_descriptor *
async_xor(struct page *dest, struct page **src_list,
unsigned int offset, int src_cnt, size_t len,
struct async_submit_ctl *submit)
{
struct dma_chan *chan;
struct dma_device *device;
/* 1단계: XOR 기능 DMA 채널 탐색 */
chan = async_tx_find_channel(submit, DMA_XOR,
&dest, 1, src_list, src_cnt, len);
device = chan ? chan->device : NULL;
if (device && src_cnt <= device->max_xor) {
/* 2단계: DMA XOR 경로 */
struct dma_async_tx_descriptor *tx;
dma_addr_t dma_dest, dma_src[IOAT_NUM_SRC_TEST];
unsigned long dma_flags = 0;
/* 페이지 → DMA 주소 변환 */
dma_dest = dma_map_page(device->dev, dest,
offset, len, DMA_BIDIRECTIONAL);
for (int i = 0; i < src_cnt; i++)
dma_src[i] = dma_map_page(device->dev,
src_list[i], offset, len,
DMA_TO_DEVICE);
/* DMA XOR descriptor 준비 */
tx = device->device_prep_dma_xor(chan,
dma_dest, dma_src, src_cnt,
len, dma_flags);
/* 3단계: 비동기 제출 (콜백 체인) */
async_tx_submit(chan, tx, submit);
return tx;
}
/* 4단계: SW 폴백 — CPU XOR (SIMD 최적화) */
if (submit->flags & ASYNC_TX_XOR_ZERO_DST)
memset(page_address(dest) + offset, 0, len);
xor_blocks(src_cnt, len,
page_address(dest) + offset, srcs);
return NULL;
}
코드 설명
- 핵심async_xor() 상세 경로: (1)
async_tx_find_channel()이DMA_XOR기능을 가진 DMA 채널을 탐색합니다. IOAT, mv_xor 등이 등록되어 있으면 매칭됩니다. (2) DMA 경로에서는 소스/대상 페이지를 DMA 주소로 매핑하고,device_prep_dma_xor()로 HW descriptor를 준비합니다. (3)async_tx_submit()으로 DMA 엔진에 제출하고, 완료 시 콜백이 호출되어 다음 연산(디스크 쓰기)이 트리거됩니다. (4) DMA 엔진이 없으면xor_blocks()가 CPU에서 XOR을 수행합니다. 이때 커널은 부팅 시 벤치마크한 최적의 XOR 알고리즘(AVX-512, SSE2, NEON 등)을 자동 선택합니다.
RAID 5/6 쓰기 시 async_tx 호출 흐름
md RAID 5/6의 쓰기 경로에서 async_tx가 호출되는 전체 흐름을 살펴봅니다. 스트라이프 단위로 패리티가 계산되며, 비동기 콜백 체인이 전체 과정을 조율합니다.
- raid5_make_request(): bio를 받아 스트라이프 해시 테이블에서 해당 stripe_head를 찾습니다.
- handle_stripe(): 스트라이프 상태를 분석하여 읽기/쓰기/패리티 연산을 결정합니다.
- ops_run_compute5(): RAID 5 패리티를 계산합니다. 내부에서
async_xor()를 호출합니다. - ops_run_compute6_1()/ops_run_compute6_2(): RAID 6의 P/Q 이중 패리티를 계산합니다.
async_gen_syndrome()을 호출합니다. - ops_complete_compute(): 패리티 연산 완료 콜백입니다. 스트라이프를 "쓰기 준비" 상태로 전환합니다.
- ops_run_io(): 데이터와 패리티를 디스크에 기록합니다.
NAS 보안 강화 체크리스트
NAS는 기업의 핵심 데이터를 저장하므로 다층적 보안이 필수입니다. 물리 보안부터 네트워크, 인증, 감사, 랜섬웨어 방어까지 포괄적인 보안 강화 전략을 정리합니다.
물리 보안
- SED(Self-Encrypting Drive): TCG Opal 2.0 호환 SSD/HDD를 사용하여 디스크 도난 시 데이터를 보호합니다. 성능 손실 없이 AES-256 전체 디스크 암호화를 제공합니다.
- Kensington Lock: 물리적 도난 방지를 위한 기본 조치입니다. 서버 랙 마운트 시 랙 잠금장치를 병행합니다.
- TPM 2.0: LUKS2 키를 TPM에 봉인(seal)하여 부팅 체인이 변조되면 자동으로 디스크 잠금해제를 거부합니다.
systemd-cryptenroll --tpm2-device=auto로 설정합니다. - 시리얼 콘솔 비활성화: 물리 접근이 가능한 시리얼/VGA 콘솔을 비활성화하거나 BIOS 비밀번호를 설정합니다.
네트워크 보안
- VLAN 분리: NAS 관리 트래픽(SSH, Web UI)과 데이터 트래픽(SMB/NFS/iSCSI)을 별도 VLAN으로 격리합니다. 관리 VLAN은 지정된 관리자 IP에서만 접근을 허용합니다.
- 방화벽 (iptables/nftables): 필요한 포트(SMB: 445, NFS: 2049, iSCSI: 3260, SSH: 22)만 열고 나머지는 차단합니다.
- fail2ban: SSH, SMB, Web UI 로그인 실패 시 자동 차단합니다. NAS 특화 jail 설정을 구성합니다.
- NFS 보안: NFSv4+를 사용하고,
sec=krb5p(Kerberos 암호화)를 활성화합니다. NFSv3의 IP 기반 인증은 스푸핑에 취약합니다. - SMB 보안: SMB1 비활성화, SMB3 암호화 필수(
smb encrypt = required), kTLS 오프로드로 성능 보완합니다.
# NAS 방화벽 기본 설정 (nftables)
nft add table inet nas_filter
nft add chain inet nas_filter input { type filter hook input priority 0\; policy drop\; }
# 루프백 허용
nft add rule inet nas_filter input iif lo accept
# 기존 연결 허용
nft add rule inet nas_filter input ct state established,related accept
# 관리 VLAN (vlan100)에서만 SSH 허용
nft add rule inet nas_filter input iifname "vlan100" tcp dport 22 accept
# 데이터 VLAN (vlan200)에서 서비스 포트 허용
nft add rule inet nas_filter input iifname "vlan200" tcp dport { 445, 2049, 3260 } accept
# RDMA 포트 허용 (RoCEv2)
nft add rule inet nas_filter input iifname "vlan200" udp dport 4791 accept
# fail2ban SMB jail
cat >> /etc/fail2ban/jail.d/smb.conf << 'EOF'
[smb]
enabled = true
port = 445
filter = smb
logpath = /var/log/samba/log.%m
maxretry = 5
bantime = 3600
EOF
인증과 접근 제어
- Kerberos 인증: Active Directory 또는 FreeIPA와 연동하여 Kerberos 기반 인증을 적용합니다. NFS는
sec=krb5p, SMB는 AD 조인으로 자동 Kerberos를 사용합니다. - LDAP 디렉토리: 중앙 집중 사용자/그룹 관리를 위해 OpenLDAP 또는 AD LDAP을 연동합니다.
sssd(System Security Services Daemon)를 사용하여 LDAP/Kerberos를 통합합니다. - 2FA(이중 인증): SSH는
google-authenticator-libpam또는pam_u2f로 TOTP/FIDO2 이중 인증을 적용합니다. Web UI 관리 콘솔에도 2FA를 필수 적용합니다. - 최소 권한 원칙: NAS 공유 폴더에 POSIX ACL 또는 NFSv4 ACL을 세밀하게 설정합니다. root 접근은
no_root_squash를 사용하지 않습니다.
감사(Audit) 로깅
- auditd: 파일 접근, 권한 변경, 사용자 인증 이벤트를 기록합니다. NAS 데이터 디렉토리에 대한 파일 접근 감사 규칙을 설정합니다.
- SMB 감사 모듈: Samba의
vfs_full_audit모듈로 SMB 파일 접근을 상세히 기록합니다. - 중앙 로그 수집: rsyslog/syslog-ng로 감사 로그를 별도의 로그 서버에 실시간 전송합니다. NAS 자체에만 로그를 보관하면 공격자가 로그를 삭제할 수 있습니다.
# auditd NAS 데이터 디렉토리 감사 규칙
auditctl -w /srv/nas-data -p rwxa -k nas_file_access
# Samba 감사 모듈 설정
# smb.conf [share] 섹션
# vfs objects = full_audit
# full_audit:prefix = %u|%I|%m|%S
# full_audit:success = connect disconnect mkdir rmdir open read write rename unlink
# full_audit:failure = connect
# full_audit:facility = local5
# full_audit:priority = notice
암호화 계층 조합 가이드
NAS에서 여러 암호화 계층을 조합할 수 있지만, 성능 영향과 키 관리 복잡도를 고려해야 합니다.
| 조합 | 보호 범위 | 성능 영향 | 키 관리 | 적합 시나리오 |
|---|---|---|---|---|
| SED 단독 | 물리 도난 | 0% | TCG Opal (단순) | 물리 보안만 필요, 최고 성능 |
| dm-crypt (LUKS2) | 물리 도난 + OS 우회 | 10-30% | LUKS2 키슬롯 | 범용 NAS, 유연한 키 관리 |
| SED + fscrypt | 물리 + 다중 사용자 격리 | 5-15% | Opal + 파일별 키 | 멀티 테넌트 NAS |
| dm-crypt + SMB3 암호화 | 물리 + 네트워크 도청 | 20-40% | LUKS2 + Kerberos | 규정 준수 (금융/의료) |
| SED + kTLS | 물리 + 네트워크 (HW가속) | 0-5% | Opal + TLS 인증서 | 고성능 + 전구간 암호화 |
랜섬웨어 방어
NAS는 랜섬웨어의 주요 타겟입니다. 다층 방어 전략으로 데이터를 보호합니다.
- Immutable Snapshot: ZFS/Btrfs 스냅샷에
hold(ZFS) 또는 읽기 전용 플래그를 설정하여 관리자 권한으로도 삭제할 수 없는 불변 스냅샷을 생성합니다. - Air-gapped Backup: 3-2-1 백업 규칙(3개 복사본, 2개 매체, 1개 오프사이트)을 준수합니다. 백업 후 네트워크에서 분리하거나 WORM(Write Once Read Many) 스토리지를 사용합니다.
- SMB 파일 스크리닝:
vfs_virusfilter또는 ClamAV FUSE를 통해 알려진 랜섬웨어 확장자(.encrypted, .locked 등)를 차단합니다. - 이상 탐지: 파일 변경 패턴을 모니터링하여 대량 암호화 행위를 감지합니다. 짧은 시간 내 대량의 파일 이름 변경/쓰기가 감지되면 SMB 세션을 자동 차단합니다.
- 스냅샷 자동화: 15분~1시간 간격의 자동 스냅샷으로 RPO(Recovery Point Objective)를 최소화합니다.
# ZFS 불변 스냅샷 생성
zfs snapshot tank/nas-data@backup-2024-01-15
zfs hold keep tank/nas-data@backup-2024-01-15
# hold가 설정된 스냅샷은 zfs destroy로 삭제 불가
# 자동 스냅샷 (systemd timer)
# /etc/systemd/system/zfs-snapshot.timer
[Timer]
OnCalendar=*:0/15 # 15분마다
Persistent=true
# Btrfs 읽기 전용 스냅샷
btrfs subvolume snapshot -r /srv/nas-data \
/srv/.snapshots/nas-data-$(date +%Y%m%d-%H%M%S)
# 스냅샷 보존 정책 (30일 이상 자동 삭제)
find /srv/.snapshots -maxdepth 1 -mtime +30 -exec \
btrfs subvolume delete {} \;
hold 기능은 zfs release 명령 없이는 삭제할 수 없으므로, hold 키 이름을 별도로 관리합니다.
NAS 보안 강화 종합 체크리스트
| 범주 | 항목 | 구현 방법 | 우선순위 |
|---|---|---|---|
| 물리 보안 | 디스크 암호화 | SED TCG Opal 2.0 | 필수 |
| TPM 자동 잠금해제 | systemd-cryptenroll --tpm2 | 권장 | |
| 물리 잠금 | Kensington Lock, 랙 잠금 | 권장 | |
| 시리얼 콘솔 보호 | BIOS 비밀번호, 콘솔 비활성화 | 선택 | |
| 네트워크 | VLAN 분리 | 관리/데이터 VLAN 격리 | 필수 |
| 방화벽 | nftables, 필요 포트만 허용 | 필수 | |
| fail2ban | SSH, SMB, Web UI jail | 필수 | |
| SMB1 비활성화 | server min protocol = SMB3 | 필수 | |
| kTLS 암호화 | SMB3 + kTLS HW 오프로드 | 권장 | |
| 인증 | Kerberos | AD/FreeIPA 연동 | 높음 |
| 2FA | google-authenticator, FIDO2 | 높음 | |
| LDAP 중앙 관리 | sssd + OpenLDAP/AD | 권장 | |
| 최소 권한 | POSIX/NFSv4 ACL, no_root_squash 금지 | 필수 | |
| 감사 | auditd | 파일 접근/권한 변경 로깅 | 높음 |
| SMB 감사 | vfs_full_audit 모듈 | 권장 | |
| 원격 로그 | rsyslog → 별도 로그 서버 | 필수 | |
| 랜섬웨어 방어 | 불변 스냅샷 | ZFS hold, Btrfs readonly | 필수 |
| 3-2-1 백업 | Air-gapped + WORM | 필수 | |
| 파일 스크리닝 | ClamAV, vfs_virusfilter | 권장 | |
| 이상 탐지 | 대량 변경 감지 → 세션 차단 | 권장 | |
| 암호화 | 저장 데이터 | SED 또는 dm-crypt LUKS2 | 필수 |
| 전송 데이터 | SMB3 암호화, NFS krb5p | 높음 | |
| 키 관리 | KMIP, HashiCorp Vault | 엔터프라이즈 |
보안 강화 자동화 스크립트
#!/bin/bash
# NAS 보안 강화 자동 점검 스크립트
echo "=== NAS 보안 점검 ==="
# 1. SMB1 비활성화 확인
echo -n "[SMB1] "
if smbclient -L localhost -m NT1 2>&1 | grep -q "NT1 disabled"; then
echo "OK - SMB1 비활성화"
else
echo "WARNING - SMB1이 활성화되어 있습니다!"
fi
# 2. SSH root 로그인 비활성화 확인
echo -n "[SSH] "
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
echo "OK - root 로그인 비활성화"
else
echo "WARNING - root 로그인이 허용되어 있습니다!"
fi
# 3. fail2ban 상태 확인
echo -n "[fail2ban] "
if systemctl is-active fail2ban >/dev/null 2>&1; then
echo "OK - fail2ban 활성"
else
echo "WARNING - fail2ban이 비활성 상태입니다!"
fi
# 4. 방화벽 규칙 확인
echo -n "[방화벽] "
if nft list ruleset 2>/dev/null | grep -q "policy drop"; then
echo "OK - 기본 정책 drop"
else
echo "WARNING - 방화벽 기본 정책이 accept입니다!"
fi
# 5. SED 상태 확인
echo -n "[SED] "
for dev in /dev/sd?; do
if sedutil-cli --query $dev 2>/dev/null | grep -q "Locked = Y"; then
echo -n "$dev:잠금 "
fi
done
echo ""
# 6. 스냅샷 보호 확인
echo -n "[스냅샷] "
hold_count=$(zfs holds -r tank 2>/dev/null | grep -c "anti-ransom" || echo 0)
echo "보호된 스냅샷: $hold_count개"
# 7. 원격 로그 전송 확인
echo -n "[원격 로그] "
if grep -q "^@@" /etc/rsyslog.conf 2>/dev/null; then
echo "OK - 원격 로그 전송 설정됨"
else
echo "WARNING - 원격 로그 전송이 설정되지 않았습니다!"
fi
echo "=== 점검 완료 ==="
참고 링크
- 커널 문서 — DMA Engine: kernel.org DMA Engine API
- 커널 문서 — RDMA: kernel.org InfiniBand/RDMA
- 커널 문서 — NVMe: kernel.org NVMe 문서
- Intel DSA 커널 드라이버 (Bootlin): drivers/dma/idxd/
- blk-crypto 커널 소스 (Bootlin): block/blk-crypto.c
- async_tx 커널 소스 (Bootlin): crypto/async_tx/
- LWN.net — Intel DSA 드라이버: The idxd driver and user-space DMA
- LWN.net — 인라인 암호화: Inline encryption for block devices
- NVMe Copy Command 규격: NVM Express Specifications — TP 4065 Simple Copy Command를 포함합니다
- Intel QAT 오픈소스 드라이버: github.com/intel/QAT_Engine
관련 문서
NAS HW 오프로드와 관련된 다른 주제를 더 깊이 이해하고 싶다면 다음 문서를 참고하세요.