読者です 読者をやめる 読者になる 読者になる

GeekFactory

int128.hatenablog.com

Sambaにおける複数パーティションの容量の補正

samba golang

Samba複数パーティションをまたがる共有ドライブを公開すると、空き容量が正しく表示されない問題があります。

例えば、下表のように /home の下に複数パーティションをマウントしている場合、 /home の共有ドライブに対する容量は10 GBと表示されてしまいます。本来は210 GBとなるはずです。また、容量が正しく表示されないだけでなく、大きなファイルをコピーできない問題も発生します。

マウントポイント ディスク 容量
/home /dev/sda1 10 GB
/home/fiz /dev/sdb1 100 GB
/home/buz /dev/sdc1 100 GB

dfreeによる解決策

Sambaでは dfree command という設定が用意されており、ディスクの全容量や空き容量を外部コマンドに計算させることが可能です。具体的には、以下のように dfree command に外部コマンドのパスを渡すと、ディスク容量の計算が必要になった時に外部コマンドが実行されます。また、 dfree cache time で指定した秒数だけ計算結果をキャッシュさせることも可能です。

# smb.conf
[home]
path = /home
dfree command = /etc/samba/samba-dfree
dfree cache time = 60

外部コマンドの仕様は、マニュアルには以下のように記載されています。

The external program will be passed a single parameter indicating a directory in the filesystem being queried. This will typically consist of the string ./. The script should return two integers in ASCII. The first should be the total disk space in blocks, and the second should be the number of available blocks. An optional third return value can give the block size in bytes. The default blocksize is 1024 bytes. https://www.samba.org/samba/docs/man/manpages/smb.conf.5.html#idp59614672

外部コマンドの引数にはディレクトリのパスが渡されます。また、外部コマンドは全容量と空き容量の2つの値を標準出力に表示する必要があります。値は1024 byteのブロック単位です。バイト数を1024で割るとよいでしょう。

マニュアルに詳細が書かれていないので、外部コマンドがどのように実行されるか調べてみました。カレントディレクトリは共有ドライブのパス(例では /home )になるようです。また、引数には . しか渡されないようです。

このことから、 dfree command で指定した外部コマンドは以下の動作をすればよいことが分かります。

  1. カレントディレクトリ(例: /home)と引数(例: .)から計算対象のディレクトリを調べる。
  2. 計算対象のディレクトリに含まれるサブディレクトリを調べる。例では /home/fiz/home/buz になる。
  3. サブディレクトリの全容量と空き容量を合算する。例では 210 GBになる。
  4. 全容量と空き容量のバイト数を1024で割った値を表示する。

dfreeの実装

せっかくなのでGoで実装してみました。

github.com

ソースコードだけでなくx86_64で動作するバイナリも公開しているので、よかったら利用してください。Travis CIでビルドされたバイナリをGitHubに直接リリースしています。