第3章 NFS基本应用

1.1 概述

相似ext家族、xfs格式的本地文件系统,它们都是经过单个文件名称空间(name space)来包含不少文件,并提供基本的文件管理和空间分配功能。而文件是存放在文件系统中(上述名称空间内)的单个命名对象,每一个文件都包含了文件实际数据和属性数据。可是,这些类型的文件系统和其内文件都是存放在本地主机上的。html

实际上,还有网络文件系统。顾名思义,就是跨网络的文件系统,将远程主机上的文件系统(或目录)存放在本地主机上,就像它自己就是本地文件系统同样。在Windows环境下有cifs协议实现的网络文件系统,在Unix环境下,最出名是由NFS协议实现的NFS文件系统。node

NFS即network file system的缩写,nfs是属于用起来很是简单,研究起来很是难的东西。相信,使用过它或学过它的人都不会认为它的使用有任何难点,只需将远程主机上要共享给客户端的目录导出(export),而后在客户端上挂载便可像本地文件系统同样。到目前为止,nfs已经有5个版本,NFSv1是未公布出来的版本,v2和v3版本目前来讲基本已经淘汰,v4版本是目前使用最多的版本,nfsv4.1是目前最新的版本。ios

1.2 RPC不可不知的原理

要介绍NFS,必然要先介绍RPC。RPC是remote procedure call的简写,人们都将其译为"远程过程调用",它是一种框架,这种框架在大型公司应用很是多。而NFS正是其中一种,此外NIS、hadoop也是使用rpc框架实现的。centos

1.2.1 RPC原理

所谓的remote procedure call,就是在本地调用远程主机上的procedure。以本地执行"cat -n ~/abc.txt"命令为例,在本地执行cat命令时,会发起某些系统调用(如open()、read()、close()等),并将cat的选项和参数传递给这些函数,因而最终实现了文件的查看功能。在RPC层面上理解,上面发起的系统调用就是procedure,每一个procedure对应一个或多个功能。而rpc的全名remote procedure call所表示的就是实现远程procedure调用,让远程主机去调用对应的procedure。缓存

上面的cat命令只是本地执行的命令,如何实现远程cat,甚至其余远程命令?一般有两种可能实现的方式:安全

(1).使用ssh类的工具,将要执行的命令传递到远程主机上并执行。但ssh没法直接调用远程主机上cat所发起的那些系统调用(如open()、read()、close()等)。cookie

(2).使用网络socket的方式,告诉远程服务进程要调用的函数。但这样的主机间进程通讯方式通常都是daemon类服务,daemon类的客户端(即服务的消费方)每调用一个服务的功能,都须要编写一堆实现网络通讯相关的代码。不只容易出错,还比较复杂。网络

而rpc是最好的解决方式。rpc是一种框架,在此框架中已经集成了网络通讯代码和封包、解包方式(编码、解码)。如下是rpc整个过程,以cat NFS文件系统中的a.sh文件为例。并发

    

nfs客户端执行cat a.sh,因为a.sh是NFS文件系统内的文件,因此cat会发起一些procedure调用(如open/read/close),这些procedure对应的ID号码和对应的参数会发送给rpc client(多是单个procedure ID,也多是多个procedure组合在一块儿一次性发送给rpc client,在NFSv4上是后者),rpc client会将这些数据进行编码封装(封装和解封装功能由stub代码实现),封装后的消息称为"call message",而后将call message经过网络发送给rpc server,rpc server会对封装的数据进行解封提取,因而就获得了要调用的procedures ID和对应的参数,而后将它们交给NFS服务进程,最终调用procedure ID对应的procedure来执行,并返回结果。NFS服务发起procedure调用后,会获得数据(多是数据自己,多是状态消息等),因而将返回结果交给rpc server,rpc server会将这些数据封装,这部分数据称为"reply message",而后将reply message经过网络发送给rpc client,rpc client解封提取,因而获得最终的返回结果。app

从上面的过程能够知道,rpc的做用是数据封装,rpc client封装待调用的procedure ID及其参数(其实还有一个program ID,关于program,见下文),rpc server封装返回的数据。

举个更简单的例子,使用google搜索时,实现搜索功能的program ID以及涉及到的procedure ID和要搜索的内容就是rpc client封装的对象,也是rpc server要解封的对象,搜索的结果则是rpc server封装的对象,也是rpc client要解封的对象。解封后的最终结果即为google搜索的结果。

1.2.2 RPC工具介绍

在CentOS 6/7上,rpc server由rpcbind程序实现,该程序由rpcbind包提供。

[root@xuexi ~]# yum -y install rpcbind

[root@xuexi ~]# rpm -ql rpcbind | grep bin/
/usr/sbin/rpcbind
/usr/sbin/rpcinfo

其中rpcbind是rpc主程序,在rpc服务端该程序必须处于已运行状态,其默认监听在111端口。rpcinfo是rpc相关信息查询工具。

对于rpc而言,其所直接管理的是programs,programs由一个或多个procedure组成。这些program称为RPC program或RPC service。

以下图,其中NFS、NIS、hadoop等称为网络服务,它们由多个进程或程序(program)组成。例如NFS包括rpc.nfsd、rpc.mountd、rpc.statd和rpc.idmapd等programs,其中每一个program都包含了一个或多个procedure,例如rpc.nfsd这个程序包含了如OPEN、CLOSE、READ、COMPOUND、GETATTR等procedure,rpc.mountd也主要有MNT和UMNT两个procedure。

对于RPC而言,它是不知道NFS/NIS/hadoop这一层的,它直接管理programs。每一个program启动时都须要找111端口的rpc服务登记注册,而后RPC服务会为该program映射一个program number以及分配一个端口号。其中每一个program都有一个惟一与之对应的program number,它们的映射关系定义在/etc/rpc文件中。之后rpc server将使用program number来判断要调用的是哪一个program中的哪一个procedure(由于这些都是rpc client封装在"call message"中的),并将解包后的数据传递给该program和procedure。

例如只启动rpcbind时。

[root@xuexi ~]# systemctl start rpcbind.service

[root@xuexi ~]# rpcinfo -p localhost
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper

其中第一列就是program number,第二列vers表示对应program的版本号,最后一列为RPC管理的RPC service名,其实就是各program对应的称呼。

当客户端获取到rpc所管理的service的端口后,就能够与该端口进行通讯了。但注意,即便客户端已经获取了端口号,客户端仍会借助rpc作为中间人进行通讯。也就是说,不管什么时候,客户端和rpc所管理的服务的通讯都必须经过rpc来完成。之因此如此,是由于只有rpc才能封装和解封装数据。

既然客户端不能直接拿着端口号和rpc service通讯,那还提供端口号干吗?这个端口号是为rpc server提供的,rpc server解包数据后,会将数据经过此端口交给对应的rpc service。

1.3 启动NFS

NFS自己是很复杂的,它由不少进程组成。这些进程的启动程序由nfs-utils包提供。因为nfs是使用RPC框架实现的,因此须要先安装好rpcbind。不过安装nfs-utils时会自动安装rpcbind。

[root@xuexi ~]# yum -y install nfs-utils

[root@xuexi ~]# rpm -ql nfs-utils | grep /usr/sbin
/usr/sbin/blkmapd
/usr/sbin/exportfs
/usr/sbin/mountstats
/usr/sbin/nfsdcltrack
/usr/sbin/nfsidmap
/usr/sbin/nfsiostat
/usr/sbin/nfsstat
/usr/sbin/rpc.gssd
/usr/sbin/rpc.idmapd
/usr/sbin/rpc.mountd
/usr/sbin/rpc.nfsd
/usr/sbin/rpc.svcgssd
/usr/sbin/rpcdebug
/usr/sbin/showmount
/usr/sbin/sm-notify
/usr/sbin/start-statd

其中以"rpc."开头的程序都是rpc service,分别实现不一样的功能,启动它们时每一个都须要向rpcbind进行登记注册。

[root@xuexi ~]# systemctl start nfs.service

[root@xuexi ~]# rpcinfo -p localhost
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100024    1   udp  56229  status
    100024    1   tcp  57226  status
    100005    1   udp  20048  mountd
    100005    1   tcp  20048  mountd
    100005    2   udp  20048  mountd
    100005    2   tcp  20048  mountd
    100005    3   udp  20048  mountd
    100005    3   tcp  20048  mountd
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   udp   2049  nfs_acl
    100021    1   udp  48609  nlockmgr
    100021    3   udp  48609  nlockmgr
    100021    4   udp  48609  nlockmgr
    100021    1   tcp  50915  nlockmgr
    100021    3   tcp  50915  nlockmgr
    100021    4   tcp  50915  nlockmgr

能够看到,每一个program都启动了不一样版本的功能。其中nfs program为rpc.nfsd对应的program,为nfs服务的主进程,端口号为2049。mountd对应的program为rpc.mountd,它为客户端的mount和umount命令提供服务,即挂载和卸载NFS文件系统时会联系mountd服务,由mountd维护相关挂载信息。nlockmgr对应的program为rpc.statd,用于维护文件锁和文件委托相关功能,在NFSv4之前,称之为NSM(network status manager)。nfs_acl和status,很显然,它们是访问控制列表和状态信息维护的program。

再看看启动的相关进程信息。

[root@xuexi ~]# ps aux | grep -E "[n]fs|[r]pc"
root        748  0.0  0.0      0     0 ?        S<   Jul26   0:00 [rpciod]
rpc        6127  0.0  0.0  64908  1448 ?        Ss   Jul26   0:00 /sbin/rpcbind -w
rpcuser    6128  0.0  0.0  46608  1836 ?        Ss   Jul26   0:00 /usr/sbin/rpc.statd --no-notify
root       6242  0.0  0.0      0     0 ?        S<   Jul26   0:00 [nfsiod]
root       6248  0.0  0.0      0     0 ?        S    Jul26   0:00 [nfsv4.0-svc]
root      17128  0.0  0.0  44860   976 ?        Ss   02:49   0:00 /usr/sbin/rpc.mountd
root      17129  0.0  0.0  21372   420 ?        Ss   02:49   0:00 /usr/sbin/rpc.idmapd
root      17134  0.0  0.0      0     0 ?        S<   02:49   0:00 [nfsd4]
root      17135  0.0  0.0      0     0 ?        S<   02:49   0:00 [nfsd4_callbacks]
root      17141  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17142  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17143  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17144  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17145  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17146  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17147  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]
root      17148  0.0  0.0      0     0 ?        S    02:49   0:00 [nfsd]

其中有一项/usr/sbin/rpc.idmapd进程,该进程是提供服务端的uid/gid <==> username/groupname的映射翻译服务。客户端的uid/gid <==> username/groupname的映射翻译服务则由"nfsidmap"工具实现,详细说明见下文。

1.4 配置导出目录和挂载使用

1.4.1 配置nfs导出目录

在将服务端的目录共享(share)或者说导出(export)给客户端以前,须要先配置好要导出的目录。好比何人可访问该目录,该目录是否可写,以何人身份访问导出目录等。

配置导出目录的配置文件为/etc/exports或/etc/exports.d/*.exports文件,在nfs服务启动时,会自动加载这些配置文件中的全部导出项。如下是导出示例:

/www    172.16.0.0/16(rw,async,no_root_squash)

其中/www是导出目录,即共享给客户端的目录;172.16.0.0/16是访问控制列表ACL,只有该网段的客户端主机才能访问该导出目录,即挂载该导出目录;紧跟在主机列表后的括号及括号中的内容定义的是该导出目录对该主机的导出选项,例如(rw,async,no_root_squash)表示客户端挂载/www后,该目录可读写、异步、可保留root用户的权限,具体的导出选项稍后列出。

如下是可接收的几种导出方式:

/www1    (rw,async,no_root_squash)  # 导出给全部主机,此时称为导出给world
/www2    172.16.1.1(rw,async)       # 仅导出给单台主机172.16.1.1
/www3    172.16.0.0/16(rw,async) 192.168.10.3(rw,no_root_squash)   # 导出给网段172.16.0.0/16,还导出给单台
                                                                   # 主机192.168.10.3,且它们的导出选项不一样
/www4    www.a.com(rw,async)        # 导出给单台主机www.a.com主机,但要求能解析该主机名
/www     *.b.com(rw,async)          # 导出给b.com下的全部主机,要求能解析对应主机名

如下是经常使用的一些导出选项说明,更多的导出选项见man exports:常见的默认项是:ro,sync,root_squash,no_all_squash,wdelay。

导出选项

(加粗标红为默认)

选项说明

rw、ro

导出目录可读写仍是只读(read-only)。

sync、async

同步共享仍是异步共享。异步时,客户端提交要写入的数据到服务端,服务端接收数据后直接响应客户端,但此时数据并不必定已经写入磁盘中,而同步则是必须等待服务端已将数据写入磁盘后才响应客户端。也就是说,给定异步导出选项时,虽然能提高一些性能,但在服务端忽然故障或重启时有丢失一部分数据的风险。

固然,对于只读(ro)的导出目录,设置sync或async是没有任何差异的。

anonuid

anongid

此为匿名用户(anonymous)的uid和gid值,默认都为65534,在/etc/passwd和/etc/shadow中它们对应的用户名为nfsnobody。该选项指定的值用于身份映射被压缩时。

root_squash

no_root_squash

是否将发起请求(即客户端进行访问时)的uid/gid=0的root用户映射为anonymous用户。便是否压缩root用户的权限。

all_squash

no_all_squash

是否将发起请求(即客户端进行访问时)的全部用户都映射为anonymous用户,便是否压缩全部用户的权限。

对于root用户,将取(no_)root_squash和(no_)all_squash的交集。例如,no_root_squash和all_squash同时设置时,root仍被压缩,root_squash和no_all_squash同时设置时,root也被压缩。

有些导出选项须要配合其余设置。例如,导出选项设置为rw,但若是目录自己没有w权限,或者mount时指定了ro挂载选项,则一样不容许写操做。

至于别的导出选项,基本无需去关注。

在配置文件写好要导出的目录后,直接重启nfs服务便可,它会读取这些配置文件。随后就能够在客户端执行mount命令进行挂载。

例如,exports文件内容以下:

/vol/vol0       *(rw,no_root_squash)
/vol/vol2       *(rw,no_root_squash)
/backup/archive *(rw,no_root_squash)

1.4.2 挂载nfs文件系统

而后去客户端上挂载它们。

[root@xuexi ~]# mount -t nfs 172.16.10.5:/vol/vol0 /mp1
[root@xuexi ~]# mount 172.16.10.5:/vol/vol2 /mp2
[root@xuexi ~]# mount 172.16.10.5:/backup/archive /mp3

挂载时"-t nfs"能够省略,由于对于mount而言,只有挂载nfs文件系统才会写成host:/path格式。固然,除了mount命令,nfs-utils包还提供了独立的mount.nfs命令,它其实和"mount -t nfs"命令是同样的。

mount挂载时能够指定挂载选项,其中包括mount通用挂载选项,如rw/ro,atime/noatime,async/sync,auto/noauto等,也包括针对nfs文件系统的挂载选项。如下列出几个常见的,更多的内容查看man nfs和man mount。

选项

参数意义

默认值

suid

nosuid

若是挂载的文件系统上有设置了suid的二进制程序,

使用nosuid能够取消它的suid

suid

rw

ro

尽管服务端提供了rw权限,可是挂载时设定ro,则仍是ro权限

权限取交集

rw

exec/noexec

是否可执行挂载的文件系统里的二进制文件

exec

user

nouser

是否运行普通用户进行档案的挂载和卸载

nouser

auto

noauto

auto等价于mount -a,意思是将/etc/fstab里设定的所有重挂一遍

auto

sync

nosync

同步挂载仍是异步挂载

async

atime

noatime

是否修改atime,对于nfs而言,该选项是无效的,理由见下文

 

diratime

nodiratime

是否修改目录atime,对于nfs而言,该挂载选项是无效的,理由见下文

 

remount

从新挂载

 

如下是针对nfs文件系统的挂载选项。其中没有给出关于缓存选项(ac/noac、cto/nocto、lookupcache)的说明,它们能够直接采用默认值,若是想要了解缓存相关内容,能够查看man nfs。

选项

功能

默认值

fg/bg

挂载失败后mount命令的行为。默认为fg,表示挂载失败时将直接报错退出,若是是bg,

挂载失败后会建立一个子进程不断在后台挂载,而父进程mount自身则当即退出并返回0状态码。

fg

timeo

NFS客户端等待下一次重发NFS请求的时间间隔,单位为十分之一秒。

基于TCP的NFS的默认timeo的值为600(60秒)。

 

hard/soft

决定NFS客户端当NFS请求超时时的恢复行为方式。若是是hard,将无限从新发送NFS请求。

例如在客户端使用df -h查看文件系统时就会不断等待。

设置soft,当retrans次数耗尽时,NFS客户端将认为NFS请求失败,从而使得NFS客户端

返回一个错误给调用它的程序。

hard

retrans

NFS客户端最多发送的请求次数,次数耗尽后将报错表示链接失败。若是hard挂载选项生效,

则会进一步尝试恢复链接。

3

rsize

wsize

一次读出(rsize)和写入(wsize)的区块大小。若是网络带宽大,这两个值设置大一点能提高传

输能力。最好设置到带宽的临界值。

单位为字节,大小只能为1024的倍数,且最大只能设置为1M。

 

注意三点:

(1).所谓的soft在特定的环境下超时后会致使静态数据中断。所以,仅当客户端响应速度比数据完整性更重要时才使用soft选项使用基于TCP的NFS(除非显示指定使用UDP,不然如今老是默认使用TCP)或增长retrans重试次数能够下降使用soft选项带来的风险。

若是真的出现NFS服务端下线,致使NFS客户端无限等待的状况,能够强制将NFS文件系统卸载,卸载方法:

umount -f -l MOUNT_POINT

其中"-f"是强制卸载,"-l"是lazy umount,表示将该文件系统从当前目录树中剥离,让全部对该文件系统内的文件引用都强制失效。对于丢失了NFS服务端的文件系统,卸载时"-l"选项是必须的。

(2).因为nfs的客户端挂载后会缓存文件的属性信息,其中包括各类文件时间戳,因此mount指定时间相关的挂载选项是没有意义的,它们不会有任何效果,包括atime/noatime,diratime/nodiratime,relatime/norelatime以及strictatime/nostrictatime等。具体可见man nfs中"DATA AND METADATA COHERENCE"段的"File timestamp maintainence"说明,或者见本文末尾的翻译。

(3).若是是要开机挂载NFS文件系统,方式天然是写入到/etc/fstab文件或将mount命令放入rc.local文件中。若是是将/etc/fstab中,那么在系统环境初始化(exec /etc/rc.d/rc.sysinit)的时候会加载fstab中的内容,若是挂载fstab中的文件系统出错,则会致使系统环境初始化失败,结果是系统开机失败。因此,要开机挂载nfs文件系统,则须要在/etc/fstab中加入一个挂载选项"_rnetdev"或"_netdev"(centos 7中已经没有"_rnetdev"),防止没法联系nfs服务端时致使开机启动失败。例如:

172.16.10.5:/www    /mnt    nfs    defaults,_rnetdev    0    0

当导出目录后,将在/var/lib/nfs/etab文件中写入一条对应的导出记录,这是nfs维护的导出表,该表的内容会交给rpc.mountd进程,并在必要的时候(mountd接受到客户端的mount请求时),将此导出表中的内容加载到内核中,内核也单独维护一张导出表。

1.4.3 nfs伪文件系统

服务端导出/vol/vol0、/vol/vol2和/backup/archive后,其中vol0和vol1是连在一个目录下的,但它们和archive目录没有连在一块儿,nfs采用伪文件系统的方式来桥接这些不链接的导出目录。桥接的方式是建立那些未导出的链接目录,如伪vol目录,伪backup目录以及顶级的伪根,以下图所示。

当客户端挂载后,每次访问导出目录时,其实都是经过找到伪文件系统(文件系统都有id,在nfs上伪文件系统的id称为fsid)并定位到导出目录的。

1.5 showmount命令

使用showmount命令能够查看某一台主机的导出目录状况。由于涉及到rpc请求,因此若是rpc出问题,showmount同样会傻傻地等待。

主要有3个选项。

showmount [ -ade]  host
-a:以host:dir格式列出客户端名称/IP以及所挂载的目录。但注意该选项是读取NFS服务端/var/lib/nfs/rmtab文件,
  :而该文件不少时候并不许确,因此showmount -a的输出信息极可能并不是准确无误的
-e:显示NFS服务端全部导出列表。
-d:仅列出已被客户端挂载的导出目录。

另外showmount的结果是排序过的,因此和实际的导出目录顺序可能并不一致。

例如:

[root@xuexi ~]# showmount -e 172.16.10.5
Export list for 172.16.10.5:
/backup/archive *
/vol/vol2       *
/vol/vol0       *
/www            172.16.10.4
[root@xuexi ~]# showmount -d 172.16.10.5
Directories on 172.16.10.5:
/backup/archive
/vol/vol0
/vol/vol2

1.6 nfs身份映射

NFS的目的是导出目录给各客户端,所以导出目录中的文件在服务端和客户端上必然有两套属性、权限集。

例如,服务端导出目录中某a文件的全部者和所属组都为A,但在客户端上不存在A,那么在客户端上如何显示a文件的全部者等属性。再例如,在客户端上,以用户B在导出目录中建立了一个文件b,若是服务端上没有用户B,在服务端上该如何决定文件b的全部者等属性。

因此,NFS采用uid/gid <==> username/groupname映射的方式解决客户端和服务端两套属性问题。因为服务端只能控制它本身一端的身份映射,因此客户端也一样须要身份映射组件。也就是说,服务端和客户端两端都须要对导出的全部文件的全部者和所属组进行映射。

但要注意,服务端的身份映射组件为rpc.idmapd,它以守护进程方式工做。而客户端使用nfsidmap工具进行身份映射。

服务端映射时以uid/gid为基准,意味着客户端以身份B(假设对应uid=Xb,gid=Yb)建立的文件或修改了文件的全部者属性时,在服务端将从/etc/passwd(此处不考虑其余用户验证方式)文件中搜索uid=Xb,gid=Yb的用户,若是能搜索到,则设置该文件的全部者和所属组为此uid/gid对应的username/groupname,若是搜索不到,则文件全部者和所属组直接显示为uid/gid的值。

客户端映射时以username/groupname为基准,意味着服务端上文件全部者为A时,则在客户端上搜索A用户名,若是搜索到,则文件全部者显示为A,不然都将显示为nobody。注意,客户端不涉及任何uid/gid转换翻译过程,即便客户端上A用户的uid和服务端上A用户的uid不一样,也仍显示为用户A。也就是说,客户端上文件全部者只有两种结果,要么和服务端用户同名,要么显示为nobody。

所以考虑一种特殊状况,客户端上以用户B(其uid=B1)建立文件,假如服务端上没有uid=B1的用户,那么建立文件时提交给服务端后,在服务端上该文件全部者将显示为B1(注意它是一个数值)。再返回到客户端上看,客户端映射时只简单映射username,不涉及uid的转换,所以它认为该文件的全部者为B1(不是uid,而是username),但客户端上必然没有用户名为B1的用户(尽管有uid=B1对应的用户B),所以在客户端,此文件全部者将诡异地将显示为nobody,其诡异之处在于,客户端上以身份B建立的文件,结果在客户端上却显示为nobody。

综上考虑,强烈建议客户端和服务端的用户身份要统一,且尽可能让各uid、gid能对应上。

1.7 使用exportfs命令导出目录

除了启动nfs服务加载配置文件/etc/exports来导出目录,使用exportfs命令也能够直接导出目录,它无需加载配置文件/etc/exports,固然exportfs也能够加载/etc/exports文件来导出目录。实际上,nfs服务启动脚本中就是使用exportfs命令来导出/etc/exports中内容的。

例如,CentOS 6上/etc/init.d/nfs文件中,导出和卸载导出目录的命令为:

[root@xuexi ~]# grep exportfs /etc/init.d/nfs  
        [ -x /usr/sbin/exportfs ] || exit 5
        action $"Starting NFS services: " /usr/sbin/exportfs -r
        cnt=`/usr/sbin/exportfs -v | /usr/bin/wc -l`
 action $"Shutting down NFS services: " /usr/sbin/exportfs -au
        /usr/sbin/exportfs -r

在CentOS 7上则以下:

[root@xuexi ~]# grep exportfs /usr/lib/systemd/system/nfs.service      
ExecStartPre=-/usr/sbin/exportfs -r
ExecStopPost=/usr/sbin/exportfs -au
ExecStopPost=/usr/sbin/exportfs -f
ExecReload=-/usr/sbin/exportfs -r

固然,不管如何,nfsd等守护进程是必须已经运行好的。

如下是CentOS 7上exportfs命令的用法。注意, CentOS 7比CentOS 6多一些选项。

-a     导出或卸载全部目录。
-o options,...
       指定一系列导出选项(如rw,async,root_squash),这些导出选项在exports(5)的man文档中有记录。
-i     忽略/etc/exports和/etc/exports.d目录下文件。此时只有命令行中给定选项和默认选项会生效。
-r     从新导出全部目录,并同步修改/var/lib/nfs/etab文件中关于/etc/exports和/etc/exports.d/
       *.exports的信息(即还会从新导出/etc/exports和/etc/exports.d/*等导出配置文件中的项)。该
       选项会移除/var/lib/nfs/etab中已经被删除和无效的导出项。
-u     卸载(即再也不导出)一个或多个导出目录。
-f     若是/prof/fs/nfsd或/proc/fs/nfs已被挂载,即工做在新模式下,该选项将清空内核中导出表中
       的全部导出项。客户端下一次请求挂载导出项时会经过rpc.mountd将其添加到内核的导出表中。
-v     输出详细信息。
-s     显示适用于/etc/exports的当前导出目录列表。

例如:

(1).导出/www目录给客户端172.16.10.6。

exportfs 172.16.10.6:/www

(2).导出/www目录给全部人,并指定导出选项。

exportfs :/www -o rw,no_root_squash

(3).导出exports文件中的内容。

exportfs -a

(4).从新导出全部已导出的目录。包括exports文件中和exportfs单独导出的目录。

exportfs -ar

(5).卸载全部已导出的目录,包括exports文件中的内容和exportfs单独导出的内容。即其本质为清空内核维护的导出表。

exportfs -au

(6).只卸载某一个导出目录。

exportfs -u 172.16.10.6:/www

1.8 RPC的调试工具rpcdebug

在不少时候NFS客户端或者服务端出现异常,例如链接不上、锁状态丢失、链接很是慢等等问题,均可以对NFS进行调试来发现问题出在哪一个环节。NFS有很多进程均可以直接支持调试选项,但最直接的调试方式是调试rpc,由于NFS的每一个请求和响应都会通过RPC去封装。但显然,调试RPC比直接调试NFS时更难分析出问题所在。如下只介绍如何调试RPC。

rpc单独提供一个调试工具rpcdebug。

[root@xuexi ~]# rpcdebug -vh
usage: rpcdebug [-v] [-h] [-m module] [-s flags...|-c flags...]
       set or cancel debug flags.
 
Module     Valid flags
rpc        xprt call debug nfs auth bind sched trans svcsock svcdsp misc cache all
nfs        vfs dircache lookupcache pagecache proc xdr file root callback client mount fscache pnfs pnfs_ld state all
nfsd       sock fh export svc proc fileop auth repcache xdr lockd all
nlm        svc client clntlock svclock monitor clntsubs svcsubs hostcache xdr all

其中:

-v:显示更详细信息
-h:显示帮助信息
-m:指定调试模块,有rpc/nfs/nfsd/nlm共4个模块可调试。
  :顾名思义,调试rpc模块就是直接调试rpc的问题,将记录rpc相关的日志信息;
  :调试nfs是调试nfs客户端的问题,将记录nfs客户端随之产生的日志信息;
  :nfsd是调试nfs服务端问题,将记录nfsd随之产生的日志信息;
  :nlm是调试nfs锁管理器相关问题,将只记录锁相关信息
-s:指定调试的修饰符,每一个模块都有不一样的修饰符,见上面的usage中"Valid flags"列的信息
-c:清除或清空已设置的调试flage

例如设置调试nfs客户端的信息。

rpcdebug -m nfs -s all

当有信息出现时,将记录到syslog中。例如如下是客户端挂载nfs导出目录产生的信息,存放在/var/log/messages中,很是多,因此排解问题时须要有耐心。

Jul 29 11:24:04 xuexi kernel: NFS: nfs mount opts='vers=4,addr=172.16.10.9,clientaddr=172.16.10.3'
Jul 29 11:24:04 xuexi kernel: NFS:   parsing nfs mount option 'vers=4'
Jul 29 11:24:04 xuexi kernel: NFS:   parsing nfs mount option 'addr=172.16.10.9'
Jul 29 11:24:04 xuexi kernel: NFS:   parsing nfs mount option 'clientaddr=172.16.10.3'
Jul 29 11:24:04 xuexi kernel: NFS: MNTPATH: '/tmp/testdir'
Jul 29 11:24:04 xuexi kernel: --> nfs4_try_mount()
Jul 29 11:24:04 xuexi kernel: --> nfs4_create_server()
Jul 29 11:24:04 xuexi kernel: --> nfs4_init_server()
Jul 29 11:24:04 xuexi kernel: --> nfs4_set_client()
Jul 29 11:24:04 xuexi kernel: --> nfs_get_client(172.16.10.9,v4)
Jul 29 11:24:04 xuexi kernel: NFS: get client cookie (0xffff88004c561800/0xffff8800364cd2c0)
Jul 29 11:24:04 xuexi kernel: nfs_create_rpc_client: cannot create RPC client. Error = -22
Jul 29 11:24:04 xuexi kernel: --> nfs4_realloc_slot_table: max_reqs=1024, tbl->max_slots 0
Jul 29 11:24:04 xuexi kernel: nfs4_realloc_slot_table: tbl=ffff88004b715c00 slots=ffff880063f32280 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_realloc_slot_table: return 0
Jul 29 11:24:04 xuexi kernel: NFS: nfs4_discover_server_trunking: testing '172.16.10.9'
Jul 29 11:24:04 xuexi kernel: NFS call  setclientid auth=UNIX, 'Linux NFSv4.0 172.16.10.3/172.16.10.9 tcp'
Jul 29 11:24:04 xuexi kernel: NFS reply setclientid: 0
Jul 29 11:24:04 xuexi kernel: NFS call  setclientid_confirm auth=UNIX, (client ID 578d865901000000)
Jul 29 11:24:04 xuexi kernel: NFS reply setclientid_confirm: 0
Jul 29 11:24:04 xuexi kernel: NFS: <-- nfs40_walk_client_list using nfs_client = ffff88004c561800 ({2})
Jul 29 11:24:04 xuexi kernel: NFS: <-- nfs40_walk_client_list status = 0
Jul 29 11:24:04 xuexi kernel: nfs4_schedule_state_renewal: requeueing work. Lease period = 5
Jul 29 11:24:04 xuexi kernel: NFS: nfs4_discover_server_trunking: status = 0
Jul 29 11:24:04 xuexi kernel: --> nfs_put_client({2})
Jul 29 11:24:04 xuexi kernel: <-- nfs4_set_client() = 0 [new ffff88004c561800]
Jul 29 11:24:04 xuexi kernel: <-- nfs4_init_server() = 0
Jul 29 11:24:04 xuexi kernel: --> nfs4_get_rootfh()
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=040000
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=4651240235397459983
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0x0/0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=2
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=0555
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=23
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=1501990255
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501989952
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501989952
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=1
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_supported: bitmask=fdffbfff:00f9be3e:00000000
Jul 29 11:24:04 xuexi kernel: decode_attr_fh_expire_type: expire type=0x0
Jul 29 11:24:04 xuexi kernel: decode_attr_link_support: link support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_symlink_support: symlink support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_aclsupport: ACLs supported=3
Jul 29 11:24:04 xuexi kernel: decode_server_caps: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_lease_time: file size=90
Jul 29 11:24:04 xuexi kernel: decode_attr_maxfilesize: maxfilesize=18446744073709551615
Jul 29 11:24:04 xuexi kernel: decode_attr_maxread: maxread=131072
Jul 29 11:24:04 xuexi kernel: decode_attr_maxwrite: maxwrite=131072
Jul 29 11:24:04 xuexi kernel: decode_attr_time_delta: time_delta=1 0
Jul 29 11:24:04 xuexi kernel: decode_attr_pnfstype: bitmap is 0
Jul 29 11:24:04 xuexi kernel: decode_attr_layout_blksize: bitmap is 0
Jul 29 11:24:04 xuexi kernel: decode_fsinfo: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: <-- nfs4_get_rootfh() = 0
Jul 29 11:24:04 xuexi kernel: Server FSID: 0:0
Jul 29 11:24:04 xuexi kernel: Pseudo-fs root FH at ffff880064c4ad80 is 8 bytes, crc: 0x62d40c52:
Jul 29 11:24:04 xuexi kernel: 01000100 00000000
Jul 29 11:24:04 xuexi kernel: --> nfs_probe_fsinfo()
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_supported: bitmask=fdffbfff:00f9be3e:00000000
Jul 29 11:24:04 xuexi kernel: decode_attr_fh_expire_type: expire type=0x0
Jul 29 11:24:04 xuexi kernel: decode_attr_link_support: link support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_symlink_support: symlink support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_aclsupport: ACLs supported=3
Jul 29 11:24:04 xuexi kernel: decode_server_caps: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_lease_time: file size=90
Jul 29 11:24:04 xuexi kernel: decode_attr_maxfilesize: maxfilesize=18446744073709551615
Jul 29 11:24:04 xuexi kernel: decode_attr_maxread: maxread=131072
Jul 29 11:24:04 xuexi kernel: decode_attr_maxwrite: maxwrite=131072
Jul 29 11:24:04 xuexi kernel: decode_attr_time_delta: time_delta=1 0
Jul 29 11:24:04 xuexi kernel: decode_attr_pnfstype: bitmap is 0
Jul 29 11:24:04 xuexi kernel: decode_attr_layout_blksize: bitmap is 0
Jul 29 11:24:04 xuexi kernel: decode_fsinfo: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: set_pnfs_layoutdriver: Using NFSv4 I/O
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_maxlink: maxlink=255
Jul 29 11:24:04 xuexi kernel: decode_attr_maxname: maxname=255
Jul 29 11:24:04 xuexi kernel: decode_pathconf: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: <-- nfs_probe_fsinfo() = 0
Jul 29 11:24:04 xuexi kernel: <-- nfs4_create_server() = ffff88007746a800
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_supported: bitmask=fdffbfff:00f9be3e:00000000
Jul 29 11:24:04 xuexi kernel: decode_attr_fh_expire_type: expire type=0x0
Jul 29 11:24:04 xuexi kernel: decode_attr_link_support: link support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_symlink_support: symlink support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_aclsupport: ACLs supported=3
Jul 29 11:24:04 xuexi kernel: decode_server_caps: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=040000
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=4651240235397459983
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0x0/0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=2
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=0555
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=23
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=1501990255
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501989952
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501989952
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=1
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS: nfs_fhget(0:38/2 fh_crc=0x62d40c52 ct=1)
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=00
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=4651240235397459983
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0x0/0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=00
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=1
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=-2
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=-2
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=0
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=0
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501989952
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501989952
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS: nfs_update_inode(0:38/2 fh_crc=0x62d40c52 ct=2 info=0x26040)
Jul 29 11:24:04 xuexi kernel: NFS: permission(0:38/2), mask=0x1, res=0
Jul 29 11:24:04 xuexi kernel: NFS: permission(0:38/2), mask=0x81, res=0
Jul 29 11:24:04 xuexi kernel: NFS: lookup(/tmp)
Jul 29 11:24:04 xuexi kernel: NFS call  lookup tmp
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=040000
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=16540743250786234113
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0xf199fcb4fb064bf5/0xa1b7a15af0f7cb47)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=391681
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=01777
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=5
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=1501990260
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=391681
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS reply lookup: 0
Jul 29 11:24:04 xuexi kernel: NFS: nfs_fhget(0:38/391681 fh_crc=0xb4775a3f ct=1)
Jul 29 11:24:04 xuexi kernel: --> nfs_d_automount()
Jul 29 11:24:04 xuexi kernel: nfs_d_automount: enter
Jul 29 11:24:04 xuexi kernel: NFS call  lookup tmp
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=040000
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=16540743250786234113
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0xf199fcb4fb064bf5/0xa1b7a15af0f7cb47)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=391681
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=01777
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=5
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=1501990260
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=391681
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS reply lookup: 0
Jul 29 11:24:04 xuexi kernel: --> nfs_do_submount()
Jul 29 11:24:04 xuexi kernel: nfs_do_submount: submounting on /tmp
Jul 29 11:24:04 xuexi kernel: --> nfs_xdev_mount()
Jul 29 11:24:04 xuexi kernel: --> nfs_clone_server(,f199fcb4fb064bf5:a1b7a15af0f7cb47,)
Jul 29 11:24:04 xuexi kernel: --> nfs_probe_fsinfo()
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_supported: bitmask=fdffbfff:00f9be3e:00000000
Jul 29 11:24:04 xuexi kernel: decode_attr_fh_expire_type: expire type=0x0
Jul 29 11:24:04 xuexi kernel: decode_attr_link_support: link support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_symlink_support: symlink support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_aclsupport: ACLs supported=3
Jul 29 11:24:04 xuexi kernel: decode_server_caps: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_lease_time: file size=90
Jul 29 11:24:04 xuexi kernel: decode_attr_maxfilesize: maxfilesize=18446744073709551615
Jul 29 11:24:04 xuexi kernel: decode_attr_maxread: maxread=131072
Jul 29 11:24:04 xuexi kernel: decode_attr_maxwrite: maxwrite=131072
Jul 29 11:24:04 xuexi kernel: decode_attr_time_delta: time_delta=1 0
Jul 29 11:24:04 xuexi kernel: decode_attr_pnfstype: bitmap is 0
Jul 29 11:24:04 xuexi kernel: decode_attr_layout_blksize: bitmap is 0
Jul 29 11:24:04 xuexi kernel: decode_fsinfo: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: set_pnfs_layoutdriver: Using NFSv4 I/O
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_maxlink: maxlink=255
Jul 29 11:24:04 xuexi kernel: decode_attr_maxname: maxname=255
Jul 29 11:24:04 xuexi kernel: decode_pathconf: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: <-- nfs_probe_fsinfo() = 0
Jul 29 11:24:04 xuexi kernel: Cloned FSID: f199fcb4fb064bf5:a1b7a15af0f7cb47
Jul 29 11:24:04 xuexi kernel: <-- nfs_clone_server() = ffff88006f407000
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_supported: bitmask=fdffbfff:00f9be3e:00000000
Jul 29 11:24:04 xuexi kernel: decode_attr_fh_expire_type: expire type=0x0
Jul 29 11:24:04 xuexi kernel: decode_attr_link_support: link support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_symlink_support: symlink support=true
Jul 29 11:24:04 xuexi kernel: decode_attr_aclsupport: ACLs supported=3
Jul 29 11:24:04 xuexi kernel: decode_server_caps: xdr returned 0!
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=040000
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=16540743250786234113
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0xf199fcb4fb064bf5/0xa1b7a15af0f7cb47)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=391681
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=01777
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=5
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=1501990260
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=391681
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS: nfs_fhget(0:40/391681 fh_crc=0xb4775a3f ct=1)
Jul 29 11:24:04 xuexi kernel: <-- nfs_xdev_mount() = 0
Jul 29 11:24:04 xuexi kernel: nfs_do_submount: done
Jul 29 11:24:04 xuexi kernel: <-- nfs_do_submount() = ffff880064fdfb20
Jul 29 11:24:04 xuexi kernel: nfs_d_automount: done, success
Jul 29 11:24:04 xuexi kernel: <-- nfs_d_automount() = ffff880064fdfb20
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=00
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=16540743250786234113
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0x0/0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=00
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=1
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=-2
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=-2
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=0
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=0
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1501990117
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS: nfs_update_inode(0:40/391681 fh_crc=0xb4775a3f ct=2 info=0x26040)
Jul 29 11:24:04 xuexi kernel: NFS: permission(0:40/391681), mask=0x1, res=0
Jul 29 11:24:04 xuexi kernel: NFS: lookup(/testdir)
Jul 29 11:24:04 xuexi kernel: NFS call  lookup testdir
Jul 29 11:24:04 xuexi kernel: --> nfs4_alloc_slot used_slots=0000 highest_used=4294967295 max_slots=1024
Jul 29 11:24:04 xuexi kernel: <-- nfs4_alloc_slot used_slots=0001 highest_used=0 slotid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_type: type=040000
Jul 29 11:24:04 xuexi kernel: decode_attr_change: change attribute=7393570666420598027
Jul 29 11:24:04 xuexi kernel: decode_attr_size: file size=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_fsid: fsid=(0xf199fcb4fb064bf5/0xa1b7a15af0f7cb47)
Jul 29 11:24:04 xuexi kernel: decode_attr_fileid: fileid=391682
Jul 29 11:24:04 xuexi kernel: decode_attr_fs_locations: fs_locations done, error = 0
Jul 29 11:24:04 xuexi kernel: decode_attr_mode: file mode=0754
Jul 29 11:24:04 xuexi kernel: decode_attr_nlink: nlink=3
Jul 29 11:24:04 xuexi kernel: decode_attr_owner: uid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_group: gid=0
Jul 29 11:24:04 xuexi kernel: decode_attr_rdev: rdev=(0x0:0x0)
Jul 29 11:24:04 xuexi kernel: decode_attr_space_used: space used=4096
Jul 29 11:24:04 xuexi kernel: decode_attr_time_access: atime=1501990266
Jul 29 11:24:04 xuexi kernel: decode_attr_time_metadata: ctime=1497209702
Jul 29 11:24:04 xuexi kernel: decode_attr_time_modify: mtime=1496802409
Jul 29 11:24:04 xuexi kernel: decode_attr_mounted_on_fileid: fileid=391682
Jul 29 11:24:04 xuexi kernel: decode_getfattr_attrs: xdr returned 0
Jul 29 11:24:04 xuexi kernel: decode_getfattr_generic: xdr returned 0
Jul 29 11:24:04 xuexi kernel: nfs4_free_slot: slotid 0 highest_used_slotid 4294967295
Jul 29 11:24:04 xuexi kernel: NFS reply lookup: 0
Jul 29 11:24:04 xuexi kernel: NFS: nfs_fhget(0:40/391682 fh_crc=0xec69f317 ct=1)
Jul 29 11:24:04 xuexi kernel: NFS: dentry_delete(/tmp, 202008c)
Jul 29 11:24:04 xuexi kernel: NFS: clear cookie (0xffff88005eaf4620/0x          (null))
Jul 29 11:24:04 xuexi kernel: NFS: clear cookie (0xffff88005eaf4a40/0x          (null))
Jul 29 11:24:04 xuexi kernel: NFS: releasing superblock cookie (0xffff88007746a800/0x          (null))
Jul 29 11:24:04 xuexi kernel: --> nfs_free_server()
Jul 29 11:24:04 xuexi kernel: --> nfs_put_client({2})
Jul 29 11:24:04 xuexi kernel: <-- nfs_free_server()
Jul 29 11:24:04 xuexi kernel: <-- nfs4_try_mount() = 0

1.9 深刻NFS的方向

本文仅简单介绍了一些NFS的基本使用方法,但NFS自身实际上是很复杂的,想深刻也不是一件简单的事。例如,如下列出了几个NFS在实现上应该要解决的问题。

(1).多台客户端挂载同一个导出的目录后,要同时编辑其中同一个文件时,应该如何处理?这是共享文件更新问题,通用的解决方法是使用文件锁。

(2).客户端上对文件内容作出修改后是否要当即同步到服务端上?这是共享文件的数据缓存问题,体现的方式是文件数据是否要在各客户端上保证一致性。和第一个问题结合起来,就是分布式(集群)文件数据一致性问题。

(3).客户端或服务端进行了重启,或者它们出现了故障,亦或者它们之间的网络出现故障后,它们的对端如何知道它已经出现了故障?这是故障通知或重启通知问题。

(4).出现故障后,正常重启成功了,那么如何恢复到故障前状态?这是故障恢复问题。

(5).若是服务端故障后一直没法恢复,客户端是否能自动故障转移到另外一台正常工做的NFS服务节点?这是高可用问题。(NFS版本4(后文将简写为NFSv4)能够从自身实现故障转移,固然使用高可用工具如heartbeat也同样能实现)

总结起来就几个关键词:锁、缓存、数据和缓存一致性、通知和故障恢复。从这些关键字中,很天然地会联想到了集群和分布式文件系统,其实NFS也是一种简易的分布式文件系统,但没有像集群或分布式文件系统那样实现几乎完美的锁、缓存一致性等功能。并且NFSv4为了体现其特色和性能,在一些通用问题上采用了与集群、分布式文件系统不一样的方式,如使用了文件委托(服务端将文件委托给客户端,由此实现相似锁的功能)、锁或委托的租约等(就像DHCP的IP租约同样,在租约期内,锁和委托以及缓存是有效的,租约过时后这些内容都无效)。

由此知,深刻NFS其实就是在深刻分布式文件系统,因为网上对NFS深刻介绍的文章几乎没有,因此想深刻它并不是一件简单的事。若是有深刻学习的想法,能够阅读NFSv4的RFC3530文档的前9章以及RCP的RFC文档。如下是本人的一些man文档翻译。

 

翻译:man rpcbind(rpcbind中文手册)
翻译:man nfsd(rpc.nfsd中文手册)
翻译:man mountd(rpc.mountd中文手册)
翻译:man statd(rpc.statd中文手册)
翻译:man sm-notify(sm-notify命令中文手册)
翻译:man exportfs(exportfs命令中文手册)

如下是man nfs中关于传输方法和缓存相关内容的翻译。

TRANSPORT METHODS
       NFS客户端是经过RPC向NFS服务端发送请求的。RPC客户端会自动发现远程服务端点,处理每请求(per-request)的
       身份验证,调整当客户端和服务端之间出现不一样字节字节序(byte endianness)时的请求参数,而且当请求在网络
       上丢失或被服务端丢弃时重传请求。rpc请求和响应数据包是经过网络传输的。
 
       在大多数情形下,mount(8)命令、NFS客户端和NFS服务端能够为挂载点自动协商合适的传输方式以及数据传输时
       的大小。但在某些状况下,须要使用mount选项显式指定这些设置。
 
       对于的传统NFS,NFS客户端只使用UDP传输请求给服务端。尽管实现方式很简单,但基于UDP的NFS有许多限制,在
       一些通用部署环境下,这些限制项会限制平滑运行的能力,还会限制性能。即便是UDP丢包率极小的状况,也将
       致使整个NFS请求丢失;所以,重传的超时时间通常都是亚秒级的,这样可让客户端从请求丢失中快速恢复,但
       即便如此,这可能会致使无关的网络阻塞以及服务端负载加剧。
 
       可是在专门设置了网络MTU值是相对于NFS的输出传输大小时(例如在网络环境下启用了巨型以太网帧)(注:相对的
       意思,例如它们成比例关系),UDP是很是高效的。在这种环境下,建议修剪rsize和wsize,以便让每一个NFS的读或
       写请求都能容纳在几个网络帧(甚至单个帧)中。这会下降因为单个MTU大小的网络帧丢失而致使整个读或写请求丢
       失的几率。
      
       (译者注:UDP是NFSv2和NFSv3所支持的,NFSv4使用TCP,因此以上两段不用考虑)
 
       现代NFS都默认采用TCP传输协议。在几乎全部可想到的网络环境下,TCP都表现良好,且提供了很是好的保证,防
       止由于网络不可靠而引发数据损坏。但使用TCP传输协议,基本上都会考虑设置相关防火墙。
 
       在正常环境下,网络丢包的频率比NFS服务丢包的频率要高的多。所以,没有必要为基于TCP的NFS设置极短的重传
       超时时间。通常基于TCP的NFS的超时时间设置在1分钟和10分钟之间。当客户端耗尽了重传次数(选项retrans的值),
       它将假定发生了网络分裂,并尝试以新的套接字从新链接服务端。因为TCP自身使得网络传输的数据是可靠的,所
       以,能够安全地使用处在默认值和客户端服务端同时支持的最大值之间的rszie和wsize,而再也不依赖于网络MTU大小。
 
DATA AND METADATA COHERENCE
       如今有些集群文件系统为客户端之间提供了很是完美的缓存一致性功能,但对于NFS客户端来讲,实现完美的缓
       存一致性是很是昂贵的,特别是大型局域网络环境。所以,NFS提供了稍微薄弱一点的缓存一致性功能,以知足
       大多数文件共享需求。
 
   Close-to-open cache consistency
       通常状况下,文件共享是彻底序列化的。首先客户端A打开一个文件,写入一些数据,而后关闭文件而后客户端B
       打开同一个文件,并读取到这些修改后的数据。
      
       当应用程序打开一个存储在NFSv3服务端上的文件时,NFS客户端检查文件在服务端上是否存在,并经过是否发送
       GETATTR或ACCESS请求判断文件是否容许被打开。NFS客户端发送这些请求时,不会考虑已缓存文件属性是不是新
       鲜有效的。
 
       当应用程序关闭文件,NFS客户端当即将已作的修改写入到文件中,以便下一个打开者能够看到所作的改变。这
       也给了NFS客户端一个机会,使得它能够经过文件关闭时的返回状态码向应用程序报告错误。
 
       在打开文件时以及关闭文件刷入数据时的检查行为被称为close-to-open缓存一致性,或简称为CTO。能够经过使
       用nocto选项来禁用整个挂载点的CTO。
      
       (译者注:NFS关闭文件时,客户端会将所作的修改刷入到文件中,而后发送GETATTR请求以确保该文件的属性缓存
       已被更新。以后其余的打开者打开文件时会发送GETATTR请求,根据文件的属性缓存能够判断文件是否被打开并作
       了修改。这能够避免缓存无效)
 
   Weak cache consistency
       客户端的数据缓存仍有几乎包含过时数据。NFSv3协议引入了"weak cache consistency"(WCC),它提供了一种在单
       个文件被请求以前和以后有效地检查文件属性的方式。这有助于客户端识别出由其余客户端对此文件作出的改变。
 
       当某客户端使用了并发操做,使得同一文件在同一时间作出了屡次更新(例如,后台异步写入),它仍将难以判断
       是该客户端的更新操做修改了此文件仍是其余客户端的更新操做修改了文件。
 
   Attribute caching
       使用noac挂载选项可让多客户端之间实现属性缓存一致性。几乎每一个文件系统的操做都会检查文件的属性信息。
       客户端自身会保留属性缓存一段时间以减小网络和服务端的负载。当noac生效时,客户端的文件属性缓存就会被
       禁用,所以每一个会检查文件属性的操做都被强制返回到服务端上来操做文件,这表示客户端以牺牲网络资源为代
       价来快速查看文件发生的变化。
 
       不要混淆noac选项和"no data caching"。noac挂载选项阻止客户端缓存文件的元数据,但仍然可能会缓存非元数
       据的其余数据。
 
       NFS协议设计的目的不是为了支持真正完美的集群文件系统缓存一致性。若是要达到客户端之间缓存数据的绝对
       一致,那么应该使用文件锁的方式。
 
   File timestamp maintainence
       NFS服务端负责管理文件和目录的时间戳(atime,ctime,mtime)。当服务端文件被访问或被更新,文件的时间戳也会
       像本地文件系统那样改变。
 
       NFS客户端缓存的文件属性中包括了时间戳属性。当NFS客户端检索NFS服务端文件属性时,客户端文件的时间戳会
       更新。所以,在NFS服务端的时间戳更新后显示在NFS客户端以前可能会有一些延迟。
 
       为了遵照POSIX文件系统标准,Linux NFS客户端须要依赖于NFS服务端来保持文件的mtime和ctime时间戳最新状态。
       实现方式是先让客户端将改变的数据刷入到服务端,而后再输出文件的mtime。
 
       然而,Linux客户端能够很轻松地处理atime的更新。NFS客户端能够经过缓存数据来保持良好的性能,但这意味着
       客户端应用程序读取文件(会更新atime)时,不会反映到服务端,但实际上服务端的atime已经修改了。
 
       因为文件属性缓存行为,Linux NFS客户端mount时不支持通常的atime相关的挂载选项。
 
       特别是mount时指定了atime/noatime,diratime/nodiratime,relatime/norelatime以及strictatime/nostrictatime
       挂载选项,实际上它们没有任何效果。
 
   Directory entry caching
       Linux NFS客户端缓存全部NFS LOOKUP请求的结果。若是所请求目录项在服务端上存在,则查询的结果称为正查询
       结果。若是请求的目录在服务端上不存在(服务端将返回ENOENT),则查询的结果称为负查询结果。
 
       为了探测目录项是否添加到NFS服务端或从其上移除了,Linux NFS客户端会监控目录的mtime。若是客户端监测到
       目录的mtime发生了改变,客户端将丢弃该目录相关的全部LOOKUP缓存结果。因为目录的mtime是一种缓存属性,因
       此服务端目录mtime发生改变后,客户端可能须要等一段时间才能监测到它的改变。
 
       缓存目录提升了不与其余客户端上的应用程序共享文件的应用程序的性能。但使用目录缓存可能会干扰在多个客户
       端上同时运行的应用程序,而且须要快速检测文件的建立或删除。lookupcache挂载选项容许对目录缓存行为进行一
       些调整。
     
       若是客户端禁用目录缓存,则每次LOOKUP操做都须要与服务端进行验证,那么该客户端能够当即探测到其余客户端
       建立或删除的目录。可使用lookupcache=none来禁用目录缓存。若是禁用了目录缓存,因为须要额外的NFS请求,
       这会损失一些性能,但禁用目录缓存比使用noac损失的性能要少,且对NFS客户端缓存文件属性没有任何影响。
 
   The sync mount option
       NFS客户端对待sync挂载选项的方式和挂载其余文件系统不一样。若是即不指定sync也不指定async,则默认为async。
       async表示异步写入,除了发生下面几种特殊状况,NFS客户端会延迟发送写操做到服务端:
 
              ● 内存压力迫使回收系统内存资源。
              ● 客户端应用程序显式使用了sync类的系统调用,如sync(2),msync(2)或fsync(3)。
              ● 关闭文件时。
              ● 文件被锁/解锁。
 
       换句话说,在正常环境下,应用程序写的数据不会当即保存到服务端。(固然,关闭文件时是当即同步的)
 
       若是在挂载点上指定sync选项,任何将数据写入挂载点上文件的系统调用都会先把数据刷到服务端上,而后系统调
       用才把控制权返回给用户空间。这提供了客户端之间更好的数据缓存一致性,但消耗了大量性能。
 
       在未使用sync挂载选项时,应用程序可使用O_SYNC修饰符强制当即把单个文件的数据刷入到服务端。
 
   Using file locks with NFS
       网络锁管理器(Network Lock Manager,NLM)协议是一个独立的协议,用于管理NFSv2和NFSv3的文件锁。为了让客户端
       或服务端在重启后能恢复锁,须要使用另外一个网络状态管理器(Network Status Manager,NSM)协议。在NFSv4中,NFS
       直协议自身接支持文件锁相关功能,因此NLM和NSM就再也不使用了。
 
       在大多数状况下,NLM和NSM服务是自动启动的,而且不须要额外的任何配置。但须要配置NFS客户端使用的是fqdn名
       称,以保证NFS服务端能够找到客户端并通知它们服务端的重启动做。
 
       NLS仅支持advisory文件锁。要锁定NFS文件,可使用待F_GETLK和F_SETLK的fcntl(2)命令。NFS客户端会转换经过
       flock(2)获取到的锁为advisory文件锁。
 
       当服务端不支持NLM协议,或者当NFS服务端是经过防火墙但阻塞了NLM服务端口时,则须要指定nolock挂载选项。
       当客户端挂载导出的/var目录时,必须使用nolock禁用NLM锁,由于/var目录中包含了NLM锁相关的信息。
       (注,由于NLM仅在nfsv2和nfsv3中支持,因此NFSv4不支持nolock选项)
 
       当仅有一个客户端时,使用nolock选项能够提升必定的性能。
 
   NFS version 4 caching features
       NFSv4上的数据和元数据缓存行为和以前的版本类似。可是NFSv4添加了两种特性来提高缓存行为:change attributes
       以及delegation。(注:nfsv4中取消了weak cache consistency)
 
       change attribute是一种新的被跟踪的文件/目录元数据信息。它替代了使用文件mtime和ctime做为客户端验证缓存内
       容的方式。但注意,change attributes和客户端/服务端文件的时间戳的改变无关。
 
       文件委托(file delegation)是NFSv4的客户端和NFSv4服务端以前的一种合约,它容许客户端临时处理文件,就像没有
       其余客户端正在访问该文件同样。当有其余客户端尝试访问被委托文件时,服务端必定会通知服务端(经过callback请
       求)。一旦文件被委托给某客户端,客户端能够尽量大地缓存该文件的数据和元数据,而不须要联系服务端。
 
       文件委托有两种方式:read和write。读委托意味着当其余客户端尝试向委托文件写入数据时,服务端通知客户端。而
       写委托意味着其余客户端不管是尝试读仍是写,服务端都会通知客户端。
 
       NFSv4上当文件被打开的时候,服务端会受权文件委托,而且当其余客户端想要访问该文件但和已受权的委托冲突时,
       服务端能够在任意时间点重调(recall)委托关系。不支持对目录的委托。
       (译者注:只有读委托和读委托不会冲突)
 
       为了支持委托回调(delegation callback),在客户端初始联系服务端时,服务端会检查网络并返回路径给客户端。若是
       和客户端的联系没法创建,服务端将不会受权任何委托给客户端。
相关文章
相关标签/搜索