Ceph MDS处理客户端创建目录操作源码分析

Ceph版本:14.2.22

 

Server::handle_client_mkdir


文件路径:ceph/src/mds/Server.cc

当客户端发送创建目录文件请求到mds服务端时,mds会根据客户端请求类型,执行Server::handle_client_mkdir函数;该函数主要实现以下功能:

  • 从mdr中解析出客户端请求;
  • 从客户端请求中解析出将要创建的目录文件是否是隐藏文件,是则终止流程,否则继续流程;
  • 根据将要创建的目录文件路径构造出该目录的CDentry;
  • 为将要创建的目录文件构造新的CInode,并填充CInode信息;
void Server::handle_client_mkdir(MDRequestRef &mdr)
{
    //获取客户端请求
    const MClientRequest::const_ref &req = mdr->client_request;

    //如果新建的目录是.或者..隐藏目录,直接返回
    if (req->get_filepath().is_last_dot_or_dotdot())
    {
        respond_to_request(mdr, -EEXIST);
        return;
    }

    MutationImpl::LockOpVec lov;
    //根据目录路径解析出本级目录关联的CDentry,并对父目录和本级目录的相关联的结构加锁
    CDentry *dn = rdlock_path_xlock_dentry(mdr, 0, lov, false, false, false);

    if (!dn)
        return;

    if (mdr->snapid != CEPH_NOSNAP)
    {
        respond_to_request(mdr, -EROFS);
        return;
    }

    //获取父级目录CDir
    CDir *dir = dn->get_dir();

    //获取父级目录CInode
    CInode *diri = dir->get_inode();

    //对父级目录CInode的authlock锁加读操作锁
    lov.add_rdlock(&diri->authlock);

    //加锁是否成功?
    if (!mds->locker->acquire_locks(mdr, lov))
        return;

    // mkdir check access
    //检查客户端对父级目录是否有写权限
    if (!check_access(mdr, diri, MAY_WRITE))
        return;

    //检查父级目录的分片大小是否足够
    if (!check_fragment_space(mdr, dir))
        return;

    // new inode
    unsigned mode = req->head.args.mkdir.mode;
    mode &= ~S_IFMT;
    mode |= S_IFDIR;

    //创建本级目录CInode,inode号与req->head.ino绑定
    CInode *newi = prepare_new_inode(mdr, dn->get_dir(), inodeno_t(req->head.ino), mode);
    ceph_assert(newi);

    // it's a directory.
    //将本级目录关联的CDentry与本级目录CInode建立链接关系
    dn->push_projected_linkage(newi);

    //填充本级目录CInode内容
    newi->inode.version = dn->pre_dirty();
    newi->inode.rstat.rsubdirs = 1;
    newi->inode.update_backtrace();

    snapid_t follows = mdcache->get_global_snaprealm()->get_newest_seq();
    SnapRealm *realm = dn->get_dir()->inode->find_snaprealm();
    ceph_assert(follows >= realm->get_newest_seq());

    dout(12) << " follows " << follows << dendl;
    ceph_assert(dn->first == follows + 1);
    newi->first = dn->first;

    // ...and that new dir is empty.
    //创建本级目录CDir
    CDir *newdir = newi->get_or_open_dirfrag(mdcache, frag_t());

    //填充本级目录CDir内容
    newdir->state_set(CDir::STATE_CREATING);
    newdir->mark_complete();
    newdir->fnode.version = newdir->pre_dirty();

    // prepare finisher
    //获取log分片
    mdr->ls = mdlog->get_current_segment();

    //创建一个新的log事件
    EUpdate *le = new EUpdate(mdlog, "mkdir");

    //启动log事件
    mdlog->start_entry(le);

    //将客户端ID添加到log事件中
    le->metablob.add_client_req(req->get_reqid(), req->get_oldest_client_tid());

    journal_allocated_inos(mdr, &le->metablob);

    mdcache->predirty_journal_parents(mdr, &le->metablob, newi, dn->get_dir(), PREDIRTY_PRIMARY | PREDIRTY_DIR, 1);

    //将本级目录关联的Dentry添加到log事件中
    le->metablob.add_primary_dentry(dn, newi, true, true);

    //将本级目录CDir添加到log事件中
    le->metablob.add_new_dir(newdir); // dirty AND complete AND new

    // issue a cap on the directory
    int cmode = CEPH_FILE_MODE_RDWR;

    //获取新的Capability
    Capability *cap = mds->locker->issue_new_caps(newi, cmode, mdr->session, realm, req->is_replay());
    if (cap)
    {
      cap->set_wanted(0);

      // put locks in excl mode
      newi->filelock.set_state(LOCK_EXCL);
      newi->authlock.set_state(LOCK_EXCL);
      newi->xattrlock.set_state(LOCK_EXCL);
    }

    // make sure this inode gets into the journal
    //将当前目录CInode的序号添加到log事件中
    le->metablob.add_opened_ino(newi->ino());

    //处理日志
    journal_and_reply(mdr, newi, dn, le, new C_MDS_mknod_finish(this, mdr, dn, newi));

    // We hit_dir (via hit_inode) in our finish callback, but by then we might
    // have overshot the split size (multiple mkdir in flight), so here is
    // an early chance to split the dir if this mkdir makes it oversized.

    //判断父级目录CDir是否需要被分片
    mds->balancer->maybe_fragment(dir, false);
}

由于时间问题,文章还在努力完善中…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ceph是一个开的分布式存储系统,它提供了可扩展的对象存储、块存储和文件系统。Ceph MDS(Metadata Server)是Ceph文件系统(CephFS)的组件之一,负责管理文件系统的元数据。 Ceph MDS软件包包含了一组用于构建和管理Ceph MDS的工具和库。它提供了以下功能: 1. 元数据服务器(MDS):Ceph MDS软件包中的主要组件是元数据服务器,它负责管理Ceph文件系统的元数据。MDS将文件系统的目录结构、文件属性和权限等信息存储在内存中,并提供对文件系统的元数据操作接口。 2. 元数据池(Metadata Pool):Ceph MDS使用元数据池来存储文件系统的元数据。元数据池是一个特殊的Ceph对象存储池,用于存储文件和目录的元数据信息。 3. 元数据缓存(Metadata Cache):为了提高性能,Ceph MDS使用元数据缓存来缓存最常访问的文件和目录的元数据。元数据缓存可以减少对元数据服务器的访问次数,加快文件系统的访问速度。 4. 元数据日志(Metadata Journal):Ceph MDS使用元数据日志来记录文件系统的元数据变更操作。元数据日志可以用于恢复文件系统的一致性,并提供了高可靠性和高性能的元数据操作。 5. 元数据负载均衡(Metadata Load Balancing):Ceph MDS使用负载均衡算法来平衡不同元数据服务器之间的负载,确保文件系统的高可用性和性能。 总结来说,Ceph MDS软件包提供了构建和管理Ceph文件系统的必要组件和功能,包括元数据服务器、元数据池、元数据缓存、元数据日志和负载均衡等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值