extX 파일시스템 블록사이즈에 따른 그룹 디스크립터 테이블의 시작위치

Ext(ext2, ext3, ext4) Filesystem 에서 Group Descriptor Table의 시작위치

First address of Group Descriptor Table on ExtX Filesystem


ext 파일시스템의 모든 블록의 크기는 동일하다.

ext 파일시스템의 처음 1024 블록은 0x00로 채워져 있는 예약영역이다.
Block Size가 얼마이든 Superblock은 1024바이트 다음에 나타난다.
ext 파일시스템을 마운트할때 블록의 크기를 알 수 없기에 1024로 가정하고 1024바이트의 예약영역다음 1024바이트를 읽어 슈퍼블록으로 해석한다.

그렇다면, 슈퍼블록다음에 나타날 그룹 디스크립터 테이블(Group Descriptor Table)은 어디서 나타날까?
  1. block size가 1KB, 2KB 일때
  2. 맨 처음부터 2048바이트 다음 위치부터 나타난다.
  3. block size가 4KB 일때
  4. 맨 처음부터 4096 바이트 다음 위치부터 나타난다.

즉 block size가 1KB, 2KB일때는 슈퍼블록이 나타난다음 바로 그룹 디스크립터 테이블이 나타나고, 4KB 일때는 2KB의 공간이 비어있고 나타나게 된다.


아래는 슈퍼블록의 구조체이다.
/*
  * Structure of the super block
  */
 struct ext4_super_block {
 /*00*/  __le32  s_inodes_count;         /* Inodes count */
         __le32  s_blocks_count_lo;      /* Blocks count */
         __le32  s_r_blocks_count_lo;    /* Reserved blocks count */
         __le32  s_free_blocks_count_lo; /* Free blocks count */
 /*10*/  __le32  s_free_inodes_count;    /* Free inodes count */
         __le32  s_first_data_block;     /* First Data Block */
         __le32  s_log_block_size;       /* Block size */
         __le32  s_obso_log_frag_size;   /* Obsoleted fragment size */
 /*20*/  __le32  s_blocks_per_group;     /* # Blocks per group */
         __le32  s_obso_frags_per_group; /* Obsoleted fragments per group */
         __le32  s_inodes_per_group;     /* # Inodes per group */
         __le32  s_mtime;                /* Mount time */
 /*30*/  __le32  s_wtime;                /* Write time */
         __le16  s_mnt_count;            /* Mount count */
         __le16  s_max_mnt_count;        /* Maximal mount count */
         __le16  s_magic;                /* Magic signature */
         __le16  s_state;                /* File system state */
         __le16  s_errors;               /* Behaviour when detecting errors */
         __le16  s_minor_rev_level;      /* minor revision level */
 /*40*/  __le32  s_lastcheck;            /* time of last check */
         __le32  s_checkinterval;        /* max. time between checks */
         __le32  s_creator_os;           /* OS */
         __le32  s_rev_level;            /* Revision level */
 /*50*/  __le16  s_def_resuid;           /* Default uid for reserved blocks */
         __le16  s_def_resgid;           /* Default gid for reserved blocks */
         /*
          * These fields are for EXT4_DYNAMIC_REV superblocks only.
          *
          * Note: the difference between the compatible feature set and
          * the incompatible feature set is that if there is a bit set
          * in the incompatible feature set that the kernel doesn't
          * know about, it should refuse to mount the filesystem.
          *
          * e2fsck's requirements are more strict; if it doesn't know
          * about a feature in either the compatible or incompatible
          * feature set, it must abort and not try to meddle with
          * things it doesn't understand...
          */
         __le32  s_first_ino;            /* First non-reserved inode */
         __le16  s_inode_size;           /* size of inode structure */
         __le16  s_block_group_nr;       /* block group # of this superblock */
         __le32  s_feature_compat;       /* compatible feature set */
 /*60*/  __le32  s_feature_incompat;     /* incompatible feature set */
         __le32  s_feature_ro_compat;    /* readonly-compatible feature set */
 /*68*/  __u8    s_uuid[16];             /* 128-bit uuid for volume */
 /*78*/  char    s_volume_name[16];      /* volume name */
 /*88*/  char    s_last_mounted[64];     /* directory where last mounted */
 /*C8*/  __le32  s_algorithm_usage_bitmap; /* For compression */
         /*
          * Performance hints.  Directory preallocation should only
          * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
          */
         __u8    s_prealloc_blocks;      /* Nr of blocks to try to preallocate*/
         __u8    s_prealloc_dir_blocks;  /* Nr to preallocate for dirs */
         __le16  s_reserved_gdt_blocks;  /* Per group desc for online growth */
         /*
          * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
          */
 /*D0*/  __u8    s_journal_uuid[16];     /* uuid of journal superblock */
 /*E0*/  __le32  s_journal_inum;         /* inode number of journal file */
         __le32  s_journal_dev;          /* device number of journal file */
         __le32  s_last_orphan;          /* start of list of inodes to delete */
         __le32  s_hash_seed[4];         /* HTREE hash seed */
         __u8    s_def_hash_version;     /* Default hash version to use */
         __u8    s_reserved_char_pad;
         __le16  s_desc_size;            /* size of group descriptor */
 /*100*/ __le32  s_default_mount_opts;
         __le32  s_first_meta_bg;        /* First metablock block group */
         __le32  s_mkfs_time;            /* When the filesystem was created */
         __le32  s_jnl_blocks[17];       /* Backup of the journal inode */
         /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
 /*150*/ __le32  s_blocks_count_hi;      /* Blocks count */
         __le32  s_r_blocks_count_hi;    /* Reserved blocks count */
         __le32  s_free_blocks_count_hi; /* Free blocks count */
         __le16  s_min_extra_isize;      /* All inodes have at least # bytes */
         __le16  s_want_extra_isize;     /* New inodes should reserve # bytes */
         __le32  s_flags;                /* Miscellaneous flags */
         __le16  s_raid_stride;          /* RAID stride */
         __le16  s_mmp_interval;         /* # seconds to wait in MMP checking */
         __le64  s_mmp_block;            /* Block for multi-mount protection */
         __le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
         __u8    s_log_groups_per_flex;  /* FLEX_BG group size */
         __u8    s_reserved_char_pad2;
         __le16  s_reserved_pad;
         __le64  s_kbytes_written;       /* nr of lifetime kilobytes written */
         __u32   s_reserved[160];        /* Padding to the end of the block */
 };
그룹 디스크립터가 나타나는 위치는 block sizefirst data block 과 관계가 있다. block size가 0x00 이면 1KB, 0x01 이면 2KB, 0x02이면 4KB 인데, 0x01 일때 first data block 의 값은 0x00이 아니라 0x01이다. 즉, 첫번째 블록을 스킵하게된다.

따라서 block size가 1KB일때 2048바이트 이후에 first data block 위치에서 1KB를 슈퍼블록으로 보고 그다음 나타나는 블록을 그룹 디스크립터 테이블로 인식한다.

  2KB일때는 first data block의 값이 0x00 이므로 처음 2KB를 슈퍼블록으로 인식한다.

그러므로, 블록사이즈가 1KB일때와 2KB일때 같은위치에서 그룹 디스크립터 테이블이 나타난다.

댓글

  1. 블록사이즈가 0x0이면 1KB, 0x1이면 2KB, 0x2이면 4KB아닌가요?

    답글삭제
    답글
    1. 네 맞습니다. 덕분에 오랜만에 찾아보았습니다. 수정하였고,
      참고로 2 ^( 10 + s_log_block_size) 로 계산이 됩니다.

      삭제

댓글 쓰기

이 블로그의 인기 게시물

C#에서 포인터 사용

WPF RichTextBox 와 Document의 바인딩

WPF 이미지위에 라인 그리기(WPF DrawLine on exist Image)