#chiroito ’s blog

Java を中心とした趣味の技術について

OSが起動したままマウントしてる XFS のサイズを増やしてみた

/ の領域が足りなくなってきてしまったけど、仮想マシンからデタッチして、他の仮想マシンにアタッチ・マウントしてからサイズ増やして、また戻してからマウントするの面倒臭いなと2ヶ月ぐらい思っていたら、growpartというツールでマウントしたままパーティション情報変えられるようだったので試してみた。

今のサイズはこんな感じ

# df
ファイルシス   1K-ブロック      使用    使用可 使用% マウント位置
(略)
/dev/sda3          9753600   8619504   1134096   89% /
(略)

growpartを使うにはcloud-utils-growpart というパッケージを入れるだけです。

# yum install cloud-utils-growpart
読み込んだプラグイン:langpacks, ulninfo
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ cloud-utils-growpart.noarch 0:0.29-2.el7 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

================================================================================
 Package                   アーキテクチャー
                                       バージョン         リポジトリー     容量
================================================================================
インストール中:
 cloud-utils-growpart      noarch      0.29-2.el7         ol7_latest       26 k

トランザクションの要約
================================================================================
インストール  1 パッケージ

総ダウンロード容量: 26 k
インストール容量: 61 k
Is this ok [y/d/N]: y
Downloading packages:
cloud-utils-growpart-0.29-2.el7.noarch.rpm                 |  26 kB   00:03     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : cloud-utils-growpart-0.29-2.el7.noarch          1/1 
  検証中                  : cloud-utils-growpart-0.29-2.el7.noarch          1/1 

インストール:
  cloud-utils-growpart.noarch 0:0.29-2.el7                                      

完了しました!

インストールが終わったらパーティションサイズを増やして、XFS ファイルシステムのサイズも拡張します。 パーティションサイズを増やすにはgrowpart <デバイス> <パーティション番号>を実行します。今回は/dev/sda3のパーティションが対象なのでデバイスは/dev/sda、パーティション番号は3を指定します。

# growpart /dev/sda 3
CHANGED: partition=3 start=1443840 old: size=19527680 end=20971520 new: size=40499167,end=41943007

# xfs_growfs /
meta-data=/dev/sda3              isize=256    agcount=6, agsize=478976 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=2440960, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2440960 to 5062395

これだけで完了です。dfしてみると容量が増えてるのが確認できます。

[root@localhost ~]# df
ファイルシス   1K-ブロック      使用    使用可 使用% マウント位置
(略)
/dev/sda3         20239340   8820276  11419064   44% /
(略)

Terraform を使って Cloud上に OpenJDK の開発環境を整えてみた

OpenJDK のビルドやテストは時間が非常に掛かるので、クラウド上で大量の CPU リソースを使って短時間化できないかを試してみました。

今回作った環境に自分で書いたパッチを置いて Terraform を実行すると、あとはクラウド上で大量のリソースを使ってビルドとテストが終わるようになりました。試しに 48 vCPU の環境を作ったところ、ビルドは4~5分、fastdebug での Tier1 のテストは40分程度で完了しました。

ソースコードはこちら(sandbox/Terraform/developOpenJDK at master · chiroito/sandbox · GitHub

クラウドを使うと言えど毎回この全行程を実行するのは時間(=料金)がかかるので、できる限り再利用したいと思います。 今回は、再利用できる部分と毎回処理する部分に分けて環境を構築してみました。再利用できる部分は環境構築時に作成して Block Storage として保管しておきます。Block Storage は 2 つ作ってあり、1つはOSや作業スクリプトなど一回作ったらしばらく変らない部分を Boot イメージとして作成し、もう1つは、OpenJDK のソースコードなどわりと頻繁に変る部分を作業用のボリュームとして作成しました。

今回は Terraform を使って Oracle Cloud 上に環境を構築していきます。OpenJDK 関連の作業はシェル化してあるので他のクラウドサービス上でも環境構築できると思います。

f:id:chiroito:20190106155351p:plain

OpenJDK の環境を整えてテストを流すために必要な作業は以下のようになります。

  1. ビルドやテストに必要なパッケージのインストール
  2. OpenJDK ソースコードのダウンロード
  3. テストツールであるJTREG ソースコードのダウンロード
  4. 自分で書いたパッチを適用
  5. OpenJDK と JTREG のビルド
  6. JTREG を使って OpenJDK のテストを実行

今回は、再利用できる部分として1~3 を済ませた Block Storage を作成し、テスト実行時に 4 以降の作業をするようにします。1~3の部分はダウンロード時間がほとんどを占めるため、CPU の量が少ないインスタンスを使えます。

OpenJDK のスクリプト

  1. ビルドやテストに必要なパッケージのインストール
  2. OpenJDK ソースコードのダウンロード
  3. テストツールであるJTREG ソースコードのダウンロード
SRC_BASE_PATH=${1}
sudo yum groupinstall -y "Development Tools"
sudo yum install -y freetype-devel cups-devel libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel alsa-lib-devel libffi-devel autoconf java-1.8.0-openjdk-devel fontconfig-devel java-11-openjdk-devel mercurial
mkdir -p ${SRC_BASE_PATH}
cd ${SRC_BASE_PATH}
hg clone http://hg.openjdk.java.net/jdk/jdk
hg clone http://hg.openjdk.java.net/code-tools/jtreg

4 . 自分で書いたパッチを適用

5 . OpenJDK と JTREG のビルド

SRC_BASE_PATH=${1}
cd ${SRC_BASE_PATH}/jtreg
hg pull -u
bash make/build-all.sh /usr/lib/jvm/java-1.8.0

cd ${SRC_BASE_PATH}/jdk
hg pull -u
patch -p1 < /home/opc/myPatch
bash configure --enable-debug --with-native-debug-symbols=internal --with-boot-jdk=/usr/lib/jvm/java-11 --with-jtreg=${SRC_BASE_PATH}/jtreg/build/images/jtreg
time make images

6 . JTREG を使って OpenJDK のテストを実行

SRC_BASE_PATH=${1}
cd ${SRC_BASE_PATH}/jdk
time make test-tier1

Terraform のスクリプト

環境構築時に実行されて、以後再利用される処理

resource "null_resource" "preparing_task" {
  depends_on = ["oci_core_instance.prepare_instance", "oci_core_volume_attachment.prepare_volume_attach"]
  connection {
    agent       = false
    timeout     = "300m"
    host        = "${oci_core_instance.prepare_instance.public_ip}"
    user        = "opc"
    private_key = "${file("${var.ssh_private_key}")}"
  }
  provisioner "file" {
    source = "script"
    destination = "/home/opc/"
  }
  provisioner "remote-exec" {
    inline = [ <<EOS
sh /home/opc/script/prepareForOpenJDK.sh /src
EOS
    ]
  }
}

ビルドとテストのたびに実行される処理

resource "null_resource" "build_and_test_task" {
  depends_on = ["oci_core_instance.worker_instance", "oci_core_volume_attachment.worker_volume_attach"]
  connection {
    agent       = false
    timeout     = "120m"
    host        = "${oci_core_instance.worker_instance.public_ip}"
    user        = "opc"
    private_key = "${file("${var.ssh_private_key}")}"
  }
  provisioner "file" {
    source = "script"
    destination = "/home/opc/"
  }
  provisioner "file" {
    source = "userdata/myPatch"
    destination = "/home/opc/"
  }
  provisioner "remote-exec" {
    inline = [ <<EOS
sh /home/opc/script/buildOpenJDK.sh /src
sh /home/opc/script/testOpenJDK.sh /src
EOS
    ]
  }
}

全体のソースコードはこちら(sandbox/Terraform/developOpenJDK at master · chiroito/sandbox · GitHub

OpenJDK のテストをデバッグ実行するためいろいろ試みてみた

Java のコードをデバッグ実行するには-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345みたいな感じのを付けます。これを使って OpenJDK の Java 部分のデバッグができるだろうなと思って試してみました。

jtreg で実行するテストコードにこれを付けたところ、アタッチするまでに気が遠くなるぐらい長い時間がかかり、やっと繋がったと思ったら jtreg のタイムアウトにやられるため実用に耐えられなかったです。

なので、もっと気軽にアタッチできる方法は無いか試してみました。

make で jtreg を使うには configure するときに --with-jtreg=/src/jtreg/build/images/jtreg を付けないといけません。自分がどのオプションで実行したかは build/linux-x86_64-server-fastdebug/configure.log で確認できます。linux-x86_64fastdebug の部分は環境や指定したオプションによって変ります。

jtreg で実行したテストへアタッチ

jtreg でテストを実行する JVM へVM引数を渡すには JTREG="VM_OPTIONS=*****" のような形式でmake の実行時に指定します。***** の部分がVM引数としてテストを実行する JVM へ渡されます。

今回は JTREG="VM_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345" としています。

> make test TEST="test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java" JTREG="VM_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345"

Building target 'test' in configuration 'linux-x86_64-server-fastdebug'
Skip building of Graal unit tests because 3rd party libraries directory is not specified
Skip building of Graal unit tests because 3rd party libraries directory is not specified
Running tests using JTREG control variable 'VM_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345'
Test selection 'test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java', will run:
* jtreg:test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java

Running test 'jtreg:test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java'
[2019-01-02 11:48:15,081] Agent[0]: stdout: Listening for transport dt_socket at address: 12345
[2019-01-02 11:48:32,392] Agent[0]: stderr: openjdk version "13-internal" 2019-09-17
[2019-01-02 11:48:32,397] Agent[0]: stderr: OpenJDK Runtime Environment (fastdebug build 13-internal+0-adhoc.chito.jdk)
[2019-01-02 11:48:32,397] Agent[0]: stderr: OpenJDK 64-Bit Server VM (fastdebug build 13-internal+0-adhoc.chito.jdk, mixed mode)

実行してみると分かりますが、恐ろしく長い時間が掛かりますし、いつになったらアタッチできるのか分かりません。ポートは開くのですがアタッチされる準備は出来ていないようなので、Connection Refused されてしまい「接続できない??」と思うほどです。

jtreg を使わずにテストを実行してみる

これでは OpenJDK を開発する中で軽い気持ちで動作を確認できないので、方法を模索してみました。

各種 IDE 上でテストコードをコンパイルして実行してみようと思ったのですが、IDE ちからがなくて断念。

面倒臭い部分は全て jtreg にやってもらって、実行だけできないかと思い、jtreg が生成するクラスファイルなどを使用することにしました。

make test すると build/linux-x86_64-server-fastdebug/test-support/ ディレクトリ以下にいろいろ作ってくれます。その中にはクラスファイルも含まれるためこちらを使用することとしました。

以下 5 つの変数を使ってテストを実行したいと思います。

  • JAVA_EXE はテストしたい環境の java ファイルを指定します。
  • JAVA_OPTIONS は自分が追加したい VM 引数を指定します。
  • TEST_CLASSPATH はjtregに作成されたクラスファイル群を指定します。
  • TEST_OPTIONS はテストのファイルに記載されているオプションを指定します。
  • TEST_CLASS は実行したいテストクラスを指定します。
> export JAVA_EXE=build/linux-x86_64-server-fastdebug/images/jdk/bin/java
> export JAVA_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345

> export TEST_CLASSPATH=build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_jdk_jfr_startupargs_TestRepositoryPath_java/classes/jdk/jfr/startupargs/TestRepositoryPath.d
> export TEST_OPTIONS=-XX:StartFlightRecording=name=TestStartRecording,settings=profile -XX:FlightRecorderOptions=repository=./repo
> export TEST_CLASS=jdk.jfr.startupargs.TestRepositoryPath

> ${JAVA_EXE} ${JAVA_OPTIONS} -cp  ${TEST_CLASSPATH} ${TEST_OPTIONS} ${TEST_CLASS}

Listening for transport dt_socket at address: 12345

この方法だと、すぐにアタッチできるようになりタイムアウトもなくなったので、OpenJDK のデバッグライフがより快適になるのではないかと思います。