表題の機能を動作確認したので、結果を残しておきます。
概要
node01, node02の2台のクライアントで、同じボリュームをNativeプロトコル、もしくはNFSでマウントします。この状態で、一方のクライアントがボリューム上のファイルにflock()(Linux独自のAdvisory Lock)、もしくはlockf()(POSIX File Lock)を取得すると、もう一方のクライアントからもロックが認識されます。
特にNFSロックは、GlusterFS3.2.xでは未対応でしたので、NFSロックが必要なアプリケーションを利用する際は、RHS2.0/GlusterFS3.3以降をご使用ください。
※ GlusterFSが稼働するストレージノード自身をNFSクライアントとして使用することはできませんのでご注意下さい。
flock()の動作確認(Nativeマウント編)
flock()は、Linux独自の実装で、Write Lock(Exclusive Lock)/Read Lock(Shared Lock)があって、さらにファイル以外にディレクトリにもロックが取得できます。
次のシェルスクリプトで、いろいろな組み合わせをテストしてみます。簡単のためにLinuxのflockコマンドを使用しています。
flocktest.sh
#!/bin/sh NODE_A=node01 NODE_B=node02 function linuxlock { node=$1 opt=$2 lockfile=$3 echo $node ": Trying to take an $opt lock on " $lockfile ssh $node "flock $opt $lockfile -c \" echo -n $node \\\": Succeeded at \\\"; date +%T; sleep 10; echo -n $node \\\": Releasing the lock at \\\"; date +%T; \"" } echo "=== Write-Write file lock test." linuxlock $NODE_A -x /mnt/dir01/file01 & sleep 1 linuxlock $NODE_B -x /mnt/dir01/file01 & wait echo "=== Write-Read file lock test." linuxlock $NODE_A -x /mnt/dir01/file01 & sleep 1 linuxlock $NODE_B -s /mnt/dir01/file01 & wait echo "=== Read-Write file lock test." linuxlock $NODE_A -s /mnt/dir01/file01 & sleep 1 linuxlock $NODE_B -x /mnt/dir01/file01 & wait echo "=== Read-Read file lock test." linuxlock $NODE_A -s /mnt/dir01/file01 & sleep 1 linuxlock $NODE_B -s /mnt/dir01/file01 & wait echo "=== Write-Write dir lock test." linuxlock $NODE_A -x /mnt/dir01 & sleep 1 linuxlock $NODE_B -x /mnt/dir01 & wait echo "=== Write-Read dir lock test." linuxlock $NODE_A -x /mnt/dir01 & sleep 1 linuxlock $NODE_B -s /mnt/dir01 & wait echo "=== Read-Write dir lock test." linuxlock $NODE_A -s /mnt/dir01 & sleep 1 linuxlock $NODE_B -x /mnt/dir01 & wait echo "=== Read-Read dir lock test." linuxlock $NODE_A -s /mnt/dir01 & sleep 1 linuxlock $NODE_B -s /mnt/dir01 & wait
各ノードの/mntにボリュームをNatvieマウントして、ファイル「/mnt/dir01/file01」を作成しておきます。
# ssh node01 mount | grep mnt rhs20-01:/vol01 on /mnt type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072) # ssh node02 mount | grep mnt rhs20-01:/vol01 on /mnt type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)
この状態で上記のシェルを実行します。
# ./flocktest.sh === Write-Write file lock test. node01 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Succeeded at 01:11:26 node02 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:11:36 node02 : Succeeded at 01:11:37 node02 : Releasing the lock at 01:11:47 === Write-Read file lock test. node01 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Succeeded at 01:11:46 node02 : Trying to take a -s lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:11:56 node02 : Succeeded at 01:11:57 node02 : Releasing the lock at 01:12:07 === Read-Write file lock test. node01 : Trying to take a -s lock on /mnt/dir01/file01 node01 : Succeeded at 01:12:06 node02 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:12:16 node02 : Succeeded at 01:12:17 node02 : Releasing the lock at 01:12:27 === Read-Read file lock test. node01 : Trying to take a -s lock on /mnt/dir01/file01 node01 : Succeeded at 01:12:26 node02 : Trying to take a -s lock on /mnt/dir01/file01 node02 : Succeeded at 01:12:28 node01 : Releasing the lock at 01:12:36 node02 : Releasing the lock at 01:12:38 === Write-Write dir lock test. node01 : Trying to take a -x lock on /mnt/dir01 node01 : Succeeded at 01:12:37 node02 : Trying to take a -x lock on /mnt/dir01 node02 : Succeeded at 01:12:39 node01 : Releasing the lock at 01:12:47 node02 : Releasing the lock at 01:12:49 === Write-Read dir lock test. node01 : Trying to take a -x lock on /mnt/dir01 node01 : Succeeded at 01:12:49 node02 : Trying to take a -s lock on /mnt/dir01 node02 : Succeeded at 01:12:50 node01 : Releasing the lock at 01:12:59 node02 : Releasing the lock at 01:13:00 === Read-Write dir lock test. node01 : Trying to take a -s lock on /mnt/dir01 node01 : Succeeded at 01:13:00 node02 : Trying to take a -x lock on /mnt/dir01 node02 : Succeeded at 01:13:02 node01 : Releasing the lock at 01:13:10 node02 : Releasing the lock at 01:13:12 === Read-Read dir lock test. node01 : Trying to take a -s lock on /mnt/dir01 node01 : Succeeded at 01:13:11 node02 : Trying to take a -s lock on /mnt/dir01 node02 : Succeeded at 01:13:13 node01 : Releasing the lock at 01:13:21 node02 : Releasing the lock at 01:13:23
地味ですが、すべて期待通りの結果です。Read-Readのロックは同時に取得できる点に注意してください。
flock()の動作確認(NFSマウント編)
先と同じことを/mntにボリュームをNFSマウントした状態で行います。
# ssh node01 mount | grep mnt rhs20-01:/vol01 on /mnt type nfs (rw,vers=3,addr=192.168.122.21) # ssh node02 mount | grep mnt rhs20-01:/vol01 on /mnt type nfs (rw,vers=3,addr=192.168.122.21)
この例ではマウント先のGlusterFSサーバは同一ですが、同じクラスタ内の異なるサーバを指定してNFSマウントした場合でも、NFS Lockは機能します。
# ./flocktest.sh === Write-Write file lock test. node01 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Succeeded at 01:15:35 node02 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:15:45 node02 : Succeeded at 01:15:46 node02 : Releasing the lock at 01:15:56 === Write-Read file lock test. node01 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Succeeded at 01:15:55 node02 : Trying to take a -s lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:16:05 node02 : Succeeded at 01:16:06 node02 : Releasing the lock at 01:16:16 === Read-Write file lock test. node01 : Trying to take a -s lock on /mnt/dir01/file01 node01 : Succeeded at 01:16:15 node02 : Trying to take a -x lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:16:25 node02 : Succeeded at 01:16:26 node02 : Releasing the lock at 01:16:36 === Read-Read file lock test. node01 : Trying to take a -s lock on /mnt/dir01/file01 node01 : Succeeded at 01:16:35 node02 : Trying to take a -s lock on /mnt/dir01/file01 node02 : Succeeded at 01:16:37 node01 : Releasing the lock at 01:16:45 node02 : Releasing the lock at 01:16:47 === Write-Write dir lock test. node01 : Trying to take a -x lock on /mnt/dir01 node01 : Succeeded at 01:16:46 node02 : Trying to take a -x lock on /mnt/dir01 node02 : Succeeded at 01:16:48 node01 : Releasing the lock at 01:16:56 node02 : Releasing the lock at 01:16:58 === Write-Read dir lock test. node01 : Trying to take a -x lock on /mnt/dir01 node01 : Succeeded at 01:16:57 node02 : Trying to take a -s lock on /mnt/dir01 node02 : Succeeded at 01:16:59 node01 : Releasing the lock at 01:17:07 node02 : Releasing the lock at 01:17:09 === Read-Write dir lock test. node01 : Trying to take a -s lock on /mnt/dir01 node01 : Succeeded at 01:17:09 node02 : Trying to take a -x lock on /mnt/dir01 node02 : Succeeded at 01:17:10 node01 : Releasing the lock at 01:17:19 node02 : Releasing the lock at 01:17:20 === Read-Read dir lock test. node01 : Trying to take a -s lock on /mnt/dir01 node01 : Succeeded at 01:17:20 node02 : Trying to take a -s lock on /mnt/dir01 node02 : Succeeded at 01:17:22 node01 : Releasing the lock at 01:17:30 node02 : Releasing the lock at 01:17:32
NFSの場合は、ディレクトリに対するロックは取得できないので注意してください。
※結果は記載しませんが、面白いことに、一方がNativeマウントで、一方がNFSマウントの場合でもファイルに対しては、分散flock()が機能しました。
lockf()の動作確認
続いて、POSIXロックの確認です。POSIXロックは、Writeロック(Exclusiveロック)のみで、ディレクトリに対しては取得できないので、テストケースは1つですみます。
・・・と、ここで、POSIXロックを取得するlockfコマンドは、Linuxにも無いことに気づきました。Cのlockf()システムコールで一からテストを書くのも悔しいので、flockコマンドのソースをQuick Hackして、lockfコマンドを用意しました。
ここで見つけたflock.cに下記の修正を加えて、コンパイルして、lockfコマンドを作ります。
# diff -uprN flock.c lockf.c --- flock.c 2012-04-19 07:41:34.000000000 +0900 +++ lockf.c 2012-04-19 07:56:19.000000000 +0900 @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) } filename = argv[optind]; - fd = open(filename, O_RDONLY|O_NOCTTY|O_CREAT, 0666); + fd = open(filename, O_RDWR|O_NOCTTY|O_CREAT, 0666); /* Linux doesn't like O_CREAT on a directory, even though it should be a no-op */ if (fd < 0 && errno == EISDIR) @@ -257,7 +257,7 @@ int main(int argc, char *argv[]) } } - while ( flock(fd, type|block) ) { + while ( lockf(fd, F_LOCK, 0) ) { switch( (err = errno) ) { case EWOULDBLOCK: /* -n option set and failed to lock */ exit(1);
できたものを/root/work/lockfにおいて、次のスクリプトでテストします。
lockftest.sh
#!/bin/sh NODE_A=node01 NODE_B=node02 function posixlock { node=$1 opt=$2 lockfile=$3 echo $node ": Trying to take an $opt lock on " $lockfile ssh $node "/root/work/lockf $opt $lockfile -c \" echo -n $node \\\": Succeeded at \\\"; date +%T; sleep 10; echo -n $node \\\": Releasing the lock at \\\"; date +%T; \"" } echo "=== Write-Write file lock test." posixlock $NODE_A -x /mnt/dir01/file01 & sleep 1 posixlock $NODE_B -x /mnt/dir01/file01 & wait
ここでは、代表的な結果のみを記載しますが、Nativeマウント同士、NFSマウント同士、NativeマウントとNFSマウントの組み合わせ、すべて同じ結果です。
# ./lockftest.sh === Write-Write file lock test. node01 : Trying to take an -x lock on /mnt/dir01/file01 node01 : Succeeded at 01:33:28 node02 : Trying to take an -x lock on /mnt/dir01/file01 node01 : Releasing the lock at 01:33:38 node02 : Succeeded at 01:33:39 node02 : Releasing the lock at 01:33:49