linux+内核中开启nfs,NFS Client in Linux Kernel - Open

1. Callstack for Opening for a file

open() => nfs4_file_open() => nfs4_atomic_open() => nfs4_do_open() => _nfs4_do_open()

_nfs4_do_open分析:

nfs4_get_state_owner()获得open owner对象

设置claim,他有几种可能CLAIM_NULL(文件用文件名描述),CLAIM_FH(文件用current filehandle描述), CLAIM_PREVIOUS(用于reclaim open)

nfs4_opendata_alloc()分配nfs4_opendata

_nfs4_open_and_get_state()发送OPEN NFS命令

4.1 _nfs4_proc_open, 发送OPEN NFS命令

4.2 nfs4_opendata_to_nfs4_state() =>_nfs4_opendata_to_nfs4_state(), 创建open state,并将OPEN NFS命令得到的open state id,跟新这里。

open state存在ctx->state,其中ctx是nfs_open_context,它存储在filp->private_data。对文件open以后,就可以通过filp->private_data得到ctx,并得到ctx->state->open_stateid,通过这个stateid向NFS Server发送READ/WRITE/LOCK操作。

2. NFS协议中的Open owner

NFS协议规定发送OPEN时候要发送一个open owner,标识这个open的owner。在Server看来,clientid可以区分是来自哪个client的,open owner可以区分不同进程的open请求。

摘自[nfs4.1协议]https://tools.ietf.org/html/rfc5661

NFS协议中Open owner和Lock owner都用下面这个结构体表达。

struct state_owner4 {

clientid4 clientid;

opaque owner;

};

clientid,Server分配的,唯一标识一个和server建立session的client

字符串+字符串的长度,唯一标识client中的一个进程

client标识+进程标识,唯一确定一个lock的owner。

### 2.1 Linux Kernel中对Open owner的设置

static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)

{

...

*p++ = cpu_to_be32(24);

p = xdr_encode_opaque_fixed(p, "open id:", 8);

*p++ = cpu_to_be32(arg->server->s_dev);

*p++ = cpu_to_be32(arg->id.uniquifier);

xdr_encode_hyper(p, arg->id.create_time);

}

Lock owner大小24字节:

8字节的固定字符,"lock id:"

4字节的s_dev,表示是本地哪个文件系统。

4字节的id。由ida_get_new函数创建,在本地文件系统中唯一。

8字节的create_time

以上三点,保证了在一个client内Lock owner是唯一的。

再加上clientid,可以保证所有和Server建立session连接的client来自的lock owner是唯一确定。

3. Linux Kernel对一个打开实体Owner的描述

struct nfs4_state_owner {

struct nfs_server *so_server;

struct list_head so_lru;

unsigned long so_expires;

struct rb_node so_server_node;

struct rpc_cred *so_cred; //以这个为key,插入到红黑树里

spinlock_t so_lock;

atomic_t so_count;

unsigned long so_flags;

struct list_head so_states;

struct nfs_seqid_counter so_seqid;

seqcount_t so_reclaim_seqcount;

struct mutex so_delegreturn_mutex;

};

3.1 创建nfs4_state_owner

nfs4_get_state_owner()

首先通过so_cred为key,在红黑树里搜索

如果没有搜到,创建一个

4. Linux Kernel对一个打开实体的描述

这个数据结构专门描述open state,一个实体会被多个Owner打开,所以struct nfs4_state和struct nfs4_state_owner是一对多的关系

struct nfs4_state {

struct list_head open_states; //对于同一个inode,所有open state存在inode->open_states

struct list_head inode_states; //对于同一个owner,所有的open state存在owner->so_states

struct list_head lock_states; //这个open state下所有的lock state

struct nfs4_state_owner *owner; /* Pointer to the open owner */

struct inode *inode; /* Pointer to the inode */

unsigned long flags; /* Do we hold any locks? */

spinlock_t state_lock; /* Protects the lock_states list */

seqlock_t seqlock; /* Protects the stateid/open_stateid */

nfs4_stateid stateid; /* Current stateid: may be delegation */

nfs4_stateid open_stateid; /* OPEN stateid */

/* The following 3 fields are protected by owner->so_lock */

unsigned int n_rdonly; /* Number of read-only references */

unsigned int n_wronly; /* Number of write-only references */

unsigned int n_rdwr; /* Number of read/write references */

fmode_t state; /* State on the server (R,W, or RW) */

atomic_t count;

};

4.1 创建nfs4_state

nfs4_get_open_state

通过owner和inode的组合,试图寻找一下

如果找不到创建一个和inode关联

4. open stateid for Read/Write/Lock/Setattr/Close

这些操作都是依靠open stateid来向Server交互的。

参见下列函数的实现

encode_read()

encode_write()

encode_setattr()

encode_close()

encode_lock()

encode_locku()

static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args,

struct compound_hdr *hdr)

{

__be32 *p;

encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);

encode_nfs4_stateid(xdr, &args->stateid); //NFS Server需要通过stateid找到file owner

p = reserve_space(xdr, 12);

p = xdr_encode_hyper(p, args->offset);

*p = cpu_to_be32(args->count);

}

调用栈

//open for file

nfs4_file_open <= sys_open

open_context // nfs4_atomic_open

nfs4_do_open

_nfs4_do_open

nfs4_recover_expired_lease

//如果当前Dentry访问过,则claim = NFS4_OPEN_CLAIM_FH

nfs4_opendata_alloc

_nfs4_open_and_get_state

_nfs4_proc_open

nfs4_run_open_task //send OPEN request to server

nfs4_open_prepare

//如果claim == NFS4_OPEN_CLAIM_FH,将OPEN修改成OPEN_NOATTR

//open for dir

nfs_opendir <= sys_open

if (filp->f_path.dentry == filp->f_path.mnt->mnt_root)

__nfs_revalidate_inode

getattr

//read dir

nfs_readdir <= sys_getdents

readdir_search_pagecache

find_cache_page

get_cache_page

=> nfs_readdir_filler

nfs_readdir_xdr_to_array

nfs_readdir_xdr_filler

readdir //nfs4_proc_readdir

_nfs4_proc_readdir //send READDIR

nfs_readdir_search_array

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值