7nfs客户端没权限_cephfs: 用户态客户端lookup

文件系统最重要的就是读和写,在进行读和写之前,得索引到该文件,即知道要读写的文件的inode。怎么去获得到要读写文件的inode,就要用到lookup。在客户端这边,也就是发送请求,然后处理请求。但是这里涉及到元数据缓存,就稍微复杂点。

lookup流程(没命中缓存)

ff19beeaa5e3568062a4736958575561.png

命中缓存逻辑

inode中有一个dir成员,如下

Dir       *dir;     // if i'm a dir.

Dir里面有一个dentries的map,此map就存有子目录、文件的名字和Dentry键值对

ceph::unordered_map<string, Dentry*> dentries;

Dentry中存有该目录/文件的Inode指针

InodeRef inode;

是否命中缓存,举个例子来说明,比如lookup /test/test1,就得先看test的inode->dir->dentries中是否有"test1"的key。

if (dir->dir && dir->dir->dentries.count(dname))

当然,光有"test1"的Dentry缓存也不行,也得看Dentry中Inode是否可用,即Inode中包含CEPH_STAT_CAP_INODE_ALL权限,且Inode中的caps没有过期。

dn->inode->caps_issued_mask(mask, true)

最后判断父目录"test"的inode是否有CEPH_CAP_FILE_SHARED权限,以及在缓存完"test1"的Dentry后,是否有其他客户端更改"test"目录的inode

if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED, true)) {
	if (dn->cap_shared_gen == dir->shared_gen

当上面的条件满足时,才算命中缓存,这时"test"的inode只需从缓存里拿,无需再发请求找mds拿。

发送请求的内容

MetaRequest

struct MetaRequest {
private:
  InodeRef _inode, _old_inode, _other_inode;       // _inode为父目录(test)的inode指针
  Dentry *_dentry;                                 //associated with path, _dentry->dir是父目录的Dir,_dentry->name = "test1"
public:
  ceph_mds_request_head head;                      // head.op = CEPH_MDS_OP_LOOKUP 
                                                   // head.args.getattr.mask = CEPH_STAT_CAP_INODE_ALL
  filepath path, path2;                            // path.ino = 0x1000012(父目录test的inode号), path.path = "test1"
  ......
  ceph::cref_t<MClientReply> reply;                // the reply
  InodeRef target;                                 // target是创建的目录的Inode指针,从mds的回复中组装而成。
}

MClientRequest

class MClientRequest : public Message {
public:
  mutable struct ceph_mds_request_head head;   // head.op = CEPH_MDS_OP_LOOKUP
                                               // head.args.getattr.mask = CEPH_STAT_CAP_INODE_ALL
  // path arguments
  filepath path, path2;             // path.ino = 0x1000012, path.path = "test1"
  ......
}   

收到的回复内容

class MClientReply : public Message {
public:
  // reply data
  struct ceph_mds_reply_head head {};
      /* client reply */
    struct ceph_mds_reply_head {
            ......
	    __u8 is_dentry, is_target;     /* true if dentry, target inode records are included with reply; is_dentry = 1, is_target = 1*/
    } 
  bufferlist trace_bl;                // trace_bl里面存着真正的信息,用于更新目的inode和父目录inode
}

处理回复的流程和之前mkdir的差不多。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值