2005年11月07日(月) [長年日記]
■ [unix] Linuxのflock(2)でNFS上にあるファイルをロックする
flock(2)を使う
flock(2) は NFS 上のファイルのロックをしない。代わりに fcntl(2) を使用すること。これにより、十分に新しいバージョンの Linux と、ロック機能をサポートした NFS サーバを使用することにより、NFS 上でロックができる。
とある。が、
Linux NFS faqのD.10に、
The NFS client in 2.6.12 provides support for flock()/BSD locks on NFS files by emulating the BSD-style locks in terms of POSIX byte range locks. Other NFS clients that use the same emulation mechanism, or that use fcntl()/POSIX locks, will then see the same locks that the Linux NFS client sees.
とあり、よく分からんがLinuxのカーネル2.6.12からはflock(2)を使ってもNFS上のファイルをロックできるように読めたのでFedora Core 3のカーネル2.6.12-1.1381_FC3で試してみた。プログラムは次の通り。
#include <stdio.h> #include <stdlib.h> #include <sys/file.h> #include <sys/types.h> #include <time.h> #include <unistd.h> void lock_flock(int fd) { if (flock(fd, LOCK_EX)) { perror("flock"); exit(1); } } void unlock_flock(fd) { if (flock(fd, LOCK_UN)) { perror("flock"); exit(1); } } void lock_fcntl(int fd) { struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; if (fcntl(fd, F_SETLKW, &lock)) { perror("fcntl"); exit(1); } } void unlock_fcntl(int fd) { struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; if (fcntl(fd, F_UNLCK, &lock)) { perror("fcntl"); exit(1); } } int main(int argc, char *argv[]) { FILE *fp; int fd; pid_t pid; time_t start; if (argc < 2) { exit(1); } /* ファイルをオープンして */ fp = fopen(argv[1], "r+"); if (fp == NULL) { perror("fopen"); exit(1); } start = time(NULL); pid = getpid(); fd = fileno(fp); /* ロックして */ printf("[%d] %ld: before locking.\n", pid, time(NULL) - start); lock_flock(fd); // lock_fcntl(fd); printf("[%d] %ld: file was locked. sleeping...\n", pid, time(NULL) - start); /* 2秒スリープして */ sleep(2); /* アンロックする */ unlock_flock(fd); // unlock_fcntl(fd); printf("[%d] %ld: file was unlocked\n", pid, time(NULL) - start); fclose(fp); return 0; }
これをコンパイルしてできたプログラム「locker」を、次のシェルスクリプト
#!/bin/sh ./locker $1 & ./locker $1 & ./locker $1 &
を使って2台のNFSクライアントで同時に実行する($1にNFS上のファイルを指定)と、次のように出力された。
PC1
[3886] 0: before locking. [3888] 0: before locking. [3887] 0: before locking. [3886] 0: file was locked. sleeping... [3886] 2: file was unlocked [3887] 2: file was locked. sleeping... [3887] 4: file was unlocked [3888] 4: file was locked. sleeping... [3888] 6: file was unlocked
PC2
[3892] 0: before locking. [3894] 0: before locking. [3893] 0: before locking. [3892] 6: file was locked. sleeping... [3892] 8: file was unlocked [3893] 8: file was locked. sleeping... [3893] 10: file was unlocked [3894] 10: file was locked. sleeping... [3894] 12: file was unlocked
うん、うまくロックできているようだ。
が、同じプログラムをNFSクライアントとNFSサーバの2台で同時に実行したら、それぞれ独立にロックを獲得してしまった。flock(2)を使った場合、NFSサーバ上のプロセスは特別扱いされてしまうようだ(もっと新しいカーネルなら改善されているのかもしれないけど)。
また、カーネルを2.6.11-1.35_FC3にして試すと、NFSクライアント間でも独立にロックを獲得してしまった(単一PC内のプロセス間では正しくロックできていた)。確かに2.6.12から挙動が変わっているようだ。
fcntl(2)を使う
上のプログラムでコメントアウトしている所を生かし、fcntlだとどうなるかも試した。
結果、こちらだとNFSクライアント間、NFSクライアント〜NFSサーバ間共に、きちんとロックできているようだった。なので、NFSサーバ上でもプログラムが動く場合はfcntlを使う方がよさそう。
また、flockを使うプログラムとfcntlを使うプログラムを同時に起動してみると、NFSクライアント間であればきちんとロックできていた。
■ [unix] fcntl(2)がアンロックを検出しない
上のプログラムを最初に試したときは思惑通りに動かず、
[4154] 0: before locking. [4155] 0: before locking. [4156] 0: before locking. [4154] 0: file was locked. sleeping... [4154] 2: file was unlocked [4155] 30: file was locked. sleeping... [4155] 32: file was unlocked [4156] 60: file was locked. sleeping... [4156] 62: file was unlocked
のような出力になっていた。最初のプロセスがロックを解放しても次のプロセスがなかなかロックを獲得してくれなかった(獲得するのは30秒後)。
iptablesをまず疑い、確かにフィルタリングが掛かっていたのでiptablesを止めてみたが改善せず。その後何をどうしても原因がわからず、もうそういう仕様なのだと結論付けていたのだが、ふと気付き、NFSサーバのhostsファイルにNFSクライアントのエントリを追加したら治った。
tcpdumpの出力を眺めていてふと気付いたので、困ったらパケットキャプチャしろ、というのが教訓。
■ やること
- 蛍光灯を捨てる
請書- 宛名シール
- 収入印紙
- 44 https://www.google.co.jp/
- 13 ----------googleusercontent.com検索(cache:69vq7dcVfygJ:ogawa.s18.xrea.com/tdiary/20051107.html linux nfs flock)
- 8 http://redmine.yumemi.st/systec/issues/169
- 6 http://t.co/8U7bLAtOVc
- 4 http://takagi-hiromitsu.jp/diary/20050427.html
- 3 ----------google.co.jp検索(fcntrl NFS)
- 3 ----------google.co.jp検索(NFS fcntl)
- 3 ----------google.co.jp検索(ruby flock nfs)
- 3 ----------search.yahoo検索(flock2 Linux バージョン)
- 3 ----------search.yahoo検索(NFS ロック)
- 3 http://my.yahoo.co.jp/p/1.html
- 2 ----------google.com検索(NFS nlm 30秒)
- 2 http://www.google.com/search
- 2 ----------google.co.jp検索(flock nfs )
- 2 ----------google.co.jp検索(linux ファイル ロック)
- 2 ----------google.co.jp/hws検索(nfs lock 30秒)
- 2 ----------google.co.jp/hws検索(nfs fcntl)
- 2 ----------google.co.jp/hws検索(NFS lock 30秒)
- 2 ----------google.co.jp/hws検索(fedora fopen 読めない)
- 2 http://www.google.co.jp/
- 2 http://wiki.wiir.jp/2jun/?MemoMemo
- 2 32nd diary (20051107.html)
- 2 ----------search.yahoo検索(nfs ファイルロック)
- 2 ----------search.yahoo検索(fcntl nfs)
- 2 http://quanp.cps.ricoh.co.jp/trac/quanp-world/tick...
- 2 Not Enough Resource - Diary (200403.html)
- 1 http://ysearch.luna.tv/search.aspx?puid=109&client...
- 1 http://yandex.ru/yandsearch?text=01 02 03 04 05 06...
- 1 ----------google.com検索(flock nfs)
- 1 ----------google.com検索(nfs ロック 30秒)
- 1 ----------google.com検索(flook nfs)
- 1 ----------google.com検索()
- 1 ----------google.com検索()
- 1 ----------google.com検索(NFS flock)
- 1 ----------google.com検索(fcntl NFS)
- 1 ----------google.com検索(nfs flock)
- 1 google検索(nfs flock)
- 1 ----------google.co.jp検索(fcntl NFS F_SETLK)
- 1 ----------google.co.jp検索(nfs flock linux)
- 1 ----------google.co.jp検索(fcntl ファイルロック 検知)
- 1 ----------google.co.jp検索(nfs flock)
- 1 ----------google.co.jp検索(fcntl NFS)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(fcntl NFS)
- 1 ----------google.co.jp検索(Fcntl NFS)
- 1 ----------google.co.jp検索(fcntl NFS ロックできない)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(シェル flock)
- 1 ----------google.co.jp検索(tcpdump NFSファイルを出力)
- 1 ----------google.co.jp検索(fcntl シェルスクリプト)
- 1 ----------google.co.jp検索(NFS fcntl lockできない)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(flock NFS)
- 1 ----------google.co.jp検索(flock NFS)
- 1 ----------google.co.jp検索(flock nfs)
- 1 ----------google.co.jp検索(nfs linux fcntl)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(flock NFS)
- 1 ----------google.co.jp検索(fcntl fopen)
- 1 ----------google.co.jp検索(NFS posix lock)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(flock nfs linux)
- 1 ----------google.co.jp検索(posix locking)
- 1 ----------google.co.jp検索(fcntl 検出)
- 1 ----------google.co.jp検索(ruby nfs flock)
- 1 ----------google.co.jp検索(posix lock nfs)
- 1 ----------google.co.jp検索(nfs flock)
- 1 ----------google.co.jp検索(nfs flock)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(nfs+%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AD%E3%83%83%E3%82%AF)
- 1 ----------google.co.jp検索(nfs flock)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(nfs fcntl)
- 1 ----------google.co.jp検索(linux nfs ファイルロック "30秒" -php)
- 1 ----------google.co.jp検索(linux+fcntl+%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%AD%E3%83%83%E3%82%AF)
- 1 ----------google.co.jp検索(http%3A%2F%2Fogawa.s18.xrea.com%2Ftdiary%2F20051107.html)
- 1 ----------google.co.jp検索(flock nfs)
- 1 ----------google.co.jp検索(flock() fcntl() nfs)
- 1 ----------google.co.jp検索(flock%e3%80%8030%e7%a7%92)
- 1 ----------google.co.jp検索(fcntrl nfs linux)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(fcntl NFS)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(fcntl+nfs)
- 1 ----------google.co.jp検索(fcntl+flock+%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB)
- 1 ----------google.co.jp検索(fcntl+NFS)
- 1 ----------google.co.jp検索(fcntl ruby f_setlk)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(fcntl nfs)
- 1 ----------google.co.jp検索(fcntl nfs lock)
- 1 ----------google.co.jp検索(fcntl nfs linux)
- 1 ----------google.co.jp検索(fcntl nfs linux)
- 1 ----------google.co.jp検索(bsd nfs)
- 1 ----------google.co.jp検索(Sleeping, pid: 3888)
- 1 ----------google.co.jp検索(NFS fcntl)
- 1 ----------google.co.jp検索(NFS+fcntl)