首页 > 其他 > 详细

从handle_client_mkdir函数操作来分析MDlog与LogSegment过程

时间:2015-10-30 12:28:14      阅读:1209      评论:0      收藏:0      [点我收藏+]

首先看下handle_client_mkdir函数内容

// MKDIR
/* This function takes responsibility for the passed mdr*/
void Server::handle_client_mkdir(MDRequestRef& mdr)
{
  MClientRequest *req = mdr->client_request;
  set<SimpleLock*> rdlocks, wrlocks, xlocks;
  CDentry *dn = rdlock_path_xlock_dentry(mdr, 0, rdlocks, wrlocks, xlocks, false, false, false);  //获取该directory的目录项
  if (!dn) return;
  if (mdr->snapid != CEPH_NOSNAP) {
    respond_to_request(mdr, -EROFS);
    return;
  }
  CInode *diri = dn->get_dir()->get_inode();
  rdlocks.insert(&diri->authlock);
  if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
    return;

  // new inode
  SnapRealm *realm = dn->get_dir()->inode->find_snaprealm();
  snapid_t follows = realm->get_newest_seq();

  unsigned mode = req->head.args.mkdir.mode;
  mode &= ~S_IFMT;
  mode |= S_IFDIR;
  CInode *newi = prepare_new_inode(mdr, dn->get_dir(), inodeno_t(req->head.ino), mode);    //创建该dir的新节点newi
  assert(newi);

  // it‘s a directory.
  dn->push_projected_linkage(newi);

  newi->inode.version = dn->pre_dirty();
  newi->inode.rstat.rsubdirs = 1;
  newi->inode.update_backtrace();

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

  // ...and that new dir is empty.
  CDir *newdir = newi->get_or_open_dirfrag(mds->mdcache, frag_t());      //获取或创建newdir 
  newdir->mark_complete();
  newdir->fnode.version = newdir->pre_dirty();

  // prepare finisher
 // 以下工作为将上面的改变记入日志MDlog中 mdr->ls = mdlog->get_current_segment(); EUpdate *le = new EUpdate(mdlog, "mkdir"); //为类EUpdate对象le分配空间并记录到mdlog此操作为mkdir mdlog->start_entry(le); //找到将要写入日志的起始地址 le->metablob.add_client_req(req->get_reqid(), req->get_oldest_client_tid()); //将req加入到用于记录客户端请求的pair容器中;metablob类注释为a bunch of metadata in the journal (日志中的一堆元数据) journal_allocated_inos(mdr, &le->metablob); //为inode的成员变量赋予对应的值 mdcache->predirty_journal_parents(mdr, &le->metablob, newi, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1); //为将当前目录的目录项标记为脏 le->metablob.add_primary_dentry(dn, newi, true, true); //将此inode的目录项加入到链表lump中,该链表记录相关的dentry+inode,并标记此inode was last journaled le->metablob.add_new_dir(newdir); // dirty AND complete AND new //标记newdir为dirty AND complete AND new // issue a cap on the directory int cmode = CEPH_FILE_MODE_RDWR; //赋予其读写权限 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); cap->issue_norevoke(CEPH_CAP_AUTH_EXCL|CEPH_CAP_AUTH_SHARED| CEPH_CAP_XATTR_EXCL|CEPH_CAP_XATTR_SHARED); } // make sure this inode gets into the journal le->metablob.add_opened_ino(newi->ino()); //将newi的ino赋予类emetablob中的opened_ino LogSegment *ls = mds->mdlog->get_current_segment(); ls->open_files.push_back(&newi->item_open_file);  //将newi添加到ls->open_files链表 journal_and_reply(mdr, newi, dn, le, new C_MDS_mknod_finish(mds, mdr, dn, newi, follows)); //见下边的函数 }

注意emetablob类用来存储要写入日志的元数据。

以下为journal_and_reply函数

/*******
 * some generic stuff for finishing off requests
 */
void Server::journal_and_reply(MDRequestRef& mdr, CInode *in, CDentry *dn, LogEvent *le, MDSInternalContextBase *fin)
{
  dout(10) << "journal_and_reply tracei " << in << " tracedn " << dn << dendl;

  // note trace items for eventual reply.
  mdr->tracei = in;
  if (in)
    mdr->pin(in);

  mdr->tracedn = dn;
  if (dn)
    mdr->pin(dn);

  early_reply(mdr, in, dn);   //此函数判断一些条件若符合则将mdlog刷出并返回,否则进行reply
  
  mdr->committing = true;
  submit_mdlog_entry(le, fin, mdr, __func__);
  
  if (mdr->client_request && mdr->client_request->is_replay()) {
    if (mds->queue_one_replay()) {         //若队列不为空则排队
      dout(10) << " queued next replay op" << dendl;
    } else {          //队列为空则将mdlog刷出
      dout(10) << " journaled last replay op, flushing" << dendl;
      mdlog->flush();
    }
  } else if (mdr->did_early_reply)      //若执行了early_reply则drop_rdlocks
    mds->locker->drop_rdlocks(mdr.get());
  else        //以上不符合则将mdlog刷出
    mdlog->flush();
}

最终将mdlog刷出。

从handle_client_mkdir函数操作来分析MDlog与LogSegment过程

原文:http://www.cnblogs.com/noblemore/p/4922845.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!