文件锁是保持文件同步的一种手段,当多个用户同时操作同一个文件时,文件锁可以保证数据不发生冲突。NFSv2和NFSv3依靠NLM协议实现文件锁,NFSv4本身实现了文件锁,不需要NLM协同工作了。NFS中的文件锁既可以加在客户端,也可以加在服务器端。如果客户端挂载NFS文件系统时使用了选项nolock,表示在客户端加锁。这种情况下可以保证同一个客户端的多个进程访问同一个文件的过程不发生冲突,但是不同客户端访问同一个文件时还可能发生冲突,因为文件锁加在了客户端,其他客户端不知道这个文件锁的存在。如果客户端挂载NFS文件系统时使用了选项lock,表示在服务器端加锁,这样所有的客户端都可以检查服务器端是否存在文件锁,因此所有客户端访问同一个文件时都不会发生冲突。客户端加锁时和其他文件系统的加锁过程没有什么区别,因此我们只讲解服务器端加锁的情况。
1.NFS中文件锁操作
NFSV4中,服务器端锁处理函数的入口点是nfs4_proc_lock(),这个函数处理了NFSv4中所有关于文件锁的操作,函数代码如下:
参数filp:这是一个文件对象指针,表示对哪个文件进行锁处理
参数cmd:这是文件锁操作的方法,取值为:F_GETLK、F_SETLK、F_SETLKW
参数request:这里包含了文件锁信息
static int
nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
{
struct nfs_open_context *ctx;
struct nfs4_state *state;
unsigned long timeout = NFS4_LOCK_MINTIMEOUT;
int status;
/* verify open state */
// ctx是打开文件时设置的数据结构,其中包含了nfs4_state指针.
ctx = nfs_file_open_context(filp); // return filp->private_data
state = ctx->state; // 取出nfs4_state结构
// 检查文件锁的起始位置和结束位置是否非法
if (request->fl_start < 0 || request->fl_end < 0)
return -EINVAL;
// 文件锁包含三种操作:F_GETLK、F_SETLK、F_SETLKW
if (IS_GETLK(cmd)) { // 查询文件锁的信息
if (state != NULL)
return nfs4_proc_getlk(state, F_GETLK, request);