<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>글루시스 기술 블로그</title>
    <description>A simple yet classy theme for your Jekyll website or blog.
</description>
    <link>https://tech.gluesys.com/</link>
    <atom:link href="https://tech.gluesys.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 03 Feb 2026 00:36:28 +0000</pubDate>
    <lastBuildDate>Tue, 03 Feb 2026 00:36:28 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Lustre Changelog DR</title>
        <description>&lt;h2 id=&quot;목차&quot;&gt;목차&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#인사말&quot;&gt;인사말&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#전통적인-rsync-방식의-한계와-파일-히스토리-기반-dr&quot;&gt;전통적인 rsync 방식의 한계와 파일 히스토리 기반 DR&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lustre-changelog&quot;&gt;Lustre Changelog&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#changelog의-동작-원리&quot;&gt;Changelog의 동작 원리&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#changelog-활성화-및-확인&quot;&gt;Changelog 활성화 및 확인&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#changelog_mask-이벤트-타입&quot;&gt;changelog_mask 이벤트 타입&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#changelog-읽기&quot;&gt;Changelog 읽기&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#글루시스-dr-솔루션&quot;&gt;글루시스 DR 솔루션&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#주요-특징&quot;&gt;주요 특징&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#시스템-구성&quot;&gt;시스템 구성&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#시스템-아키텍처&quot;&gt;시스템 아키텍처&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#컴포넌트별-상세-기능&quot;&gt;컴포넌트별 상세 기능&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#동작-원리&quot;&gt;동작 원리&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#1-이벤트-수집-단계&quot;&gt;1. 이벤트 수집 단계&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#2-동기화-처리-단계&quot;&gt;2. 동기화 처리 단계&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#3-이벤트-처리-상태-관리&quot;&gt;3. 이벤트 처리 상태 관리&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#4-예상치-못한-종료-시-복구-메커니즘&quot;&gt;4. 예상치 못한 종료 시 복구 메커니즘&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#5-오류-처리-및-재시도-메커니즘&quot;&gt;5. 오류 처리 및 재시도 메커니즘&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dr-솔루션-등급-기준-및-시장-요구사항&quot;&gt;DR 솔루션 등급 기준 및 시장 요구사항&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#글루시스-dr-솔루션-테스트-결과&quot;&gt;글루시스 DR 솔루션 테스트 결과&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#테스트-결과-기반-rpo--rto-평가&quot;&gt;테스트 결과 기반 RPO / RTO 평가&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#마치며&quot;&gt;마치며&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;인사말&quot;&gt;인사말&lt;/h2&gt;

&lt;p&gt;2022년 10월 15일 발생한 SK C&amp;amp;C 데이터센터 화재와 2025년 9월 26일 국가정보자원관리원 데이터센터 화재 사례에서 보듯이, 예기치 못한 재난 상황에서도 시스템이 정상적으로 운영되기 위해서는 데이터 손실을 최소화할 수 있는 효율적인 백업 및 복구 전략이 필수적입니다.&lt;/p&gt;

&lt;p&gt;데이터센터에서의 재해 복구(Disaster Recovery) 계획에서 RPO(Recovery Point Objective)&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;는 가장 중요한 지표 중 하나로, RPO가 짧을수록 재난 발생 시 보호할 수 있는 데이터의 범위가 넓어져 비즈니스 연속성을 보다 안정적으로 보장할 수 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 Lustre와 같은 대용량 분산 파일시스템 환경에서는 전체 데이터를 주기적으로 동기화하는 기존 방식이 많은 시간과 자원을 요구한다는 한계가 있습니다. 이러한 제약을 극복하기 위해 변경된 데이터만을 추적하고 동기화하는 방식을 적용하면, 동기화 시간을 크게 줄이고 RPO를 최소화할 수 있습니다.&lt;/p&gt;

&lt;p&gt;이번 블로그에서는 Lustre 파일시스템에서 파일 생성, 수정, 삭제와 같은 모든 메타데이터 변경 이벤트를 기록하는 Changelog&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; 기능과, 이를 기반으로 구현한 글루시스의 DR 솔루션을 소개합니다.&lt;/p&gt;

&lt;p&gt;이전에 제가 작성한 블로그 &lt;a href=&quot;https://tech.gluesys.com/blog/2025/03/13/Lustre_FID_1.html&quot;&gt;Lustre_FID_1&lt;/a&gt;과 &lt;a href=&quot;https://tech.gluesys.com/blog/2025/09/01/Lustre_FID_2.html&quot;&gt;Lustre_FID_2&lt;/a&gt;에서 Lustre의 파일 생성 방식과 파일의 고유한 FID(File Identifier)로 관리하는 방식에 대해 다루었습니다. 해당 내용은 이번 블로그에서 설명하는 Changelog와 DR 솔루션의 동작 원리를 이해하는 데 도움이 되니 참고해 주시기 바랍니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;전통적인-rsync-방식의-한계와-파일-히스토리-기반-dr&quot;&gt;전통적인 rsync 방식의 한계와 파일 히스토리 기반 DR&lt;/h2&gt;

&lt;p&gt;DR을 구현하기 위해 전통적으로 사용되는 방식은 rsync&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;를 활용한 전체 스캔 기반 동기화입니다. 이 방식은 SSH 명령어 또는 SSH 데몬을 통해 실행할 수 있으며, 파일시스템 전체를 주기적으로 스캔하여 변경된 파일을 식별한 뒤 이를 동기화합니다.&lt;/p&gt;

&lt;p&gt;그러나 rsync 기반 동기화 방식은 파일시스템 전체를 스캔한 이후에야 동기화가 이루어지기 때문에, 파일시스템의 규모가 커질수록 스캔 시간이 선형적으로 증가하는 한계를 가집니다. 특히 Lustre와 같은 대규모 파일시스템에서는 동기화에 수십 시간이 소요될 수 있으며, 동기화 주기가 스캔 주기에 의존하게 되어 RPO를 최소화하는 데에도 제약이 발생합니다. 이러한 이유로, 대규모 파일시스템 환경에서 실시간에 가까운 DR을 구현하기에는 전통적인 rsync 방식만으로는 한계가 있습니다.&lt;/p&gt;

&lt;p&gt;이러한 한계를 극복하기 위한 대안으로, 파일 히스토리를 기반으로 한 DR 방식을 고려할 수 있습니다. 해당 방식은 파일시스템에서 발생한 변경 이력을 기반으로 수정된 파일 목록만 선별하여 동기화함으로써, 전체 파일시스템을 반복적으로 스캔하는 rsync 방식에 비해 스캔에 소요되는 시간을 크게 줄일 수 있습니다. 더 나아가 파일시스템 모니터링을 통해 변경된 파일 정보를 실시간에 가깝게 수집할 수 있다면, RPO를 최소화하는 고효율 DR 환경을 구현할 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;lustre-changelog&quot;&gt;Lustre Changelog&lt;/h2&gt;

&lt;p&gt;Lustre Changelog는 Lustre 파일시스템에서 발생하는 모든 메타데이터 변경 사항을 기록하는 기능입니다.&lt;br /&gt;
  파일 생성, 수정, 삭제, 권한 변경, 디렉토리 구조 변경 등과 같은 이벤트들이 시간 순서대로 기록되며, 이를 통해 파일시스템의 변경 이력을 추적할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/changelog_2.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changelog 동작 흐름:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changelog 등록&lt;/strong&gt;: Lustre 관리자가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changelog_register&lt;/code&gt;로 MDT(Metadata Target)에 Changelog를 등록합니다. 이 과정을 통해 해당 MDT에서 발생하는 메타데이터 변경 이벤트를 기록할 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;클라이언트 I/O 발생&lt;/strong&gt;: 클라이언트가 파일 생성, 수정, 삭제 등의 I/O 작업을 Lustre 파일시스템에 요청합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changelog 저장&lt;/strong&gt;: MDS(Metadata Server)가 클라이언트의 I/O 작업을 확인하고 처리한 후, 해당 이벤트를 Changelog로 MDT에 저장합니다. 각 이벤트는 타임스탬프, FID, 이벤트 타입 등의 정보와 함께 순차적으로 기록됩니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changelog 읽기 요청&lt;/strong&gt;: Changelog Reader(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs changelog&lt;/code&gt; 명령어 또는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llapi_changelog_recv()&lt;/code&gt; API)가 Changelog 내용을 확인하기 위해 읽기 요청을 보냅니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changelog 조회&lt;/strong&gt;: MDS가 MDT에서 Changelog를 가져와 읽기 요청에 대응할 데이터를 준비합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changelog 전달&lt;/strong&gt;: MDS가 조회한 Changelog 내용을 Changelog Reader에게 전달합니다. Reader는 이 정보를 활용하여 파일시스템 변경 이벤트를 실시간으로 추적하고 처리할 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;changelog의-동작-원리&quot;&gt;Changelog의 동작 원리&lt;/h3&gt;

&lt;p&gt;Changelog는 MDS에서 관리되며, 각 MDT별로 독립적으로 기록됩니다.&lt;br /&gt;
  클라이언트에서 메타데이터 변경 작업이 발생하면, MDS는 해당 작업을 처리한 후 Changelog에 이벤트를 기록합니다.&lt;/p&gt;

&lt;p&gt;Changelog는 내부적으로 순차적인 로그 파일 형태로 저장되며, 각 로그 엔트리는 다음과 같은 정보를 포함합니다:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;타임스탬프&lt;/strong&gt;: 이벤트 발생 시간&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;FID&lt;/strong&gt;: 변경된 파일 또는 디렉토리의 FID&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;이벤트 타입&lt;/strong&gt;: CREAT, UNLINK, RENME, SETATTR 등의 작업 유형&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;부가 정보&lt;/strong&gt;: 작업과 관련된 추가 메타데이터&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Changelog는 비동기적으로 기록되기 때문에 일반적인 파일시스템 작업 성능에는 거의 영향을 주지 않습니다. 다만, 활성화된 이벤트 타입이 많을수록 디스크 사용량이 증가할 수 있으므로, 실제로 필요한 이벤트만 선택적으로 활성화하는 것이 좋습니다.&lt;/p&gt;

&lt;h3 id=&quot;changelog-활성화-및-확인&quot;&gt;Changelog 활성화 및 확인&lt;/h3&gt;

&lt;p&gt;Changelog 기능을 사용하려면 먼저 MDS에서 Changelog를 활성화해야 합니다.&lt;br /&gt;
Changelog는 기본적으로 비활성화되어 있으며, 다음과 같이 활성화할 수 있습니다:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 1. Changelog 등록 (changelog_register)&lt;/span&gt;
lctl changelog_register &amp;lt;MDT_device&amp;gt;

&lt;span class=&quot;c&quot;&gt;# 2. Changelog 활성화 및 이벤트 타입 설정&lt;/span&gt;
lctl set_param mdd.&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.changelog_mask&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;CREAT UNLINK RENME SETATTR&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 3. Changelog 상태 확인&lt;/span&gt;
lctl get_param mdd.&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.changelog_mask
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;먼저 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changelog_register&lt;/code&gt;를 통해 MDT에 Changelog를 등록한 후, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changelog_mask&lt;/code&gt; 파라미터를 통해 기록할 이벤트 타입을 선택적으로 지정할 수 있습니다. 필요한 이벤트만 기록하도록 설정하면 디스크 사용량을 절약할 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;changelog_mask-이벤트-타입&quot;&gt;changelog_mask 이벤트 타입&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changelog_mask&lt;/code&gt;에서 사용할 수 있는 주요 이벤트 타입은 다음과 같습니다:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;파일 및 디렉토리 작업:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CREAT&lt;/strong&gt;: 파일 또는 디렉토리 생성&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;UNLINK&lt;/strong&gt;: 파일 또는 디렉토리 삭제&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;MKDIR&lt;/strong&gt;: 디렉토리 생성&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RMDIR&lt;/strong&gt;: 디렉토리 삭제&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RENME&lt;/strong&gt;: 파일 또는 디렉토리 이름 변경&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;파일 속성 및 메타데이터:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;SETATTR&lt;/strong&gt;: 파일 속성 변경 (권한, 소유자, 그룹 등)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SATTR&lt;/strong&gt;: 파일 속성 설정 (SETATTR과 유사하지만 세부 동작이 다름)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;XATTR&lt;/strong&gt;: 확장 속성(Extended Attribute) 설정 또는 변경&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;TRUNCATE&lt;/strong&gt;: 파일 크기 변경&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;파일 접근:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;OPEN&lt;/strong&gt;: 파일 열기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CLOSE&lt;/strong&gt;: 파일 닫기&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;HSM 관련:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;HSM&lt;/strong&gt;: HSM(Hierarchical Storage Management) 관련 작업 (파일 아카이빙, 복원 등)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;기타:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;MARK&lt;/strong&gt;: 마커 이벤트 (특정 시점을 표시하기 위한 이벤트)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ATIME&lt;/strong&gt;: 접근 시간 변경 (기본적으로 비활성화)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GXATR&lt;/strong&gt;: 확장 속성 접근 (기본적으로 비활성화)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;NOPEN&lt;/strong&gt;: 파일 열기 거부 (기본적으로 비활성화)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;일부 이벤트 타입(ATIME, GXATR, NOPEN 등)은 기본적으로 비활성화되어 있으며, 이러한 이벤트를 기록하려면 명시적으로 mask에 포함시켜야 합니다.&lt;br /&gt;
다만, 이러한 이벤트는 빈번하게 발생할 수 있어 디스크 사용량이 크게 증가할 수 있으므로 신중하게 선택해야 합니다.&lt;/p&gt;

&lt;h3 id=&quot;changelog-읽기&quot;&gt;Changelog 읽기&lt;/h3&gt;

&lt;p&gt;Changelog를 읽기 위해서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs changelog&lt;/code&gt; 명령어를 사용합니다:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 특정 MDT의 Changelog 읽기&lt;/span&gt;
lfs changelog &amp;lt;MDT_device&amp;gt;

&lt;span class=&quot;c&quot;&gt;# 특정 시점 이후의 Changelog 읽기&lt;/span&gt;
lfs changelog &amp;lt;MDT_device&amp;gt; &amp;lt;start_record&amp;gt;

&lt;span class=&quot;c&quot;&gt;# 실시간으로 Changelog 모니터링&lt;/span&gt;
lfs changelog &amp;lt;MDT_device&amp;gt; &lt;span class=&quot;nt&quot;&gt;--follow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Changelog는 순차적인 레코드 번호를 가지며, 특정 레코드 번호부터 읽어올 수 있습니다. 각 레코드는 다음과 같은 형식으로 출력됩니다:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;12345 08/01/2025 14:30:25 CREAT [0x200000007:0x1:0x0] /lustre/test/file.txt
12346 08/01/2025 14:30:26 MODIFY [0x200000007:0x1:0x1] /lustre/test/file.txt
12347 08/01/2025 14:30:27 UNLINK [0x200000007:0x1:0x1] /lustre/test/file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;각 레코드는 레코드 번호, 타임스탬프, 이벤트 타입, FID, 그리고 파일 경로(가능한 경우)를 포함합니다. 이 정보를 활용하여 특정 시점 이후의 변경 사항만 추출하거나, 특정 파일의 변경 이력을 추적할 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;글루시스-dr-솔루션&quot;&gt;글루시스 DR 솔루션&lt;/h2&gt;

&lt;p&gt;지금까지 Lustre의 Changelog 기능에 대해 소개해 보았는데요, 글루시스에서도 Lustre의 Changelog 기능을 적용한 DR 솔루션을 제공하고 있습니다.&lt;br /&gt;
  글루시스 DR 솔루션은 실시간으로 파일시스템 내 변경 사항을 추적해 원격 사이트에 동기화하는 기능을 제공합니다. &lt;br /&gt;
  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt;와 같은 전통적인 동기화 방식과 달리, 변경된 파일만 효율적으로 추적하고 복제하기 때문에 네트워크 트래픽과 처리 시간을 크게 절감할 수 있습니다.&lt;/p&gt;

&lt;h3 id=&quot;주요-특징&quot;&gt;주요 특징&lt;/h3&gt;

&lt;h4 id=&quot;효율적인-증분-동기화&quot;&gt;효율적인 증분 동기화&lt;/h4&gt;

&lt;p&gt;전체 파일시스템을 스캔하는 대신, Changelog를 통해 변경된 파일만 식별하여 동기화합니다. 이를 통해 대규모 파일시스템에서도 빠른 동기화가 가능하며, 네트워크 트래픽을 효율적으로 활용할 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;실시간-동기화&quot;&gt;실시간 동기화&lt;/h4&gt;

&lt;p&gt;이벤트 발생 즉시 처리되므로, 재해 발생 시 최신 데이터까지 복구할 수 있습니다. 또한 Changelog Index를 추적하여 시스템 재시작 후에도 중복 처리나 누락 없이 동기화를 계속할 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;안정적인-오류-처리&quot;&gt;안정적인 오류 처리&lt;/h4&gt;

&lt;p&gt;동기화 실패 시 상세한 오류 정보를 기록하고, 재시도 가능한 작업은 자동으로 재시도 큐에 추가하여 처리합니다. 실패한 파일 목록을 추적하여 관리자가 수동으로 처리할 수 있도록 지원합니다.&lt;/p&gt;

&lt;h4 id=&quot;파일-필터링-시스템&quot;&gt;파일 필터링 시스템&lt;/h4&gt;

&lt;p&gt;설정 파일의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;excludePatterns&lt;/code&gt;를 통해 불필요한 파일, 확장자를 동기화 대상에서 제외할 수 있습니다. 기본적으로 Vim 임시 파일(.swp, .swo, .swx)과 백업 파일(~)이 제외됩니다.&lt;/p&gt;

&lt;h3 id=&quot;시스템-구성&quot;&gt;시스템 구성&lt;/h3&gt;

&lt;p&gt;글루시스 DR 솔루션은 다음과 같은 기술 스택으로 구성됩니다&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;모니터링&lt;/strong&gt;&lt;br /&gt;
 실시간성이 중요한 모니터링 작업을 위해, 해당 컴포넌트는 C 언어로 구현되어 Lustre API를 직접 호출하여 이벤트를 수집합니다. &lt;br /&gt;
 이는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs changelog&lt;/code&gt;와 같은 사용자 레벨 도구를 통해 간접적으로 Changelog를 조회하는 방식보다, 호출-응답 지연을 최소화하고 불필요한 프로세스 오버헤드를 줄일 수 있어 성능과 리소스 효율 측면에서 유리하기 때문입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;이벤트 큐&lt;/strong&gt;&lt;br /&gt;
    Redis Stream&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;을 사용하여 이벤트를 비동기적으로 전달합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;원격 통신&lt;/strong&gt;&lt;br /&gt;
    gRPC&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;를 사용하여 타겟 서버와 통신합니다.&lt;br /&gt;
    gRPC는 google이 개발한 HTTP/2 기반의 고성능 RPC(Remote Procedure Call) 프레임워크로, 타입 안전성과 효율적인 직렬화를 제공합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;파일 동기화&lt;/strong&gt;&lt;br /&gt;
    SSH 기반 rsync를 사용하여 안전하고 효율적으로 파일을 전송합니다.&lt;br /&gt;
    rsync는 증분 동기화에 최적화된 도구로, 변경된 부분만 전송하여 네트워크 대역폭을 절약합니다. SSH를 통해 암호화된 안전한 전송을 보장합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;설정 관리&lt;/strong&gt;&lt;br /&gt;
    가독성이 좋고 다양한 프로그래밍 언어에서 쉽게 파싱할 수 있는 JSON 파일로 관리합니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;시스템-아키텍처&quot;&gt;시스템 아키텍처&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/changelog_DR.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;

&lt;p&gt;글루시스 DR 솔루션은 세 가지 주요 컴포넌트로 구성됩니다:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;모니터링 컴포넌트&lt;/strong&gt;&lt;br /&gt;
  Lustre Changelog를 실시간으로 모니터링하고 이벤트를 수집합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;소스 서버 컴포넌트&lt;/strong&gt;&lt;br /&gt;
  소스 서버에서 실행되며, 수집된 이벤트를 처리하고 동기화 작업을 수행합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;타겟 서버 컴포넌트&lt;/strong&gt;&lt;br /&gt;
  타겟 서버에서 실행되며, 원격에서 전송된 파일 작업 요청을 처리합니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이 세 컴포넌트는 Redis Stream을 통해 이벤트를 전달하고, gRPC를 통해 원격 파일 작업을 수행합니다.&lt;/p&gt;

&lt;h4 id=&quot;컴포넌트별-상세-기능&quot;&gt;컴포넌트별 상세 기능&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;모니터링 컴포넌트&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;MDT가 여러 개인 경우, 각 MDT별로 독립적인 프로세스로 동작합니다.&lt;/li&gt;
  &lt;li&gt;메인 스레드 1개와 서브 스레드 2개로 이루어진 멀티 스레드 구조입니다.
    &lt;ul&gt;
      &lt;li&gt;메인 스레드: MDT 상태를 모니터링하고 코드 내 리소스를 관리합니다.&lt;/li&gt;
      &lt;li&gt;모니터링 스레드: Lustre Changelog 이벤트를 수집합니다.&lt;/li&gt;
      &lt;li&gt;필터 스레드: 설정 파일에 정의된 필터링을 이용하여 Redis에 저장합니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Lustre Changelog 이벤트는 원본, create_modify, rename_delete 세 그룹으로 분류하여 저장합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;소스 서버 컴포넌트&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Redis Stream에서 이벤트를 가져와 처리합니다.
    &lt;ul&gt;
      &lt;li&gt;rsync를 통한 동기화 작업은 create_modify 그룹을 가져옵니다.&lt;/li&gt;
      &lt;li&gt;gRPC를 통한 동기화 작업은 rename_delete 그룹을 가져옵니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;MDT별 Changelog Index와 동기화 체크포인트를 관리합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;타겟 서버 컴포넌트&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;rename_delete 그룹에 속한 파일 목록에 있는 파일을 동기화합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;동작-원리&quot;&gt;동작 원리&lt;/h3&gt;

&lt;h4 id=&quot;1-이벤트-수집-단계&quot;&gt;1. 이벤트 수집 단계&lt;/h4&gt;

&lt;p&gt;모니터링 컴포넌트는 Lustre의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llapi_changelog_recv()&lt;/code&gt; API를 사용하여 파일시스템 변경 이벤트를 &lt;strong&gt;실시간으로 수집&lt;/strong&gt;합니다.&lt;br /&gt;
각 MDT(Metadata Target)별로 &lt;strong&gt;독립적인 프로세스&lt;/strong&gt;로 동작하며, 수집된 이벤트는 Redis Stream에 저장됩니다.&lt;/p&gt;

&lt;p&gt;이 과정에서 불필요한 파일(예: Vim 임시 파일, 백업 파일 등)은 설정 파일의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;excludePatterns&lt;/code&gt;를 통해 필터링되어 동기화 대상에서 제외됩니다.&lt;br /&gt;
또한 시스템 재시작 시 &lt;strong&gt;중복 처리를 방지&lt;/strong&gt;하기 위해, Redis에 저장된 마지막 처리 Changelog Index를 로드하여 해당 지점부터 이벤트 수집을 재개합니다.&lt;/p&gt;

&lt;p&gt;Lustre에서 수집되는 이벤트 타입은 내부적으로 &lt;strong&gt;두 개의 그룹&lt;/strong&gt;으로 분류하여 처리합니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;create_modify&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREAT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MKDIR&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLOSE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TRUNC&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SATTR&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MTIME&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;rename_delete&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RMDIR&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RENME&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UNLINK&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;왜 Redis Stream인가?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;실시간 DR 솔루션에서 이벤트 큐로 Redis Stream을 선택한 이유는 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;순서 보장의 중요성&lt;/strong&gt;&lt;br /&gt;
실시간 동기화 환경에서는 이벤트가 발생한 순서대로 처리되는 것이 매우 중요합니다.&lt;br /&gt;
예를 들어, 파일 생성 → 수정 → 삭제 순서가 뒤바뀔 경우 데이터 불일치가 발생할 수 있습니다.&lt;br /&gt;
Redis Stream은 시간 순으로 정렬된 로그 구조를 제공하여, 이벤트의 &lt;strong&gt;순차적 처리&lt;/strong&gt;를 보장합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;빈번한 이벤트 처리 성능&lt;/strong&gt;&lt;br /&gt;
대규모 Lustre 파일시스템 환경에서는 초당 수천 건 이상의 파일 변경 이벤트가 발생할 수 있습니다.&lt;br /&gt;
Redis Stream은 메모리 기반의 고성능 데이터 구조로, 이러한 빈번한 이벤트를 빠르게 수집하고 처리할 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;대량 이벤트 저장 및 관리&lt;/strong&gt;&lt;br /&gt;
파일시스템 변경 이벤트는 지속적으로 누적되며, 동기화 처리 지연 시 대량의 이벤트가 일시적으로 적재될 수 있습니다.&lt;br /&gt;
Redis Stream은 수백만 건 이상의 엔트리를 효율적으로 저장·관리할 수 있어, 피크 시간대의 이벤트 폭주 상황에서도 안정적인 처리가 가능합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Consumer Group을 통한 안전한 이벤트 처리&lt;/strong&gt;&lt;br /&gt;
Redis Stream의 Consumer Group 기능을 활용하면, 여러 소비자가 동일한 스트림을 안전하게 읽고 처리할 수 있습니다.&lt;br /&gt;
이를 통해 이벤트의 &lt;strong&gt;중복 처리나 누락 없이&lt;/strong&gt;, 작업을 여러 소비자에게 분산할 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;비동기 처리 및 버퍼링&lt;/strong&gt;&lt;br /&gt;
이벤트를 수집하는 모니터링 컴포넌트와 이를 처리하는 소스 서버 컴포넌트 간에는 처리 속도 차이가 발생할 수 있습니다.&lt;br /&gt;
Redis Stream은 이러한 속도 차이를 효과적으로 버퍼링하여, &lt;strong&gt;이벤트 손실 없는 안정적인 비동기 처리 구조&lt;/strong&gt;를 제공합니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Redis Stream 구조&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;수집된 이벤트는 처리 목적과 동기화 방식에 따라 여러 개의 Redis Stream으로 분리하여 관리됩니다. 이를 통해 이벤트 처리 흐름을 명확히 구분하고, 동기화 실패 시에도 효율적으로 재처리할 수 있도록 설계했습니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;원본 이벤트 스트림&lt;/strong&gt;&lt;br /&gt;
Lustre Changelog를 통해 수집한 파일 생성, 수정, 삭제 등의 이벤트를 &lt;strong&gt;가공 없이 그대로 저장&lt;/strong&gt;하는 스트림입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;rsync 동기화 이벤트 스트림&lt;/strong&gt;&lt;br /&gt;
원본 이벤트 스트림(1)에서 선별된 이벤트 중 &lt;strong&gt;rsync 기반 동기화 대상 이벤트 그룹&lt;/strong&gt;을 저장하는 스트림입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;gRPC 동기화 이벤트 스트림&lt;/strong&gt;&lt;br /&gt;
원본 이벤트 스트림(1)에서 선별된 이벤트 중 &lt;strong&gt;gRPC 기반 동기화 대상 이벤트 그룹&lt;/strong&gt;을 저장하는 스트림입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;rsync 재동기화 이벤트 스트림&lt;/strong&gt;&lt;br /&gt;
rsync 동기화 이벤트 스트림(2)에서 &lt;strong&gt;동기화에 실패한 이벤트 중 재처리가 필요한 이벤트&lt;/strong&gt;를 저장하는 스트림입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;gRPC 재동기화 이벤트 스트림&lt;/strong&gt;&lt;br /&gt;
gRPC 동기화 이벤트 스트림(3)에서 &lt;strong&gt;동기화에 실패한 이벤트 중 재처리가 필요한 이벤트&lt;/strong&gt;를 저장하는 스트림입니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;전체 구조 요약&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;event: 이벤트 타입 (CREATE, MODIFY, MKDIR, DELETE, RENAME)&lt;/li&gt;
  &lt;li&gt;path: 파일/디렉토리 절대 경로 (RENAME 시 원본 경로)&lt;/li&gt;
  &lt;li&gt;to_path: RENME 이벤트 시 변경될 경로&lt;/li&gt;
  &lt;li&gt;mdt: MDT 이름&lt;/li&gt;
  &lt;li&gt;index: Lustre Changelog index&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Redis
│
├── Streams (Redis Stream)
│   ├── rsync 동기화 이벤트 스트림
│   │   └── Entry: {event, path, mdt, index}
│   │
│   ├── gRPC 동기화 이벤트 스트림
│   │   └── Entry: {event, path, to_path, mdt, index}
│   │
│   ├── 원본 이벤트 스트림
│   │   └── Entry: {event, path, mdt, index}
│   │
│   ├── rsync 재동기화 이벤트 스트림
│   │   └── Entry: {event, path, mdt, index}
│   │
│   └── gRPC 재동기화 이벤트 스트림
│       └── Entry: {event, path, to_path, mdt, index}
│
├── Checkpoints (String)
│   ├── 마지막 처리된 rsync 동기화 이벤트 스트림 ID를 저장하는 Hash
│   │   └── Value: &quot;1234567890124-0&quot; 
│   │
│   └── 마지막 처리된 gRPC 동기화 이벤트 스트림 ID를 저장하는 Hash
│       └── Value: &quot;1234567890126-0&quot; 
│
└── Indexes (String)
    ├── 마지막 처리 이벤트의 Lustre Changelog Index를 저장하는 Hash
        └── Value: &quot;12350&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. 원본 이벤트 스트림 구조&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│  Entry ID: 1234567890123-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    │
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;CREATE&quot;                               │    │
│  │ path       │ &quot;/lustre/file.txt&quot;                     │    │
│  │ mdt        │ &quot;MDT0000&quot;                              │    │
│  │ index      │ &quot;12345&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. rsync 동기화 이벤트 스트림 구조&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│  Entry ID: 1234567890123-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    │
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;CREATE&quot; / &quot;MODIFY&quot; / &quot;MKDIR&quot;          │    │
│  │ path       │ &quot;/lustre/file.txt&quot;                     │    │
│  │ mdt        │ &quot;MDT0000&quot;                              │    │
│  │ index      │ &quot;12345&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Entry ID: 1234567890124-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    │
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;MODIFY&quot;                               │    │
│  │ path       │ &quot;/lustre/file2.txt&quot;                    │    │
│  │ mdt        │ &quot;MDT0001&quot;                              │    │
│  │ index      │ &quot;12346&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. gRPC 동기화 이벤트 스트림 구조&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│  Entry ID: 1234567890125-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    │
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;RENAME&quot;                               │    │
│  │ path       │ &quot;/lustre/old.txt&quot;                      │    │
│  │ to_path    │ &quot;/lustre/new.txt&quot;                      │    │
│  │ mdt        │ &quot;MDT0000&quot;                              │    │
│  │ index      │ &quot;12347&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Entry ID: 1234567890126-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    |
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;DELETE&quot;                               │    │
│  │ path       │ &quot;/lustre/file.txt&quot;                     │    │
│  │ to_path    │ &quot;&quot;                                     │    │
│  │ mdt        │ &quot;MDT0000&quot;                              │    │
│  │ index      │ &quot;12348&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;4. rsync 재동기화 이벤트 스트림&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│  Entry ID: 1234567890127-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    │
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;CREATE&quot;                               │    │
│  │ path       │ &quot;/lustre/retry_file.txt&quot;               │    │
│  │ mdt        │ &quot;MDT0000&quot;                              │    │
│  │ index      │ &quot;12349&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;5. gRPC 재동기화 이벤트 스트림&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│  Entry ID: 1234567890128-0                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Field      │ Value                                  │    │
│  ├─────────────────────────────────────────────────────┤    │
│  │ event      │ &quot;RENAME&quot;                               │    │
│  │ path       │ &quot;/lustre/old_retry.txt&quot;                │    │
│  │ to_path    │ &quot;/lustre/new_retry.txt&quot;                │    │
│  │ mdt        │ &quot;MDT0000&quot;                              │    │
│  │ index      │ &quot;12350&quot;                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-동기화-처리-단계&quot;&gt;2. 동기화 처리 단계&lt;/h4&gt;

&lt;p&gt;소스 서버 컴포넌트는 Redis Stream에서 이벤트를 읽어 이벤트 타입에 따라 적절한 동기화 방법을 선택하여 처리합니다.&lt;br /&gt;
  동기화는 이벤트 타입에 따라 두 가지 방식으로 나뉩니다:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;rsync를 통한 동기화&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;파일 생성이나 수정 이벤트의 경우, 대용량 데이터 전송에 최적화된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt;를 사용합니다. 소스 서버 컴포넌트는 변경된 파일 목록을 수집하고, SSH를 통해 타겟 서버로 파일을 복사합니다. 이 방식은 파일의 실제 데이터를 효율적으로 전송하는 데 적합합니다.&lt;/p&gt;

&lt;p&gt;동기화 과정은 다음과 같이 진행됩니다:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;이벤트 수집&lt;/strong&gt;: Redis Stream의 rsync 동기화 스트림에서 배치 크기만큼 가져와서 동기화 파일 목록을 생성합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;파일 존재 확인&lt;/strong&gt;: 각 파일의 존재 여부를 사전 확인하여 존재하지 않는 파일은 동기화 파일 목록에서 제거합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;임시 파일 생성&lt;/strong&gt;: 존재하는 파일들의 상대 경로를 rsync 동기화에 사용할 임시 파일에 추가합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;rsync 실행&lt;/strong&gt;: 생성된 임시 파일을 이용하여 rsync 동기화를 실행합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;결과 확인&lt;/strong&gt;: rsync 실행 후 실패 파일, 추가 변경 파일을 확인하여 재동기화가 필요한 파일들은 재동기화 스트림에 저장합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Index 업데이트&lt;/strong&gt;: 동기화 완료 후 Changelog Index를 업데이트합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;gRPC를 통한 동기화&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;파일명 변경이나 삭제 이벤트의 경우, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gRPC&lt;/code&gt;를 통해 타겟 서버 컴포넌트에 직접 요청합니다.&lt;br /&gt;
  타겟 서버 컴포넌트는 gRPC 요청을 받아 파일 이동, 삭제 등의 작업을 수행하며, 소스 서버와 타겟 서버 간의 경로 차이를 자동으로 변환하여 올바른 위치에 동기화합니다.&lt;/p&gt;

&lt;p&gt;gRPC를 통한 동기화 과정은 다음과 같습니다:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;이벤트 수집&lt;/strong&gt;: Redis Stream의 gRPC 동기화 스트림에서 배치 크기만큼 가져와서 동기화 파일 목록을 생성합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;gRPC 요청 전송&lt;/strong&gt;: 타겟 서버의 API를 호출하여 작업을 수행합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;파일 작업 실행&lt;/strong&gt;: 타겟 서버에서 파일 이동 또는 삭제를 수행합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;결과 반환&lt;/strong&gt;: 성공/실패 여부와 상세 오류 정보를 소스 서버에 반환합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;결과 확인&lt;/strong&gt;: 실패 파일 목록 중에서 재동기화가 필요한 파일들을 재동기화 스트림에 저장합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Index 업데이트&lt;/strong&gt;: 성공한 작업에 대해서만 Changelog Index를 업데이트합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;3-이벤트-처리-상태-관리&quot;&gt;3. 이벤트 처리 상태 관리&lt;/h4&gt;

&lt;p&gt;시스템 재시작이나 예기치 않은 장애 상황에서도 이벤트의 중복 처리나 누락을 방지하기 위해, 글루시스 DR 솔루션은 이벤트 처리 상태를 체계적으로 추적·관리합니다.
  이를 위해 두 가지 레벨의 상태 관리 메커니즘을 적용하여, 수집 단계부터 동기화 단계까지 안정적인 처리가 가능하도록 설계했습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MDT별 Changelog Index 관리&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;각 MDT에서 마지막으로 처리된 Changelog Index는 Redis에 해시(Hash) 형태로 저장되며, 해당 값은 MDT별로 독립적으로 관리됩니다.&lt;/p&gt;

&lt;p&gt;모니터링 컴포넌트는 시작 시 Redis에 저장된 각 MDT의 마지막 Changelog Index를 로드한 뒤, 해당 지점 이후부터 Changelog를 읽기 시작합니다. 예를 들어 MDT0000의 마지막 처리 Index가 12350인 경우, 다음 이벤트인 12351부터 Changelog를 읽어 이벤트 수집을 재개합니다.&lt;/p&gt;

&lt;p&gt;이와 같은 방식으로 동작함으로써, 시스템이 예기치 않게 종료되더라도 각 MDT별로 정확한 처리 지점부터 이벤트 수집을 재개할 수 있어, 중복 처리나 이벤트 누락 없이 안정적인 모니터링이 가능합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;동기화 인덱스 관리&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;소스 서버 컴포넌트는 Redis Stream에서 이벤트를 읽어 처리할 때, 마지막으로 처리된 Stream Entry ID를 체크포인트로 저장합니다.&lt;br /&gt;
  동기화 작업이 완료될 때마다 체크포인트는 갱신되며, 다음 동기화 작업 시 이 체크포인트 이후의 이벤트만 읽어 처리합니다.&lt;br /&gt;
  이를 통해 동기화 작업 중 장애가 발생하더라도, 재시작 시 이전에 처리된 이벤트를 다시 처리하지 않고 정확한 지점부터 동기화를 재개할 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;4-예상치-못한-종료-시-복구-메커니즘&quot;&gt;4. 예상치 못한 종료 시 복구 메커니즘&lt;/h4&gt;

&lt;p&gt;시스템 크래시, 네트워크 장애, 프로세스 강제 종료와 같은 &lt;strong&gt;예상치 못한 상황&lt;/strong&gt;으로 프로그램이 중단되더라도, 사전에 저장된 인덱스 정보를 활용하여 &lt;strong&gt;이전 작업을 이어서 수행할 수 있도록&lt;/strong&gt; 복구 메커니즘을 설계했습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;모니터링 컴포넌트 재시작&lt;/strong&gt;&lt;br /&gt;
MDT별로 저장된 인덱스를 로드하여, &lt;strong&gt;마지막으로 처리된 Changelog Index 이후의 이벤트만 수집&lt;/strong&gt;합니다.&lt;br /&gt;
이미 수집되어 Redis Stream에 저장된 이벤트는 다시 저장되지 않으므로, &lt;strong&gt;이벤트 중복 수집이 발생하지 않습니다.&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;소스 서버 컴포넌트 재시작&lt;/strong&gt;&lt;br /&gt;
Redis Stream에 저장된 &lt;strong&gt;동기화 체크포인트(Stream Entry ID)&lt;/strong&gt; 를 로드하여, 마지막으로 처리된 Entry ID 이후의 이벤트만 읽어 처리합니다.&lt;br /&gt;
동기화가 완료되지 않은 이벤트는 자동으로 재처리되어, 작업의 연속성이 보장됩니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;타겟 서버 컴포넌트 재시작&lt;/strong&gt;&lt;br /&gt;
gRPC 서버가 재시작되더라도, 소스 서버에서 재시도 요청을 전달하면 해당 요청을 정상적으로 처리할 수 있도록 설계되어 있습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이와 같은 &lt;strong&gt;이중 인덱스 관리 구조(MDT별 Changelog Index + Redis Stream 체크포인트)&lt;/strong&gt; 를 통해, 시스템이 어떤 단계에서 중단되더라도 &lt;strong&gt;정확한 처리 지점부터 이벤트 수집과 동기화를 재개&lt;/strong&gt;할 수 있습니다.&lt;br /&gt;
  이를 통해 중복 처리나 이벤트 누락 없이, 안정적인 DR 동작을 보장합니다.&lt;/p&gt;

&lt;h4 id=&quot;5-오류-처리-및-재시도-메커니즘&quot;&gt;5. 오류 처리 및 재시도 메커니즘&lt;/h4&gt;

&lt;p&gt;동기화 과정에서 발생하는 오류를 효율적으로 처리하기 위해 재시도 메커니즘을 구현했습니다.&lt;br /&gt;
  동기화에 실패한 파일 목록을 분석하여, 재시도 가능한 오류와 재시도 불가능한 오류를 구분합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;재시도 스트림을 통한 누락 방지&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;동기화 과정에서 실패한 이벤트는 재시도 가능 여부를 판단하여 적절히 처리됩니다.&lt;br /&gt;
  재시도 가능한 오류(일시적인 네트워크 오류, 파일 잠금, 타임아웃 등)는 rsync 재동기화 스트림과 gRPC 재동기화 스트림에 저장됩니다.&lt;/p&gt;

&lt;p&gt;다음 동기화 작업 시 일반 스트림과 재동기화 스트림의 이벤트를 함께 처리하여, 일시적인 문제로 실패한 파일들도 정상적으로 동기화됩니다.&lt;br /&gt;
  재동기화 스트림의 이벤트도 동일한 체크포인트 메커니즘을 통해 관리되므로, 재동기화 과정에서도 중복 처리가 발생하지 않습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;재시도 불가능한 오류 처리&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;재시도 불가능한 오류(예: 파일이 존재하지 않음, 권한 오류 등)는 상세한 오류 정보와 함께 로그에 기록되어 관리자가 수동으로 처리할 수 있도록 합니다.&lt;br /&gt;
  각 실패 이벤트에는 오류 메시지, 오류 코드, 재시도 가능 여부 등의 정보가 포함되어 있어 문제 진단이 용이합니다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;dr-솔루션-등급-기준-및-시장-요구사항&quot;&gt;DR 솔루션 등급 기준 및 시장 요구사항&lt;/h3&gt;

&lt;p&gt;아래 표는 시장에서 일반적으로 요구되는 &lt;strong&gt;재해 복구(DR) 솔루션의 등급 기준&lt;/strong&gt;을 정리한 것입니다.&lt;br /&gt;
본 기준은 RPO(Recovery Point Object)와 RTO(Recovery Time Object)&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;를 포함한 복구 목표 수준에 따라 업무 중요도를 구분하며,&lt;br /&gt;
이후 글루시스 DR 솔루션의 테스트 결과를 해당 기준에 대입하여 등급을 평가합니다.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;구분&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Platinum&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Gold&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Silver&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Bronze&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;대상 업무&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;기업의 생산, 판매 및 영업활동에 직접적인 영향을 주는 업무&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;기업의 대고객 서비스에 영향을 주는 업무&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;기업의 내부 운영에 영향을 주는 업무&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;기업의 내부 업무 지원을 위한 개발, 테스트 업무&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;RPO&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0에 근접&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0에 근접&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt; 2일&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt; 2일&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;RTO&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt; 3시간&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt; 24시간&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt; 7일&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&amp;lt; 30일&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;권장 거리&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;근거리 + 장거리&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;근거리, 장거리&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;근거리, 장거리&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;근거리, 장거리&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;권장 DR 형태&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;≤ 3 x 데이터센터&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2 x 데이터센터&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2 x 데이터센터&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2 x 데이터센터&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;권장 DR 솔루션&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;디스크 복제&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;디스크 복제&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;소프트웨어 복제&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;소프트웨어 복제, 백업&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;업무 성능 저하 허용 여부&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;불가&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;불가&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;허용&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;허용&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;글루시스-dr-솔루션-테스트-결과&quot;&gt;글루시스 DR 솔루션 테스트 결과&lt;/h3&gt;

&lt;p&gt;아래 표는 &lt;strong&gt;글루시스 DR 솔루션의 실제 테스트 결과&lt;/strong&gt;를 정리한 것입니다.&lt;br /&gt;
본 솔루션은 동기화 시 파일을 개별 처리하지 않고, &lt;strong&gt;여러 파일을 하나의 배치로 묶어 처리하는 배치 기반 동기화 방식&lt;/strong&gt;을 사용합니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;동기화 평균 시간&lt;/strong&gt;: 배치(파일 300개 기준)에 포함된 파일들을 실제로 동기화하는 데 소요된 시간&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;배치 대기 시간&lt;/strong&gt;: 파일 변경을 감지한 시점부터 동기화가 시작되기까지의 대기 시간&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;구분&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;파일 평균 사이즈&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;파일 수&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;처리 속도&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;동기화 평균 시간 (배치당 300개 파일 기준)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;배치 대기 시간&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;큰 파일&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;55MB&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;412 MB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;39s&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;19m 40s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;작은 파일&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;314KB&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10,000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;24.2 MB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0.32s&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;2m 42s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;테스트-결과-기반-rpo--rto-평가&quot;&gt;테스트 결과 기반 RPO / RTO 평가&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;파일 동기화&lt;/strong&gt;는 재해 복구 과정에서 &lt;strong&gt;가장 먼저 안정적으로 동작해야 하는 핵심 단계&lt;/strong&gt;입니다.&lt;br /&gt;
테스트 결과를 살펴보면, 글루시스 DR 솔루션은 데이터 변경을 실시간으로 감지하고 배치 단위로 동기화를 수행하여, 아래와 같은 시간 내에 동기화가 완료되는 것을 확인할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;작은 파일 중심의 업무 환경&lt;/strong&gt;에서는 약 &lt;strong&gt;3분 이내&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;대용량 파일이 주로 생성되는 업무 환경&lt;/strong&gt;에서도 약 &lt;strong&gt;20분 이내&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이는 장애 발생 시 데이터 손실이 거의 발생하지 않는 수준으로, &lt;strong&gt;실질적인 RPO가 0에 가깝게 유지됨&lt;/strong&gt;을 의미합니다.&lt;/p&gt;

&lt;p&gt;RTO는 기업의 시스템 구성과 운영 환경에 따라 차이가 있을 수 있으나, 실제 운영 시나리오를 기준으로 볼 때 &lt;strong&gt;수 시간에서 최대 하루 이내에 서비스 복구가 가능한 수준&lt;/strong&gt;으로 판단됩니다.&lt;/p&gt;

&lt;p&gt;앞서 정리한 시장 요구사항 등급 기준과 비교해보면, 글루시스 DR 솔루션은 &lt;strong&gt;Platinum 또는 Gold 등급 수준의 요구사항을 충족하는 DR 솔루션&lt;/strong&gt;에 해당한다고 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;이번 글에서는 대규모 Lustre 환경에서 전통적인 rsync 기반 DR 방식이 갖는 한계를 짚어보고, Lustre Changelog를 활용해 변경 이벤트를 추적·동기화하는 글루시스 DR 솔루션의 구조와 동작 원리를 소개했습니다. 또한 테스트 결과를 통해 배치 기반 동기화 환경에서도 RPO를 낮게 유지할 수 있음을 확인했습니다.&lt;/p&gt;

&lt;p&gt;다음 글에서는 ZFS의 스냅샷/복제 기능을 활용한 DR 방식과 Lustre 기반 접근 방식의 차이점을 비교해보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;각주&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;RPO : 재해 복구에서 허용 가능한 최대 데이터 손실 시간 &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Changelog : https://doc.lustre.org/lustre_manual.xhtml#lustre_changelogs &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;rsync : Unix/Linux 시스템에서 파일과 디렉토리를 효율적으로 동기화하는 유틸리티 - https://rsync.samba.org/ &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Redis Stream : Redis 5.0에서 도입된 데이터 구조로, 시간 순서대로 정렬된 로그 형태의 메시지 큐 - https://redis.io/docs/data-types/streams/ &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;gRPC : Google에서 개발한 고성능 오픈소스 RPC 프레임워크 - https://grpc.io/ &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;RTO : 업무의 복구 목표 시간 &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 28 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2025/11/28/Lustre_Changelog_DR.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2025/11/28/Lustre_Changelog_DR.html</guid>
        
        <category>Lustre</category>
        
        <category>Changelog</category>
        
        <category>DR</category>
        
        <category>rsync</category>
        
        <category>sync</category>
        
        <category>재해 복구</category>
        
        <category>Redis</category>
        
        <category>gRPC</category>
        
        <category>RPO</category>
        
        <category>RTO</category>
        
        <category>AI Storage</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Lustre의 파일 create &amp; open 과정 분석 - 2</title>
        <description>&lt;h2 id=&quot;들어가기-앞서&quot;&gt;들어가기 앞서&lt;/h2&gt;
&lt;p&gt;이번 블로그에서 설명할 내용은 지난 &lt;a href=&quot;https://tech.gluesys.com/blog/2025/03/13/Lustre_FID_1.html&quot;&gt;Lustre의 파일 create &amp;amp; open 과정 분석 -1&lt;/a&gt;의 후속 내용으로, 클라이언트에서 보낸 요청이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에서 처리되는 과정과 이후 클라이언트의 후속 처리 과정을 담고 있습니다. 
아래 그림에서 1번은 지난 1편 블로그의 내용이고, 2번은 본 편에서 설명할 내용입니다. 1편의 내용을 숙지하고, 2편을 보시면 전체 흐름을 이해하는 데 도움이 될 수 있습니다.
&lt;br /&gt;&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/lustre_software_stack.png&quot; alt=&quot;러스터의 전체적인 software stack&quot; width=&quot;800&quot; /&gt;
  &lt;br /&gt;
  &lt;em&gt;러스터의 전체적인 software stack&lt;/em&gt;
&lt;/p&gt;

&lt;h2 id=&quot;mds에서의-처리&quot;&gt;MDS에서의 처리&lt;/h2&gt;
&lt;p&gt;지난 1편에서 클라이언트의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;가 보낸 요청을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;가 받는 것을 확인하고 마무리 하였습니다.
이 요청을 받아 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;가 처리하는 과정의 첫 시작은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_reint_open&lt;/code&gt; 함수 입니다. 
해당 함수는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;로 부터 요청을 받으면 다음과 같은 로그 메세지를 출력합니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;am&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;going&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000007&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Melon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x20000a811&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cr_flag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;0100000000102&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;0100666&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg_flag&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;메시지를 살펴보면, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x20000a811:0x1:0x0&lt;/code&gt; FID를 가진 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Melon&lt;/code&gt;이라는 파일에 대한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open&lt;/code&gt; 요청임을 알 수 있습니다. 
그 다음 해당 파일에 대한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_object&lt;/code&gt; 가 존재하는지 찾는 과정이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_object_find&lt;/code&gt; 함수에 의해 수행됩니다. 
아래 코드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_object_find&lt;/code&gt; 함수 수행을 포함해 앞으로의 설명에 나오는 함수들 위주로 추린 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_reint_open&lt;/code&gt; 함수 코드입니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/mdt/mdt_open.c&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mdt_reint_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt_thread_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt_lock_handle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lhc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt_object_find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mti_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rr_fid1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fid_zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child_fid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENOENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENOENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;child&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt_object_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mti_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;child_fid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENOENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdo_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mti_env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt_object_child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                                    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rr_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdt_object_child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                                    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mti_spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mti_attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ERESTART&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;out:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;lustre_msg_set_transno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rq_repmsg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_object&lt;/code&gt;는 여러 계층으로 구성된 러스터의 디바이스들을 묶어 공통으로 관리하는 객체로 아래와 같은 구조체로 정의되어 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/include/lu_object.h&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/**
 * Layer in the layered object.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * Header for this object.
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_object_header&lt;/span&gt;           &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * Device for this layer.
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_device&lt;/span&gt;                  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo_dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * Operations for this object.
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_object_operations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo_ops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * Linkage into list of all layers.
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_head&lt;/span&gt;                   &lt;span class=&quot;n&quot;&gt;lo_linkage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * Link to the device, for debugging.
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_ref_link&lt;/span&gt;                 &lt;span class=&quot;n&quot;&gt;lo_dev_ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;현재 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Melon&lt;/code&gt; 이라는 파일은 신규로 생성하는 파일이어서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_object&lt;/code&gt;를  찾지 못하고, 결과값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ENOENT&lt;/code&gt;로 됩니다(위의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_reint_open&lt;/code&gt; 함수 코드에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result= -ENOENT&lt;/code&gt; 부분입니다.)
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_reint_open&lt;/code&gt; 함수는 결과값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ENOENT&lt;/code&gt;로 되면, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdt_object_new&lt;/code&gt;를 통해 신규로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_object&lt;/code&gt; 객체를 할당 및 초기화를 진행합니다. 
 초기화 시에  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Melon&lt;/code&gt; 파일의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_object&lt;/code&gt; 계층 구성은 아래와 같이 됩니다.&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;/assets/luobj_passthrough.jpg&quot; alt=&quot;러스터 디바이스 계층 구조&quot; width=&quot;400&quot; /&gt;
  &lt;br /&gt;
  &lt;em&gt;러스터 디바이스 계층 구조&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDD&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOD&lt;/code&gt;라는 새로운 계층이 MDT 하위에 구성되었는데, Lustre 공식 위키의 내용에 따르면  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDD(Metadata Device Driver)&lt;/code&gt;는  POSIX appliance 계층으로, 해당 semantics를 구현하기 위해 존재합니다. 
그리고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOD(Logical Object Device)&lt;/code&gt;는 러스터에서 쓰는 객체들을 어느 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDT&lt;/code&gt; 혹은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에 생성할지 결정하는 계층입니다. 
위와 같은 계층 구조로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_object&lt;/code&gt;가 정상적으로 만들어지면, 본격적으로 파일을 생성 및 열기 위한 작업이 수행됩니다. 
먼저 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdo_create&lt;/code&gt; 함수가 호출되는데, 이 함수는 결과적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_create&lt;/code&gt; 함수를 호출합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_create&lt;/code&gt;에서는 크게 다음과 같은 작업을 수행합니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;어느 OST에 해당 파일을 생성 할지에 대한 Hint 생성&lt;/li&gt;
  &lt;li&gt;POSIX의 하드 링크 관리를 위한 메타데이터 구성&lt;/li&gt;
  &lt;li&gt;앞선 Hint를 기반으로 파일을 생성할 OST 선택&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;위 작업과 관련된 함수 내 코드는 아래와 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre mdd/mdd_dir.c&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mdd_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md_op_spec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md_attr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mdd_object_make_hint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_pobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;son&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OBD_FAIL_CHECK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OBD_FAIL_LFSCK_BAD_PARENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_fid&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tfid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mdd_object_fid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mdd_pobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

                &lt;span class=&quot;n&quot;&gt;tfid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_oid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_linkea_prepare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;son&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tfid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_linkea_prepare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;son&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;n&quot;&gt;mdd_object_fid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mdd_pobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                                        &lt;span class=&quot;n&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_declare_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_pobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;son&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;def_acl_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acl_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_create_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mdd_pobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;son&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acl_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;def_acl_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hsm_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hint를 생성하는 작업은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_object_make_hint&lt;/code&gt; 함수가 수행하며, 관련된 힌트 정보들은 아래의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dt_allocation_hint&lt;/code&gt;  구조체에 저장합니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/include/dt_object.h&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/**
 * This is a general purpose dt allocation hint.
 * It now contains the parent object.
 * It can contain any allocation hint in the future.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dt_allocation_hint&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dt_object&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dah_parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;              &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dah_eadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;dah_eadata_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;dah_acl_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;__u32&lt;/span&gt;                   &lt;span class=&quot;n&quot;&gt;dah_mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;dah_append_stripes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt;                    &lt;span class=&quot;n&quot;&gt;dah_can_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;                    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dah_append_pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hint 정보는 해당 파일의 부모 디렉토리의 정보를 바탕으로 구성되며, 부모의 속성 및 striping 정책 등을 활용합니다. &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Hint가 구성되고 나면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_linkea_prepare&lt;/code&gt; 함수가 호출되어 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linkea_data&lt;/code&gt;를 구성합니다. 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linkea_data&lt;/code&gt;는 해당 파일이 어떤 디렉토리 하위에 무슨 이름으로 존재하는지를 담고 있는 구조체입니다. 
 러스터는 이를 활용해 POSIX의 하드 링크를 손쉽게 관리할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/include/lustre_linkea.h&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linkea_data&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * Buffer to keep link EA body.
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_buf&lt;/span&gt;           &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ld_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/**
         * The matched header, entry and its length in the EA
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_ea_header&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ld_leh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_ea_entry&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ld_lee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;ld_reclen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 두 가지 작업이 끝나면, 본격적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;를 선택하기 위한 과정을 수행합니다. 
실질적인 선택은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_declare_create&lt;/code&gt; 함수에서 이루어지는데, 일반적인 파일일 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lod_qos_prep_create&lt;/code&gt; 함수가 최종적으로 호출되게 됩니다. 해당 함수에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;를 선택하는 방법은 아래와 같이 구현되어 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/lod/lod_qos.c&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lod_qos_prep_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lod_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lu_attr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thandle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__u64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lod_comp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llc_ostlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op_array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 사용자가 지정한 OST에 할당&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;lod_comp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llc_ostlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lod_alloc_ost_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stripe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ost_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lod_comp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llc_stripe_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOV_OFFSET_DEFAULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 지정하지 않으면, 먼저 QoS 정책에 의해 할당&lt;/span&gt;
                        &lt;span class=&quot;cm&quot;&gt;/**
                         * collect OSTs and OSSs used in other mirrors whose
                         * components cross the ldo_comp_entries[comp_idx]
                         */&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lod_prepare_avoidance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;GOTO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put_ldts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

                        &lt;span class=&quot;n&quot;&gt;QOS_DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;collecting conflict osts for comp[%d]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                  &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;lod_collect_avoidance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

                        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lod_ost_alloc_qos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stripe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ost_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                               &lt;span class=&quot;n&quot;&gt;flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EAGAIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// QoS 할당 실패 시 라운드로빈 방식으로 할당&lt;/span&gt;
                                &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lod_ost_alloc_rr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stripe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                      &lt;span class=&quot;n&quot;&gt;ost_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                      &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 사용자가 지정한 offset에 맞춰 할당&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lod_ost_alloc_specific&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stripe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                    &lt;span class=&quot;n&quot;&gt;ost_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                                    &lt;span class=&quot;n&quot;&gt;comp_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;먼저 사용자가 지정한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;들이 있다면, 해당 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;들에 생성되도록 합니다(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lod_alloc_ost_list&lt;/code&gt;). 
만약 별도로 지정하지 않고 기본값을 쓰도록 한다면, 러스터는 자체 QoS 정책에 의해 먼저 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt; 선택을 시도하고(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lod_ost_alloc_qos&lt;/code&gt;), 
만약 QoS를 통한 할당이 실패한다면 라운드로빈 방식으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;를 선택합니다(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lod_ost_alloc_rr&lt;/code&gt;). 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llc_stripe_offset&lt;/code&gt; 값이 기본값이 아니면 사용자가 offset을 지정한 것으로, 이 경우에는 사용자의 요구 사항에 맞춰 선택됩니다(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lod_ost_alloc_specific&lt;/code&gt;).
offset은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs setstripe&lt;/code&gt; 명령어에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt; 옵션을 통해 지정할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lfs setstripe -i 3 -c 2 -S 1M &amp;lt;target path, directory or file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이렇게 선택된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에 대한 정보는 추후에 클라이언트가 접근할 때 필요로 하게 되는데, 이를 위해서 러스터는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lovea&lt;/code&gt;에 해당 정보를 저장하고 클라이언트에게 넘겨줍니다. 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lovea&lt;/code&gt;는 별도의 특별한 구조체는 아니고,  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lu_buf&lt;/code&gt;라는 러스터에서 일반적으로 쓰는 버퍼 구조체를 활용합니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_declare_create&lt;/code&gt; 작업이 완료되면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdd_create_object&lt;/code&gt;를 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에 보관이 필요한 메타데이터 객체를 생성하고, 클라이언트에게 응답 메시지를 보냅니다. 
이후는 해당 응답 메시지를 활용한 클라이언트 측의 후속 처리 과정에 대한 내용입니다.&lt;/p&gt;

&lt;h2 id=&quot;클라이언트에서의-후속처리&quot;&gt;클라이언트에서의 후속처리&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에서의 작업이 잘 수행되고 응답 메시지를 받으면 클라이언트에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_create_it&lt;/code&gt; 과정이 시작됩니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/lliste/namei.c&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ll_create_it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup_intent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__u32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_create_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IS_ERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;RETURN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR_ERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;d_instantiate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_create_it&lt;/code&gt;에서는 생성하려는 파일에 대해 메타데이터가 정상적으로 만들어졌기 때문에, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로부터 받은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lovea&lt;/code&gt;의 정보를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lov_stripe_md&lt;/code&gt; 구조체에 옮긴 다음, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inode&lt;/code&gt;에 업데이트합니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lov_stripe_md&lt;/code&gt; 구조체의 형태는 아래와 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/lov/lov_object.c&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lov_stripe_md&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;atomic_t&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;lsm_refc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;spinlock_t&lt;/span&gt;      &lt;span class=&quot;n&quot;&gt;lsm_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pid_t&lt;/span&gt;           &lt;span class=&quot;n&quot;&gt;lsm_lock_owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* debugging */&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;cm&quot;&gt;/* maximum possible file size, might change as OSTs status
                 * changes, e.g. disconnected, deactivated
                 */&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;lsm_maxbytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;cm&quot;&gt;/* size of full foreign LOV */&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;lsm_foreign_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ost_id&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;lsm_oi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;lsm_magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;u32&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;lsm_layout_gen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;u16&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;lsm_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;lsm_is_released&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;u16&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;lsm_mirror_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;u16&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;lsm_entry_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lov_stripe_md_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lsm_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;그리고 최종 적으로 업데이트된 내용을 바탕으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VFS&lt;/code&gt;에게 기존 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dentry&lt;/code&gt; 경로에 새로운 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inode&lt;/code&gt;의 추가를 요청합니다.&lt;/p&gt;

&lt;p&gt;디버그 메시지 내에서 다음과 같이 저장된 정보를 출력해 주는 것을 확인할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;lsm&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00000000435&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c78ed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objid&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;43025&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxbytes&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7fffffffffffffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0BD10BD0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mirror&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout_gen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xffffffffffffffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0BD10BD0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;layout_gen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stripe&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sstripe&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1048576&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;oinfo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edee2c32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ostid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1186&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ost&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;해당 디버그 메시지를 통해서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Melon&lt;/code&gt;이라는 파일은 1번 OST(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ost idx:1&lt;/code&gt;)에 객체 ID 값 1186(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ostid: 0x0:1186&lt;/code&gt;)으로 지정되었음을 알 수 있습니다.&lt;/p&gt;

&lt;h2 id=&quot;ost-에서의-확인과정&quot;&gt;OST 에서의 확인과정&lt;/h2&gt;

&lt;p&gt;실제 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에서의 생성은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write&lt;/code&gt; 과정을 통해 이루어지는데, 해당 내용은 이번 분석 범위에 포함되지 않아 생략하도록 하겠습니다. 
대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Write&lt;/code&gt;를 통해 정상적으로 쓰였음을 가정하고, 위의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lov_stripe_md&lt;/code&gt;에 대한 디버그 메시지 내용대로 잘 생성되었음을 확인하는 과정에 대해 간단히 소개하겠습니다. 
그리고 추가로 러스터의 하위 파일 시스템으로 쓰는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ZFS&lt;/code&gt;에서도 확인하는 방법을 간단히 소개하고 마치도록 하겠습니다. &lt;br /&gt;&lt;br /&gt;
먼저 러스터에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs getstripe&lt;/code&gt; 명령어를 통해 다음과 같이 앞선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Melon&lt;/code&gt; 파일에 대한 정보 확인이 가능합니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs getstripe&lt;/code&gt;의 결과와 위 디버그 메세지의 결과를 비교해보면, 동일한 것을 확인하실 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# lfs getstripe Melon&lt;/span&gt;
Melon
lmm_stripe_count:  1
lmm_stripe_size:   1048576
lmm_pattern:       raid0
lmm_layout_gen:    0
lmm_stripe_offset: 1
        obdidx           objid           objid           group
             1            1186          0x4a2                0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;다음으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zfs&lt;/code&gt;에서 확인하기 위해서는, 우선 현재 1번 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;가 쓰고 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zpool&lt;/code&gt; 정보를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zpool list&lt;/code&gt;를 통해 알 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# zpool list&lt;/span&gt;
NAME          SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
ost_B         199G   426M   199G        -         -     0%     0%  1.00x    ONLINE  -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그다음 출력 내용 중 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zpool&lt;/code&gt;의 이름을  가지고,  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zfs&lt;/code&gt;에서 제공하는 디버깅 툴인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zdb&lt;/code&gt;에 인자로 넘겨주면 정보를 출력할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# zdb -e -dddd ost_B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; 옵션은 가끔 캐시 정보로 인해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zdb&lt;/code&gt; 정보가 정상적으로 출력되지 않는 문제가 발생하는데, 이를 해결하기 위해 캐시를 참조하지 않게끔 하는 옵션입니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zdb&lt;/code&gt;가 정상적으로 수행되면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ost_B&lt;/code&gt;에 대한 정보가 출력되는데, 여기서 앞선 객체 ID 값(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1186&lt;/code&gt;)에 대한 정보를 찾을 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    Object  lvl   iblk   dblk  dsize  dnsize  lsize   %full  type
       902    2   128K    16K    35K      1K    32K  100.00  ZFS directory
                                               152   bonus  System attributes
    dnode flags: USED_BYTES USERUSED_ACCOUNTED USEROBJUSED_ACCOUNTED
    dnode maxblkid: 1
    uid     0
    gid     0
    atime   Thu Jan  1 09:00:00 1970
    mtime   Thu Jan  1 09:00:00 1970
    ctime   Thu Jan  1 09:00:00 1970
    crtime  Wed Jan 22 11:04:17 2025
    gen 63
    mode    40755
    size    0
    parent  896
    links   0
    pflags  800000000000
    rdev    0x0000000000000000
    Fat ZAP stats:
        Pointer table:
            1024 elements
            zt_blk: 0
            zt_numblks: 0
            zt_shift: 10
            zt_blks_copied: 0
            zt_nextblk: 0
        ZAP entries: 2
        Leaf blocks: 1
        Total blocks: 2
        zap_block_type: 0x8000000000000001
        zap_magic: 0x2f52ab2ab
        zap_salt: 0x1859bddd
        Leafs with 2^n pointers:
              9:      1 *
        Blocks with n*5 entries:
              0:      1 *
        Blocks n/10 full:
              1:      1 *
        Entries with n chunks:
              3:      2 **
        Buckets with n entries:
              0:    510 ****************************************
              1:      2 *
        1186 = 338 (type: Regular File)
        2 = 964 (type: Regular File)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 메시지에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1186&lt;/code&gt;은 러스터에서의 객체 ID 값이고, 뒤의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;338&lt;/code&gt;은 이에 해당하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zfs&lt;/code&gt;에서의 객체 ID 값입니다. 
실제로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;338&lt;/code&gt;에 대한 값을 찾아보면 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    Object  lvl   iblk   dblk  dsize  dnsize  lsize   %full  type
       338    1   128K     4K      0     512     4K    0.00  ZFS plain file
                                               312   bonus  System attributes
    dnode flags: USERUSED_ACCOUNTED USEROBJUSED_ACCOUNTED
    dnode maxblkid: 0
    uid     0
    gid     0
    atime   Thu Aug 14 15:42:43 2025
    mtime   Thu Aug 14 15:42:43 2025
    ctime   Thu Aug 14 15:42:43 2025
    crtime  Thu Aug 14 15:41:47 2025
    gen 2247042
    mode    107666
    size    0
    parent  902
    links   1
    pflags  800000000000
    rdev    0x0000000000000000
    SA xattrs: 160 bytes, 2 entries
        trusted.lma = \010\000\000\000\000\000\000\000\000\000\001\000\001\000\000\000\242\004\000\000\000\000\000\000
        trusted.fid = \021\250\000\000\002\000\000\000\001\000\000\000\000\000\000\000\000\000\020\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;간단히 mtime 비교를 위한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; 명령어 조회 결과는 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ls -alh&lt;/span&gt;
total 200M
drwxr-xr-x 6 root     root      25K Aug 14 15:42 &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 root     root     100M Jan 23  2025 Pumpkin
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 root     root     100M Feb 10  2025 Apple
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 root     root        0 Aug 14 15:42 Melon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;mtime 비교는 조금 부족할 수 있어서, 실제 데이터를 가진 다른 파일로 추가 확인을 해보도록 하겠습니다. 현재 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Apple&lt;/code&gt; 이라는 파일을 열어보면 내부 데이터는 아래와 같습니다.
100M 파일이라, 편의상 일부 데이터만 옮겨 적었습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I have an apple
I have a pen
pineapple


I was a ghost, I was alone, hah
어두워진, hah, 앞길속에 (Ah)
Given the throne, I didn&apos;t know how to believe
I was the queen that I&apos;m meant to be
I lived two lives, tried to play both sides
But I couldn&apos;t find my own place
Called a problem child &apos;cause I got too wild
But now that&apos;s how I&apos;m getting paid, 끝없이 on stage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 파일을 먼저 동일하게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lfs getstripe&lt;/code&gt;로 확인해보면 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Apple
lmm_stripe_count:  1
lmm_stripe_size:   1048576
lmm_pattern:       raid0
lmm_layout_gen:    0
lmm_stripe_offset: 0
        obdidx           objid           objid           group
             0            1160          0x488                0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;현재 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;번 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obdidx:0&lt;/code&gt;)에 존재하고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objid&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1160&lt;/code&gt; 인것을 확인 할 수 있습니다. 이를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zdb&lt;/code&gt;를 통해 내용을 검색하면 다음과 같이 확인이 가능합니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    Object  lvl   iblk   dblk  dsize  dnsize  lsize   %full  type
       914    2   128K    16K    35K      1K    32K  100.00  ZFS directory
                                               152   bonus  System attributes
    dnode flags: USED_BYTES USERUSED_ACCOUNTED USEROBJUSED_ACCOUNTED
    dnode maxblkid: 1
    path    /O/0/d8
    uid     0
    gid     0
    atime   Thu Jan  1 09:00:00 1970
    mtime   Thu Jan  1 09:00:00 1970
    ctime   Thu Jan  1 09:00:00 1970
    crtime  Wed Jan 22 11:03:59 2025
    gen 61
    mode    40755
    size    0
    parent  896
    links   0
    pflags  800000000000
    rdev    0x0000000000000000
    Fat ZAP stats:
        Pointer table:
            1024 elements
            zt_blk: 0
            zt_numblks: 0
            zt_shift: 10
            zt_blks_copied: 0
            zt_nextblk: 0
        ZAP entries: 2
        Leaf blocks: 1
        Total blocks: 2
        zap_block_type: 0x8000000000000001
        zap_magic: 0x2f52ab2ab
        zap_salt: 0x16dde0e75
        Leafs with 2^n pointers:
              9:      1 *
        Blocks with n*5 entries:
              0:      1 *
        Blocks n/10 full:
              1:      1 *
        Entries with n chunks:
              3:      2 **
        Buckets with n entries:
              0:    510 ****************************************
              1:      2 *

        8 = 970 (type: Regular File)
        1160 = 348 (type: Regular File)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Apple&lt;/code&gt; 파일이 부여받은 러스터의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objid&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1160&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zfs&lt;/code&gt;에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;348&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;값을 가진 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object&lt;/code&gt;에 존재하는 것을 확인 할 수 있습니다.
이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;348&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object&lt;/code&gt; 의 정보를 동일 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zdb&lt;/code&gt; 결과 내에서 확인하면 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
    Object  lvl   iblk   dblk  dsize  dnsize  lsize   %full  type
       348    1   128K     8K  23.5K     512     8K  100.00  ZFS plain file
                                               192   bonus  System attributes
    dnode flags: USED_BYTES USERUSED_ACCOUNTED USEROBJUSED_ACCOUNTED SPILL_BLKPTR
    dnode maxblkid: 0
    path    /O/0/d8/1160
    uid     0
    gid     0
    atime   Thu Jan  1 09:00:00 1970
    mtime   Mon Aug 11 15:29:09 2025
    ctime   Mon Aug 11 15:29:09 2025
    crtime  Mon Aug 11 15:21:58 2025
    gen 1725358
    mode    100666
    size    7902
    parent  914
    links   1
    pflags  800000000000
    rdev    0x0000000000000000
    SA xattrs: 204 bytes, 3 entries

        trusted.lma = \010\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\210\004\000\000\000\000\000\000
        trusted.fid = \101\240\000\000\002\000\000\000\015\000\000\000\000\000\000\000\000\000\020\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
        trusted.version = \074\000\000\000\025\000\000\000

Spill block: 0:21003a8000:2000 200L/200P F=1 B=1725487/1725487 cksum=0000000463402dff:000001c2ded1efcc:00005d31e8e4d796:000d328f2dec511d
Indirect blocks:
               0 L0 0:2100040000:4000 2000L/2000P F=1 B=1725487/1725487 cksum=000002da23a8c5b2:000bf16a4d8e66fa:2022a6b4b0f36087:9e7ec08e337a8708

        segment [0000000000000000, 0000000000002000) size    8K

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object&lt;/code&gt; 정보를 활용해서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zfs&lt;/code&gt; 혹은 러스터에서 실제 데이터 확인이 가능한데, 러스터에서 추적하는 방법만 소개하도록 하겠습니다.&lt;/p&gt;

&lt;p&gt;위 정보에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path&lt;/code&gt; 정보가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/O/0/d8/1160&lt;/code&gt; 으로 나와있는 것을 확인 할 수 있습니다. 이를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt; 가 마운트된 경로에서 해당 파일을 열어보면 되는데,
기본적으로 러스터는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readonly&lt;/code&gt;로 마운트 되기 때문에 열어 볼 수 없습니다. 해서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zfs&lt;/code&gt; 스냅샷 기능을 활용해 스냅샷을 찍고 복제본을 만들어 마운트하면 확인이 가능합니다.
최종적으로 복제본이 마운트된 경로에 해당 파일을 열어보면 다음과 같이 확인이 가능합니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; # pwd
&amp;gt; /ost/ost_debug/O/0/d8
&amp;gt; # ls
&amp;gt; 1160  8
&amp;gt; cat 1160

I have an apple
I have a pen
pineapple


I was a ghost, I was alone, hah
어두워진, hah, 앞길속에 (Ah)
Given the throne, I didn&apos;t know how to believe
I was the queen that I&apos;m meant to be
I lived two lives, tried to play both sides
But I couldn&apos;t find my own place
Called a problem child &apos;cause I got too wild
But now that&apos;s how I&apos;m getting paid, 끝없이 on stage

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;
&lt;p&gt;지금까지 러스터의 디버그 메시지를 바탕으로, 러스터에서 하나의 파일을 생성하고 열 때의 과정을 소개하였습니다. 
러스터는 다양한 컴포넌트들이 분산 환경에서 동작하기 때문에 분석 과정에 많은 어려움이 있는데, 소개한 내용이 도움이 되셨길 바라며 마치도록 하겠습니다.&lt;/p&gt;

&lt;h2 id=&quot;참고-링크-및-자료&quot;&gt;참고 링크 및 자료&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;[1] &lt;a href=&quot;https://tech.gluesys.com/blog/2025/03/13/Lustre_FID_1.html&quot;&gt;Lustre의 파일 create &amp;amp; open 과정 분석 -1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;[2] &lt;a href=&quot;https://doc.lustre.org/lustre_manual.xhtml&quot;&gt;Lustre Software Release 2.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;[3] Braam, Peter., “The Lustre storage architecture.”, arXiv preprint arXiv:1903.01955, 2019&lt;/li&gt;
  &lt;li&gt;[4] Understanding Lustre Internals, https://wiki.lustre.org/Understanding_Lustre_Internals&lt;/li&gt;
  &lt;li&gt;[5] &lt;a href=&quot;https://github.com/lustre/lustre-release.git&quot;&gt;Lustre github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 01 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2025/09/01/Lustre_FID_2.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2025/09/01/Lustre_FID_2.html</guid>
        
        <category>Lustre</category>
        
        <category>File</category>
        
        <category>Metadata</category>
        
        <category>Data</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Lustre의 파일 create &amp; open 과정 분석 - 1</title>
        <description>&lt;h1 id=&quot;들어가기-앞서&quot;&gt;들어가기 앞서&lt;/h1&gt;
&lt;p&gt;이번 블로그에서 설명할 내용은 러스터를 활용하고 있는 환경에서 사용자가 새로운 파일을 생성하면, 내부적으로 이루어지는 과정을 분석한 내용을 담고 있습니다.
 본 내용은 러스터의 전반적인 구조에 대해 기본적으로 알고 있는 것으로 가정하고 기술하고 있어서, 러스터의 구조가 궁금하신 분들은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lustre 파일시스템과 GPUDirect Storage 소개&lt;/code&gt;[1] 글을 참고하실 수 있습니다.
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;또한 러스터에서 새로운 파일의 생성은 다양한 컴포넌트들의 상호작용에 의해 이루어지기 때문에, 총 2편에 걸쳐 설명할 예정입니다.
1편에서는 전체적인 흐름을 간략하게 소개하기 위해 러스터의 software stack 및 분석에 활용될 러스터 디버그 시스템에 대한 소개 후, 러스터 클라이언트에서
러스터 서버로 요청을 보내는 부분까지 서술할 예정입니다. 그리고 이어서 2편에서는 러스터 서버에서의 처리 과정과, 서버에서 처리한 내용을 바탕으로 실제
데이터가 쓰일 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST(Object Storage Target)&lt;/code&gt;에 접근하는 과정을 서술할 예정입니다.&lt;/p&gt;

&lt;h2 id=&quot;lustre-software-stack&quot;&gt;Lustre software stack&lt;/h2&gt;
&lt;p&gt;러스터 소프트웨어 스택은 아래 그림과 같이 여러 계층으로 구성되어 있습니다. 해당 그림에서 화살표는 클라이언트에서 러스터 서버로의 요청 흐름을 나타냅니다.
최초 클라이언트에서 실행된 POSIX  시스템 콜은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VFS&lt;/code&gt; 계층을 거쳐 러스터의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE(Lustre LITE)&lt;/code&gt; 계층으로 이동합니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt;는 해당 요청이 메타데이터에 대한 접근이 필요한 경우 먼저 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LMV(Logical Metadata Volume)&lt;/code&gt; 계층으로 요청을 보냅니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LMV&lt;/code&gt; 계층은 단일 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDT(Meta Data Target)&lt;/code&gt; 구조일 경우에는
별다른 역할을 수행하지 않지만, 하나 이상의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDT&lt;/code&gt;를 사용하는 구조에서는 사용자의 요청을 분산하는 역할을 수행합니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;이후 직접적으로 러스터 서버의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS(Meta Data Server)&lt;/code&gt;와 통신하는  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC(Metadata Client)&lt;/code&gt;로 요청이 보내지고, 최종적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;가 러스터 서버의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에 요청하게 됩니다. &lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt;에 들어온 요청이 메타데이터가 아니고 데이터에 대한 요청이라면, 해당 요청을 어느 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;로 보낼지 선택하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOV(Logical Object Volume)&lt;/code&gt; 계층으로 전달됩니다. 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOV&lt;/code&gt;는 현재 러스터에 존재하는 클라이언트 수만큼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OSC(Object Storage Client)&lt;/code&gt;를 보유하고, 각 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OSC&lt;/code&gt;를 통해 해당하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에 접근이 가능합니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/lustre_software_stack.png&quot; alt=&quot;Alt text&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; 러스터의 전체적인 software stack &amp;#62;&lt;/center&gt;

&lt;p&gt;만약 클라이언트에서 파일을 열고 내용을 읽으려고 한다면, 먼저 POSIX를 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OPEN&lt;/code&gt; 시스템 콜이 호출됩니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt;는 해당 파일을 열기 위해서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에 정보를 요청해야 하므로, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LMV&lt;/code&gt;,&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;를 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;와 통신해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Layout EA&lt;/code&gt; 정보를 받아오게 됩니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Layout EA&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Layout Extended Attributes&lt;/code&gt;의 약자로, 러스터에서 파일의 레이아웃을 관리하기 위한 자료구조입니다. 이 자료구조는 파일을 식별하기 위한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID(File Identifiers)&lt;/code&gt; 정보와
어느 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에 존재하는지에 대한 정보가 존재합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로 받은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Layout EA&lt;/code&gt;를 통해 클라이언트는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOV&lt;/code&gt;,&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OSC&lt;/code&gt;를 거쳐
최종적으로 해당 데이터 블럭이 존재하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에 접근해 데이터를 읽거나 쓰게 됩니다.&lt;/p&gt;

&lt;p&gt;다음 내용부터는 러스터에서 새로운 파일을 생성할 때, 위의 software stack에서 어떠한 작업이 이루어지는지를 추적할 방법을 소개한 다음, 클라이언트에서부터 과정을 서술할 예정입니다.&lt;/p&gt;

&lt;h2 id=&quot;how-to-lustre-debugging&quot;&gt;How to lustre debugging&lt;/h2&gt;
&lt;p&gt;본격적인 내용에 앞서, 해당 내용은 러스터에서 제공하는 디버그 메세지를 바탕으로 작성되었습니다.
실제 러스터를 구축하고, 본문의 내용을 검증하고자 할 때 활용할 수 있도록, 간단히 소개하겠습니다.&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;debug-설정&quot;&gt;debug 설정&lt;/h3&gt;
&lt;p&gt;러스터에서는 다양한 디버그 메세지들을 분류해 두었기 때문에, 원하는 분류의 메세지만 출력하도록 설정하는 것이 가능합니다.
현재 설정 가능한 분류는 다음과 같습니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;trace inode super iotrace malloc cache info ioctl neterror net warning buffs other
dentry nettrace page dlmtrace error emerg ha rpctrace vfstrace reada mmap config console quota sec lfsck hsm snapshot layout
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;설정 방법은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lctl&lt;/code&gt;명령어를 활용하여 설정이 가능하며, 다음과 같습니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 단일 분류 설정&lt;/span&gt;
lctl set_param &lt;span class=&quot;nv&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;+inode

&lt;span class=&quot;c&quot;&gt;# 복수 분류 설정&lt;/span&gt;
lctl set_param &lt;span class=&quot;nv&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;+inode,iotrace, ...

&lt;span class=&quot;c&quot;&gt;# 모든 분류 설정&lt;/span&gt;
lctl set_param &lt;span class=&quot;nv&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;+all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;한 번에 모든 설정들을 제거하고자 할 때는  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+all&lt;/code&gt; 대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-all&lt;/code&gt;로 설정해 주면 됩니다.
설정이 잘 적용되었는지는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lctl get_param debug&lt;/code&gt;로 가능하며, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-all&lt;/code&gt;로 모든 설정들을 제거하여도
 몇 가지 기본적인 설정들을 제외한 나머지가 제거됩니다. 기본 설정 리스트는 다음과 같습니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;warning error emerg console
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;subsystem-별-debug-설정&quot;&gt;subsystem 별 debug 설정&lt;/h3&gt;
&lt;p&gt;러스터는 메세지뿐만 아니라 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subsystem&lt;/code&gt; 별로 디버그 메세지의 분류가 가능합니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subsystem&lt;/code&gt;은 몇 가지를 제외하면 커널 내의 러스터 모듈들을 의미합니다. 
따라서 원하는 모듈만 선택적으로 디버깅이 가능합니다. 러스터에서 지원하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subsystem&lt;/code&gt;은 다음과 같습니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;all_subs, undefined, mdc, mds, osc, ost, class, log, llite, rpc, mgmt, lnet, lnd, pinger, filter, libcfs, echo, ldlm, lov, lquota, osd, lfsck, snapshot, lmv, sec, gss, mgc, mgs, fid, fld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subsystem&lt;/code&gt; 설정도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lctl&lt;/code&gt; 명령어로 가능하며, 방법은 다음과 같습니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 단일 subsystem 설정&lt;/span&gt;
lctl set_param &lt;span class=&quot;nv&quot;&gt;subsystem_debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mds&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 복수 subsystem 설정&lt;/span&gt;
lctl set_param &lt;span class=&quot;nv&quot;&gt;subsystem_debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mds mdc ost llite ...&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 모든 subsystem 설정&lt;/span&gt;
lctl set_param &lt;span class=&quot;nv&quot;&gt;subsystem_debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;모든 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subsystem&lt;/code&gt;을 비활성화하려면  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1&lt;/code&gt; 대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;으로 설정하시면 됩니다.
 설정이 잘 되었는지는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lctl get_param subsystem_debug&lt;/code&gt; 명령어로 가능하며, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;으로 설정했을 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subsystem_debug=0&lt;/code&gt;으로 결과가 출력됩니다. &lt;br /&gt;&lt;/p&gt;

&lt;h1 id=&quot;클라이언트의-최초-처리-과정&quot;&gt;클라이언트의 최초 처리 과정&lt;/h1&gt;
&lt;p&gt;러스터는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt; 계층을 활용해 POSIX로 들어온 요청을 러스터에 맞게 변환해서 활용하고 있습니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VFS&lt;/code&gt; 계층은 실제 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Underlying&lt;/code&gt; 파일 시스템에 맞는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Open&lt;/code&gt; 함수를 호출하는데, 아래 코드 블럭에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;atomic_open&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dir-&amp;gt;i_op-&amp;gt;atomic_open&lt;/code&gt; 입니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// fs/namei.c&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* Handle the last step of open() */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do_last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameidata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;got_write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lookup_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameidata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;got_write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;....&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir_inode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i_op&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atomic_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;atomic_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlikely&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENOENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;atomic_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameidata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;umode_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DENTRY_NOT_SET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1UL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d_inode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O_EXCL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_CREAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* both O_EXCL and O_CREAT */&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O_TRUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOOKUP_DIRECTORY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_DIRECTORY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DENTRY_NOT_SET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mnt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i_op&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atomic_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                       &lt;span class=&quot;n&quot;&gt;open_to_namei_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                                       &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;d_lookup_done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 코드가 수행되면 아래의 코드와 같이 러스터 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt; 계층의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_dir_inode_operations&lt;/code&gt;에 정의된 함수인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt;이 호출됩니다.&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/llite/namei.c&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode_operations&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_dir_inode_operations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mknod&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_mknod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atomic_open&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_atomic_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_lookup_nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_create_nd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Open&lt;/code&gt; 과정에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt;의 시작 지점은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt; 함수입니다.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt; 함수부터는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inode&lt;/code&gt;나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dentry&lt;/code&gt;와 같이
일반적인 파일 시스템에 관한 메타데이터 대신 러스터에서 활용하는 메타데이터들로 요청을 처리합니다.
여러 종류의 메타데이터가 존재하지만,  제일 먼저 활용되는 메타데이터는 앞서 언급된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt; 입니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;는 러스터에서 파일이나 디렉토리를 식별하기 위한 메타데이터로, 다음과 같이 정의되어 있습니다.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C&quot;&gt;// lustre/include/uapi/linux/lustre/lustre_user.h
struct lu_fid {
       /**
        * FID sequence. Sequence is a unit of migration: all files (objects)
        * with FIDs from a given sequence are stored on the same server.
        * Lustre should support 2^64 objects, so even if each sequence
        * has only a single object we can still enumerate 2^64 objects.
        **/
        __u64 f_seq;
        /* FID number within sequence. */
        __u32 f_oid;
        /**
         * FID version, used to distinguish different versions (in the sense
         * of snapshots, etc.) of the same file system object. Not currently
         * used.
         **/
        __u32 f_ver;
} __attribute__((packed));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;의 구성은 sequence 번호(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_seq&lt;/code&gt;), object id(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_oid&lt;/code&gt;), version(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_ver&lt;/code&gt;)으로 구성되어 있습니다.
sequence 번호는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로부터 부여받고,  object id는 동일한 sequence 번호에 새로운 파일이 생성되면 순차적으로 증가하며,
version은 버전 관리를 위해 부여되는데 코드 내 주석에서 현재 쓰이지 않는다고 되어있습니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;아래 디버그 메세지의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fid&lt;/code&gt;(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x200000bd2:0x1:0x0&lt;/code&gt;)를 예로 들면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_seq = 0x200000bd2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_oid = 0x1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_ver = 0x0&lt;/code&gt;이 됩니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;VFS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000bd2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c19f0c4c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000000027&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a7ccd5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8941&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;81&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opened&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;이 메세지는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt;라는 파일을 열고자 할 때, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt; 함수에서 기록되는 러스터 디버그 메세지입니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x200000bd2:0x1:0x0&lt;/code&gt; 라는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;를 가진 디렉토리의 하위에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt; 라는 파일을 열려고 하고 있습니다. 이때의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;는
아직 새로운 파일에 대한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;가 아직 할당되지 않았기 때문에, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt;에 대한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;는 아직 존재하지 않습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt; 함수가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VFS&lt;/code&gt;로부터 요청을 넘겨 받으면 먼저 파일을 단순히 열기만 하는지, 아니면 새로운 파일을 생성하고 여는지 확인합니다.
단순 파일 열기라면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IT_OPEN&lt;/code&gt; 플래그만 설정하고, 그게 아니라 파일 생성 후에 여는 작업이라면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O_CREAT&lt;/code&gt; 플래그 값까지 설정합니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;이 후 수행하는 작업은 크게 2가지 입니다. 첫 번째는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_lookup_it&lt;/code&gt; 이고 두 번째는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_create_it&lt;/code&gt; 입니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_lookup_it&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에 해당 파일이 존재하는지 찾고, 없다면 관련 메타데이터 생성까지 요청한 후, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_create_it&lt;/code&gt; 에서 쓸 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout EA&lt;/code&gt; 메타데이터를 요청하는 작업까지 수행합니다.
그리고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_create_it&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_lookup_it&lt;/code&gt;의 수행 결과로 받은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout EA&lt;/code&gt; 를 가지고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt;에 실제 파일을 만드는 작업을 수행합니다.&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lustre/llite/namei.c&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/*
 * For cached negative dentry and new dentry, handle lookup/create/open
 * together.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ll_atomic_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;n&quot;&gt;umode_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_last_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup_intent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOOKUP_OPEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it_op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IT_OPEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_CREAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it_op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IT_CREAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;lookup_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOOKUP_CREATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

        &lt;span class=&quot;cm&quot;&gt;/* Dentry added to dcache tree in ll_lookup_it */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;de&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_lookup_it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pca&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IS_ERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PTR_ERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;de&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;CFS_FAIL_TIMEOUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OBD_FAIL_LLITE_CREATE_FILE_PAUSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cfs_fail_val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it_disposition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DISP_OPEN_CREATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;cm&quot;&gt;/* Dentry instantiated in ll_create_it. */&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ll_create_it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                          &lt;span class=&quot;n&quot;&gt;encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                          &lt;span class=&quot;n&quot;&gt;open_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;ll_security_release_secctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;llcrypt_free_ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encctxlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;out_release:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ll_intent_release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;OBD_FREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;RETURN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt;의 첫 번째 처리 과정인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_lookup_it&lt;/code&gt; 함수를 살펴보기 전에, 먼저 함수 이름에 사용된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;it&lt;/code&gt;에 대해 간단히 설명하고 넘어가도록 하겠습니다.
함수 명의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;it&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intent&lt;/code&gt;를 의미합니다. 러스터에서는 클라이언트의 요청이 네트워크를 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로 전달되어 처리가 되기 때문에,
네트워크 요청을 최소화하기 위해서 한번 요청에 필요한 여러 작업을 전달하려고 이와 같은 방식을 쓰고 있습니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;다시 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_lookup_it&lt;/code&gt;로 돌아오면, 현재 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt;라는 파일은 새로 생성하려는 파일이므로 아래와 같은 디버그 메세지가 출력 됩니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ll_atomic_open&lt;/code&gt; 함수에서의 디버그 메세지와 동일하게 생성하려는 파일명, 부모 디렉토리의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt; 가 출력되었고, 수행할 작업(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intent&lt;/code&gt;)이 추가로 출력되어 있습니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;VFS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000bd2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;00000000&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c19f0c4c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;creat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이와 같이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에서 수행할 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intent&lt;/code&gt;가 구성되면, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLITE&lt;/code&gt; 계층에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LMV&lt;/code&gt; 계층으로 넘어가게 됩니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LMV&lt;/code&gt;에서는 먼저 동시성을 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에 보낼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lock&lt;/code&gt;에 관한 요청 작업을 처리하는데, 여기에 앞선 파일 열기에 관한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intent&lt;/code&gt;를 포함 시킵니다.
이렇게 요청을 만들면, 클라이언트에서 하나의 요청만으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;가 수행이 필요한 모든 작업을 요청할 수 있게 됩니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;INTENT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOCK&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;creat&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drunk&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000bd2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이후 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LMV&lt;/code&gt;에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt; 파일을 위한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;를 할당받은 다음  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로 요청을 보내기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt; 계층으로 전달합니다.&lt;br /&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cli&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cli&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ClstAuto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MDT0000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mdc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ffff8e6499843800&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Allocated&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FID&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000bd2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3fe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;OPEN_INTENT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fid1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000bd2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fid2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x200000bd2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3fe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drunk&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mds&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;최종적으로 위와 같은 요청이 클라이언트의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;에서 서버의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로 전달되게 됩니다. 로그에 대해 간단히 설명하면,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClstAuto&lt;/code&gt;는 현재 러스터의 클러스터 볼륨명을 의미합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDT0000&lt;/code&gt; 은 클라이언트의 요청이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;가 0인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDT&lt;/code&gt;에 전달되는 것을 의미하고,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdc&lt;/code&gt;는 이 요청은 클라이언트의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdc&lt;/code&gt;가 보냄을 의미합니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt; 파일은  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[0x200000bd2:0x3fe:0x0]&lt;/code&gt; 이라는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;를 할당받았고,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt; 쪽에  이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;에 관해 요청한 것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OPEN_INTENT&lt;/code&gt; 입니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fid1&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt; 파일의 부모 디렉토리의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt;이고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fid2&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drunk&lt;/code&gt; 자신의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FID&lt;/code&gt; 입니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;의 요청은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PTLRPC&lt;/code&gt; 계층을 거쳐 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;로 보내지고, 러스터 서버측의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PTLRPC&lt;/code&gt; 계층의 데몬이 이를 받아서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt; 계층에게 넘겨주게 됩니다.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;이렇게 create &amp;amp; open 의 시작 부분인 클라이언트의 첫 처리 과정을 코드 레벨로 살펴보았습니다. 이후 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDC&lt;/code&gt;의 요청을 받아 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MDS&lt;/code&gt;에서 처리하는 과정 및 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OST&lt;/code&gt; 연동 내용은 2편에 이어서 진행하도록 하겠습니다.&lt;/p&gt;

&lt;h2 id=&quot;참고-링크-및-자료&quot;&gt;참고 링크 및 자료&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;[1] &lt;a href=&quot;https://tech.gluesys.com/blog/2022/07/22/lustre_GPU_Direct_Storage.html&quot;&gt;Lustre 파일시스템과 GPUDirect Storage 소개&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;[2] &lt;a href=&quot;https://doc.lustre.org/lustre_manual.xhtml&quot;&gt;Lustre Software Release 2.x&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;[3] Braam, Peter., “The Lustre storage architecture.”, arXiv preprint arXiv:1903.01955, 2019&lt;/li&gt;
  &lt;li&gt;[4] Understanding Lustre Internals, https://wiki.lustre.org/Understanding_Lustre_Internals&lt;/li&gt;
  &lt;li&gt;[5] &lt;a href=&quot;https://github.com/lustre/lustre-release.git&quot;&gt;Lustre github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 13 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2025/03/13/Lustre_FID_1.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2025/03/13/Lustre_FID_1.html</guid>
        
        <category>Lustre</category>
        
        <category>File</category>
        
        <category>Metadata</category>
        
        <category>Data</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>디자인 도구 Penpot(펜팟) 설치부터 활용까지</title>
        <description>&lt;h1 id=&quot;디자인-도구-penpot펜팟-설치부터-활용까지&quot;&gt;디자인 도구 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot(펜팟)&lt;/code&gt; 설치부터 활용까지&lt;/h1&gt;

&lt;p&gt;안녕하세요?&lt;br /&gt;
글루시스 웹 개발팀에서 근무하고 있는 이현태입니다.&lt;br /&gt;
프로젝트 개발 과정 중 애플리케이션 또는 웹페이지의 레이아웃과 요소를 보여주기 위해 사용되는 디자인의 시각적 표현 또는 프로토타입을 목업이라 합니다.&lt;br /&gt;
목업은 개발로 넘어가기 전에 애플리케이션 또는 웹사이트의 제품이나 디자인을 시각적으로 표현하는 것으로, 이러한 디자인 작업을 하는 도구인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot(펜팟)&lt;/code&gt;을 소개하고자 합니다.&lt;br /&gt;
Penpot은 오픈소스 프로그램으로, Figma와 유사한 기능을 제공합니다. 디자인 도구로써 다양한 기능을 제공하며, 디자인 프로젝트를 효율적으로 관리할 수 있습니다.&lt;br /&gt;
저는 완전한 제어와 보안을 위해 툴킷을 내부적으로 호스팅하는 것을 선호하기 때문에 Penpot을 자체적으로 호스팅하고 사용하면서 느꼈던 장단점들과 활용 방법을 소개하도록 하겠습니다.&lt;/p&gt;

&lt;h2 id=&quot;docker로-셀프-호스팅-구성하기&quot;&gt;Docker로 셀프 호스팅 구성하기&lt;/h2&gt;

&lt;p&gt;Penpot은 Elestio와 Docker로 설치가 가능합니다.&lt;br /&gt;
저는 Windows 환경에서 개발하기 때문에 도커 데스크톱(Docker Desktop)에서 WSL2(Linux용 Windows 하위 시스템, 버전 2)를 사용하도록 설정해 Linux 컨테이너를 실행하는 환경에서 설치를 하였습니다.&lt;br /&gt;
WSL2에서 별도로 Docker 인스턴스를 설치하고 실행할 수 있지만, 저는 초보자이기 때문에 Docker와 관련된 모든 설정과 작업을 CLI를 통해 작업할 자신이 없었습니다.&lt;br /&gt;
그러므로 여기서는 WSL2를 활성화하고 Linux를 설치한 뒤, Docker Desktop을 사용해 Penpot은 설치해 보도록 하겠습니다.&lt;br /&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;strong&gt;항목&lt;/strong&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;컨테이너(소프트웨어를 실행하는 데 필요한 모든 파일, 라이브러리, 설정 파일 등을 포함하는 패키지) 기반의 오픈소스 가상화 시스템&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Docker Desktop&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Windows 및 macOS 운영 체제에서 Docker를 쉽게 설치하고 사용할 수 있게 해주는 애플리케이션&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;WSL&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Windows 운영 체제에서 Linux 커널을 실행할 수 있게 해주는 기능&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;wsl2-활성화-후-windows에-linux를-설치&quot;&gt;WSL2 활성화 후 Windows에 Linux를 설치&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Windows - PowerShell - 관리자로 실행을 시켜줍니다.
  &lt;img src=&quot;/assets/penpot/images_1.JPG&quot; alt=&quot;images_1.JPG&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;PowerShell&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;WSL 기능 활성화
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;시스템 재부팅
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Restart-Computer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;WSL 버전을 WSL2로 설정
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--set-default-version&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;사용 가능한 배포판 목록 확인
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--online&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;원하는 Linux 배포판 설치
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ubuntu&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;WSL에 설치된 배보판 목록
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--verbose&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;설치한 Ubuntu 배포판 실행
        &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;docker-desktop-설치-및-wsl2-설정&quot;&gt;Docker Desktop 설치 및 WSL2 설정&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.docker.com/products/docker-desktop/&quot;&gt;Docker Desktop&lt;/a&gt; 공식 홈페이지에서 [Download for Windows]를 클릭해 다운로드하고 설치합니다.
  &lt;img src=&quot;/assets/penpot/images_2.JPG&quot; alt=&quot;images_2.JPG&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Docker Desktop 실행 후 작업 표시줄의 숨겨진 아이콘 메뉴에서 Docker 아이콘을 선택합니다. 아이콘을 마우스 오른쪽 단추로 클릭해 Docker 명령 메뉴를 표시하고 “설정”을 선택합니다.
  &lt;img src=&quot;/assets/penpot/images_3.JPG&quot; alt=&quot;images_3.JPG&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;설정 &amp;gt; 일반에서 “WSL 2 기반 엔진 사용”이 선택되어 있는지 확인합니다.
  &lt;img src=&quot;/assets/penpot/images_4.JPG&quot; alt=&quot;images_4.JPG&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;설정 &amp;gt; 리소스 &amp;gt; WSL 통합으로 이동해 Docker 통합을 사용하도록 설정하려는 설치된 WSL 2 배포판에서 선택합니다.
  &lt;img src=&quot;/assets/penpot/images_5.JPG&quot; alt=&quot;images_5.JPG&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Docker가 설치되었는지 확인하려면 PowerShell에서 확인을 합니다.
    &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Docker가 이미지를 실행할 수 있도록 올바르게 설치되었는지 아래와 같은 명령을 PowerShell에서 실행합니다.
    &lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hello-world&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;penpot-설치시작하기&quot;&gt;&lt;a href=&quot;https://help.penpot.app/technical-guide/getting-started/#start-penpot&quot;&gt;Penpot 설치/시작하기&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Docker Compose는 Docker 컨테이너들을 정의하고 실행하는 도구인데, 이를 정의하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt; 파일을 Penpot GitHub 저장소에서 다운로드해 실행할 수 있습니다.&lt;br /&gt;
그러려면 Docker Compose라는 플러그인도 설치가 필요하겠죠?? WSL에서 Docker 엔진으로 설치했다면, Docker Compose도 따로 명령어를 통해 설치하고 복잡한 과정을 거쳐야 합니다.&lt;br /&gt;
하지만 저는 Docker Desktop을 설치했기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt; 파일만 다운로드하면 됩니다.&lt;br /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;설치한 Ubuntu에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt; 파일을 다운로드
    &lt;ul&gt;
      &lt;li&gt;Windows의 WSL2에서 설치한 Ubuntu를 실행해 다운로드합니다.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
      &lt;li&gt;docker-compose.yaml를 설치할 파일 경로는 따로 신경 쓰실 필요 없어요~!&lt;/li&gt;
      &lt;li&gt;wget: 인터넷에서 파일을 다운로드할 때 사용되는 명령 줄 도구
&lt;img src=&quot;/assets/penpot/images_6.JPG&quot; alt=&quot;images_6.JPG&quot; /&gt;
        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/penpot/penpot/main/docker/images/docker-compose.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  - 실질적으로 Windows에서 Ubuntu 가상 시스템을 실행했기 때문에 파일 경로는 파일 탐색기를 열어보면 확인하실 수 있습니다. (Ubuntu 실행 명령어에서 `ll`을 쳤을 때 실제 경로예요~!)  ![images_7.JPG](/assets/penpot/images_7.JPG)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Penpot 서비스 실행하기
    &lt;ul&gt;
      &lt;li&gt;항상 Docker Compose를 통해 명령줄 도구(CLI)를 실행할 땐 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Docker Desktop&lt;/code&gt;이 실행되고 있어야 합니다.&lt;/li&gt;
      &lt;li&gt;Ubuntu에서 Penpot 서비스를 실행하고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:9001&lt;/code&gt;로 접속을 합니다.&lt;/li&gt;
      &lt;li&gt;포트 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9001&lt;/code&gt;은 wget으로 설치한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt; 파일에 기본으로 설정되어 있고, 변경해서 사용할 수 있어요~!
        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; docker compose &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; penpot &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; docker-compose.yaml up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
        &lt;p&gt;&lt;img src=&quot;/assets/penpot/images_8.JPG&quot; alt=&quot;images_8.JPG&quot; /&gt;&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Penpot 서비스 실행 중지
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  docker compose &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; penpot &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; docker-compose.yaml down
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;gitlab-연동하기&quot;&gt;GitLab 연동하기&lt;/h3&gt;

&lt;p&gt;앞서 Penpot 컨테이너의 이미지, 환경 변수, 볼륨, 네트워크 설정 등을 명시하는 파일인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt;을 사용해 서비스를 실행했습니다. &lt;br /&gt;
이제 &lt;a href=&quot;https://help.penpot.app/technical-guide/developer/&quot;&gt;공식 사이트의 가이드&lt;/a&gt;에 따라 GitLab을 사용해 로그인 할 수 있게 설정해 보겠습니다.&lt;/p&gt;

&lt;h4 id=&quot;docker-composeyaml-파일-수정하기&quot;&gt;docker-compose.yaml 파일 수정하기&lt;/h4&gt;

&lt;p&gt;저는 wget을 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt;을 받았습니다. 파일 경로는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\wsl.localhost\Ubuntu\home\gluesys&lt;/code&gt; 하위에 속해있고, &lt;br /&gt;
해당 파일의 확장자는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yaml&lt;/code&gt; 파일이기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt; 파일의 속성에 들어가서 연결 프로그램을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;메모장&lt;/code&gt;으로 변경 후 파일 내용을 수정했습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;수정된 내용은 아래와 같습니다.
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;penpot-frontend&lt;/code&gt; 밑에 줄에 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PENPOT_FLAGS&lt;/code&gt;라는 환경 변수를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disable-secure-session-cookies disable-login enable-login-with-gitlab disable-registration&lt;/code&gt;로 정의했습니다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;penpot-backend&lt;/code&gt; 밑에 줄에 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PENPOT_FLAGS&lt;/code&gt;라는 환경 변수를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disable-secure-session-cookies disable-login enable-login-with-gitlab&lt;/code&gt;로 정의했습니다.&lt;/li&gt;
      &lt;li&gt;GitLab에 인증에 관련된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PENPOT_GITLAB_BASE_URI, PENPOT_GITLAB_CLIENT_ID, PENPOT_GITLAB_CLIENT_SECRET&lt;/code&gt; 환경 변수를 설정했습니다.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;직접 수정하기 귀찮다면 &lt;a href=&quot;/assets/penpot/docker-compose.yaml&quot;&gt;docker-compose.yaml&lt;/a&gt; 파일을 바로 사용하셔도 됩니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;이렇게 설정을 변경한 후에 서비스를 재구동해 보면 기존에 보이던 계정 생성 버튼이 없어지고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;깃랩(GitLab)&lt;/code&gt; 버튼이 생깁니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/penpot/images_9.JPG&quot; alt=&quot;images_9.JPG&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;gitlab에-penpot을-인증할-애플리케이션-생성-후-인증키-등록&quot;&gt;GitLab에 Penpot을 인증할 애플리케이션 생성 후 인증키 등록&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GitLab 로그인&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;사용자 설정&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;애플리케이션&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[새 애플리케이션 추가]&lt;/code&gt;
  &lt;img src=&quot;/assets/penpot/images_10.JPG&quot; alt=&quot;images_10.JPG&quot; /&gt;
    &lt;ul&gt;
      &lt;li&gt;이름: Penpot&lt;/li&gt;
      &lt;li&gt;Redirect URL: http://&lt;penpot을 설치한=&quot;&quot; 장비=&quot;&quot; IP=&quot;&quot;&gt;/api/auth/oauth/gitlab/callback&lt;/penpot을&gt;&lt;/li&gt;
      &lt;li&gt;옵션(선택 사항)&lt;/li&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
      &lt;li&gt;read_user&lt;/li&gt;
      &lt;li&gt;openid&lt;/li&gt;
      &lt;li&gt;profile&lt;/li&gt;
      &lt;li&gt;email
  &lt;img src=&quot;/assets/penpot/images_11.JPG&quot; alt=&quot;images_11.JPG&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;인증키 복사
    &lt;ul&gt;
      &lt;li&gt;애플리케이션 ID와 비밀키를 복사합니다.
 &lt;img src=&quot;/assets/penpot/images_12.JPG&quot; alt=&quot;images_12.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;여기서 복사한 내용은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt;파일에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PENPOT_GITLAB_CLIENT_ID, PENPOT_GITLAB_CLIENT_SECRET&lt;/code&gt;에 입력 후 저장해 Penpot 서비스를 재실행합니다.
 ```yaml
 # Backend &amp;amp; Frontend
 PENPOT_FLAGS=”[…] enable-login-with-gitlab”&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;# Backend only
 PENPOT_GITLAB_BASE_URI=https://gitlab.com
 PENPOT_GITLAB_CLIENT_ID=&lt;client-id&gt;
 PENPOT_GITLAB_CLIENT_SECRET=&lt;client-secret&gt;
 ```
         - 마지막으로 서비스 접속 후 - [GitLab] 클릭 - 인증 - 로그인하면 끝~!
 ![images_13.JPG](/assets/penpot/images_13.JPG)&lt;/client-secret&gt;&lt;/client-id&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;penpot-활용하기&quot;&gt;Penpot 활용하기&lt;/h2&gt;

&lt;p&gt;이제는 Penpot에서 제공하는 라이브러리를 다운로드하고 해당 디자인 템플릿을 활용해 간단한 로그인 페이지의 목업 작업을 하는 방법을 소개하도록 하겠습니다.&lt;br /&gt;
라이브러리를 다운로드하고, 라이브러리 안에 마음에 드는 템플릿을 공유해 개인 프로젝트에서 해당 디자인을 활용해서 작업을 할 것입니다.&lt;br /&gt;
&lt;a href=&quot;https://penpot.app/libraries-templates&quot;&gt;Penpot에서 제공되는 라이브러리&lt;/a&gt; 중에서 저는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Firefox mockup&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot Design System&lt;/code&gt;이라는 라이브러리를 사용하겠습니다.&lt;/p&gt;

&lt;h3 id=&quot;라이브러리-다운로드&quot;&gt;&lt;a href=&quot;https://penpot.app/libraries-templates&quot;&gt;라이브러리&lt;/a&gt; 다운로드&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;해당 홈페이지에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Firefox mockup&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot Design System&lt;/code&gt;를 다운로드합니다.
  &lt;img src=&quot;/assets/penpot/images_14.JPG&quot; alt=&quot;images_14.JPG&quot; /&gt;
  &lt;img src=&quot;/assets/penpot/images_15.JPG&quot; alt=&quot;images_15.JPG&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;다운로드한 라이브러리를 추가해 줍니다.
    &lt;ul&gt;
      &lt;li&gt;로그인 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[초안]&lt;/code&gt; - 상단 왼쪽 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;설정&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Import Penpot files]&lt;/code&gt;를 클릭해줍니다.
 &lt;img src=&quot;/assets/penpot/images_16.JPG&quot; alt=&quot;images_16.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;다운로드 받은 라이브러리를 선택 후 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Import&lt;/code&gt;를 해줍니다.&lt;/li&gt;
      &lt;li&gt;인내심을 갖고 등록된 후 허가까지 해주셔야 해요~!
 &lt;img src=&quot;/assets/penpot/images_17.JPG&quot; alt=&quot;images_17.JPG&quot; /&gt;
 &lt;img src=&quot;/assets/penpot/images_18.JPG&quot; alt=&quot;images_18.JPG&quot; /&gt;
 &lt;img src=&quot;/assets/penpot/images_19.JPG&quot; alt=&quot;images_19.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;해당 라이브러리가 추가가 되었다면 추가된 라이브러리가 나타날 것입니다.
 &lt;img src=&quot;/assets/penpot/images_20.JPG&quot; alt=&quot;images_20.JPG&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;디자인 템플릿을 공유하기
    &lt;ul&gt;
      &lt;li&gt;개인 프로젝트에서 사용하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Firefox mockup&lt;/code&gt;에서 웹 브라우저 화면 디자인을 선택해서 공유해 보겠습니다.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Firefox mockup&lt;/code&gt;라이브러리를 선택합니다.(더블클릭을 해주셔야 해요~!)
&lt;img src=&quot;/assets/penpot/images_21.JPG&quot; alt=&quot;images_21.JPG&quot; /&gt;
&lt;img src=&quot;/assets/penpot/images_22.JPG&quot; alt=&quot;images_22.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[LAYERS]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[templates]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[light]&lt;/code&gt; 우클릭 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Create component]&lt;/code&gt; 클릭을 해줍니다.
        &lt;ul&gt;
          &lt;li&gt;저는 하얀색을 좋아하기 때문에 밝은색 디자인을 선택할게요~!
&lt;img src=&quot;/assets/penpot/images_23.JPG&quot; alt=&quot;images_23.JPG&quot; /&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ASSETS]&lt;/code&gt; - 좌측 하단에 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[COMPONENTS]&lt;/code&gt;에서 방금 선택한 디자인이 추가가 되었는지 확인합니다.
&lt;img src=&quot;/assets/penpot/images_24.JPG&quot; alt=&quot;images_24.JPG&quot; /&gt;
      - 자 이제는 로그인 폼 디자인을 선택해서 공유해 보겠습니다. 똑같은 방법이니 빠르게 넘어가셔도 되요~!&lt;br /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot Design System&lt;/code&gt; 라이브러리를 선택합니다.
&lt;img src=&quot;/assets/penpot/images_25.JPG&quot; alt=&quot;images_25.JPG&quot; /&gt;
&lt;img src=&quot;/assets/penpot/images_26.JPG&quot; alt=&quot;images_26.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[LAYERS]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[PAGES]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Login]&lt;/code&gt; 우클릭 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Create component]&lt;/code&gt; 클릭을 해줍니다.
&lt;img src=&quot;/assets/penpot/images_27.JPG&quot; alt=&quot;images_27.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ASSETS]&lt;/code&gt; - 좌측 하단에 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[COMPONENTS]&lt;/code&gt;에서 방금 선택한 디자인이 추가가 되었는지 확인합니다.
&lt;img src=&quot;/assets/penpot/images_28.JPG&quot; alt=&quot;images_28.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;대시보드 페이지 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[초안]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[해당 라이브러리 우클릭]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[공유 라이브러리로 추가하기]&lt;/code&gt; 클릭해 줍니다.
&lt;img src=&quot;/assets/penpot/images_29.JPG&quot; alt=&quot;images_29.JPG&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;개인 프로젝트에서 공유한 디자인으로 목업하기
    &lt;ul&gt;
      &lt;li&gt;자 다시 그러면 대시보드(메인 페이지)로 돌아와 프로젝트를 생성해 보겠습니다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[NEW PROJECT]&lt;/code&gt; 버튼 클릭 후 생성된 프로젝트를 클릭해 줍니다. (저는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Login&lt;/code&gt;이라 할게요!)
 &lt;img src=&quot;/assets/penpot/images_30.JPG&quot; alt=&quot;images_30.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ASSETS]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[LIBRARIES]&lt;/code&gt; - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Firefox mockup&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot Design System&lt;/code&gt; 추가해 줍니다.
 &lt;img src=&quot;/assets/penpot/images_31.JPG&quot; alt=&quot;images_31.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;공유된 라이브러리를 확인합니다.
 &lt;img src=&quot;/assets/penpot/images_32.JPG&quot; alt=&quot;images_32.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Firefox mockup&lt;/code&gt; 라이브러리에 생성한 디자인 컴포넌트를 가운데 화면으로 드래그해 줍니다.
 &lt;img src=&quot;/assets/penpot/images_33.JPG&quot; alt=&quot;images_33.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;자 이러면 웹 브라우저 화면의 디자인 UI 목업이 추가했으니 Penpot의 로그인 디자인도 입혀보겠습니다.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penpot Design System&lt;/code&gt; 라이브러리에 생성한 로그인 폼 디자인 컴포넌트를 가운데 화면으로 드래그해 줍니다.
&lt;img src=&quot;/assets/penpot/images_34.JPG&quot; alt=&quot;images_34.JPG&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;로그인 폼 목업 작업
&lt;img src=&quot;/assets/penpot/images_35.JPG&quot; alt=&quot;images_35.JPG&quot; /&gt;
        &lt;ul&gt;
          &lt;li&gt;로그인 폼 디자인과 웹 브라우저 창 디자인의 규격이 안 맞을 텐데 이 부분은 사이즈를 잘 조정해서 맞춰야 해요~!&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;마치면서&quot;&gt;마치면서&lt;/h2&gt;

&lt;p&gt;전 디자이너가 아니다 보니 제한적으로 몇몇 기능만 사용하고 있는 상황에서 다루지 못한 Penpot의 기능과 디자인 작업에 대한 내용들이 많이 있습니다.&lt;br /&gt;
Penpot을 사용하면서 디자인 템플릿(CSS, SVG, HTML 등의 디자인 요소)으로 네이티브하게 표현함으로써, 디자인에서 개발 과정으로 별도의 작업 없이 인터페이스에서 바로 작업하는 장점은 최고의 장점이라 봅니다.&lt;br /&gt; 
물론 Penpot의 클라이언트와 서버 모두 느리고 비효율적인 부분도 있고, 신생 프로젝트인 만큼, 안정성이나 성능 측면에서는 기존 도구들에 비해 부족할 수도 있습니다.&lt;br /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;텍스트 편집 중 영어가 아닌 언어(한글)로 입력할 때 발생하는 버그가 있으니 주의하세요!&lt;/em&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/penpot/penpot/issues/4163&quot;&gt;이 이슈&lt;/a&gt;는 Penpot GitHub 저장소에서도 알려진 이슈입니다.&lt;/li&gt;
      &lt;li&gt;천천히 입력하는 우회법(?)도 있습니다…&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Penpot은 개발 중심의 조직이라면 별도 비용 부담 없이 자체적으로 호스팅해 사용할 수 있다는 점이 최고의 장점이지 않을까 생각합니다.&lt;/p&gt;

&lt;h2 id=&quot;참고-링크-및-자료&quot;&gt;참고 링크 및 자료&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://penpot.app/&quot;&gt;Penpot 공식 사이트&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://penpot.app/self-host&quot;&gt;Penpot 셀프 호스트 안내서&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.penpot.app/user-guide/libraries/&quot;&gt;Penpot 사용자 안내서&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/tutorials/wsl-containers&quot;&gt;WSL2에서 Docker 원격 컨테이너 시작&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://penpot.app/libraries-templates&quot;&gt;Penpot 라이브러리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 31 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2024/07/31/penpot.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2024/07/31/penpot.html</guid>
        
        <category>Penpot</category>
        
        <category>펜팟</category>
        
        <category>목업</category>
        
        <category>디자인</category>
        
        <category>오픈소스</category>
        
        <category>Docker</category>
        
        <category>도커</category>
        
        <category>WSL</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>병렬 네트워크 파일 시스템 pNFS의 재조명</title>
        <description>&lt;p&gt;AI 서비스의 정확도는 AI 모델의 정교함에 달려 있고, AI 모델의 정교함은 데이터셋을 얼마나 많이 학습했는지에 따라 고도화됩니다. 그리고 학습 시간과 비용을 줄이기 위해서는 데이터셋을 보다 빠르게 처리할 수 있는 컴퓨팅 자원과 데이터를 빠르게 주입해 주는 고성능 스토리지가 필요합니다. 하지만 스토리지는 고성능 컴퓨팅 환경에서 항상 병목의 근원으로 지목되어 왔습니다.&lt;/p&gt;

&lt;p&gt;이러한 스토리지 병목 문제를 해결하기 위해 다양한 접근법이 연구되고 있는데, 그중 하나가 기존 NFS(Network File System)의 한계를 극복하고자 등장했던 &lt;strong&gt;병렬 NFS(parallel NFS, 이하 pNFS)&lt;/strong&gt;입니다. 이번 포스트에서는 최근 새롭게 주목받고 있는 pNFS에 대해 소개하겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;기존-nfs와-병렬-파일-시스템&quot;&gt;기존 NFS와 병렬 파일 시스템&lt;/h2&gt;

&lt;p&gt;대부분의 AI 애플리케이션은 리눅스 기반 환경에서 호스팅되며, 보편적으로 리눅스의 기본 스토리지 프로토콜인 NFS를 사용합니다. 하지만 기존 NFS는 클라이언트와 스토리지 사이에 NFS 서버를 통해 데이터를 주고받는 단일 서버 구성입니다. 이 때문에 다수의 클라이언트가 여러 스토리지 노드에 접근하려면 NFS 서버를 통해 접근해야 하고, 1개의 클라이언트가 1개 스토리지 노드에만 접근할 수 있기 때문에 성능이 제한적입니다. 게다가 데이터셋이 커지면 그만큼 대역폭 부하도 높아진다는 문제가 있습니다.&lt;/p&gt;

&lt;p&gt;이 때문에 입출력 집약적인 환경에서는 병렬 파일 시스템이 활용됩니다. 병렬 파일 시스템을 통해, 모든 클라이언트는 데이터를 여러 스토리지에 병렬로 직접 요청할 수 있고, 데이터가 여러 스토리지에 분산 저장되어 있기 때문에, 스토리지 노드를 확장할수록 입출력 성능도 높아집니다. 게다가 GPFS와 같은 병렬 파일 시스템의 경우, 메타데이터 서버와 데이터 서버가 분리되어 있어 작업 경로 구분에 따라 대역폭 부하를 크게 줄일 수 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 이러한 병렬 파일 시스템은 각 클라이언트에 전용 에이전트를 설치해야 하는 등 설치에 대한 공수와 병렬 인프라에 대한 전문성이 요구되어 유지보수 비용이 발생합니다. 무엇보다, 병렬 파일 시스템이 일반적인 파일 시스템에 비해 상대적으로 기능이 많아 무겁다 보니, 추가 소프트웨어 계층으로 인한 지연 시간과 파일 시스템에 대한 종속성 문제가 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;pnfs-소개&quot;&gt;pNFS 소개&lt;/h2&gt;

&lt;p&gt;pNFS는 기존의 단일 NFS 서버의 병목 문제를 해결하기 위해 NFSv4.1부터 등장한 병렬 파일 시스템 구조입니다. 병렬 파일 시스템처럼 데이터와 메타데이터 작업 경로를 구분해 클라이언트가 직접 스토리지에 병렬로 접근할 수 있게 합니다. 데이터와 메타데이터를 구분하여 처리함으로써 기존 NFS의 메타데이터 처리로 인한 네트워크 병목 및 확장성 문제를 해소합니다. 무엇보다, 이러한 병렬 파일 시스템 기능을 리눅스 배포판을 사용하는 모든 환경에서 네이티브로 지원하기 때문에, 추가 하드웨어 및 소프트웨어 계층이 없어도 되고, 별도의 라이선스 비용이 없다는 장점이 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;pnfs의-구조&quot;&gt;pNFS의 구조&lt;/h2&gt;

&lt;p&gt;pNFS의 아키텍처는 크게 클라이언트와 &lt;strong&gt;메타데이터 서버(Metadata Server, 이하 MDS)&lt;/strong&gt;, &lt;strong&gt;데이터 서버(Data Server, 이하 DS)&lt;/strong&gt;로 구성됩니다. NFS 서버였던 MDS는 메타데이터 및 접근 관리 역할을 수행하며, &lt;strong&gt;레이아웃(layout)&lt;/strong&gt;이라는 메타데이터에 따라 각 파일의 데이터를 DS에 분산 저장합니다. 레이아웃은 메타데이터 서버에서 관리하며, 파일은 최소 데이터 단위인 &lt;strong&gt;유닛(unit)&lt;/strong&gt;으로 나뉘고 저장 패턴에 따라 DS에 분산 저장됩니다. 파일 접근 시 클라이언트는 pNFS 프로토콜로 MDS에 쿼리를 보내 데이터 위치에 대한 맵과 접근 권한 정보를 얻습니다. 그리고 클라이언트에서 NFS 프로토콜을 통해 각 DS에 저장된 데이터에 직접 접근하고, 레이아웃에 의해 정의된 데이터 유형에 따라 파일, 블록, 오브젝트 프로토콜을 활용할 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/pNFSarchitecture.png&quot; alt=&quot;pNFS 구조&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; pNFS 구조 &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;이렇게 NFS 트래픽을 분리하고 클라이언트의 직접 접근까지 가능하게 되었습니다만, 여기에 더해 NFSv4.1부터는 세션 트렁킹(session trunking)을 통해 대역폭을 확장하는 기능까지 추가되었습니다. 세션 트렁킹은 같은 세션 내에 서로 다른 소스와 목적지 주소를 가진 연결을 묶는 것을 말하며, 쉽게 말해 클라이언트와 스토리지 간 인터페이스를 묶어서 대역폭을 확장할 수 있다는 것입니다. 이러한 고대역폭 구성을 통해 클러스터 환경에서 NFS RPC(remote procedure call)를 안정적으로 전송할 수 있게 되었습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;flex-files&quot;&gt;Flex Files&lt;/h2&gt;

&lt;p&gt;NFSv4.2부터는 Flex Files라는 새로운 pNFS 레이아웃이 도입되었습니다. &lt;strong&gt;Flex Files(또는 Flexible File Layout)&lt;/strong&gt;는 파일을 복사하는 도중에도 애플리케이션 서비스의 데이터 접근을 방해하지 않아 데이터 무결성과 서비스 연속성을 보장합니다. 덕분에 데이터 마이그레이션이나 업데이트를 위해 서버를 중단하지 않아도 됩니다. 이러한 데이터 이동은 전적으로 백그라운드에서 동작하기 때문에 클라이언트는 어떠한 유형의 데이터라도 방해 없이 접근할 수 있습니다. 게다가 NFSv3부터 NFSv4.2까지 이전 버전 프로토콜을 통해 DS에 입출력을 요청할 수 있어, 기존 NFSv3를 사용하는 레거시 NFS 스토리지도 클러스터에 추가할 수 있습니다. 또한, 파일 레벨 스트라이핑이 가능해 로드 밸런싱이나 티어링 같은 기능에 최적화되어 있습니다.&lt;/p&gt;

&lt;p&gt;Flex Files는 스토리지 장치 수준에서 멀티패스를 지원합니다. 이로써 트렁킹을 통해 대역폭 확장뿐만 아니라 장치 장애 발생에 대비한 고가용성까지 제공할 수 있습니다. 또한, 클라이언트는 멀티패스를 통해 한 데이터 스트라이프 유닛을 불러올 경우, MDS에 추가 레이아웃 요청 없이 한 스토리지 장치 주소에서 다른 장치 주소로 전환할 수 있습니다.&lt;/p&gt;

&lt;p&gt;pNFS가 최근 다시 화두가 되고 있는 이유는, 바로 Hammerspace&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;에서 자사 제품으로 pNFS의 실용성을 증명한 것에 있습니다. Hammerspace는 Flex Files를 리눅스 커뮤니티에 소개해 NFSv4.2에 기여한 바 있으며, AI/ML 워크로드에 최적화된 성능과 확장성을 제공하는 소프트웨어 정의 스토리지 솔루션을 개발했습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;고집적-워크로드에-특화된-pnfs&quot;&gt;고집적 워크로드에 특화된 pNFS&lt;/h2&gt;

&lt;p&gt;이렇게 pNFS는 기존 목표였던 병렬성뿐만 아니라, 고속 입출력에 대한 요구사항이 보편화되어 가는 현대 스토리지 트렌드에 맞추어 높은 성능과 최적화된 각종 스토리지 기능들을 제공합니다. AI/ML 워크로드는 대규모 데이터셋을 처리하고 분석하는 데 있어 고성능 병렬 파일 시스템을 필요로 하며, pNFS는 이러한 요구사항에 부합할 것으로 보입니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;데이터 경로 최적화로 인한 고성능 입출력:&lt;/strong&gt; pNFS는 클라이언트가 네임스페이스 내 볼륨에 직접 접근할 수 있으며, 동적인 데이터 배치가 가능해 노드와 스토리지 장치에 유연하게 데이터를 분산시켜 성능과 스토리지 효율성을 높일 수 있습니다. 게다가, MDS와 DS 간 파일 시스템 정보 동기화를 통해 병목을 최소화할 수 있습니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;뛰어난 데이터 접근성:&lt;/strong&gt; pNFS의 Flex Files 레이아웃은 입출력이 완료되기 전에 신규 레이아웃을 요청할 수 있어, 파일을 복사하는 도중에도 데이터 접근 및 무결성을 유지할 수 있습니다. 게다가, 특정 하드웨어 및 설정에 국한된 일부 병렬 파일 시스템(예: DAOS, GPFS)과는 달리, 어떠한 유형의 스토리지 타입에도 적용할 수 있습니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;클라이언트 중심 메타데이터 관리:&lt;/strong&gt; 데이터 스토리지의 개입 전에 클라이언트 측에서 메타 데이터에 접근할 수 있어 스토리지의 부하를 줄일 뿐만 아니라, 대규모 메타 데이터의 랜덤 읽기가 많이 요구되는 AI 학습 및 추론에 최고의 성능을 제공할 수 있습니다. 그리고 클라이언트 측에서 레이아웃 정보를 기반으로 데이터의 입출력 수행 경로를 결정할 수 있어 뛰어난 로드 밸런싱 및 서버 병목 해소를 제공합니다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;적응형 데이터 운영:&lt;/strong&gt; 새로운 스토리지 자원이 추가되거나 네트워크 상태가 바뀌는 등 시스템 변화에 맞추어 레이아웃이 동적으로 조정됩니다. 또한, 로드 밸런싱을 위해 클러스터 내 볼륨이 노드 간에 이동해도 파일 시스템 마운트 작업 등 네임스페이스에 개입 없이 위치를 알 수 있어 CPU 및 메모리 집약적인 환경에서도 효율적인 로드 밸런싱이 가능합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;pNFS는 기존 NFS의 한계를 극복하고 NFS가 가진 범용성을 살려 고성능 컴퓨팅 환경에서의 스토리지 병목 문제를 해결하는 혁신적인 기술입니다. 앞으로 pNFS가 AI 및 머신러닝 파이프라인을 위한 스토리지 인프라의 중요한 구성 요소로 자리 잡을 것으로 기대됩니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;http://www.pnfs.com/&lt;/li&gt;
  &lt;li&gt;https://www.snia.org/educational-library/standards-based-parallel-global-file-systems-and-automated-data-orchestration&lt;/li&gt;
  &lt;li&gt;https://www.snia.org/sites/default/files/education/webcasts/What%27s-New-with-NFS-4.2.pdf&lt;/li&gt;
  &lt;li&gt;https://www.netapp.com/blog/why-parallel-nfs-is-the-right-choice-for-ai-ml-workloads/&lt;/li&gt;
  &lt;li&gt;https://www.keepertech.com/new/wp-content/uploads/2024/05/KT_Hammerspace-pNFS-4.2-File-System-Summary.pdf&lt;/li&gt;
  &lt;li&gt;https://www.hpcwire.com/2024/02/29/pnfs-provides-performance-and-new-possibilities/&lt;/li&gt;
  &lt;li&gt;https://www.datacenterknowledge.com/data-storage/seven-new-nfs-capabilities&lt;/li&gt;
  &lt;li&gt;https://datatracker.ietf.org/doc/html/rfc8435#section-5&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;각주&quot;&gt;각주&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Hammerspace: pNFS를 기반으로 데이터 오케스트레이션 소프트웨어를 개발한 기업임. Hammerspace의 소프트웨어는 pNFS의 메타데이터 서버에 탑재되어 파일 관리 및 각종 스토리지 기능을 제공함. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 10 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2024/06/10/pnfsintro.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2024/06/10/pnfsintro.html</guid>
        
        <category>pNFS</category>
        
        <category>NFS</category>
        
        <category>병렬 파일시스템</category>
        
        <category>Parallel File System</category>
        
        <category>고성능</category>
        
        <category>High Performance</category>
        
        <category>Storage</category>
        
        <category>스토리지</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>LVM 스냅샷 관리 기능 개발 후기 (1)</title>
        <description>&lt;p&gt;장애 복구나 유실된 데이터 복원을 위해서 AnyStor는 이전부터 스냅샷 기능을 지원하였습니다. 그러나 스냅샷 생성과 확인은 가능할 뿐, 실제로 복원 등에 사용하기 위해서는 관리자가 CLI 명령어를 사용하여 데이터를 복원할 수밖에 없었습니다. 실제 복원 시에는 고객 서비스에 영향이 없도록 진행되어야 했기에 도입하기 까다로웠던 점도 있었습니다. 이번에 스냅샷 기능을 재편하게 되었는데, 스냅샷을 안정적으로 도입하기 위해서 거쳤던 테스트와 이슈 대응 방안에 대해서 살펴보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;배경-설명&quot;&gt;배경 설명&lt;/h3&gt;

&lt;p&gt;본 제품에서는 LVM 볼륨을 주로 다룹니다. LVM 볼륨의 프로비저닝 정책에 따라서 스냅샷의 종류도 나뉘게 되는데, 우선 볼륨의 프로비저닝 종류에 대해서 간략히 설명해 보겠습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;씬 프로비저닝(Thin Provisioning)된 볼륨&lt;/strong&gt; : 사용자에게 필요한 만큼의 스토리지 공간을 할당하되, 실제로는 사용한 만큼의 공간만 실제 스토리지에서 차지하는 방식입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;씩 프로비저닝(Thick Provisioning)된 볼륨&lt;/strong&gt; : 미리 정해진 크기의 스토리지 공간을 사용자에게 할당하는 방식입니다. 이 공간은 사용자가 실제로 사용하지 않더라도 할당된 크기만큼 스토리지에서 차지합니다. 스토리지 공간을 확보하는 데 있어서 보다 안정적이지만, 사용하지 않는 공간이 발생할 수 있어 스토리지 공간의 사용이 비효율적일 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;프로비저닝 된 볼륨에 따라서 스냅샷의 저장 방식도 바뀝니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;씬 프로비저닝된 볼륨과 씩 프로비저닝된 볼륨에 대해서 약칭으로 각각 Thin 볼륨, Thick 볼륨으로 변경하여 설명하겠습니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Thin 볼륨의 스냅샷&lt;/strong&gt;: 원본 볼륨의 데이터를 공유하며, 자체 메타데이터 영역을 가지고 있습니다. 메타데이터 영역에는 스냅샷의 논리적 익스텐트와 물리적 익스텐트 간의 매핑이 저장되어 있습니다. 이를 통해 스냅샷은 원본 볼륨의 상태를 보존하고, 변경 사항을 추적하게 됩니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Thick 볼륨의 스냅샷&lt;/strong&gt; : 원본 볼륨의 데이터를 복사하여 새로운 공간에 저장합니다. 원본 데이터의 완전한 복사본을 제공하지만, 스토리지 공간을 더 많이 차지하게 됩니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;여기까지만 살펴봤을 때 차이점이 여럿 보입니다. Thin 볼륨은 저장 방식이 다르기 때문에, 스냅샷 또한 저장하는 방법이 다르게 보입니다. 실제로 Thin 볼륨은 스냅샷을 다음과 같은 구조로 저장합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;:bulb: NOTE &lt;br /&gt;
물리적 익스텐트(Physical Extents: PE): 디스크의 섹터로 매핑된 물리적 할당 단위&lt;br /&gt;
논리적 익스텐트(Logical Extents: LE): 물리적 익스텐트로 매핑된 논리적 할당 단위&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/Snapshot1intro_maincover.png&quot; alt=&quot;Thin 볼륨 구조&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; Thin 볼륨 구조 &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;위 구조를 보게 되면 Thin 볼륨과 스냅샷 볼륨은 공통의 데이터 볼륨을 공유합니다. 그렇기 때문에 많은 스냅샷을 생성할 수 있지만, 스냅샷을 삭제하더라도 여유 공간이 추가로 확보되지 않을 수도 있습니다. 데이터 볼륨 말고도 메타데이터 볼륨도 보이는데, 메타데이터 볼륨에서는 각 Thin 볼륨에 속한 데이터 볼륨을 추적합니다. 볼륨 그룹 별로 여러 씬 풀(Thin Pool)이 생성 될 수 있는데, 예비 메타데이터로 불리는&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmspare&lt;/code&gt; 는 볼륨 그룹에 대해서 하나만 생성됩니다. 이 pmspare 는 볼륨 그룹 내의 모든 씬 풀(Thin Pool)의 메타데이터를 복구하기 위해서 사용됩니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;씬 풀(Thin Pool) 은 약칭으로 Thin 풀로 변경하여 설명하겠습니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;스냅샷-도입-전-테스트&quot;&gt;스냅샷 도입 전 테스트&lt;/h3&gt;

&lt;p&gt;스냅샷을 도입하기 전에 몇 가지 스냅샷 기능에 관한 테스트를 진행하였습니다. 진행하면서 있었던 고려 사항들을 공유드리고자 합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4 id=&quot;1-thin-풀-데이터-볼륨-저장-공간-확보&quot;&gt;1. Thin 풀 데이터 볼륨 저장 공간 확보&lt;/h4&gt;

&lt;p&gt;Thin 볼륨의 파일 시스템에서 파일을 삭제하면 일반적으로 씬 풀에 Free 블록을 다시 추가하지 않습니다. 파일 시스템에서는 삭제되었지만, 씬 풀에 적용되지 않은 경우, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fstrim&lt;/code&gt; 을 통해서 물리적 공간을 Thin 풀에 복원할 수 있습니다. 비슷한 효과를 마운트 시에 옵션으로 처리할 수도 있는데, 마운트시에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;discard&lt;/code&gt; 옵션으로 Thin 풀의 데이터 공간에 대한 자동 해제 옵션을 추가하여 데이터 볼륨의 저장 공간을 확보할 수 있었습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Thin 볼륨 데이터 쌓기&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;mount_path&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;/fileN &lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096 &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000000&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 용량 확인 &lt;/span&gt;
lvs
  LV           VG        Attr       LSize   Pool         Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root         anystor-e &lt;span class=&quot;nt&quot;&gt;-wi-ao----&lt;/span&gt; &amp;lt;44.00g                      
  swap         anystor-e &lt;span class=&quot;nt&quot;&gt;-wi-ao----&lt;/span&gt;   5.00g                          
  ThinLV       thinvpool Vwi-aotz--  60.00g tp_thinvpool        58.33  
  tp_thinvpool thinvpool twi---tz--  40.00g                     87.51  3.28 

&lt;span class=&quot;c&quot;&gt;# 데이터 삭제 후 재 마운트&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount 시에 `-o discard` 추가&lt;/span&gt;
mount &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; discard /dev/mapper/thinvpool-ThinLV /&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;mount_path&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Thin 볼륨 데이터 쌓기&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;mount_path&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;/fileN &lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096 &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000000&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 용량 확인&lt;/span&gt;
lvs
  LV           VG        Attr       LSize   Pool         Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root         anystor-e &lt;span class=&quot;nt&quot;&gt;-wi-ao----&lt;/span&gt; &amp;lt;44.00g                                
  swap         anystor-e &lt;span class=&quot;nt&quot;&gt;-wi-ao----&lt;/span&gt;   5.00g                                      
  ThinLV       thinvpool Vwi-aotz--  60.00g tp_thinvpool        1.78             
  tp_thinvpool thinvpool twi---tz--  40.00g                     2.67   1.64 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4 id=&quot;2-thin-데이터-볼륨-공간-부족&quot;&gt;2. Thin 데이터 볼륨 공간 부족&lt;/h4&gt;

&lt;p&gt;자동 확장을 설정한 경우 데이터 공간이 부족해지기 전에 설정값에 따라서 씬 풀의 데이터 공간이 확장됩니다. 하지만 확장할 공간이 없고 씬 풀의 데이터 공간이 이미 100%인 경우에도 추가로 디스크를 증설해 준다면 이후에 수동으로 확장할 수 있습니다. 만약 자동 확장 시 볼륨의 물리적인 용량이 부족한 경우 확장에 실패하여 데이터 볼륨이 가득 차게 되는 경우가 있는데, 그 경우의 쓰기 동작을 설정할 수 있습니다.&lt;/p&gt;

&lt;p&gt;데이터 볼륨에 여유 공간이 없는 경우, 큐 버퍼에 쓰기 명령을 넣었다가 확장이 완료되면 버퍼를 사용합니다. 기본 타임아웃(60초)이 지난 경우에는, 모든 쓰기 명령이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;error&lt;/code&gt; 를 반환하게 됩니다. Thin 풀에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--errorwhenfull&lt;/code&gt; 옵션으로 Thin 풀이 가득 찼을 때, 큐 버퍼 사용 유무를 지정할 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Thin 풀의 데이터 볼륨이 가득 찬 경우&lt;/span&gt;
lvs
  LV           VG        Attr       LSize   Pool         Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root         anystor-e &lt;span class=&quot;nt&quot;&gt;-wi-ao----&lt;/span&gt; &amp;lt;44.00g          
  swap         anystor-e &lt;span class=&quot;nt&quot;&gt;-wi-ao----&lt;/span&gt;   5.00g           
  ThinLV       thinvpool Vwi-aotz--  60.00g tp_thinvpool        66.67   
  tp_thinvpool thinvpool twi---tzD-  40.00g                     100.00 3.53 

&lt;span class=&quot;c&quot;&gt;# Thin 풀의 errorwhenfull 옵션으로 파일 시스템의 동작 결정&lt;/span&gt;
lvchange &lt;span class=&quot;nt&quot;&gt;--errorwhenfull&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;y/n&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; thinvpool/tp_thinvpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Thin 풀이 가득 찼을 때 파일 시스템의 동작을 결정했다면, 다음으로는 Thin 풀의 수동 확장으로 용량을 확장할 수 있습니다. Thin 풀만 확장해 준다면, Thin 볼륨은 자동으로 확장됩니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lvextend &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;size&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; thinvpool/tp_thinvpool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4 id=&quot;3-thin-풀-메타데이터-볼륨-공간-부족&quot;&gt;3. Thin 풀 메타데이터 볼륨 공간 부족&lt;/h4&gt;

&lt;p&gt;Thin 풀 메타데이터의 볼륨이 작고, 스냅샷이 많은 경우 메타데이터 볼륨이 부족할 수 있습니다. 만약 Thin 풀 메타데이터의 볼륨이 가득 찬 경우 메타데이터의 볼륨이 손상될 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lvcreate &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; snap1 vg1/thinvol
...
lvcreate &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; snap600 vg1/thinvol

lvs                                         
  thinvol       vg1 Vwi-aotz--  10.00g tp_thinpool        82.70       
  tp_thinpool   vg1 twi-aotzM-  10.00g                    84.81  100.00                          
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;메타데이터를 확인하고 복구하는 것은 파일 시스템에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fsck/repair&lt;/code&gt; 를 실행하는 것과 유사합니다.  Thin 풀의 메타데이터를 복구하는 방법 중 하나는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvconvert --repair {vg}/{thinpool}&lt;/code&gt;  를 실행하는 것입니다, 이 동작에서는 pmspare 로 복구 메타데이터를 생성하고, 메타데이터를 교체할 수 있도록 유도합니다.&lt;/p&gt;

&lt;p&gt;단순히 공간이 더 필요한 경우는 메타데이터 확장을 시도해 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#lvs -a&lt;/span&gt;
  LV                 VG Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert

  thinlv             vg Vwi-aotz--  10.00g thinpool     82.70                
  thinpool           vg twi-aotzM-  10.00g              84.81  100.00        
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;thinpool_tdata]   vg Twi-ao----  10.00g                                   
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;thinpool_tmeta]   vg ewi-ao----  12.00m  

&lt;span class=&quot;c&quot;&gt;#lvextend --poolmetadatasize +{size} vg/thinpool &lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#lvs -a&lt;/span&gt;
   LV                VG Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert

  thinlv             vg Vwi-aotz--  10.00g thinpool     82.70                
  thinpool           vg twi-aotz--  10.00g              84.84  28.04         
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;thinpool_tdata]   vg Twi-ao----  10.00g                                   
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;thinpool_tmeta]   vg ewi-ao----  60.00m   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4 id=&quot;4-메타데이터-장애-복구&quot;&gt;4. 메타데이터 장애 복구&lt;/h4&gt;

&lt;p&gt;실제 이용 시에는 메타데이터의 용량이 가득 찬 경우나, 디스크 장애 등의 사례에서 메타데이터가 손실되는 경우도 있었습니다. LVM 에서는 각각의 디스크가 동일한 볼륨 풀을 사용하고 있다면, 동일한 메타데이터를 디스크에 복사하여 사용하기 때문에, 디스크에 할당된 정보(PV 정보 등)을 제외하고 복사한다면 손쉽게 복구할 수 있습니다. 메타데이터 영역 중 디스크 정보에 해당하는 656Byte를 제외하고 1024KB까지 복사하여 손상된 디스크의 메타데이터를 복구합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 메타데이터 장애 로그&lt;/span&gt;
  Metadata location on /dev/sde at 109056 begins with invalid VG name.
  Failed to &lt;span class=&quot;nb&quot;&gt;read &lt;/span&gt;metadata summary from /dev/sde
  Failed to scan VG from /dev/sde
  Couldn&lt;span class=&quot;s1&quot;&gt;&apos;t find device with uuid 3C36Fc-B9Fc-7LGH-EoAO-0r2c-ECrl-GuWorB.
  Cannot restore Volume Group VGPB with 1 PVs marked as missing.
  Restore failed.

# 임시 파일 복사 (백업용)
dd if=/dev/sde of=/root/temp bs=1020k count=1

# LVM 메타데이터 복사
dd if=/dev/sdd of=/dev/sde bs=1020k count=1 conv=notrunc

# LVM PV Header만 다시 복사
dd if=/root/temp of=/dev/sde bs=656 count=1 conv=notrunc
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;LVM 메타데이터에서는 어떤 데이터가 있는지 확인한다면, 조금 더 세부적인 이슈에 대응할 수도 있습니다. 한번 메타데이터에 대해서도 자세하게 살펴보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;lvm-의-메타데이터&quot;&gt;LVM 의 메타데이터&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;#### 4. 메타데이터 장애 복구&quot;&gt;4. 메타데이터 장애 복구&lt;/a&gt; 에서도 한 번 언급했던 LVM 의 메타데이터는 같은 볼륨 그룹 안의 물리 볼륨에 동일하게 저장되어 있습니다. 이번 장에서는 LVM 메타데이터가 어떻게 저장되어 있는지 &lt;a href=&quot;https://github.com/lvmteam/lvm2&quot;&gt;LVM2의 소스코드&lt;/a&gt;와 디스크 덤프를 비교하면서 상세하게 살펴보겠습니다.&lt;/p&gt;

&lt;p&gt;우선 덤프를 위해 샘플 메타데이터부터 위 글과 같이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sdd&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sde&lt;/code&gt; 의 물리 볼륨을 가지는 볼륨 그룹 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thick&lt;/code&gt; 과 논리 볼륨 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thick_vol&lt;/code&gt;, 스냅샷 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thick_snap&lt;/code&gt; 으로 구성해 보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# pvs&lt;/span&gt;
  PV         VG        Fmt  Attr PSize   PFree
  /dev/sdd   thick     lvm2 a--  &amp;lt;50.00g  48.98g
  /dev/sde   thick     lvm2 a--  &amp;lt;50.00g &amp;lt;50.00g

&lt;span class=&quot;c&quot;&gt;# vgs&lt;/span&gt;
  VG        &lt;span class=&quot;c&quot;&gt;#PV #LV #SN Attr   VSize  VFree&lt;/span&gt;
  thick       2   2   1 wz--n- 99.99g 98.98g

&lt;span class=&quot;c&quot;&gt;# lvs&lt;/span&gt;
  LV         VG        Attr       LSize  Pool Origin    Data%  Meta%  Move Log Cpy%Sync Convert
  thick_snap thick     swi-a-s--- 12.00m      thick_vol 0.00
  thick_vol  thick     owi-a-s---  1.00g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;우선 디스크 덤프 후 보기 편하게 16진수로 변경한 다음 전체 구성을 한번 살펴보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cat sdd_hex&lt;/span&gt;

...
0000200: 4c41 4245 4c4f 4e45 0100 0000 0000 0000  LABELONE........
0000210: a982 7799 2000 0000 4c56 4d32 2030 3031  ..w. ...LVM2 001
0000220: 4a6f 6c4f 5177 7833 4466 5033 756a 6e75  JolOQwx3DfP3ujnu
0000230: 776e 6435 4342 4735 6230 6747 5975 3874  wnd5CBG5b0gGYu8t
0000240: 0000 0080 0c00 0000 0000 1000 0000 0000  ................ 
0000250: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000260: 0000 0000 0000 0000 0010 0000 0000 0000  ................
0000270: 00f0 0f00 0000 0000 0000 0000 0000 0000  ................
0000280: 0000 0000 0000 0000 0200 0000 0100 0000  ................
0000290: 0000 0000 0000 0000 0000 0000 0000 0000  ................

...

0001000: 2af4 634e 204c 564d 3220 785b 3541 2572  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.cN LVM2 x[5A%r
0001010: 304e 2a3e 0100 0000 0010 0000 0000 0000  0N&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;............
0001020: 00f0 0f00 0000 0000 00a0 0100 0000 0000  ................
0001030: 0007 0000 0000 0000 a181 917c 0000 0000  ...........|....
0001040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001080: 0000 0000 0000 0000 0000 0000 0000 0000  ................

...

001b000: 7468 6963 6b20 7b0a 6964 203d 2022 3266  thick &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;.id &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;2f
001b010: 7559 4431 2d48 5856 792d 315a 3275 2d76  uYD1-HXVy-1Z2u-v
001b020: 797a 332d 7765 4530 2d6c 6553 4a2d 716e  yz3-weE0-leSJ-qn
001b030: 6d79 784f 220a 7365 716e 6f20 3d20 3333  myxO&quot;&lt;/span&gt;.seqno &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 33
001b040: 0a66 6f72 6d61 7420 3d20 226c 766d 3222  .format &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;lvm2&quot;&lt;/span&gt;
001b050: 0a73 7461 7475 7320 3d20 5b22 5245 5349  .status &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;RESI
001b060: 5a45 4142 4c45 222c 2022 5245 4144 222c  ZEABLE&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;READ&quot;&lt;/span&gt;,
001b070: 2022 5752 4954 4522 5d0a 666c 6167 7320   &lt;span class=&quot;s2&quot;&gt;&quot;WRITE&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;.flags.
001b080: 3d20 5b5d 0a65 7874 656e 745f 7369 7a65  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt;.extent_size

...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;메타데이터 정보가 여러 군데로 나눠서 저장되어 있는데, 크게 보자면 다음과 같이 구성되어 있는 것을 알 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/lvm_metadata1.png&quot; alt=&quot;디스크 덤프로 살펴보는 메타데이터의 구조&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; 디스크 덤프로 살펴보는 메타데이터의 구조 &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;가장 처음 부분부터 소스코드와 함께 살펴볼까요?&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mo&quot;&gt;0000200&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c41&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4245&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c4f&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4e45&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;LABELONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;........&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0000210&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a982&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7799&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c56&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d32&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2030&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3031&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LVM2&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;# cat lib/label/label.h
&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* On disk - 32 bytes */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label_header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt;	&lt;span class=&quot;kt&quot;&gt;int8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* LABELONE */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;38&lt;/span&gt;	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sector_xl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Sector number of this label */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;39&lt;/span&gt;	&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;crc_xl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* From next field to end of sector */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;	&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offset_xl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Offset from start of struct to contents */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt;	&lt;span class=&quot;kt&quot;&gt;int8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* LVM2 001 */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;맨 처음 부분은 &lt;strong&gt;Label Header&lt;/strong&gt; 입니다. &lt;strong&gt;Label Header&lt;/strong&gt; 에서는 다음과 같은 정보를 정의합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/lvm_metadata_label.png&quot; alt=&quot;Label Header&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; Label Header &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;LVM 이 사용하는 디스크라고 설명해 주며 정보가 어디까지 저장되어 있는지 설명해 주는 라벨이라고 말할 수 있습니다.&lt;/p&gt;

&lt;p&gt;다음은 &lt;strong&gt;PV Header&lt;/strong&gt; 입니다. &lt;strong&gt;PV Header&lt;/strong&gt; 에서는 다음과 같은 정보를 정의합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mo&quot;&gt;0000220&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a6f&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c4f&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5177&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7833&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4466&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5033&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;756&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;6e75&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;JolOQwx3DfP3ujnu&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0000230&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;776&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6435&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4342&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4735&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6230&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6747&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5975&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3874&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;wnd5CBG5b0gGYu8t&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0000240&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;0000250&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0000260&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0000270&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;00002&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0200&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;00002&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;# cat lib/format_text/layout.h
&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Fields with the suffix _xl should be xlate&apos;d wherever they appear */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* On disk */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pv_header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;int8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pv_uuid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ID_LEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* 32 Byte */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt; 	&lt;span class=&quot;cm&quot;&gt;/* This size can be overridden if PV belongs to a VG */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;46&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device_size_xl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Bytes */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;47&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt; 	&lt;span class=&quot;cm&quot;&gt;/* NULL-terminated list of data areas followed by */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;49&lt;/span&gt; 	&lt;span class=&quot;cm&quot;&gt;/* NULL-terminated list of metadata area headers */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; 	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disk_locn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disk_areas_xl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Two lists */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;51&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;# cat lib/format_text/format-text.h
&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;67&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* On disk */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;68&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disk_locn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;69&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Offset in bytes to start sector */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Bytes */&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;71&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;비트단위로 저장되어 있어 일일이 의미를 파악하기 어려울 수도 있는데, &lt;strong&gt;PV Header&lt;/strong&gt; 에서는 다음과 같은 정보를 포함하고 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/lvm_metadata_pv.png&quot; alt=&quot;PV Header&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; PV Header &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;디스크에 정의된 PV 를 식별하기 위한 정보와 그 외 메타데이터의 정보의 위치를 저장하고 있습니다. 위 설명을 토대로 메타데이터의 헤더 영역 정보를 계산해 보자면, 초록색으로 시작점을 알리는 offset, 과 그 길이인 size 를 확인할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Metadata Header Offset&lt;/strong&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0010 0000 0000 0000&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Metadata Header Size&lt;/strong&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;00f0 0f00 0000 0000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;:bulb: NOTE &lt;br /&gt;
bswap 을 사용하여 데이터를 저장하고 읽는 경우가 있습니다. 이는 byte 단위로 swap 해서 읽고 쓸 수 있는데, 예를 들어 metadata header offset 의 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x0000 0000 0000 1000&lt;/code&gt; 로 해석할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;이제 &lt;strong&gt;Metadata Header&lt;/strong&gt; 를 살펴보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mo&quot;&gt;0001000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;af4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;634&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;204&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;564&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3220&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;785&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3541&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2572&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LVM2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001010&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;304&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a3e&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0010&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;............&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001020&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a0&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0100&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001030&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0007&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a181&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;917&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;...........&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001040&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001050&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001060&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;0001070&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;00010&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0000&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;................&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;# cat lib/format_text/layout.h
&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;71&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* On disk */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;72&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Structure size limited to one sector */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;73&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mda_header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;74&lt;/span&gt;		&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;checksum_xl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Checksum of rest of mda_header */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt;		&lt;span class=&quot;kt&quot;&gt;int8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* To aid scans for metadata */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;76&lt;/span&gt;		&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;77&lt;/span&gt;		&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Absolute start byte of mda_header */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;78&lt;/span&gt;		&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Size of metadata area */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;79&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; 	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_locn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_locns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* NULL-terminated list */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;81&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

 &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* On disk */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;61&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_locn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;62&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Offset in bytes to start sector */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;63&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Bytes */&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;checksum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;65&lt;/span&gt; 	&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metadata Header&lt;/strong&gt; 에서는 다음과 같은 정보를 포함하고 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/lvm_metadata_metadata.png&quot; alt=&quot;Metadata Header&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; Metadata Header &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;이제 앞서 &lt;strong&gt;PV Header&lt;/strong&gt; 에서 &lt;strong&gt;Metadata Header&lt;/strong&gt; 의 저장된 위치를 계산했던 것처럼, &lt;strong&gt;Metadata&lt;/strong&gt; 의 위치를 이제 간단하게 계산해 볼 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Metadata Offset&lt;/strong&gt; : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x1000 + x1a000 = x1b000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7468&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6963&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b0a&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6964&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;203&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2022&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3266&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;thick&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2f&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;001b010: 7559 4431 2d48 5856 792d 315a 3275 2d76  uYD1-HXVy-1Z2u-v&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;001b020: 797a 332d 7765 4530 2d6c 6553 4a2d 716e  yz3-weE0-leSJ-qn&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;001b030: 6d79 784f 220a 7365 716e 6f20 3d20 3333  myxO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seqno&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b040&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a66&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f72&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d61&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7420&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;226&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;766&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3222&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;lvm2&quot;&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b050&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a73&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7461&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7475&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7320&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b22&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5245&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5349&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;RESI&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;001b060: 5a45 4142 4c45 222c 2022 5245 4144 222c  ZEABLE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;READ&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b070&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2022&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5752&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4954&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4522&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d0a&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;666&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6167&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7320&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;&quot;WRITE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;001&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b080&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b5d&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a65&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7874&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;656&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;745&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7369&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a65&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extent_size&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;실제 메타데이터에서는 볼륨 그룹 객체를 기반으로 PV 정보와 LV 정보를 정의하여 LVM 을 관리하고 있었습니다. Thin 볼륨과 Thick 볼륨은 다음과 같이 메타데이터의 형태가 다릅니다. 메타데이터를 통해서 Thin 볼륨은 Thin 풀에서 정의되어 있는 PV 의 데이터를 활용할 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/lvm_metadata2.png&quot; alt=&quot;Metadata&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; Thin, Thick 볼륨의 Metadata &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;마치며&quot;&gt;마치며&lt;/h3&gt;

&lt;p&gt;이 외에도 스냅샷 서비스의 스펙을 결정하기 위해서 많은 고민이 있었고, 또 고도화를 위해서 많은 의견들이 있었습니다. 예를 들어 섀도 복제본(Shadow copy)을 통한 스냅샷의 Windows 클라이언트 노출, Gluster 볼륨의 스냅샷 제공, PV 의 메타데이터가 너무 작은 경우 스냅샷 생성 실패 사례, 여러 가지 장애 케이스(Thin 볼륨, 파일 시스템, PV, VG, Data LV 등의 각각의 장애 사례)에 대한 위험 관리의 다양한 측면으로 서비스를 더욱더 안정적으로 확장해 가도록 진행하고 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;참고&quot;&gt;참고&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man7/lvmthin.7.html&quot;&gt;lvmthin linux manual page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lvm-글-더보기&quot;&gt;LVM 글 더보기&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://tech.gluesys.com/blog/2019/04/08/LVM.html&quot;&gt;LVM Basic Architecture&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tech.gluesys.com/blog/2024/06/03/LVM-Plugin.html&quot;&gt;LVM 스냅샷 관리 기능 개발 후기 (1)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 03 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2024/06/03/LVM-Plugin.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2024/06/03/LVM-Plugin.html</guid>
        
        <category>스냅샷</category>
        
        <category>스토리지</category>
        
        <category>LVM</category>
        
        <category>Thin Provisioning</category>
        
        <category>장애</category>
        
        <category>Storage</category>
        
        <category>Metadata</category>
        
        <category>디스크 덤프</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>CXL 3.1 소개와 스토리지</title>
        <description>&lt;p&gt;지난 번 &lt;a href=&quot;https://tech.gluesys.com/blog/2021/11/15/cxl_1.html&quot;&gt;&amp;lt;PCIe를 대체할 인터커넥트 표준 기술, CXL&amp;gt;&lt;/a&gt; 포스트에서 CXL(Compute Express Link)에 대해 2.0 버전을 기준으로 내용을 다룬 바 있었습니다. 그로부터 약 2년이 지난 현재(2024년 1월), CXL은 기술적인 성숙도 뿐만 아니라, 인터커넥트 표준으로써의 위상도 많이 높아졌습니다.&lt;/p&gt;

&lt;p&gt;현재 CPU, GPU, DPU 등 프로세서는 각각 구분된 메모리 공간을 가지고 있고, 프로세서 간 데이터 공유를 위해 메모리 간 데이터 이동 및 복사를 PCIe를 통해 수행합니다. PCIe는 고속 인터페이스이기는 하나, 대규모 데이터 전송 시 프로토콜 처리 과정에서 오버헤드가 발생하며, 메모리 채널에 비해 매우 느립니다. 게다가 프로세서 간에 메모리를 공유하는 경우, 한쪽 메모리에서 데이터가 변경되면 다른 쪽 메모리의 데이터와 일관성 문제가 발생하게 됩니다. CXL은 이러한 프로세서 메모리 간 장벽을 허물고, 공유 메모리 풀을 형성해 프로세서가 거대한 메모리 자원을 저지연으로 접근하게 하는 것이 목적입니다. 또한, 프로세서에서 메모리 풀 접근 시 이동 및 복사 과정이 필요 없기 때문에 메모리 간 일관성을 유지할 수 있습니다. CXL은 데이터센터와 같은 대규모 데이터를 운용하고 처리하는 환경에서 메모리 자원의 낭비 없이 활용할 수 있고, 기존과는 달리 애플리케이션에 매우 큰 메모리를 할당할 수 있습니다. 자세한 내용은 이전 포스트 &lt;a href=&quot;https://tech.gluesys.com/blog/2021/11/15/cxl_1.html&quot;&gt;&amp;lt;PCIe를 대체할 인터커넥트 표준 기술, CXL&amp;gt;&lt;/a&gt; 를 참고 부탁드립니다.&lt;/p&gt;

&lt;p&gt;지난 CXL 2.0 버전에서는 CXL 스위치의 등장과 퍼시스턴트 메모리 지원, CXL IDE를 통한 보안 강화가 주 내용이였습니다. 그리고 2022년 8월에 3.0 버전, 작년 11월에 3.1 버전을 공개하면서 새로운 아키텍처와 기능들을 발표했습니다. 많이 늦기는 했지만 이번 포스트에서는 지난 CXL 3.0 버전부터 어떤 내용들이 업데이트되었는지 알아보고자 합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;cxl-31까지의-주요-변경사항&quot;&gt;CXL 3.1까지의 주요 변경사항&lt;/h2&gt;

&lt;p&gt;이번 CXL 3.0과 3.1 버전은 전세계 주요 산업 관계자들과 커뮤니티의 기여에 힘입어 매우 많은 구조와 기능들이 업데이트되었습니다. CXL 3.0부터는 PCIe 6.0을 지원하게 되면서 패브릭 기능, 구조 및 보안 등을 개선했고, 클러스터 환경에서의 캐시 일관성과 메모리 풀 공유 기능을 강화하는 등 CXL의 성능과 활용 범위가 다시 한번 확장되었습니다. 주요 업데이트 내용은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;대역폭 2배 향상:&lt;/strong&gt; CXL 2.0까지는 PCIe 5.0을 지원했는데, CXL 3.0부터는 PCIe 6.0을 지원하게 되었습니다. 이로 인해 기존 CXL 2.0 대역폭의 2배인 최대 64GT/s까지 제공해 PCIe x16 링크 기준 이론상 최대 256GB/s까지 성능을 제공할 수 있게 되었습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;PCIe 6.0 지원에 따른 기능 개선:&lt;/strong&gt; CXL 3.0부터는 PCIe 6.0에서 제공하는 4레벨 펄스 진폭 변조(PAM-4) 시그널링과 경량 FEC(Forward Error Correction), CRC(Cyclic Redundancy Check)를 그대로 활용해 낮은 지연시간과 복잡도, 전송 에러 방지를 구현하고자 했고, 256 바이트 FLIT(Flow Control Unit) 단위로 데이터를 전송합니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/CXL31_hdm_p2paccess.PNG&quot; alt=&quot;HDM에 직접 peer-to-peer 접근&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; HDM에 직접 peer-to-peer 접근 &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;캐시 일관성 강화:&lt;/strong&gt; CXL 3.0 부터는 CXL 메모리 장치에서 BISnp(Back-Invalidate Snoop)로 호스트의 캐시 상태를 변경시켜 다중 호스트 접근 환경에서 HDM&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;의 캐시 일관성이 강화(enhanced coherency)되었다고 볼 수 있습니다. 게다가 CXL 3.0 부터 호스트의 간섭 없이 Type 2 또는 Type 3 장치가 HDM에 직접 peer-to-peer 접근이 가능해져, 대규모 시스템 환경에서 안정적인 성능을 제공할 수 있게 되었습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;메모리 풀 및 메모리 공유:&lt;/strong&gt; 이런 하드웨어 기반의 일관화를 활용해 소프트웨어의 개입 없이 CXL 메모리 풀에 연결된 메모리 장치의 한 주소 영역을 복수의 호스트가 동시(simultaneously)에 접근하고, 그 영역의 데이터가 항상 일관된 최신의 상태를 유지하는 메모리 공유(memory sharing) 개념이 추가되었습니다. 예를 들어, 호스트 1과 호스트 2가 한 메모리 장치 영역에 있는 데이터 A를 일관성을 유지하면서 각각의 로컬 메모리에 동시에 불러와 작업할 수 있다는 것입니다. 메모리 공유 기능은 GPU 서버 팜과 같이 여러 컴퓨팅 서버가 대규모 연산 작업을 수행할 때 유용하다고 볼 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;새로운 패브릭 구조:&lt;/strong&gt; CXL 3.0의 패브릭은 이전 CXL 버전의 트리 구조와는 다른 non-tree 구조(또는 multipath 구조)를 제공하고, 포트 기반 라우팅(Port Based Routing, 이하 PBR)을 통해 최대 4,096개의 노드까지 상호 연결을 제공합니다. 이로 인해 지연 시간과 대역폭이 향상되었습니다. 여기서 말하는 노드는 모든 엔드 포인트를 의미하며, CPU 호스트나 스마트 NIC, 가속기, 메모리 장치, PCIe 장치, GFAM 장치 등이 될 수 있겠습니다. 추가로, CXL 3.1 에서는 PBR 스위치에 대한 CXL Fabric Manager API가 공개되었습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/CXL31_cxlswitchhierarchy.jpg&quot; alt=&quot;다중 레벨 스위치&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; 다중 레벨 스위치 &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;다중 레벨 스위치 지원:&lt;/strong&gt; CXL 2.0에서 처음 CXL 스위치를 선보이면서 스위치를 통해 호스트를 여러 장치들과 연결할 수 있게 되었고, CXL 3.0에서는 캐스캐이드 방식으로 CXL 스위치 간 계층 구성이 가능하게 되었습니다. 추가로, 호스트 당 여러 개의 Type 1과 Type 2 장치를 같이 연결시킬 수 있어, 랙 스케일 이상의 대규모 메모리 자원 풀을 구성하고 공유할 수 있겠습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;GFAM:&lt;/strong&gt; CXL 3.0의 가장 큰 업데이트 중 하나는 바로 GFAM(Global Fabric Attached Memory)입니다. GFAM은 DRAM이나 플래시 메모리 등 휘발성 및 비휘발성 메모리 장치로 구성된 별도의 공유 메모리 풀로, &lt;a href=&quot;https://tech.gluesys.com/blog/2021/12/23/genz.html#:~:text=%EA%B3%B5%EA%B0%9C%EB%90%9C%201.1%EC%9E%85%EB%8B%88%EB%8B%A4.-,Gen%2DZ%EC%99%80%20CXL%EC%9D%98%20%ED%86%B5%ED%95%A9,-%EC%A7%80%EB%82%9C%20%EC%BB%B4%ED%8F%AC%EC%A0%80%EB%B8%94%20%EC%9D%B8%ED%94%84%EB%9D%BC%EB%9E%80&quot;&gt;CXL이 흡수한 Gen-Z 인터커넥트&lt;/a&gt; 의 Fabric Attached Memory를 구현한 것으로 보입니다. 구성 자체는 기존 Type 3 장치와 비슷하다고 볼 수 있겠습니다만, GFAM은 PBR을 통해 한 개 이상의 노드에서(최대 4,095개) 메모리 풀에 접근해 필요에 따라 메모리 자원을 활용할 수 있게 한다는 점이 특징입니다. 노드는 GFAM 메모리 풀에 직접 접근할 수도 있고, CXL 스위치를 통해서 접근할 수도 있습니다. 게다가 GFAM은 여러 CXL 장치들과의 연결에 MapReduce&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; 알고리즘을 적용할 수 있어 성능 및 효율성을 향상시킬 수 있습니다. GFAM은 이처럼 대규모 멀티 노드 구성 환경에서 복수의 호스트가 일관성이나 확장성 문제없이 공유 메모리를 활용할 수 있게 하는 것이 목적이라고 볼 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;호스트 간 로컬 메모리 공유:&lt;/strong&gt; CXL 3.1에서는 GIM(Global Integrated Memory)라는 개념을 소개하고 있습니다. GIM은 호스트의 로컬 물리 주소 공간을 매핑한 메모리입니다. 원격의 호스트나 장치들이 RDMA나 도메인 간 메시징 목적으로 GIM에 접근할 것으로 정의하고 있으며, 캐싱이나 메모리 풀 용도가 아니기 때문에 CXL.cache나 CXL.mem으로는 사용이 제한됩니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;가상화 기반 TEE 보안 프로토콜 지원:&lt;/strong&gt; CXL 3.1부터는 TSP (Trusted Execution Environments Security Protocol)를 통해 기존 호스팅 환경과는 격리된 보안 환경에서 직접 연결된 CXL Type 3 메모리 풀 간의 기밀 컴퓨팅 워크로드를 호스팅할 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;메모리 확장 장치 개선:&lt;/strong&gt; CXL 3.1에서는 캐시 블록의 상태(변경, 공유 등)에 대한 2-bit 메타데이터에 32-bit를 추가했습니다. 이 34-bit 메타데이터는 접근 권한, 데이터 태깅, 메모리 티어링 등이 주 용도이고, DDR6의 메타데이터 확장 기능과도 연계 가능합니다. 게다가 각종 메모리 오류에 대한 정보를 추가해 RAS(Reliability, Availability, and Serviceability)를 개선했습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;cxl과-스토리지의-관계&quot;&gt;CXL과 스토리지의 관계&lt;/h2&gt;

&lt;p&gt;CXL은 프로세서가 활용할 수 있는 메모리 가용량을 높여 컴퓨팅 성능을 가속하고, 메모리 확장 시 발생하는 비용을 최소화하는 것이 주 목적입니다. 다만, 이처럼 CXL을 통해 컴퓨팅 성능과 비용 효율은 확보할 수 있지만, 데이터 이동으로 인한 대역폭 부하가 높아질 것이기 때문에 스토리지 대역폭에 대한 요구사항은 높아질 수밖에 없습니다. 게다가 대규모 메모리 자원을 요구하는 애플리케이션의 경우, CXL 메모리 풀을 통해 보다 더 많은 메모리 자원을 활용할 수 있고, 메모리 자원이 분산되어 있어 입출력에 대한 부하는 낮지만, 이후 작업이 끝나고 메모리가 재할당되는 과정에서 스토리지에 가해지는 부하는 급격하게 높아질 수 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 CXL은 스토리지 성능 향상에도 도움을 줄 것으로 보입니다. CXL은 호스트의 간섭 없이 peer-to-peer 읽기 및 쓰기로 데이터를 메모리에서 이동시킬 수 있어 RDMA 방식(호스트가 중간에 낌)에 비해 빠른 접근이 가능합니다. 또한, 태스크 스위칭이 일어날 때마다 호스트가 IO 스트림을 개시하거나 멈출 필요가 없기 때문에 보다 많은 전송량을 제공할 수 있고, 호스트 부하도 줄일 수 있어 입출력 성능이 향상될 수 있습니다. 무엇보다 기존 시스템 구성에 비해 메모리 자원이 커지기 때문에 캐시로 활용하는 경우, 읽기 캐시나 쓰기 캐시로 활용하는 메모리 공간도 커질 수 있어, 스토리지에 대한 부하도 그만큼 줄어들 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;CXL은 현재 인터커넥트 중에서도 독보적인 관심을 받는다고 할 수 있을 정도로, 차세대 메모리 인터커넥트로써의 위치를 공고히 하고 있습니다. 다만, 이제 막 CXL 1.1이나 2.0을 적용한 디바이스가 출시된 상황이기 때문에 조금 더 지켜볼 필요가 있겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;https://www.computeexpresslink.org/spec-landing&lt;/li&gt;
  &lt;li&gt;https://www.computeexpresslink.org/_files/ugd/0c1418_a8713008916044ae9604405d10a7773b.pdf&lt;/li&gt;
  &lt;li&gt;https://www.computeexpresslink.org/_files/ugd/0c1418_6ede12bda4d34ffeb879c3700dde38f9.pdf&lt;/li&gt;
  &lt;li&gt;https://community.cadence.com/cadence_blogs_8/b/fv/posts/navigating-cache-coherence-the-back-invalidate-feature-in-cxl-3-0&lt;/li&gt;
  &lt;li&gt;https://arxiv.org/ftp/arxiv/papers/2306/2306.11227.pdf&lt;/li&gt;
  &lt;li&gt;https://www.anandtech.com/show/17520/compute-express-link-cxl-30-announced-doubled-speeds-and-flexible-fabrics&lt;/li&gt;
  &lt;li&gt;https://www.synopsys.com/designware-ip/technical-bulletin/cxl2-3-storage-memory-applications.html&lt;/li&gt;
  &lt;li&gt;https://www.openfabrics.org/wp-content/uploads/2023-workshop/2023-workshop-presentations/day-2/202_MWagh.pdf&lt;/li&gt;
  &lt;li&gt;https://www.servethehome.com/cxl-3-1-specification-aims-for-big-topologies/&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/tip/How-the-CXL-interconnect-will-affect-enterprise-storage&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/feature/How-CXL-30-technology-will-affect-enterprise-storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;각주&quot;&gt;각주&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;HDM (Host-managed Device-attached Memory): 시스템 주소 공간에 매핑되어 호스트 측에서 일반적인 write-back 방식으로 접근 가능한 메모리를 말함. 주소 공간에 매핑이 안되어 있으나, 호스트에서 접근 가능한 메모리는 PDM(Private-managed Device-attached Memory)이라고 하며, CXL 장치의 메모리는 HDM과 PDM으로 구분됨. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;MapReduce: MapReduce를 도입한 시스템은 분산 서버의 다양한 태스크를 병렬로 수행하고, 다양한 영역의 시스템 간의 모든 통신과 데이터 전송을 관리하고, 장애 내구성과 가용성을 오케스트레이트할 수 있음. 주로 컴퓨터 노드 클러스터에서 사용하는 대규모 데이터셋의 병렬 처리에 적합하며, 데이터가 저장된 곳에서 처리(locality of data)할 수 있게 해 통신 부하를 최소화하는 것이 목적임. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 22 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2024/01/22/CXL31storage.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2024/01/22/CXL31storage.html</guid>
        
        <category>CXL</category>
        
        <category>인터커넥트</category>
        
        <category>Interconnect</category>
        
        <category>캐시 일관성</category>
        
        <category>Cache Coherence</category>
        
        <category>PCIe</category>
        
        <category>고성능</category>
        
        <category>High Performance</category>
        
        <category>Storage</category>
        
        <category>스토리지</category>
        
        <category>표준</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>ZFS 파일 시스템</title>
        <description>&lt;p&gt;이번 기술 블로그 포스트에서는 ZFS에 대해 소개하고자 합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;zfs-소개&quot;&gt;ZFS 소개&lt;/h2&gt;

&lt;p&gt;ZFS는 잘 알려진 파일 시스템 중에서도 비교적 최근에 등장한 파일 시스템입니다. 2001년 썬 마이크로시스템즈에서 자사 운영체제인 솔라리스의 일부로 개발을 시작했습니다. ZFS는 안정성과 성능, 그리고 데이터 보호 기능들이 강화된 파일 스토리지를 목적으로 개발되었습니다. 이후 오픈소스로 공개했었으나, 2010년에 오라클이 썬 마이크로시스템즈를 인수한 이후로는 오라클 ZFS라는 명칭으로 사유화되었습니다. 이와는 독립적으로 2013년부터 오픈소스 프로젝트인 OpenZFS가 오픈소스의 명맥을 이어 나가고 있습니다.&lt;/p&gt;

&lt;p&gt;일반적으로 64비트나 그 이하를 지원하는 파일 시스템들과는 달리, ZFS는 128비트 파일 시스템입니다. 이론상 단일 스토리지 풀의 최대 지원 용량이 256,000조 제타바이트로, 사실상 실제 환경에서 보기 어려운 용량 제한을 가지고 있습니다. 현재(2023년 12월) 기준으로 존재하는 파일 시스템 중 가장 큰 비트 사이즈를 지원한다고 볼 수 있습니다. 또한, ZFS의 기본 블록 크기는 128KB이지만 가변 블록 크기를 지원해 필요에 따라 블록 크기를 변경할 수 있습니다. 워크로드마다 최적의 블록 크기가 다르기도 하고, 압축 기능 사용 시 작은 블록 크기를 활용해 압축 효율을 높일 수도 있습니다.&lt;/p&gt;

&lt;p&gt;ZFS의 핵심 컨셉은 바로 파일 시스템과 볼륨 매니저를 같이 제공한다는 것입니다. 기존의 파일 시스템은 스토리지 장치별로 볼륨을 생성하고, 이 볼륨들을 관리하기 위해 볼륨 매니저가 필요했습니다. 대표적으로, ext4나 XFS와 같은 파일 시스템은 &lt;a href=&quot;https://tech.gluesys.com/blog/2019/04/08/LVM.html&quot;&gt;LVM(Logical Volume Manager)&lt;/a&gt; 과 같은 볼륨 매니저를 통해 다수의 물리적인 스토리지를 관리하고 별도의 하드웨어 및 소프트웨어 &lt;a href=&quot;https://tech.gluesys.com/blog/2020/07/22/storage_6_intro.html&quot;&gt;RAID&lt;/a&gt; 와 연계해 데이터 보호 기능을 제공해 왔습니다. 하지만 ZFS는 이러한 기능들을 한 번에 제공하는 것이 특징입니다. 물리적인 스토리지와 이로 구성된 볼륨 구조뿐만 아니라, 여기에 저장된 파일에 대한 정보도 가지고 있습니다. 이 때문에 물리적인 디스크를 추가할 때 중단 없이 스토리지 풀에 추가할 수 있고, 해당 풀을 사용하는 파일 시스템들이 즉시 신규 스토리지 공간을 활용할 수 있게 합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;zfs의-주요-기능&quot;&gt;ZFS의 주요 기능&lt;/h2&gt;

&lt;h3 id=&quot;arc-및-l2arc-캐싱&quot;&gt;ARC 및 L2ARC 캐싱&lt;/h3&gt;

&lt;p&gt;ZFS는 빠른 입출력을 지원하기 위해 독자적인 캐싱 메커니즘을 제공합니다. 다만, 모든 캐시를 RAM에 저장하기에는 공간과 비용 문제가 있어 SSD와 같은 고속 스토리지 미디어에 분산시키는 계층형 캐시 구조를 채용했습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;ARC(Adaptive Replacement Cache)&lt;/strong&gt;는 메모리에 저장되는 캐시입니다. ARC에 저장되는 데이터는 접근 시간이나 빈도뿐만 아니라, 캐시와 디스크 중 읽은 데이터의 출처가 어디가 더 많은지(hit ratio, 캐시 적중률)도 확인해서 캐시 적중률이 높은 데이터를 중심으로 저장합니다. 이는 결국 캐시 적중률이 낮은 데이터에 대한 접근도 빨라질 수 있습니다. 캐시 적중률이 높은 데이터를 저장할수록 디스크 접근에 대한 부하도 낮아지기 때문에, 결국 디스크에 저장된 캐시 적중률이 낮은 데이터에도 빠르게 접근할 수 있기 때문입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;L2ARC(Level 2 ARC)&lt;/strong&gt;는 ARC의 보조 저장 공간을 위해 SSD를 활용한 캐시입니다. ARC에서 데이터를 찾지 못하였다면 디스크에 접근하기 전 L2ARC에서 빠르게 찾아볼 수 있어 데이터에 대한 높은 접근성을 제공합니다. 일반적으로 RAM보다는 느리지만, vdev를 구성하는 스토리지 미디어보다는 빠른 SSD를 사용합니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;체크섬&quot;&gt;체크섬&lt;/h3&gt;

&lt;p&gt;ZFS가 가진 또 하나의 특징은 바로 데이터 무결성을 최대한 보장하도록 디자인되었다는 것입니다. ZFS는 파일 시스템의 모든 계층의 모든 데이터와 메타데이터에 대한 체크섬을 제공합니다. ZFS의 스크럽(Scrub) 기능을 통해 체크섬 계산으로 데이터의 손상 여부를 확인하는 유효성 검사를 수행하고, 필요시 복구하는 자가 복구(Self-healing) 과정을 통해 bit rot와 같은 사일런트 커럽션까지 대처할 수 있습니다. 그리고 이 모든 과정을 메모리에서 수행하기 때문에 실시간 작업이 가능합니다. 데이터 블록의 체크섬 데이터는 같이 저장되지 않고, 해당 데이터 블록의 포인터와 함께 저장됩니다. 이 때문에 파일 시스템이 감지할 수 없는 데이터 블록 손상이 발생하는 이슈에 영향이 없다고 볼 수 있습니다.&lt;/p&gt;

&lt;h3 id=&quot;copy-on-write&quot;&gt;Copy-on-Write&lt;/h3&gt;

&lt;p&gt;ZFS는 기본적으로 &lt;a href=&quot;https://tech.gluesys.com/blog/2020/12/16/storage_7_intro.html#:~:text=%ED%99%9C%EC%9A%A9%ED%95%A0%20%EC%88%98%EB%8F%84%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4.-,Copy%2Don%2Dwrite%20%EC%8A%A4%EB%83%85%EC%83%B7,-Copy%2Don%2Dwrite&quot;&gt;COW(copy-on-write)&lt;/a&gt; 메커니즘을 활용해 데이터를 저장합니다. 쓰기를 수행할 때 기존 데이터에 단순히 덮어쓰지 않고, 스토리지의 다른 영역에 새로운 데이터만 쓰고 메타데이터를 업데이트하는 방식을 말합니다. 이로써 시스템 장애 발생 시, 최근에 쓰기를 수행한 데이터는 잃을 수도 있겠지만, 기존 데이터나 파일 시스템에 대한 영향은 방지할 수 있어 데이터 자산 손실을 최소화할 수 있습니다.&lt;/p&gt;

&lt;h3 id=&quot;스냅샷-및-클론&quot;&gt;스냅샷 및 클론&lt;/h3&gt;

&lt;p&gt;ZFS가 기본적으로 COW 방식으로 데이터를 저장하고 있기 때문에 &lt;a href=&quot;https://tech.gluesys.com/blog/2020/12/16/storage_7_intro.html&quot;&gt;스냅샷&lt;/a&gt;을 생성하는 것이 매우 수월하다고 볼 수 있습니다. 단순히 특정 시점에 파일 시스템이 기록한 포인터의 복제를 만들어 놓는 것으로 즉각적으로 스냅샷을 만들 수 있습니다. 이렇게 특정 시점별로 생성된 스냅샷으로 랜섬웨어나 시스템 장애 등이 발생 시 손실된 데이터를 복구할 수 있습니다.&lt;/p&gt;

&lt;p&gt;이런 스냅샷은 기본적으로 읽기 전용이지만, 쓰기 가능한 스냅샷(또는 클론)도 생성할 수 있습니다. 클론은 두 개의 독립적인 파일 시스템이 특정 데이터 블록을 공유하는 형태입니다. 클론 중 한쪽에 새로운 데이터 쓰기가 발생하면 새로운 데이터 블록에 대한 쓰기가 수행되지만, 기존 데이터는 어느 클론이든 동일한 상태로 유지합니다.&lt;/p&gt;

&lt;h3 id=&quot;압축-및-중복-제거&quot;&gt;압축 및 중복 제거&lt;/h3&gt;

&lt;p&gt;ZFS는 인라인 데이터 압축과 &lt;a href=&quot;https://tech.gluesys.com/blog/2020/05/20/storage_4_intro.html&quot;&gt;중복 제거&lt;/a&gt; 기능을 제공합니다. ZFS는 LZ4, GZIP, LZJB, ZLE 등 다양한 압축 알고리즘을 지원하고, 중복된 데이터를 체크섬으로 찾아 제거하는 중복 제거 기능을 통해 데이터 저장의 효율을 높입니다. ZFS 압축 및 중복 제거 기능은 메모리를 많이 소모하기 때문에 기본적으로 비활성화되어 있습니다.&lt;/p&gt;

&lt;h3 id=&quot;raidz&quot;&gt;RAIDZ&lt;/h3&gt;

&lt;p&gt;ZFS는 RAIDZ라는 자체적인 소프트웨어 RAID 기능을 제공합니다. 제공하는 RAID 수준은 RAIDZ-1, RAIDZ-2, RAIDZ-3로 구분되며, 뒤에 붙는 숫자는 각각 RAID 수준에서 지원하는 패리티의 개수를 말합니다. 한마디로 각각 RAID 5, RAID 6, 3개 패리티를 지원하는 RAID로 보시면 됩니다. 다만 RAIDZ는 기존 RAID와는 다른 점이 몇 가지 있습니다. RAIDZ는 COW를 활용하기 때문에 메타데이터로 높은 수준의 데이터 무결성을 제공하고, 메타데이터에 대한 이중화 및 체크섬을 제공합니다. 또한, 기존 RAID와는 달리 블록 크기가 스트라이프마다 다른 크기로 저장될 수 있고, 모든 스트라이프를 새로 쓰기 때문에 RAID 5의 쓰기 구멍(write hole) 이슈&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;에서 자유롭다고 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;zfs의-스토리지-풀-구조&quot;&gt;ZFS의 스토리지 풀 구조&lt;/h2&gt;

&lt;p&gt;ZFS의 스토리지 풀은 크게 여러 디스크를 포함한 가상 장치인 vdev(virtual device의 약자)와 스토리지 풀을 말하는 zpool(ZFS pool의 약자), 그리고 데이터셋으로 구분됩니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/ZFSintro_pool.png&quot; alt=&quot;ZFS 스토리지 풀 구조&quot; width=&quot;700&quot; /&gt;&lt;/p&gt;
&lt;center&gt;&amp;#60; 표. ZFS 스토리지 풀 구조 &amp;#62;&lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3 id=&quot;vdev&quot;&gt;vdev&lt;/h3&gt;

&lt;p&gt;먼저 vdev는 스토리지 풀을 구성하는 최소 단위로, 하나 이상의 디스크나 RAID 그룹 등으로 구성됩니다. 데이터 vdev는 일반적인 데이터 저장을 목적으로 한 vdev이며, 앞서 설명한 RAIDZ 구성뿐만 아니라 디스크 간 미러링 및 스트라이핑 구성으로도 설정할 수 있습니다. 대부분의 vdev는 이처럼 일반적인 스토리지 용도로 쓰이지만, 캐시, 로그, 스페어와 같은 용도로도 쓰입니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;캐시(cache)&lt;/strong&gt;: 캐시 vdev는 L2ARC 캐시를 위한 공간을 말하며, 읽기 전용으로 제공됩니다. 주로 데이터 vdev 보다 높은 성능의 SSD로 구성합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;스페어(spare)&lt;/strong&gt;: 데이터 vdev에서 문제가 발생한 디스크를 자동으로 대체하기 위해 확보한 vdev입니다. 핫 스페어라고도 합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;로그(log)&lt;/strong&gt;: 로그 vdev는 SLOG(Separate Intent Log)라고도 불리며, 쓰기 전용 캐시입니다. 설정 시, 데이터 vdev에 데이터를 쓰기 전에 우선적으로 저장되며, 전력 장애 등 발생 시 데이터를 SLOG에서 읽어와 쓰기가 수행되지 못한 데이터를 복구할 수 있습니다. 캐시 vdev와 마찬가지로 높은 성능의 SSD로 구성합니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;zpool&quot;&gt;zpool&lt;/h3&gt;

&lt;p&gt;zpool은 ZFS 구조에서 최상위 계층에 있는 스토리지 풀로, 기본적으로 하나 이상의 vdev로 구성됩니다. 하나의 서버에는 여러 zpool이 존재할 수 있으며, 각 zpool은 독립적이라 서로 vdev를 공유할 수는 없습니다. zpool은 vdev를 추가함으로써 확장이 가능하지만, 역으로 풀을 줄이는 것은 불가능합니다. 이처럼 zpool은 vdev의 구성에 따라 용량을 유연하게 관리할 수 있으며, 이는 모두 ZFS 파일 시스템이 볼륨 구조뿐만 아니라 파일에 대한 모든 정보를 관리하기 때문입니다.&lt;/p&gt;

&lt;p&gt;이로 인한 장점 중 하나로, 결함이 발생한 디스크 교체 시 복구가 빠르다는 점이 있습니다. 디스크 장애가 발생할 경우, 결함이 발생한 디스크를 교체하고 새로운 디스크에 기존 데이터를 저장하는 리실버링(resilvering) 과정을 거칩니다. 일반적인 RAID 환경에서는 데이터를 전부 검사하는 과정이 필요하지만, ZFS 파일 시스템은 zpool의 모든 데이터를 파악하고 있기 때문에 필요한 부분만 리실버링을 수행해 작업 시간을 단축할 수 있습니다.&lt;/p&gt;

&lt;h3 id=&quot;데이터셋&quot;&gt;데이터셋&lt;/h3&gt;

&lt;p&gt;데이터셋은 zpool의 스토리지 풀을 공유하는 일종의 볼륨 또는 파티션이라고 볼 수 있습니다. 데이터셋은 zpool 내 여러 개의 파일 디렉터리처럼 생성될 수 있으며, 데이터셋 아래에 데이터셋이 존재할 수도 있습니다. 또한 데이터셋 마다 크기는 물론, 스냅샷, 쿼터, 압축 및 중복 제거 등 다른 설정으로 생성할 수 있다는 점도 특징입니다.&lt;/p&gt;

&lt;p&gt;추가로, 데이터셋 말고도 zvol이라는 볼륨도 있습니다. zvol은 데이터셋과 같이 zpool을 사용하지만, 데이터셋처럼 파일 시스템 구조가 아닌 기본적인 블록 레벨로 데이터를 관리합니다. 이 때문에 다른 파일 시스템을 올리거나 iSCSI 익스포트 등의 용도로 활용할 수 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;zfs-도입-시-고려해야-할-점&quot;&gt;ZFS 도입 시 고려해야 할 점&lt;/h2&gt;

&lt;p&gt;이처럼 ZFS는 NAS에서 널리 사용되는 파일 시스템 중에서도 다양한 기능과 안정성으로 널리 사용되고 있지만 실제로 도입하는 데 있어서 몇 가지 확인이 필요한 부분들이 있습니다. 예를 들어, ARC를 제대로 활용하기 위해서는 일정 수준 이상의 메모리 자원이 요구됩니다. 이 때문에 캐싱 등 메모리 자원이 많이 필요한 환경에서는 그만큼 메모리 용량을 늘릴 필요가 있겠습니다. 게다가 파일 시스템이 단일 서버 환경으로 제한되어 있기 때문에, 스케일아웃 스토리지 환경을 구성하려면 Lustre나 GPFS와 같은 병렬 파일 시스템과 연계하는 방법을 찾아야 합니다. 무엇보다 ZFS는 현재 오픈소스인 OpenZFS와 상용인 Oracle ZFS로 양분되어 있다는 점도 고려해야 합니다. OpenZFS는 직접 구축해야 하는 수고가 있지만 무료로 받을 수 있고 OpenZFS를 탑재한 상용 제품이 여럿 있어 선택지가 있고, Oracle ZFS는 Oracle 스토리지 제품에 종속되어 있고 비용이 발생하지만, Oracle의 기술지원 서비스를 받을 수 있다는 장점이 있습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;이번 포스트에서는 ZFS의 개요와 주요 기능 및 구조를 소개하고, 도입 시 고려해야 할 부분들을 간단하게 다루어 보았습니다. 앞으로도 ZFS와 같은 파일 시스템을 소개하는 포스트를 조금씩 올려보고자 합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;https://itslinuxfoss.com/zfs-vs-xfs-file-system/&lt;/li&gt;
  &lt;li&gt;https://www.programmathically.com/xfs-vs-zfs-which-file-system-is-best-for-your-use-case/&lt;/li&gt;
  &lt;li&gt;https://hetmanrecovery.com/recovery_news/why-is-the-zfs-file-system-in-linux-ubuntu-so-good.htm#plan_14&lt;/li&gt;
  &lt;li&gt;https://openzfs.org/wiki/System_Administration&lt;/li&gt;
  &lt;li&gt;https://itsfoss.com/what-is-zfs/&lt;/li&gt;
  &lt;li&gt;https://computingforgeeks.com/raid-vs-lvm-vs-zfs-comparison/&lt;/li&gt;
  &lt;li&gt;https://en.wikipedia.org/wiki/ZFS&lt;/li&gt;
  &lt;li&gt;https://www.open-e.com/blog/pooled-storage/&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/definition/ZFS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;주석&quot;&gt;주석&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;RAID 5 쓰기 구멍이란, 쓰기 작업 중에 전력 장애 등으로 패리티가 제대로 쓰이지 않은 경우, 이를 감지 못한 채 놔두는 상황을 말합니다. 만일 이 상태로 RAID 리빌드 작업을 수행하게 된다면 데이터 손실이 발생하게 됩니다. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 20 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2023/12/20/ZFSintro.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2023/12/20/ZFSintro.html</guid>
        
        <category>ZFS</category>
        
        <category>파일 시스템</category>
        
        <category>File System</category>
        
        <category>ARC</category>
        
        <category>L2ARC</category>
        
        <category>스냅샷</category>
        
        <category>Snapshot</category>
        
        <category>RAID</category>
        
        <category>압축</category>
        
        <category>Compression</category>
        
        <category>중복 제거</category>
        
        <category>Deduplication</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>올플래시 스토리지 선정 시 체크포인트</title>
        <description>&lt;p&gt;기업들이 올플래시 스토리지를 도입하고자 하는 주된 목적은 기본적으로 하드디스크 기반의 스토리지보다 높은 성능을 제공할 수 있다는 것에 있습니다. 플래시 기반의 스토리지는 전통적으로 미션 크리티컬하거나 지연시간에 민감한 핵심 워크로드를 운용할 목적으로 사용됐으나, 높은 가격과 부족한 유스케이스로 인해 많은 기업들이 도입을 주저해 왔습니다. 하지만, 플래시 메모리의 가격이 점점 낮아지면서 상대적으로 비용이 저렴한 올플래시 스토리지들이 시장에 등장하게 되었고, 이는 전반적인 스토리지 성능 기준과 요구사항을 향상시키는 데 일조했습니다.&lt;/p&gt;

&lt;p&gt;이렇게 올플래시 스토리지에 대한 접근성이 높아지고 올플래시 스토리지에 대한 시장 검증도 해소되면서 많은 기업들이 비즈니스 가속화를 위해 올플래시 스토리지의 도입을 추진하고 있습니다. 그러나 전통적인 스토리지 시스템에서 올플래시 스토리지로 전환하는 것은 계획적이고 신중한 접근이 필요한 결정입니다. 올플래시 스토리지 선택 시 체크 포인트를 간단히 정리해 보았습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;하드디스크-vs-ssd&quot;&gt;하드디스크 vs SSD&lt;/h2&gt;

&lt;p&gt;하드디스크와 솔리드 스테이트 드라이브(이하 SSD)의 관계를 단순히 성능과 가격 문제로 치부하기에는 복잡한 부분이 있습니다. 하드디스크는 기본적으로 기계적인 동작을 통해 데이터를 읽고 쓰는 스토리지 미디어입니다. 이 때문에 플래터의 바깥쪽 트랙이냐 안쪽 트랙이냐에 따라 데이터를 읽어오는 속도가 다르고, 읽기/쓰기 헤드가 플래터 위를 이동함에 따라 기계적 지연이 발생해 읽기 속도가 상대적으로 느릴 뿐만 아니라, 일정하지 못하다는 문제가 있습니다. 반면에 SSD는 데이터를 읽고 쓰는데 전기 회로를 활용하기 때문에 일정한 읽기 성능을 제공할 수 있어, 많은 데이터를 계속해서 요구하는 집약적인 워크로드에 적합합니다. 게다가 하드디스크에 비해 발열과 충격에 강하고, 보다 작은 용적량을 제공해 데이터센터 내 공간 비용을 최소화할 수 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 SSD는 고질적으로 수명과 쓰기 성능에 대한 이슈가 있다는 점도 알고 있어야 합니다. 우선, 플래시 메모리는 하드디스크와는 달리 쓰기 수명이 있어 일정 쓰기 횟수를 넘어가면 더 이상 쓰기 작업을 못 하게 됩니다. 게다가 SSD의 가비지 컬렉션&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; 작업은 1bit의 데이터만 수정되어도 블록 전체를 다시 써야 하고, 이것이 많아지면 쓰기 성능에 영향을 주게 됩니다. 이를 방지하기 위해 대부분의 SSD 제품은 오버 프로비저닝&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; 기능을 통해 쓰기 버퍼를 위한 공간을 확보하고, 특정 블록만 마모되지 않도록 쓰기 빈도를 관리하는 웨어 레벨링&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; 기술 등을 적용해 SSD의 쓰기 성능과 수명을 증가시키고 있습니다. 하지만 SSD의 이러한 단점들을 고려해도, 하드디스크에 비해 압도적인 성능을 제공한다는 것은 사실입니다. 그리고 이러한 성능을 완전하게 활용하기 위해서는 무엇보다 애플리케이션에서 요구하는 워크로드 유형에 대한 고민이 필요합니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;워크로드-유형&quot;&gt;워크로드 유형&lt;/h2&gt;

&lt;p&gt;올플래시 스토리지가 제공할 수 있는 성능은 운용 중인 애플리케이션이나 워크로드 유형에 따라 다를 수 있습니다. 이 때문에 단순히 성능 수치를 보기보다는 다음과 같이 자사의 애플리케이션 운용 방식에 따른 시스템 구성과 이에 따른 워크로드 유형을 알아볼 수 있어야 합니다:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;스루풋:&lt;/strong&gt; 자사 인프라 내에서 스루풋 중심의 애플리케이션을 활용하고 있는 경우, 스루풋 요구사항을 면밀히 검토해 볼 필요가 있습니다. 스루풋은 스토리지 시스템에서 오고 나가는 데이터의 양을 측정하는 지표입니다. 빅데이터 분석이나 영상 후반작업처럼 오고 나가는 데이터의 규모가 클수록 높은 스루풋을 요구하는 환경이라고 볼 수 있습니다. 그리고 운용하는 데이터의 규모가 큰 만큼 네트워크 대역폭에 대한 요구사항도 높아질 수 있습니다. 다만, 네트워크 대역폭을 확장하는 만큼, 서버 점유율 또한 높아진다는 점도 고려해야 합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;IOPS:&lt;/strong&gt; 주로 동시에 여러 사용자가 접속하는 온라인 트랜잭션이나 가상 데스크톱과 같이 병렬 작업이 많이 발생하는 환경에서 높은 IOPS가 요구됩니다. 하지만 IOPS는 많은 벤더들이 과장해서 강조하는 만큼 가장 주의 깊게 따져봐야 하는 지표입니다. IOPS는 블록 크기, 랜덤 I/O의 비중 등에 따라 수치가 크게 상이합니다. 단순히 높은 IOPS를 제공한다 해도, 실 환경에서는 그 기준이 천차만별이기 때문에 도입 전에 이러한 기준들을 잘 살펴보고, 유스 케이스가 가장 비슷한 레퍼런스를 찾아서 비교하는 것이 필요합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;지연시간:&lt;/strong&gt; 고성능 컴퓨팅이나 실시간 스트리밍 서비스를 제공하는 환경에서는 극단적으로 낮은 지연시간을 요구합니다. 하이엔드급 올플래시 스토리지는 1ms 이하의 지연시간을 제공하지만, 몇몇 초고성능을 요구하는 애플리케이션은 수십 마이크로초 이하의 지속적인 응답속도를 요구하기도 합니다. 지연시간은 최소 지연시간보다는 평균 지연시간을 참고하는 것이 중요하며, 평균에서 많이 벗어난 수치가 나올 수도 있기 때문에 최대 지연시간에 대해서도 알아보는 것이 좋습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;올플래시-스토리지-선정을-위한-체크포인트&quot;&gt;올플래시 스토리지 선정을 위한 체크포인트&lt;/h2&gt;

&lt;p&gt;이처럼 올플래시 스토리지는 기존 하드디스크 기반 스토리지에 비해 압도적인 속도와 낮은 지연시간을 제공하지만, 이러한 이점을 자사 인프라에서 최대한으로 활용할 수 있으려면 어떤 점들이 고려되어야 할지를 다루어 보고자 합니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;목표 성능과 비용:&lt;/strong&gt; 목표 성능을 제공하는 제품을 알아보기 전에 우선 벤더마다 성능에 대한 마케팅 전략도 매우 다른 점을 명심해야 합니다. 어떤 벤더는 단순히 IOPS나 스루풋에 대한 성능만을 강조하고, RAID 레벨이나 데이터 리덕션 기능에 따른 성능 저하 부분까지는 언급하지 않는 경우도 있기 때문입니다. 또한, 직접 업체에 문의하거나 벤더들이 광고하는 성능을 참고하는 것도 좋지만, SPC-1&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;와 같이 실 환경 워크로드를 구현하는 써드파티 벤치마크를 참고하는 방법도 있습니다. 목표를 정했으면, 도입하고자 하는 올플래시 스토리지의 TCO와 기존에 보유한 디스크 기반의 스토리지의 TCO를 비교하고, 용량과 애플리케이션, 데이터센터 운영비용, IT 관리 및 소프트웨어 라이선스 비용 등을 따져봐야 합니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;네트워크 구성:&lt;/strong&gt; 자사 인프라의 네트워크 사양에 대해 잘 알고 있어야 데이터 병목을 피할 수 있습니다. 올플래시 스토리지를 고성능에 고집적으로 구성함에 따라 네트워크 대역폭에 대한 요구사항 역시 대폭 높아질 수 있기 때문입니다. SSD는 기존 하드디스크에 비해 수배의 성능을 제공하기 때문에 예상과는 다르게 기존의 네트워크 대역폭을 포화시킬 수도 있습니다. 게다가 NVMe SSD를 도입해 NVMe over Fabrics를 활용하고자 하는 경우, 네트워크 구성에 따라 별도의 호스트 어댑터나 드라이버 등의 조정이 필요한 경우도 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;데이터 리덕션:&lt;/strong&gt; 스토리지 공간을 확보하기 위해 데이터 리덕션 기능을 사용하기보다는, 경우에 따라 데이터 리덕션을 수행하는 것이 더 중요합니다. 데이터 유형에 따라 중복제거율이 다르며, 중복제거를 설정하는 것 보다 성능을 확보하는 것이 비용 효율적인 경우도 있습니다. 예를 들어, 가상머신을 운용하는 환경에서는 압축 및 중복제거율이 매우 높아, 스토리지 미디어를 모두 플래시로 구성해도 용량 대비 비용 효율이 높다고 볼 수 있지만, 영상 관제 시스템과 같이 영상 및 이미지 파일을 저장하는 환경에서는 데이터의 특성으로 인해 압축 및 중복제거율이 매우 낮기 때문에 데이터 리덕션 기능은 오히려 성능 저하의 원인이 될 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;NVMe vs SAS/SATA:&lt;/strong&gt; 최근 수년 사이 NVMe SSD가 시장에 본격적으로 등장하기 시작하면서, NVMe SSD만으로 구성된 올플래시 스토리지 제품이 기존의 SAS/SATA 올플래시 스토리지의 자리를 넘보고 있습니다. NVMe SSD는 PCIe의 높은 대역폭을 활용해 SAS/SATA 인터페이스 대비 비교적 높은 성능과 낮은 지연시간을 보장합니다. 가격 차도 점점 줄어드는 추세라, 일각에서는 NVMe SSD가 SAS/SATA SSD를 빠르게 대체해 나갈 것이라고 보고 있지만, All-NVMe 스토리지 도입은 시기상조일 수도 있습니다. 우선, NVMe에 최적화된 스토리지 컨트롤러를 가진 올플래시 스토리지 제품들은 아직 많지 않으며, NVMe-oF를 지원하거나 OS의 I/O 스택을 거치지 않고 NVMe 드라이브에 접근할 수 있는 파일시스템이 없는 제품들도 있습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;올플래시 스토리지의 높은 성능과 효율성은 기업과 기관에 많은 장점을 제공합니다. 그러나 올플래시 스토리지를 도입하는 결정은 비용과 워크로드 요구 사항, 확장성이나 호환성 등 여러 가지 요소를 종합적으로 고려해야 합니다. 전문가들과 협업을 통해 적절한 솔루션을 찾고, 기술적인 변화를 반영하여 미래 지향적인 스토리지 시스템을 구축한다면 더욱 효율적인 데이터 관리와 혁신적인 비즈니스 전략을 구사할 수 있을 것입니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;참고&quot;&gt;참고&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/feature/SAS-vs-NVMe-The-future-of-the-two-key-storage-interfaces&lt;/li&gt;
  &lt;li&gt;https://www.computerweekly.com/feature/A-guide-to-choosing-and-using-all-flash-array-storage&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/feature/Building-a-business-case-for-all-flash-array-storage&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/feature/Five-factors-to-consider-before-buying-all-flash-storage-arrays&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/definition/overprovisioning-SSD-overprovisioning&lt;/li&gt;
  &lt;li&gt;https://www.techtarget.com/searchstorage/definition/wear-leveling&lt;/li&gt;
  &lt;li&gt;https://storageswiss.com/2015/02/23/what-are-iops-and-should-you-care/&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;주석&quot;&gt;주석&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;strong&gt;가비지 컬렉션(garbage collection):&lt;/strong&gt; SSD에서 데이터는 페이지 단위로 저장되며, 여러 페이지가 모여 블록을 구성합니다. 그리고 데이터의 읽기/쓰기는 페이지 단위에서 가능하지만, 데이터를 삭제할 수 있는 최소 단위는 블록입니다. 즉, 블록 내 일부 페이지를 변경하려면, 수정된 페이지를 새 블록에 쓰고 기존 블록을 삭제해 재사용이 가능하도록 비우는 작업을 수행하는데, 이를 가비지 컬렉션이라고 합니다. 가비지 컬렉션은 쓰기 작업의 부하를 줄이기 위해 활동이 적은 시점에서 수행되곤 합니다. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;strong&gt;오버 프로비저닝(overprovisioning):&lt;/strong&gt; 오버 프로비저닝이란, SSD에 기본 저장 용도와는 별도로 확보한 스토리지 공간을 말합니다. 오버 프로비저닝으로 확보한 공간은 플래시 메모리의 쓰기 부하를 분산시켜 SSD의 수명을 증가시키고, 여분의 블록을 확보해 쓰기 증폭(write amplification)으로 인한 성능 저하를 방지합니다. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;strong&gt;웨어 레벨링(wear leveling):&lt;/strong&gt; 웨어 레벨링은 SSD의 수명을 증가시키기 위해 블록별 쓰기 수준을 조절하는 기능을 말합니다. 플래시 컨트롤러에서 웨어 레벨링 알고리즘을 활용해 블록 별로 쓰기 빈도를 조절해, 쓰기 부하를 분산시켜 플래시 메모리의 소모를 최소화합니다. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;strong&gt;SPC-1:&lt;/strong&gt; SPC-1은 국제 스토리지 성능 표준화 인증 기구인 스토리지 성능 협회(Storage Performance Council)에서 주관하는 벤치마크 인증으로, 데이터베이스, 온라인 트랜잭션(OLTP) 시스템 등 무작위 입출력이 가중되는 실제 스토리지 환경을 구현해 입출력 성능(IOPS)과 응답시간(ms)을 측정합니다. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 19 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2023/07/19/allflash.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2023/07/19/allflash.html</guid>
        
        <category>올플래시 스토리지</category>
        
        <category>All-Flash Storage</category>
        
        <category>SSD</category>
        
        <category>플래시 메모리</category>
        
        <category>Flash Memory</category>
        
        <category>고성능</category>
        
        <category>High Performance</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>NVMe 시대의 RAID 2편: xiRAID</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://tech.gluesys.com/blog/2022/10/28/GRAID_and_NVMe.html&quot;&gt;지난 포스트&lt;/a&gt;에서는 &lt;a href=&quot;https://tech.gluesys.com/blog/2020/07/22/storage_6_intro.html&quot;&gt;RAID(Redundant Array of Independent Disks)&lt;/a&gt;를 구성할 때 기존에 주로 사용하던 하드 디스크(HDD)가 아닌 고성능 NVMe SSD를 사용하였을 때 발생하는 문제점들에 대하여 알아보았습니다.
또한 NVMe SSD에 최적화된 RAID 솔루션인 SupremeRAID와 PoseidonOS가 이러한 문제들에 대응하는 방법에 대해서도 살펴보았는데요, 오늘은 이에 더해 또 다른 소프트웨어 RAID 제품인 &lt;strong&gt;xiRAID&lt;/strong&gt;에 대해서 알아보겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;xinnor-xiraid&quot;&gt;Xinnor xiRAID&lt;/h2&gt;

&lt;p&gt;xiRAID는 지난 2022년 10월 등장한 이스라엘 &lt;a href=&quot;https://xinnor.io/&quot;&gt;Xinnor&lt;/a&gt; 사의 소프트웨어 RAID 솔루션입니다.
Xinnor 사는 러시아의 &lt;a href=&quot;https://www.raidix.com/&quot;&gt;RAIDIX&lt;/a&gt;가 &lt;a href=&quot;https://yadro.com/en&quot;&gt;Yadro&lt;/a&gt;에 인수된 후 기존 개발진 중 일부가 나와 새로 창립한 회사입니다.
RAIDIX를 나와 별개의 새로운 회사를 창립하였지만 관계를 이어가며 기존 RAIDIX 제품들의 판매 역시 계속하고 있는데요, 이를 위한 기존 RAIDIX ERA의 새로운 이름이 바로 Xinnor xiRAID입니다.&lt;/p&gt;

&lt;p&gt;그렇다면 xiRAID의 특징으로는 어떤 것들이 있을까요?
먼저 xiRAID는 지난 번 살펴본 PoseidonOS와는 다르게 &lt;a href=&quot;https://tech.gluesys.com/blog/2022/02/18/SPDK_1.html&quot;&gt;SPDK&lt;/a&gt;를 사용하지 않습니다.
SPDK를 사용할 경우 데이터가 커널 영역을 거쳐 가지 않는 등 불필요한 오버헤드가 줄어 성능이 향상될 수 있는데요, 그 대신 메모리 사용량을 최소화하고 NVMe뿐만 아니라 SATA나 SAS SSD/HDD도 사용할 수 있게 되었습니다.
또한 NVMe-oF로 연결된 원격 장비를 사용하여 RAID를 구성하는 것은 지원하지만, 생성된 RAID는 NVMe-oF 타겟이 아닌 로컬 블록 디바이스 형태로 제공합니다.
스토리지 노드에서 직접 애플리케이션을 구동하는 경우 좀 더 간편하게 사용할 수 있겠네요.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;그러면 이제 xiRAID의 성능을 살펴보도록 하겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;graid-supremeraid와의-성능-비교&quot;&gt;GRAID SupremeRAID와의 성능 비교&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;워크로드 종류&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;xiRAID&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;GRAID SupremeRAID&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;하이엔드 하드웨어 레이드&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4k 무작위 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;30 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;19 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;3.5 MIOPS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4k 무작위 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;11 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1.5 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;180 kIOPS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;512k 순차 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;260 GB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;110 GB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;13.5 GB/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;512k 순차 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;62 GB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;22 GB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4 GB/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;리빌드 중 4k 무작위 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;27 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5.5 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;36 kIOPS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;리빌드 중 4k 무작위 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1.1 MIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;18 kIOPS&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;center&gt; Xinnor 사에서 발표한 xiRAID, GRAID SupremeRAID, 하드웨어 레이드 장치의 성능 비교 (출처: Xinnor 사 홈페이지) &lt;/center&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;제일 먼저 살펴볼 것은 Xinnor 사에서 발표한 xiRAID와 SupremeRAID의 성능 비교 결과입니다.
이 표의 결과만을 놓고 보자면 xiRAID가 SupremeRAID(출처에서는 GPU 하드웨어 RAID로 언급)에 비해 월등히 좋은 모습을 보여주고 있고, 4k 무작위 쓰기는 그 차이가 7배를 넘어갑니다.&lt;/p&gt;

&lt;p&gt;저희도 저희 장비에서 비슷한 실험을 진행했는데요, 성능 측정 결과를 보기에 앞서 저희가 성능 측정을 진행한 환경은 다음과 같습니다.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;종류&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;장비명&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CPU&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Intel Xeon Silver 4310 CPU @ 2.10GHz x 2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;메모리&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Micron 18ASF2G72PDZ-3G2R1 3200 MHz 16G x 8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;OS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rocky Linux 8.7&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SSD&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;a href=&quot;https://media-www.micron.com/-/media/client/global/documents/products/product-flyer/7300_nvme_ssd_product_brief.pdf&quot;&gt;Micron_7300_MTFDHBE960TDF x 12&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;details&gt;
    &lt;summary&gt;fio 설정 파일&lt;/summary&gt;

    [global]
    direct=1
    ioengine=libaio
    iodepth=32
    randrepeat=0
    kb_base=1000
    filename=/mnt/raidtest/testfile
    size=512GiB
    group_reporting=1
    ramp_time=5s
    wait_for_previous

    [seqwrite]
    numjobs=1
    blocksize=1MiB
    readwrite=write

    [seqread]
    numjobs=1
    blocksize=1MiB
    readwrite=read

    [randwrite]
    numjobs=48
    blocksize=4KiB
    readwrite=randwrite

    [randread]
    numjobs=48
    blocksize=4KiB
    readwrite=randread
&lt;/details&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;다음은 저희가 수행한 xiRAID와 GRAID SupremeRAID 성능 측정의 결과입니다.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;워크로드 종류&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;xiRAID&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;GRAID SupremeRAID&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4kiB 무작위 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2,451 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2,467 kIOPS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4kiB 무작위 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;568 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;576 kIOPS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1MiB 순차 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;11,705 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;17,777 MiB/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1MiB 순차 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5,276 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;3,826 MiB/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/xiraid/bench.png&quot; alt=&quot;위 표의 막대 그래프&quot; width=&quot;600&quot; /&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;위에서 봤던 xiRAID의 자료와는 사뭇 다른 모습의 결과가 나왔습니다. 지금부터 하나씩 살펴보도록 하겠습니다.&lt;/p&gt;

&lt;p&gt;무작위 워크로드의 경우, 읽기와 쓰기 모두 xiRAID와 SupremeRAID가 비슷한 성능을 보여주었습니다.
실험에 사용한 SSD의 스펙을 토대로 미루어보면 두 제품 모두 큰 손실 없이 SSD의 성능을 모두 뽑아내어 준 것으로 보입니다.&lt;/p&gt;

&lt;p&gt;반면 순차 워크로드의 경우 읽기와 쓰기의 결과에 차이가 있었습니다.
읽기 작업의 경우 SupremeRAID가 약 1.5배의 성능을 보여주었는데, 이는 SupremeRAID의 RAID 디바이스에 읽기 작업을 수행할 때는 데이터가 SupremeRAID 카드를 거치지 않고 SSD에서 호스트로 바로 불러와지는 것이 요인으로 보입니다.
반대로 쓰기 작업의 경우 xiRAID가 약 1.4배 더 빠른 것으로 나왔습니다.
쓰기 작업의 경우 패리티를 계산해야 하니 위와 같은 지름길이 없는데, 이러한 면에서 xiRAID가 순수한 속도는 더 빠르다고도 할 수 있겠네요.&lt;/p&gt;

&lt;p&gt;위의 두 성능 측정 결과를 종합하여 생각해 보자면, xiRAID의 경우 소프트웨어 RAID이므로 호스트 하드웨어(SSD, CPU 등)가 허락하는 한 자체적인 성능상의 한계는 없거나 무의미한 것으로 보입니다.
따라서 SupremeRAID의 경우 SupremeRAID 하드웨어의 연산 성능을 초과하여 I/O를 실행하면 병목이 발생하지만, xiRAID는 그러한 문제가 발생하지 않습니다.
반면 SupremeRAID 카드에 병목이 생길 정도로 대규모가 아닌 저희 실험 서버와 같은 환경에서는 워크로드에 따라 엎치락뒤치락하며 두 제품의 특성에 따른 성능 양상이 좀 더 뚜렷하게 보이는 것 같습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;다른-애플리케이션을-같이-구동해야-한다면&quot;&gt;다른 애플리케이션을 같이 구동해야 한다면?&lt;/h2&gt;

&lt;p&gt;소프트웨어 RAID의 또 다른 약점으로는 적건 많건 호스트 장비의 CPU를 사용한다는 점이 있습니다.
이는 해당 장비를 스토리지 전용으로 사용하지 않고 그 데이터를 사용하는 애플리케이션을 같이 구동해야 하는 경우 특히 문제가 되는데요.
이러한 환경에서의 성능을 측정해보고자 저희는 다른 프로세스가 CPU를 점유하고 있는 상황에서의 성능을 측정하여 보았습니다.&lt;/p&gt;

&lt;p&gt;CPU 부하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stress&lt;/code&gt; 유틸리티(&lt;a href=&quot;https://linux.die.net/man/1/stress&quot;&gt;man 링크&lt;/a&gt;)를 사용하여 총 48개의 코어 중 46개의 코어를 100% 사용하는 방식으로 부여하였습니다.
실제 기계학습 작업을 수행하는 등의 방법도 고려하여 보았지만, 해당 작업이 스토리지 I/O를 수행하거나 CPU 사용량이 일정하지 않은 문제가 있어 적합하지 않다는 결론 하에 사용하지 않았습니다.&lt;/p&gt;

&lt;p&gt;위에서 진행하였던 별도의 CPU 부하가 없는 상황에서의 측정 결과와 비교해 보도록 하겠습니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;워크로드 종류&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;xiRAID&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;xiRAID + CPU 부하&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;성능 변화&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;비율&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4kiB 무작위 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2,451 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1,190 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-1,261 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-51%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4kiB 무작위 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;568 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;132 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-436 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-76%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1MiB 순차 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;11,705 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4,367 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-7,338 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-63%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1MiB 순차 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5,276 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1,824 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-3,452 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-65%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;워크로드 종류&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;SupremeRAID&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;SupremeRAID + CPU 부하&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;성능 변화&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;비율&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4kiB 무작위 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2,467 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2,147 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-320 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-13%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4kiB 무작위 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;576 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;540 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-35 kIOPS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-6.2%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1MiB 순차 읽기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;17,777 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;16,577 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-1,200 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-6.8%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1MiB 순차 쓰기&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;3,826 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;3,450 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-376 MiB/s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-9.8%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/xiraid/stress.png&quot; alt=&quot;위 표의 막대 그래프&quot; width=&quot;600&quot; /&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;결과는 당초 저희 예상보다 큰 두 제품 간의 차이를 보였습니다.&lt;/p&gt;

&lt;p&gt;xiRAID의 경우 모든 워크로드에서 별도의 CPU 부하가 없는 상황 대비 절반 미만의 성능을 보인 반면, SupremeRAID는 가장 많은 차이를 보인 4kiB 무작위 쓰기 실험에서도 13%만 하락하였고 나머지 워크로드에서는 10% 미만의 차이를 보였습니다.
또한, 별도의 CPU 부하가 없었을 때는 1MiB 순차 쓰기 워크로드에서 xiRAID가 더 빨랐지만, CPU 부하로 인한 성능 하락으로 인하여 오히려 GRAID SupremeRAID가 2배에 가까운 속도를 내는 것을 확인할 수 있습니다.&lt;/p&gt;

&lt;p&gt;여기에 추가적으로 우려되는 점이 있다면, 저희가 이번 성능 측정에 사용한 장비는 위에서 보았듯 SupremeRAID에 병목을 일으킬 정도로 고속으로 I/O를 처리할 수 없습니다.
xiRAID의 장점인 확장성을 살리기 위해서는 더욱 고성능의 SSD를 다수 사용해야 하는데, 그러한 환경에서는 xiRAID의 연산 요구량이 늘어나 CPU 자원에 더더욱 민감해질 가능성이 있습니다.
따라서 본 실험의 환경과 같이 스토리지 서버에서 별도의 연산 워크로드를 수행해야 한다면 xiRAID와 같은 소프트웨어 RAID보다는 GRAID SupremeRAID와 같은 하드웨어 RAID를 사용하는 것이 유리할 것으로 보입니다.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;오늘은 NVMe SSD의 성능을 활용할 수 있는 소프트웨어 RAID 솔루션인 Xinnor 사의 xiRAID에 대하여 알아보았습니다.
xiRAID는 소프트웨어 솔루션의 장점을 십분 발휘할 수 있는 대규모 스토리지 전용 서버와 같은 환경에서는 타의 추종을 불허하는 성능을 보여줍니다.
하지만 애플리케이션이 CPU 자원을 사용하는 환경이라면 별도의 하드웨어 장치를 사용하는 GRAID SupremeRAID와 같은 제품이 좀 더 적합할 것으로 보입니다.&lt;/p&gt;

&lt;p&gt;고성능의 NVMe SSD가 보급되면서 이를 활용할 수 있도록 해주는 제품들도 속속들이 등장하고 있습니다.
NVMe 시스템을 도입할 예정이신 분들께서는 신제품 소식에 계속해서 귀를 기울이고 계셔야 할 것 같습니다.
감사합니다.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;참고-링크-및-출처&quot;&gt;참고 링크 및 출처&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://xinnor.io/what-is-xiraid/&quot;&gt;https://xinnor.io/what-is-xiraid/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blocksandfiles.com/2022/11/18/startup-xinnor/&quot;&gt;https://blocksandfiles.com/2022/11/18/startup-xinnor/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;커버 이미지: &lt;a href=&quot;https://www.freepik.com/free-vector/realistic-microchip-processor-background_12977892.htm#query=cpu&amp;amp;position=4&amp;amp;from_view=search&amp;amp;track=sph&quot;&gt;Image by pikisuperstar&lt;/a&gt; on Freepik&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 10 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://tech.gluesys.com/blog/2023/01/10/xiRAID.html</link>
        <guid isPermaLink="true">https://tech.gluesys.com/blog/2023/01/10/xiRAID.html</guid>
        
        <category>RAID</category>
        
        <category>NVMe</category>
        
        <category>SSD</category>
        
        <category>GRAID</category>
        
        <category>SupremeRAID</category>
        
        <category>Xinnor</category>
        
        <category>xiRAID</category>
        
        
        <category>blog</category>
        
      </item>
    
  </channel>
</rss>
