pnfs的call back代码梳理
call back 是服务器用来向客户端召回授权布局的一种机制。
从一个使用例子来研究layout的callback;
void exfs_dm_layout_recall(struct inode *inode, u64 off, u64 length, u32 iomode)
{
struct nfsd4_pnfs_cb_layout cbl;
int err;
cbl.cbl_recall_type = RETURN_FILE;
cbl.cbl_layoutchanged = 0;
cbl.cbl_seg.clientid = 0;
cbl.cbl_seg.layout_type = EXFS_SB(inode->i_sb)->pnfs_layout_type;
cbl.cbl_seg.iomode = IOMODE_ANY;
cbl.cbl_seg.offset = off;
cbl.cbl_seg.length = length;
err = EXFS_SB(inode->i_sb)->s_pnfs_ctl.cb_op->cb_layout_recall
(inode->i_sb, inode, &cbl);
if (err && err != -ENOENT)
klog(inode->i_sb, ERROR, "%s call back layout failed, err = %d,"
"ino = %lu!\n",
__func__, err, inode->i_ino);
}
加粗的钩子函数在这里
static struct pnfsd_cb_operations pnfsd_cb_op = {
.cb_layout_recall = nfsd_layout_recall_cb,
.cb_device_notify = nfsd_device_notify_cb,
.cb_get_state = nfs4_pnfs_cb_get_state,
.cb_change_state = nfs4_pnfs_cb_change_state,
};
int nfsd_layout_recall_cb(struct super_block *sb, struct inode *inode,
struct nfsd4_pnfs_cb_layout *cbl)
{
int status;
struct nfs4_file *lrfile = NULL;
struct list_head todolist;
unsigned todo_len = 0;
nfs4_lock_state();
status = -ENOENT;
if (inode) {
lrfile = find_file(inode);
}
INIT_LIST_HEAD(&todolist);
/* If no cookie provided by FS, return a default one */
if (!cbl->cbl_cookie)
cbl->cbl_cookie = PNFS_LAST_LAYOUT_NO_RECALLS;
status = create_layout_recall_list(&todolist, &todo_len, cbl, lrfile);
int status2 = spawn_layout_recall(sb, &todolist, todo_len);
}
其中,find_file(),有个疑问:如果多个客户端打开一个文件,则会出现一个inode对应多个file,此时选择哪个file结构呢?
查数据结构得知,每个inode最多只有一个nfs4_file结构,此结构中,有state_id 和delegation_id的链表,当多个线程打开同一个文件时候,就链接到这个链表中。
在nfsd4_open2中,会用到此结构,进行一些检查。
struct nfs4_file *
find_file(struct inode *ino)
{
unsigned int hashval = file_hashval(ino);
struct nfs4_file *fp;
spin_lock(&recall_lock);
list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
if (fp->fi_inode == ino) {
get_nfs4_file(fp);
spin_unlock(&recall_lock);
return fp;
}
}
spin_unlock(&recall_lock);
return NULL;
}
create_layout_recall_list函数找到拥有此文件layout的所有client ,方法是对比state_id;这涉及到一些数据结构,可以参照张师兄给的数据结构图。
call back 是服务器用来向客户端召回授权布局的一种机制。
从一个使用例子来研究layout的callback;
void exfs_dm_layout_recall(struct inode *inode, u64 off, u64 length, u32 iomode)
{
struct nfsd4_pnfs_cb_layout cbl;
int err;
cbl.cbl_recall_type = RETURN_FILE;
cbl.cbl_layoutchanged = 0;
cbl.cbl_seg.clientid = 0;
cbl.cbl_seg.layout_type = EXFS_SB(inode->i_sb)->pnfs_layout_type;
cbl.cbl_seg.iomode = IOMODE_ANY;
cbl.cbl_seg.offset = off;
cbl.cbl_seg.length = length;
err = EXFS_SB(inode->i_sb)->s_pnfs_ctl.cb_op->cb_layout_recall
(inode->i_sb, inode, &cbl);
if (err && err != -ENOENT)
klog(inode->i_sb, ERROR, "%s call back layout failed, err = %d,"
"ino = %lu!\n",
__func__, err, inode->i_ino);
}
加粗的钩子函数在这里
static struct pnfsd_cb_operations pnfsd_cb_op = {
.cb_layout_recall = nfsd_layout_recall_cb,
.cb_device_notify = nfsd_device_notify_cb,
.cb_get_state = nfs4_pnfs_cb_get_state,
.cb_change_state = nfs4_pnfs_cb_change_state,
};
int nfsd_layout_recall_cb(struct super_block *sb, struct inode *inode,
struct nfsd4_pnfs_cb_layout *cbl)
{
int status;
struct nfs4_file *lrfile = NULL;
struct list_head todolist;
unsigned todo_len = 0;
nfs4_lock_state();
status = -ENOENT;
if (inode) {
lrfile = find_file(inode);
}
INIT_LIST_HEAD(&todolist);
/* If no cookie provided by FS, return a default one */
if (!cbl->cbl_cookie)
cbl->cbl_cookie = PNFS_LAST_LAYOUT_NO_RECALLS;
status = create_layout_recall_list(&todolist, &todo_len, cbl, lrfile);
int status2 = spawn_layout_recall(sb, &todolist, todo_len);
}
其中,find_file(),有个疑问:如果多个客户端打开一个文件,则会出现一个inode对应多个file,此时选择哪个file结构呢?
查数据结构得知,每个inode最多只有一个nfs4_file结构,此结构中,有state_id 和delegation_id的链表,当多个线程打开同一个文件时候,就链接到这个链表中。
在nfsd4_open2中,会用到此结构,进行一些检查。
struct nfs4_file *
find_file(struct inode *ino)
{
unsigned int hashval = file_hashval(ino);
struct nfs4_file *fp;
spin_lock(&recall_lock);
list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
if (fp->fi_inode == ino) {
get_nfs4_file(fp);
spin_unlock(&recall_lock);
return fp;
}
}
spin_unlock(&recall_lock);
return NULL;
}
create_layout_recall_list函数找到拥有此文件layout的所有client ,方法是对比state_id;这涉及到一些数据结构,可以参照张师兄给的数据结构图。