NFSとNIS

分散システム

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2005/2006-01-31
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/

復習

NFS(Network File System)

NFS ( Network File System ) は, Sun Microsystems 社が 開発したネットワーク・ファイル・システムの名前(固有名詞, 商標)。

ネットワーク・ファイル・システム(一般名詞)
ネットワークを通じて他のコンピュータ上にあるファイルを あたかも自分自身のローカルディスクにあるファイ ルと同じように扱えるようにしたファイルシステム
分散ファイルシステム
ネットワーク・ファイル・システムが発展して 分散透明性が実現されたもの。
NFS は、Unix 系の OS (MacOSX 含む) では、事実上の標準。

その他のネットワーク・ファイル・システム

NFSの機能

NFSを使うと, ネットワークを通じて別のコンピュータ上のファイルシステム の一部分を, ローカルディスク上にあるファイルシステムと同じように, 自分 のファイルシステムの木に マウント(mount) できる。

図? NFSによるファイルの共有

図? NFSによるファイルの共有

相互に参照し合える。

NFSの仕組み

NFSの遠隔手続き呼び出し

NFSは、 SunRPC を利用している。 データの転送には, UDP/IP または、TCP/IP (NFS v3以降) を利用している。

RPCのサーバ
ディスクを持っているホストのカーネル
RPCのクライアント
参照しているホストのカーネル
サーバ側で nfsd というプログラムが 動いているように見える( ps コマンドで表示される) が、それは普通のプロセスではない。

/usr/include/rpcsvc/nfs_prot.x

表? NFSで使われているRPCの手続き

手続き名 意味 関連するコマンド、システムコール
null() 何もしない rpcinfo -u hostname nfs コマンド
getattr() 属性の読み出し ls -l コマンド, stat システムコール , open システムコール
setattr() 属性の設定 chmod , chown コマンド
lookup() ファイルの検索 open システムコール
readlink() シンボリックリンクの読み出し ls -l コマンド, readlink システムコール
read() ファイルの読み出し read システムコール
write() ファイルの書き込み write システムコール
create() ファイルの作成 creat システムコール, open システムコール
remove() ハードリンクの削除 rm コマンド, unlink システムコール
rename() ファイル名前の変更 mv コマンド, rename システムコール
link() ハードリンクの作成 ln コマンド, link システムコール
symlink() シンボリックリンクの作成 ln -s コマンド, symlink システムコール
mkdir() ディレクトリの作成 mkdir コマンド
rmdir() ディレクトリの削除 rmdir コマンド
readdir() ディレクトリの読み出し ls コマンド
statfs() ファイルシステムの利用状況 df コマンド, statfs システムコール
commit()* ディスクへの書き込み fsync システムコール
access()* アクセス権のチェック access システムコール
* は、NFS v3 の新しい手続き。

NFSファイルハンドル

NFS でファイルやディレクトリを区別するための識別子。32バイト。

const NFS_FHSIZE	= 32;
...
/*
 * File access handle
 */
struct nfs_fh {
	opaque data[NFS_FHSIZE];
};

一番最初のNFSファイル・ハンドルをどうやって入手するか。

NFSマウントのためのRPCプログラム

一番 NFS v2, NFS v3 では、NFS 本体とは別にディレクトリ木のルートを得るため のRPC のプログラム(MOUNTPROG)がある。 /usr/include/rpcsvc/mount.x
手続き名 意味 関連するコマンド、 システムコール
null() 何もしない rpcinfo -u hostname mount コマンド
mnt() NFSファイルハンドルを返す mount コマンド
dump() マウント一覧表 showmount hostname コマンド
umnt() アンマウント umount コマンド
umntall() 全アンマウント umount -h hostname コマンド
export() アクセス可能なディレクトリのリストを返す

lookup()


2.2.5.  Look Up File Name

	diropres
	NFSPROC_LOOKUP(diropargs) = 4;

If the reply "status" is NFS_OK, then the reply "file" and reply
"attributes" are the file handle and attributes for the file "name"
in the directory given by "dir" in the argument.

2.3.10.  diropargs

    struct diropargs {
	fhandle  dir;
	filename name;
    };

The "diropargs" structure is used in directory operations.  The
"fhandle" "dir" is the directory in which to find the file "name".
A directory operation is one in which the directory is affected.

2.3.11.  diropres

    union diropres switch (stat status) {
    case NFS_OK:
	struct {
	    fhandle file;
	    fattr   attributes;
	} diropok;
    default:
	void;
    };

The results of a directory operation are returned in a "diropres"
structure.  If the call succeeded, a new file handle "file" and
the "attributes" associated with that file are returned along with
the "status".

read()

2.2.7.  Read From File

	struct readargs {
		fhandle file;
		unsigned offset;
		unsigned count;
		unsigned totalcount;
	};

	union readres switch (stat status) {
	case NFS_OK:
		fattr attributes;
		nfsdata data;
	default:
		void;
	};

	readres
	NFSPROC_READ(readargs) = 6;

Returns up to "count" bytes of "data" from the file given by "file",
starting at "offset" bytes from the beginning of the file.  The first
byte of the file is at offset zero.  The file attributes after the
read takes place are returned in "attributes".

Notes:  The argument "totalcount" is unused, and is removed in the
next protocol revision.

write()

2.2.9.  Write to File

	struct writeargs {
		fhandle file;
		unsigned beginoffset;
		unsigned offset;
		unsigned totalcount;
		nfsdata data;
	};

	attrstat
	NFSPROC_WRITE(writeargs) = 8;

Writes "data" beginning "offset" bytes from the beginning of "file".
The first byte of the file is at offset zero.  If the reply "status"
is NFS_OK, then the reply "attributes" contains the attributes of the
file after the write has completed.  The write operation is atomic.
Data from this "WRITE" will not be mixed with data from another
client's "WRITE".

Notes:  The arguments "beginoffset" and "totalcount" are ignored and
are removed in the next protocol revision.

getattr()

2.2.2.  Get File Attributes

	attrstat
	NFSPROC_GETATTR (fhandle) = 1;

If the reply status is NFS_OK, then the reply attributes contains the
attributes for the file given by the input fhandle.

2.3.9.  attrstat

    union attrstat switch (stat status) {
    case NFS_OK:
	fattr attributes;
    default:
	void;
    };

The "attrstat" structure is a common procedure result.  It
contains a "status" and, if the call succeeded, it also contains
the attributes of the file on which the operation was done.

2.3.5.  fattr

    struct fattr {
	ftype        type;
	unsigned int mode;
	unsigned int nlink;
	unsigned int uid;
	unsigned int gid;
	unsigned int size;
	unsigned int blocksize;
	unsigned int rdev;
	unsigned int blocks;
	unsigned int fsid;
	unsigned int fileid;
	timeval      atime;
	timeval      mtime;
	timeval      ctime;
    };

...
Notes:  The bits are the same as the mode bits returned by the
stat(2) system call in UNIX.  The file type is specified both in
the mode bits and in the file type.  This is fixed in future
versions.

The "rdev" field in the attributes structure is an operating
system specific device specifier.  It will be removed and
generalized in the next revision of the protocol.

冪等な操作

冪等(idempotent)な操作とは、 その操作を何回繰り返しても、1回だけ実行した時と同じ結果になるもの。

例:

冪等ではない操作
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

状態を保持しないサーバ

NFS Version 2は, サーバ側で状態を保持しない(state-less)。

操作を冪等にして、サーバを無状態にすると、障害に強くなる。

サーバを無状態にすると書き込みが重くなる。 Linux は、NFS Version 2 の約束を守っていない。

cookie

RPC のようにコネクションが作られない通信サービスを使う時に冪等や無状態 といった性質を実現する時に必要になる技術。

例:NFSでのディレクトリの読み込み手続き nfsproc_readdir() で、1回の RPC で全部のデータを返せないことが起きる。 ディレクトリのどの位置まで読み込んだかを 示す中間状態を クッキー(cookie) という形でクライアントに返す。

クライアントは、次の RPC の呼び出しで、 前回受けとった応答の中のクッキーを、サーバへの要求に含めて送す。

readdir()

const NFS_COOKIESIZE	= 4;
typedef opaque nfscookie[NFS_COOKIESIZE];
2.2.17.  Read From Directory

	 struct readdirargs {
		 fhandle dir;
		 nfscookie cookie;
		 unsigned count;
	 };

	 struct entry {
		 unsigned fileid;
		 filename name;
		 nfscookie cookie;
		 entry *nextentry;
	 };

	 union readdirres switch (stat status) {
	 case NFS_OK:
		 struct {
			 entry *entries;
			 bool eof;
		 } readdirok;
	 default:
		 void;
	 };

	 readdirres
	 NFSPROC_READDIR (readdirargs) = 16;

 Returns a variable number of directory entries, with a total size of
 up to "count" bytes, from the directory given by "dir".  If the
 returned value of "status" is NFS_OK, then it is followed by a
 variable number of "entry"s.  Each "entry" contains a "fileid" which
 consists of a unique number to identify the file within a filesystem,
 the "name" of the file, and a "cookie" which is an opaque pointer to
 the next entry in the directory.  The cookie is used in the next
 READDIR call to get more entries starting at a given point in the
 directory.  The special cookie zero (all bits zero) can be used to
 get the entries starting at the beginning of the directory.  The
 "fileid" field should be the same number as the "fileid" in the the
 attributes of the file.  (See section "2.3.5. fattr" under "Basic
 Data Types".)  The "eof" flag has a value of TRUE if there are no
 more entries in the directory.

nfsproc_readdir() で、1回目と2回目の RPC の間にディレクトリの内容が 更新された場合、どのような結果になるのか不明。

NFS非同期入出力デーモン

NFS非同期入出力デーモン ( nfsiod (local NFS asynchronous I/O Daemon) または biod (asynchronous Block I/O Daemon) ) は、NFSのクライアントホスト上で動き、NFSの非同期的な入出力を行う。

lockdとrstatd

NFS v2, NFS v3 には、ロックの機能が元々存在しない 後でロックの機能を付加した。
lockd
クライアント・ホストとサーバ・ホストの両方で走る。クライアント・ホスト上 の lockd は、受け取った要求をサーバ上の lockd に転送する。 サーバ・ホスト上の lockd は、クライアントの lockd から受け取っ た要求をシステム・コールでカーネルに伝える。
statd
サーバ・ホスト上の lockd は、クライアント・ホスト上の statd に問い合わせて、 クライアント・ホストがクラッシュしていないか調べる。 クライアント・ホストがクラッシュしたら、 そのクライアントから受け取っていたロック要求を解除する。

lockd には、当初からかなりバグが多かった。 初期の statd には、バッファ・オーバーフローのバグがあった。

NFS Version 3

NFS Version 4

2003年

  • compound() 手続きの導入。通信の遅延が大 きいネットワークでも効率よく動作させるために、複数の NFS の手続きを 1 回の遠隔手続き呼出しの中でまとめて実行する。
  • open() や close() という手続きの導入
  • ロックの機能の本体への取り込み
  • マウント機能の本体への取り込み
  • RPCSEC_GSS という仕組みによる利用者認証の機能。主に Kerberos 対応。

    CIFS

    CIFS は、Microsoft Windows で用いられているネットワーク・ファイル・ システム。

    昔の名前は、 SMB プロトコル。 Samba は、 CIFS/SMB を、Unix 系のオペレーティング・システムで実現したプログラム。

    Samba の利用法

    NIS

    NIS(Network Information Service) は、/etc/hosts/etc/passwd などを管理 するための分散型名前サービス。

    名前サービスとは、名前(ホスト名, ログイン名)から、何か別の値(アドレス, パスワードやホームディレクトリなど) へ変換する。 インターネットで使われている名前サービスは、DNS 。

    NIS は、1つの閉じた組織で使われることを想定して設計されている。

    NISは、かつて YP(Yellow Pages) と呼ばれてた。YPという商標が使われていたために、途中で名前が 変った。 しかし、コマンドの名前は、以前のまま ypXXXX になっている。

    NISの機能

    NISの主目的は、パスワード・ファイルの共有。

    NFS を使う時には、UID, GID の統一がいる。

    その他の共有できるファイル

    NISのマップとファイル

    passwd ファイルや hosts ファイルなど、 (NIS管理下の)すべてのホストで共有するファイルをNISの マップ(map) という。

    NISでは、アクセスの高速化のために、 dbm (または ndbm ) ライブラリを使って索引をつける。

    例: /etc/passwd から作られるマップ

    passwd.byname
    名前(ログイン名、文字列)から引くためのマップ。 ログイン時のパスワードやログインシェルの取得、 csh の「~」で 使われる。 getpwnam ライブラリに対応。
    passwd.byuid
    ユーザIDから引くためのマップ。 ls -l で使われる。 getpwuid ライブラリに対応。

    表? NISのマップ

    ファイル マップ
    bootparams bootparams
    ethers ethers.{byaddr,byname}
    group group.{bygid,byname}
    hosts hosts.{byaddr,byname}
    aliases mail.{aliases,byaddr}
    netgroup netgroup
    netmasks netmasks.byaddr
    networks networks.{byaddr,byname}
    passwd passwd.{byname,byuid}
    protocols protocols.{byname,bynumber}
    publickey publickey.byname
    rpc rpc.bynumber
    services services.byname
    passwd,hosts,groupnetid.byname
    なし ypservers

    NISのドメイン

    NISのマップの集合を共有するホストの集合を、 NISの ドメイン(domain) という。 インターネットの DNS でいうドメインとは、別の概念。 domainmame コマンドを使って調べたり、設定できる。

    サーバプロセス(ypserv)

    RPC のサーバ。索引付けされたマップを管理する。

    NISのサーバプロセスが走るホストの分類

    マスタサーバ
    各ドメインに1つ。 NISのマップの更新は、必ずマスタサーバ上で行う。
    スレーブサーバ
    複数個設置してよい。 NISのマップが更新された時に、 更新されたマップをマスタサーバから転送してもらう。
    クライアントからの要求に答えるのは、マスタもスレーブも同じ。

    NISクライアントライブラリ(ypclnt)

    NISクライアントライブラリ(ypclnt)は, NISサーバに RPCを行い、NISのマップを参照する。 例

    NISバインドプロセス(ypbind)

    バインドプロセス(ypbind)は、NISクライアントライブラリを 利用するホスト上で動作し、どのNISサーバを使うのかを決定するためのプロ セス。

    サーバを探す時には、 放送(broadcast) を使って、NISのサーバプロセスが走っているかを調べ、一番先 に応答したサーバプロセスのホストを /var/yp/ドメイン名.N というファイルに記録する。

    NISのサーバプロセスがクラッシュしたり、負荷が高くなった時には、 バインドプロセスは、再び放送を使って別のNISサーバを探す。

    yppush

    マスタ・サーバのホストでマップが更新されたときに、 スレーブ・サーバにマップをコピーするためのコマンド。

    例:すべてのスレーブサーバに passwd.byname マップをコピーする。

    # yppush passwd.byname
    

    /var/yp/Makefile

    マスタサーバ上の /etc/ の下のファイルの日付と、対応する マップの最終更新時刻を調べてマップを作り直す。 yppush コ マンドを使ってスレーブサーバに転送する。

    makedbm(make a dbm file)

    makedbm コマンドは, /etc/ の下のファイルから, 索引つきのファイ ルを作るコマンド。

    ypxfr

    ypxfr コマンドは、NISのスレーブサーバで、マスタサーバか らNISのマップをコピーする時に使う。

    起動方法

    cron は、yppush された時に、スレーブ・サーバが死んでいた時の備え。

    yppasswdd

    yppasswdd (YP passwd daemon) は, yp)passwd コマンド と通信を行い、マスタサーバ上の /etc/passwd を変更する。

    ypwhich

    ypwhich コマンドは, 現在利用しているNISサーバのホスト名を表示する。

    ypset

    ypset コマンドは、ypbind に働きかけ、 利用するNISのサーバを強制的に変更する。

    パスワードファイルのすり替えに使えるので、 一般ユーザからの要求は受け付けない。

    異なるネットワーク上でのNIS

    NISでは, ypbind放送(broadcast) を使ってサーバを探すので、放送が届く範囲に, NISのサーバを置く必要がある。

    NISを実現しているRPCの手続き

    /usr/include/rpcsvc/yp.x
    
    typedef string domainname<YPMAXDOMAIN>;
    typedef string mapname<YPMAXMAP>;
    typedef string peername<YPMAXPEER>;
    typedef opaque keydat<YPMAXRECORD>;
    typedef opaque valdat<YPMAXRECORD>;
    
    enum ypstat {
    	YP_TRUE		=  1,
    	YP_NOMORE	=  2,
    	YP_FALSE	=  0,
    	YP_NOMAP	= -1,
    	YP_NODOM	= -2,
    	YP_NOKEY	= -3,
    	YP_BADOP	= -4,
    	YP_BADDB	= -5,
    	YP_YPERR	= -6,
    	YP_BADARGS	= -7,
    	YP_VERS		= -8
    };
    
    struct ypreq_key {
    	domainname domain;
    	mapname map;
    	keydat key;
    };
    
    struct ypresp_val {
    	ypstat stat;
    	valdat val;
    };
    
    /*
     * YP access protocol
     */
    program YPPROG {
    	version YPVERS {
    		void
    		YPPROC_NULL(void) = 0;
    
    		bool
    		YPPROC_DOMAIN(domainname) = 1;
    
    		bool
    		YPPROC_DOMAIN_NONACK(domainname) = 2;
    
    		ypresp_val
    		YPPROC_MATCH(ypreq_key) = 3;
    
    		ypresp_key_val
    		YPPROC_FIRST(ypreq_key) = 4;
    
    		ypresp_key_val
    		YPPROC_NEXT(ypreq_key) = 5;
    
    		ypresp_xfr
    		YPPROC_XFR(ypreq_xfr) = 6;
    
    		void
    		YPPROC_CLEAR(void) = 7;
    
    		ypresp_all
    		YPPROC_ALL(ypreq_nokey) = 8;
    
    		ypresp_master
    		YPPROC_MASTER(ypreq_nokey) = 9;
    
    		ypresp_order
    		YPPROC_ORDER(ypreq_nokey) = 10;
    
    		ypresp_maplist
    		YPPROC_MAPLIST(domainname) = 11;
    	} = 2;
    } = 100004;
    

    NIS+(nisplus)

    NISの機能とセキュリティ面を強化したもの。
    1. 木構造の名前空間が使える。
    2. データの格納は、マップ形式(検索キーと値の組)ではなく、複数のカラ ムを持つ表になっている。複数のカラムに索引を付けることができる。
    3. 複数のIPのサブネットで使える。
    4. データの更新は、マスタ・サーバのファイルを更新するのではなく、独 自のコマンドやAPIを通じて行なう。
    5. インクリメンタルな更新が可能。スケーラビリティが高くなっている。
    6. 公開鍵方式を用いた暗号化通信機能と認証系を持つ。
    7. NIS+の木構造のディレクトリごと、表ごと、表のカラムごと、エントリごとにアクセス制御 が行なえる。

    Last updated: 2006/01/28 23:57:05
    Yasushi Shinjo / <yas@is.tsukuba.ac.jp>