1. Client/Owner/State的关系
一个Client可以有多个Owner,每个Owner可以拥有多个State,每个State代表获得的一种资源(Open、Lock、Delegation)。Open owner是针对open的owner。
2. Open Owner
在OPEN请求中,Client传给Server24Byte的Owner信息。OPEN请求会返回state id。以后SETATTR/READ/WRITE时候,需要使用state id。
2. 1 open owner的由来
下面是ganesha打出的log,这个owner是由NFS Kernel Client分配的。
open4_open_owner : owner=(24:0x6f70656e2069643a0000002b00000000000100bd38d66fb8)
2.2 open owner的作用
每次进行open的时候,ganesha内部都会维护open owner和state的数据结构。在open返回的时候收到stateid作为收据。以后每次read/write的时候,会根据stateid找到对应的open owner和state数据结构。然后判断state是否冲突。
3 open的过程
封装在nfs4_op_open
里。
- 调用
nfs_client_id_get_confirmed
,通过传进来的clientid,得到confirmed clientid信息,即nfs_client_id_t
。 - 调用
open4_open_owner
,通过clientid和传进来的24byte open owner,得到ganesha自己的owner对象,即state_owner_t
。第一次调用open4_open_owner,创建新的owner,以后调用都从key/value pair里取。 - 调用
open4_ex
,根据clientid和open owner得到ganesha自己的state对象,即state_t
。第一次调用创建新的state对象,并通过state_add_impl()
将state插入owner队列中。以后调用从key/value pair里取。state由owner+file_obj唯一确定。 - 调用
update_stateid
,设置返回值,其中包括stateid。
3.1 open4_open_owner()分析
- 将24byte的state owner转换成ganesha自己数据结构
state_owner_t
。这个关系记录在key/value pair中 - 如果key/value pair中不存在这个key,则是新的,不需要检查什么。
- 如果不是新的,需要简单检查一下。
以下是ganesha的log:
Open: STATE_OPEN_OWNER_NFSV4 0x7efe580207f0: clientid={0x7efe40001990 ClientID={Epoch=0x5c987c1f Counter=0x00000001} CONFIRMED Client={0x7efe400018a0 name=(27:Linux NFSv4.1 ubuntu-xenial) refcount=1} t_delta=0 reservations=1 refcount=4} owner=(24:0x6f70656e2069643a0000002b000000000001855ef8aa8e36) confirmed=1 seqid=0 refcount=1
3.2 open4_ex()分析
- 调用
alloc_state
创建state对象。调用FSAL层的open函数判断state对象是否满足需求。 - 将这个open state传进相应的FSAL的open2函数里。
- 调用
state_add_impl
将这个open state加入到open state的list里(对于open owner,这个list顶多有一个元素)。
4 read/write/lock/unlock
OPEN之后的read/write/lock/unlock都会传进来stateid,会根据这个stateid判断是否冲突。
逻辑封装在nfs4_Check_Stateid()里
stateid => state => open file object 和state owner
5. 相关数据结构
struct nfs_client_id_t {
clientid4 cid_clientid; //clientid
verifier4 cid_verifier; //verifier,重启后会变化
...
nfs_client_record_t *cid_client_record; //指回nfs_client_record_t
struct glist_head cid_openowners; //open owner list
struct glist_head cid_lockowners; //lock owners list
pthread_mutex_t cid_mutex;
...
struct gsh_client *gsh_client; //
};
//同一个client,针对不同资源,可以有多个owner。
struct state_owner_t {
state_owner_type_t so_type; //owner类型,lock or open
struct glist_head so_lock_list; //Locks for this owner
pthread_mutex_t so_mutex;
int32_t so_refcount; //Reference count for lifecyce management
int so_owner_len; //Length of owner name
char *so_owner_val; //Owner name
union {
state_nfs4_owner_t so_nfs4_owner; // All NFSv4 state owners
} so_owner;
};
struct state_nfs4_owner_t {
clientid4 so_clientid; //clientid
nfs_client_id_t *so_clientrec; //confirm and unconfirm
...
struct glist_head so_state_list; //这个owner所拥有的state
...
};
struct state_t {
struct glist_head state_list; //List of states on a file
struct glist_head state_owner_list; //List of states for an owner
struct glist_head state_export_list; //List of states on the same
pthread_mutex_t state_mutex; /**< Mutex protecting following pointers */
struct gsh_export *state_export; /**< Export this entry belongs to */
state_owner_t *state_owner; //对应的owner
struct fsal_obj_handle *state_obj; //对应的file object
struct fsal_export *state_exp; /**< FSAL export */
union state_data state_data; //根据state类型,对应不同数据
enum state_type state_type;//state类型,STATE_TYPE_SHARE,STATE_TYPE_DELEG,STATE_TYPE_LOCK
u_int32_t state_seqid; /**< The NFSv4 Sequence id */
int32_t state_refcount; /**< Refcount for state_t objects */
char stateid_other[OTHERSIZE]; //state id最重要的部分,可以通过它找到state
...
};
Owner的相关函数:
- create_nfs4_owner: 根据clientid和client传进来的24Byte的open owner,创建Server端的
state_owner_t
- open4_open_owner: 调用create_nfs4_owner,如果owner已经创建过,返回错误。
网友评论