昨年あたりからWindows XPのサポート終了にともない、Windows 7へクライアントOSを移す企業が多い。
私の仕事PCも過日、ついに7に変更された。
さすがに色んなところが改善されていて使いやすくなっているのだが、なぜかSambaに置いてあるファイルが壊れたり、誰も開いていないはずなのに読み取り専用でしか開けない事象が頻発した。
特に共有設定したOfficeドキュメントで顕著。

しばらく悩んでいたのだが、Sambaのログにoplocks failedという記録を見つけて(おそらく)対処方法が分かった。
以下に示す。
Sambaのバージョンは3.6.22である。

結論

smb.confのglobalセクションに以下を書け。

oplocks = No
blocking locks = No

ネタ元

ネットを渉猟したところ、やはりOplocksの評判はあまりよくない。

以下のホワイトペーパーが分かりやすかった。
Oplocksとread cachingが原因と断定している。

Opportunistic Locking and Read Caching on Microsoft Windows Networks
http://www.dataaccess.com/whitepapers/opportunlockingreadcaching.html

先に進む前にプロトコルとしてのSMBでいくつか確認を。

SMB(プロトコル)のバージョンについて

Windowsファイル共有で使われるプロトコルSMBは、Vistaでバージョン2, 7でバージョン2.1になった。
Oplocksとread cachingもバージョン2以降で追加、あるいは強化されている。
詳細は以下。

SMB の新機能
http://technet.microsoft.com/ja-jp/library/ff625695.aspx
SMB1⇒2⇒2.1への変化と新機能
http://blog.goo.ne.jp/mito_and_tanu/e/10c47629fbb7e7d3d73cbd54a1a9f28d

Oplocksとは

ネットワークの効率化を狙う、Windows固有の機能。
複数のプロセスが同じファイルをロックでき、なおかつクライアントがデータをキャッシュできる。

Chapter 17. File and Record Locking
http://www.samba.org/samba/docs/man/Samba-HOWTO-Collection/locking.html
http://www.samba.gr.jp/project/translation/Samba3-HOWTO/locking.html

Read Cachingとは

Oplocksの一機能。クライアント側でのデータキャッシュ。
クライアントがローカルでデータをキャッシュする目的は、ネットワーク越しの書き込み回数を減らすこと、ひいてはネットワークの効率化のため。
ファイルの同じ部分(the same region)に対する書き込みをまとめて、一回で済ませる。

Oplocksの危険性

Oplocksが狙い通りに動けば、目的通りネットワークの効率化が図られる。
問題なのはネットワークに何か問題が起こり、キャッシュが適切にフラッシュされない場合。ともするとファイルの破壊を引き起こす。
とくにデータベースが危険。
以下のリンクに詳細が。
本記事の末尾に私訳を付す。

Locks and Oplocks
http://www.samba.org/samba/docs/using_samba/ch08.html

対策:Oplocksを無効にしろ

ここまで分かれば、対策は簡単。
Oplocksを無効にすればよい。
無効にする方法には、サーバ側での方法、クライアント側での方法がある。
クライアントと言っても、たいていはWindowsであろうが、Windowsで対処しようとするとレジストリの変更が必要になる。
さすがにそれは面倒だ。
そこでサーバ側、Sambaの設定でOplocksを無効にする。

smb.confでOplocksを無効にする

oplocks = noとすればよい。
デフォルト無効にしたければ[global]セクションに、共有ごとに無効にしたければ共有のところに書けばよい。
smb.confのmanは一見、共有ごとにしか指定できないように見えるかもしれないが[global]にも使える。
また、oplocksはbooleanなのでnoでもfalseでも、はたまた0でも理解してもらえる。

なお、ファイルごとに有効無効を指定したければveto oplock filesで指定できる。

smb.confのmanより抜粋

oplocks (S)

This boolean option tells smbd whether to issue oplocks
(opportunistic locks) to file open requests on this share.
(略)

Default: oplocks = yes

smb.confのmanよりPARAMETERS抜粋

PARAMETERS
(略)
The letter G in parentheses indicates that a
parameter is specific to the [global] section. The letter S indicates
that a parameter can be specified in a service specific section. All S
parameters can also be specified in the [global] section - in which
case they will define the default behavior for all services.

blocking locks

Sambaはロックの方法を指定できる。
blocking locksというものである。
これは、ファイルをロックするときに、特定部分だけをロック(range lock)するか、ファイル全体をロックするか、というものである。
デフォルトで有効。
WindowsのRead Cachingに対応してそうな機能である。
加えてmanを見ると、「range lockに失敗すると、タイムアウトするまで何回かrange lockを再試行する」などと書いてある。
これも無効にしよう。

blocking locks (S)

This parameter controls the behavior of smbd(8) when given a
request by a client to obtain a byte range lock on a region of an
open file, and the request has a time limit associated with it.

If this parameter is set and the lock range requested cannot be
immediately satisfied, samba will internally queue the lock
request, and periodically attempt to obtain the lock until the
timeout period expires.

If this parameter is set to no, then samba will behave as previous
versions of Samba would and will fail the lock request immediately
if the lock range cannot be obtained.

Default: blocking locks = yes

設定例

以上を踏まえて、以下のように設定
しょぼい英文は勘弁しておくれ。

[global]
(略)
#
# Disable oplock
# It's supposed to improve network performance but causes problems
#
# See:
# Opportunistic Locking and Read Caching on Microsoft Windows Networks
# http://www.dataaccess.com/whitepapers/opportunlockingreadcaching.html
#
oplocks = no
blocking locks = no

再起動しておしまい。

$ sudo service samba restart
Performing sanity check on Samba configuration: OK
Stopping winbindd.
Waiting for PIDS: 667.
Stopping smbd.
Waiting for PIDS: 664, 664.
Stopping nmbd.
Waiting for PIDS: 661.
Removing stale Samba tdb files: .. done
Starting nmbd.
Starting smbd.
Starting winbindd.

(参考)Locks and Oplocks 私訳

http://www.samba.org/samba/docs/using_samba/ch08.html
Locks and Oplocks

oplocksの使用によって得られるパフォーマンス増は、大変に望ましいことがほとんどだ。
しかしながら、クライアントやネットワークのハードウェアの信頼性が怪しいような状況では、クライアントにデータをキャッシュさせることは大きなリスクになり得る。
クライアントが書き込みのためにファイルを開き、oplockを行う場合を考えてみよう。
そして他のクライアントが同じファイルを開こうとしたとき、“oplock break"要求が最初のクライアントに送られる。
もしこの要求が何らかの理由により失敗し、二番目のクライアントがファイルの書き込みをしたとする。
二つのプロセスが同時に書き込みをするわけだから、ファイルは簡単に壊れてしまうだろう。
残念なことに上記のケースは現実に起こりうる。
SMBネットワークにおける複数のWindowsクライアント環境では、このようなおかしな動きは頻繁にみられる。
たくさんのクライアントが同時に書き込みを行うデータベースファイルは特に影響を受けてしまう。

oplocksの失敗するもっと具体的な例を挙げると、それはデータベースファイルが大変に大きい場合である。
クライアントがこのようなファイルを開き、oplockを許可されると、非常に大きな遅延が発生する。
その一部を修正するためだけであっても、クライアントがファイル全部をキャッシュするからである。
このファイルを別のクライアントが開こうとしたとき、状況はさらに悪くなる。
二番目のクライアントがファイルを開くためには、最初のクライアントがキャッシュをすべてサーバに書き戻す必要があるからだ。
このために、また別の遅延が発生する(しかも双方のクライアントで)。
結果として、タイムアウトにより二番目のクライアントがファイルオープンに失敗し、たぶんデータが壊れた旨のWarning messageも併せて表示されるだろう。

In most cases, the extra performance resulting from the use of oplocks is highly desirable. However, allowing the client to cache data can be a big risk if either the client or network hardware are unreliable. Suppose a client opens a file for writing, creating an oplock on it. When another client also tries to open the file, an oplock break request is sent to the first client. If this request goes unfulfilled for any reason and the second client starts writing to the file, the file can be easily corrupted as a result of the two processes writing to it concurrently. Unfortunately, this scenario is very real. Uncoordinated behavior such as this has been observed many times among Windows clients in SMB networks (with files served by Windows NT/2000 or Samba). Typically, the affected files are database files, which multiple clients open concurrently for writing.

A more concrete example of oplock failure occurs when database files are very large. If a client is allowed to oplock this kind of file, there can be a huge delay while the client copies the entire file from the server to cache it, even though it might need to update only one record. The situation goes from bad to worse when another client tries to open the oplocked file. The first client might need to write the entire file back to the server before the second client’s file open request can succeed. This results in another huge delay (for both clients), which in practice often results in a failed open due to a timeout on the second client, perhaps along with a message warning of possible database corruption!