newfs

OpenBSD 7.2

OpenBSD 7.2 が出た。今回で53回目のリリース。いよいよアプルのM2までもがサポートされ、ThinkPad x13s とかも仲間に加わったとか。ブルジョアの人もいるものだ。

オイラーは、そんな豪華な奴には目もくれず、ひたすら仮想PCで頑張るのさ。可弱い設備でも、動けばOK。

newfs

前回はfsckからnewfsに飛び火。両者共ユーザーランドのアプリ。観光するならqemuの窮屈な所ではなく、virtualBox上でもいいだろう。こちらならemacsとかも苦労なく動くからね。

vbox$ dd if=/dev/zero of=test.img bs=1M count=125
125+0 records in
125+0 records out
131072000 bytes transferred in 1.371 secs (95584145 bytes/sec)
vbox$ doas vnconfig vnd0 /tmp/test.img
vbox$ doas disklabel -E vnd0
Label editor (enter '?' for help at any prompt)
vnd0> a a
offset: [0]
size: [256000]
FS type: [4.2BSD]
vnd0*> p
OpenBSD area: 0-256000; size: 256000; free: 0
#                size           offset  fstype [fsize bsize   cpg]
  a:           256000                0  4.2BSD   2048 16384     1
  c:           256000                0  unused
vnd0*> w
vnd0> q
No label changes.

作成するDISKのサイズを前回の 1/4 にした。何せWindows 10には色々なOSを入れてて窮屈ですから。

vbox$ hexdump -C test.img
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  57 45 56 82 0c 00 00 00  76 6e 64 20 64 65 76 69  |WEV.....vnd devi|
00000210  63 65 00 00 00 00 00 00  66 69 63 74 69 74 69 6f  |ce......fictitio|
00000220  75 73 00 00 00 00 00 00  00 02 00 00 64 00 00 00  |us..........d...|
00000230  01 00 00 00 00 0a 00 00  64 00 00 00 00 e8 03 00  |........d.......|
00000240  a2 c2 fa c8 49 6d 90 c3  00 00 00 00 00 00 00 00  |....Im..........|
00000250  00 00 00 00 00 e8 03 00  00 00 00 00 00 00 00 00  |................|
00000260  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000270  00 00 01 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000280  00 00 00 00 57 45 56 82  89 ca 10 00 00 20 00 00  |....WEV...... ..|
00000290  00 00 01 00 00 e8 03 00  00 00 00 00 00 00 00 00  |................|
000002a0  07 14 01 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000002b0  00 00 00 00 00 e8 03 00  00 00 00 00 00 00 00 00  |................|
000002c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
07d00000

出来上がったDISKのダンプ。これでdisklabelの所業が分るな。

super block

ちょっと寄り道して、要のスーパーブロックについて調べておく。簡単なものがいいだろう。 いきなり実用のOSじゃ眩暈発熱悪寒で、スーパー何とか薬のお世話になりそうだから。

at xv6

// Disk layout:
// [ boot block | super block | log | inode blocks |
//                                          free bit map | data blocks]
//
// mkfs computes the super block and builds an initial file system. The
// super block describes the disk layout:
struct superblock {
  uint size;         // Size of file system image (blocks)
  uint nblocks;      // Number of data blocks
  uint ninodes;      // Number of inodes.
  uint nlog;         // Number of log blocks
  uint logstart;     // Block number of first log block
  uint inodestart;   // Block number of first inode block
  uint bmapstart;    // Block number of first free map block
};

案内のmkfs内は、こうなっていた。こんなものなのか。

sb.size = xint(FSSIZE);
sb.nblocks = xint(nblocks);
sb.ninodes = xint(NINODES);
sb.nlog = xint(nlog);
sb.logstart = xint(2);
sb.inodestart = xint(2+nlog);
sb.bmapstart = xint(2+nlog+ninodeblocks);

at minix

簡単なものの代表って事で、もう一種類。

fs/super.h

 *      Item        # blocks
 *    boot block      1
 *    super block     1
 *    inode map     s_imap_blocks
 *    zone map      s_zmap_blocks
 *    inodes        (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK
 *    unused        whatever is needed to fill out the current zone
 *    data zones    (s_nzones - s_firstdatazone) << s_log_zone_size

EXTERN struct super_block {
  inode_nr s_ninodes;           /* # usable inodes on the minor device */
  zone_nr s_nzones;             /* total device size, including bit maps etc */
  unshort s_imap_blocks;        /* # of blocks used by inode bit map */
  unshort s_zmap_blocks;        /* # of blocks used by zone bit map */
  zone_nr s_firstdatazone;      /* number of first data zone */
  short int s_log_zone_size;    /* log2 of blocks/zone */
  file_pos s_max_size;          /* maximum file size on this device */
  int s_magic;                  /* magic number to recognize super-blocks */

  /* The following items are only used when the super_block is in memory. */
  struct buf *s_imap[I_MAP_SLOTS]; /* pointers to the in-core inode bit map */
  struct buf *s_zmap[ZMAP_SLOTS]; /* pointers to the in-core zone bit map */
  dev_nr s_dev;                 /* whose super block is this? */
  struct inode *s_isup;         /* inode for root dir of mounted file sys */
  struct inode *s_imount;       /* inode mounted on */
  real_time s_time;             /* time of last update */
  char s_rd_only;               /* set to 1 iff file sys mounted read only */
  char s_dirt;                  /* CLEAN or DIRTY */
} super_block[NR_SUPERS];

利便牲を考慮して、最終的にはメモリー上に展開し、関連部分を追加するとの事。そういう戦略も有りなんだな。

これを実際に作っているのは、tools/mkfs.c の中。

make newfs

次は、gdbにかけられるように特製のnewfsを作る。mount/ とか disklabel/ から一部のファイルを借りてきた。

vbox$ ls
Makefile        extern.h        mkfs.c          newfs.8         pathnames.h
dkcksum.c       getmntopts.c    mntopts.h       newfs.c
vbox$ make
cc -g -O0 -DMFS -I/tmp/newfs/../mount  -MD -MP  -c dkcksum.c
cc -g -O0 -DMFS -I/tmp/newfs/../mount  -MD -MP  -c getmntopts.c
cc -g -O0 -DMFS -I/tmp/newfs/../mount  -MD -MP  -c newfs.c
cc -g -O0 -DMFS -I/tmp/newfs/../mount  -MD -MP  -c mkfs.c
cc   -o newfs dkcksum.o getmntopts.o newfs.o mkfs.o -lutil
vbox# ./newfs vnd0a
/dev/rvnd0a: 125.0MB in 256000 sectors of 512 bytes
4 cylinder groups of 31.25MB, 2000 blocks, 4032 inodes each
super-block backups (for fsck -b #) at:
 160, 64160, 128160, 192160,
(gdb) b mkfs
Breakpoint 1 at 0x7058: file mkfs.c, line 177.
(gdb) r vnd0a
Starting program: /tmp/newfs/newfs vnd0a

Breakpoint 1, mkfs (pp=0x3411c888 <getdisklabel.lab+148>, fsys=0x2b7043c5 <open\
dev.namebuf> "/dev/rvnd0a", fi=4, fo=3, mfsmode=0, mfsuid=0, mfsgid=0) at mkfs.\
c:177
177             if ((fsun = calloc(1, sizeof (union fs_u))) == NULL ||

途中で、sblockってのが頻出するんで、どんな内容か確認。んが、そんなの無いと言われた。なして? 調べてみたら。

#define sblock  fsun->fs

defineで定義した奴はgdbからは見えないのか。

(gdb) p/x fsun->fs
$2 = {
  fs_firstfield = 0x0,
  fs_unused_1 = 0x0,
  fs_sblkno = 0x28,
  fs_cblkno = 0x30,
  fs_iblkno = 0x38,
  fs_dblkno = 0x230,
  fs_cgoffset = 0x0,
  fs_cgmask = 0x0,
  fs_ffs1_time = 0x0,
  fs_ffs1_size = 0x0,
  fs_ffs1_dsize = 0x0,
  fs_ncg = 0x4,
  fs_bsize = 0x4000,
  fs_fsize = 0x800,
  fs_frag = 0x8,
   :
  fs_maxsymlinklen = 0x78,
  fs_inodefmt = 0x2,
  fs_maxfilesize = 0x80100202ffff,
  fs_qbmask = 0x3fff,
  fs_qfmask = 0x7ff,
  fs_state = 0x0,
  fs_postblformat = 0x1,
  fs_nrpos = 0x1,
  fs_postbloff = 0x0,
  fs_rotbloff = 0x0,
  fs_magic = 0x19540119,
  fs_space = {0x0}
}

大事なスーパーブロックを次のループの所で、DISK内に分散して格納してる(570行目あたり)。

        for (cg = 0; cg < sblock.fs_ncg; cg++) {
                cur_cylno = (sig_atomic_t)cg;
                initcg(cg, utime);
                if (quiet)
                        continue;
                j = snprintf(tmpbuf, sizeof tmpbuf, " %lld,",
                    (long long)fsbtodb(&sblock, cgsblock(&sblock, cg)));
                if (j >= sizeof tmpbuf)
                        j = sizeof tmpbuf - 1;
=>              if (j < 0 || i+j >= width) {
                        printf("\n");
                        i = 0;
                }
                i += j;
                printf("%s", tmpbuf);
                fflush(stdout);
        }

4箇所に分散してるはずなんだけど、forの終りを定義してる、 sblock.fs_ncg が、ちょいといまいましい(上で出て来たdefine)。そんな時は、

(gdb) set $sblock=fsun->fs
(gdb) p $sblock.fs_ncg
$4 = 4

こんな風にgdbのコンビニエンス変数に、define値を写してしまおう。そして、変数の頭に$をつけて、変数を利用(参照)すれば良い。

で、スーパーブロックのサイズは、fs.hに定義されてて、SBLOCKSIZE 8192 てなってた。 ここまで、流れは分るんだけど、中身は解らず。なんとかしたいぞ。 fs.h

* For file system fs, the offsets of the various blocks of interest
* are given in the super block as:
*      [fs->fs_sblkno]         Super-block
*      [fs->fs_cblkno]         Cylinder group block
*      [fs->fs_iblkno]         Inode blocks
*      [fs->fs_dblkno]         Data blocks
* The beginning of cylinder group cg in fs, is given by
* the ``cgbase(fs, cg)'' macro.

camcontrol or atactl

/sbinにDISK関連のアプリが集中して置いてある。どんなのがあるかと思ったら、もろにatactlなんてのがあった。じゃ、FreeBSDではどうよ? ataってのが発展解消してCAM(4)になったそうだ。

DESCRIPTION
     The CAM subsystem provides a uniform and modular system for the
     implementation of drivers to control various SCSI, ATA, NVMe, and MMC /
     SD devices, and to utilize different SCSI, ATA, NVMe, and MMC / SD host
     adapters through host adapter drivers.  When the system probes buses, it
     attaches any devices it finds to the appropriate drivers.  The pass(4)
     driver, if it is configured in the kernel, will attach to all devices.

今ならSDDが主流だけど、それはどうなってるの? まあ、取り敢えず使ってみる。

root@fb:/home/sakae # camcontrol identify /dev/ada0
pass0: <HITACHI HTS545025B9A300 PB2ZC61H> ATA8-ACS SATA 2.x device
pass0: 300.000MB/s transfers (SATA 2.x, UDMA5, PIO 8192bytes)

protocol              ATA8-ACS SATA 2.x
device model          HITACHI HTS545025B9A300
firmware revision     PB2ZC61H
serial number         091026PB42041SGY80YB
WWN                   5000cca5e7cd4ce8
additional product id
cylinders             16383
heads                 16
sectors/track         63
sector size           logical 512, physical 512, offset 0
LBA supported         268435455 sectors
LBA48 supported       488397168 sectors
PIO supported         PIO4
DMA supported         WDMA2 UDMA5
media RPM             5400
Zoned-Device Commands no

Feature                      Support  Enabled   Value           Vendor
read ahead                     yes      yes
 :
Native Command Queuing (NCQ)   yes              32 tags
NCQ Priority Information       yes
NCQ Non-Data Command           no
NCQ Streaming                  no
Receive & Send FPDMA Queued    no
NCQ Autosense                  no
SMART                          yes      yes
 :

dual boot してる 10年選手のThinkpadのシステムだ。で、SMARTなんてのをサポートしてるみたい。HDDの診断だな。

smartctl

ちょっくら入れてみるか。資料はこちら。 FreeBSDでハードディスクのヘルスチェックを行う方法

root@fb:/home/sakae # /usr/local/sbin/smartctl -a /dev/ada0
=== START OF INFORMATION SECTION ===
Device Model:     HITACHI HTS545025B9A300
Serial Number:    091026PB42041SGY80YB
LU WWN Device Id: 5 000cca 5e7cd4ce8
Firmware Version: PB2ZC61H
User Capacity:    250,059,350,016 bytes [250 GB]
Sector Size:      512 bytes logical/physical
Rotation Rate:    5400 rpm
Form Factor:      2.5 inches
Device is:        Not in smartctl database 7.3/5319
ATA Version is:   ATA8-ACS T13/1699-D revision 6
SATA Version is:  SATA 2.6, 3.0 Gb/s (current: 3.0 Gb/s)
Local Time is:    Wed Oct 26 06:56:32 2022 JST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
  :

案外丈夫なものだな。

from USB

ポータブルって事で、USBからOpenBSD6.9を起動して、DISKがどう見えるか確認。 切り換えメニューは F12 キーの連打だった。すっかり忘れていたぞ。

obusb$ dmesg|grep sd
sd0 at scsibus1 targ 0 lun 0: <ATA, HITACHI HTS54502, PB2Z> naa.5000cca5e7cd4ce8
sd0: 238475MB, 512 bytes/sector, 488397168 sectors
sd1 at scsibus2 targ 1 lun 0: <BUFFALO, USB Flash Disk, 1.00> removable serial.04110239319600000407
sd1: 7626MB, 512 bytes/sector, 15618048 sectors

ちゃんと認識した。区画の確認で、知らないやつは、数字を事細かに並べて、煙に卷く作戦だんだな。まあ、dual boot なDISKだからなあ。

obusb$ fdisk sd0
Disk: sd0       Usable LBA: 40 to 488397134 [488397168 Sectors]
   #: type                                 [       start:         size ]
------------------------------------------------------------------------
   0: 83bd6b9d-7f41-11dc-be0b-001560b84f0f [          40:         1024 ]
   1: 516e7cb6-6ecf-11d6-8ff8-00022d09712b [        1064:    100662272 ]
   2: 516e7cb5-6ecf-11d6-8ff8-00022d09712b [   100663336:      8388608 ]
   3: 21686148-6449-6e6f-744e-656564454649 [   109053952:         2048 ]
   4: Linux files*                         [   109056000:    377341952 ]
   5: FAT12                                [   486397952:      1998848 ]

atactlで詳細を確認しようにも、そんなデバイスは知らないといわれた。 atactlコマンドでは、SMARTをコントロールする自前の機能を持っているんで、試してみたかったんだけど、残念至極であります。


This year's Index

Home