📄 statahead.c
字号:
minfo->mi_generation, (unsigned int)(long)minfo->mi_cbdata); ll_sai_put(sai); }out_free: ll_intent_release(it); OBD_FREE_PTR(minfo); dput(dentry); return rc;}static void sa_args_fini(struct md_enqueue_info *minfo, struct ldlm_enqueue_info *einfo){ LASSERT(minfo && einfo); OBD_FREE_PTR(minfo); OBD_FREE_PTR(einfo);}static int sa_args_prep(struct inode *dir, struct dentry *dentry, struct md_enqueue_info **pmi, struct ldlm_enqueue_info **pei){ struct ll_inode_info *lli = ll_i2info(dir); struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; OBD_ALLOC_PTR(einfo); if (einfo == NULL) return -ENOMEM; OBD_ALLOC_PTR(minfo); if (minfo == NULL) { OBD_FREE_PTR(einfo); return -ENOMEM; } minfo->mi_exp = ll_i2mdcexp(dir); minfo->mi_it.it_op = IT_GETATTR; minfo->mi_dentry = dentry; minfo->mi_cb = ll_statahead_interpret; minfo->mi_generation = lli->lli_sai->sai_generation; minfo->mi_cbdata = (void *)(long)lli->lli_sai->sai_index; einfo->ei_type = LDLM_IBITS; einfo->ei_mode = it_to_lock_mode(&minfo->mi_it); einfo->ei_cb_bl = ll_mdc_blocking_ast; einfo->ei_cb_cp = ldlm_completion_ast; einfo->ei_cb_gl = NULL; einfo->ei_cbdata = NULL; *pmi = minfo; *pei = einfo; return 0;}/* similar to ll_lookup_it(). */static int do_sa_lookup(struct inode *dir, struct dentry *dentry){ struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; int rc; ENTRY; rc = sa_args_prep(dir, dentry, &minfo, &einfo); if (rc) RETURN(rc); rc = ll_prepare_mdc_op_data(&minfo->mi_data, dir, NULL, dentry->d_name.name, dentry->d_name.len, 0, NULL); if (rc == 0) rc = mdc_intent_getattr_async(minfo->mi_exp, minfo, einfo); if (rc) sa_args_fini(minfo, einfo); RETURN(rc);}/* * similar to ll_revalidate_it(). * return value: * 1 -- dentry valid * 0 -- will send stat-ahead request * others -- prepare stat-ahead request failed */static int do_sa_revalidate(struct dentry *dentry){ struct inode *inode = dentry->d_inode; struct ll_fid fid; struct lookup_intent it = { .it_op = IT_GETATTR }; struct md_enqueue_info *minfo; struct ldlm_enqueue_info *einfo; int rc; ENTRY; if (inode == NULL) RETURN(1); if (d_mountpoint(dentry)) RETURN(1); if (dentry == dentry->d_sb->s_root) RETURN(1); ll_inode2fid(&fid, inode); rc = mdc_revalidate_lock(ll_i2mdcexp(inode), &it, &fid); if (rc == 1) { ll_intent_release(&it); RETURN(1); } rc = sa_args_prep(dentry->d_parent->d_inode, dentry, &minfo, &einfo); if (rc) RETURN(rc); rc = ll_prepare_mdc_op_data(&minfo->mi_data, dentry->d_parent->d_inode, inode, dentry->d_name.name, dentry->d_name.len, 0, NULL); if (rc == 0) rc = mdc_intent_getattr_async(minfo->mi_exp, minfo, einfo); if (rc) sa_args_fini(minfo, einfo); RETURN(rc);}static inline void ll_name2qstr(struct qstr *this, const char *name, int namelen){ unsigned long hash = init_name_hash(); unsigned int c; this->name = name; this->len = namelen; for (; namelen > 0; namelen--, name++) { c = *(const unsigned char *)name; hash = partial_name_hash(c, hash); } this->hash = end_name_hash(hash);}static int ll_statahead_one(struct dentry *parent, ext2_dirent *de){ struct inode *dir = parent->d_inode; struct ll_inode_info *lli = ll_i2info(dir); struct qstr name; struct dentry *dentry; struct ll_sai_entry *se; int rc; ENTRY;#ifdef DCACHE_LUSTRE_INVALID if (parent->d_flags & DCACHE_LUSTRE_INVALID) {#else if (d_unhashed(parent)) {#endif CDEBUG(D_READA, "parent dentry@%p %.*s is " "invalid, skip statahead\n", parent, parent->d_name.len, parent->d_name.name); RETURN(-EINVAL); } se = ll_sai_entry_get(lli->lli_sai, lli->lli_sai->sai_index, SA_ENTRY_UNSTATED); if (IS_ERR(se)) RETURN(PTR_ERR(se)); ll_name2qstr(&name, de->name, de->name_len); dentry = d_lookup(parent, &name); if (!dentry) { dentry = d_alloc(parent, &name); if (dentry) { rc = do_sa_lookup(dir, dentry); if (rc) dput(dentry); } else { GOTO(out, rc = -ENOMEM); } } else { rc = do_sa_revalidate(dentry); if (rc) dput(dentry); } EXIT;out: if (rc) { CDEBUG(D_READA, "set sai entry %p index %u stat %d rc %d\n", se, se->se_index, se->se_stat, rc); se->se_stat = rc; cfs_waitq_signal(&lli->lli_sai->sai_waitq); } else { lli->lli_sai->sai_sent++; } lli->lli_sai->sai_index++; return rc;} static inline int sa_check_stop(struct ll_statahead_info *sai){ return !!(sai->sai_thread.t_flags & SVC_STOPPING);}static inline int sa_not_full(struct ll_statahead_info *sai){ return sai->sai_index < sai->sai_hit + sai->sai_miss + sai->sai_max;}/* (1) hit ratio less than 80% * or * (2) consecutive miss more than 8 */static inline int sa_low_hit(struct ll_statahead_info *sai){ return ((sai->sai_hit < 4 * sai->sai_miss && sai->sai_hit > 7) || (sai->sai_consecutive_miss > 8));}struct ll_sa_thread_args { struct dentry *sta_parent; pid_t sta_pid;};static int ll_statahead_thread(void *arg){ struct ll_sa_thread_args *sta = arg; struct dentry *parent = dget(sta->sta_parent); struct inode *dir = parent->d_inode; struct ll_inode_info *lli = ll_i2info(dir); struct ll_sb_info *sbi = ll_i2sbi(dir); struct ll_statahead_info *sai = ll_sai_get(lli->lli_sai); struct ptlrpc_thread *thread = &sai->sai_thread; unsigned long index = 0; int first = 0; int rc = 0; char name[16] = ""; ENTRY; sbi->ll_sa_total++; snprintf(name, 15, "ll_sa_%u", sta->sta_pid); cfs_daemonize(name); spin_lock(&lli->lli_lock); thread->t_flags = SVC_RUNNING; spin_unlock(&lli->lli_lock); cfs_waitq_signal(&thread->t_ctl_waitq); CDEBUG(D_READA, "start doing statahead for %s\n", parent->d_name.name); while (1) { struct l_wait_info lwi = { 0 }; unsigned long npages; char *kaddr, *limit; ext2_dirent *de; struct page *page; npages = dir_pages(dir); /* reach the end of dir */ if (index >= npages) { CDEBUG(D_READA, "reach end, index/npages %lu/%lu\n", index, npages); break; } page = ll_get_dir_page(dir, index); if (IS_ERR(page)) { rc = PTR_ERR(page); CERROR("error reading dir %lu/%u page %lu/%u: rc %d\n", dir->i_ino, dir->i_generation, index, sai->sai_index, rc); break; } kaddr = page_address(page); limit = kaddr + CFS_PAGE_SIZE - EXT2_DIR_REC_LEN(1); de = (ext2_dirent *)kaddr; if (!index) { de = ext2_next_entry(de); /* skip "." */ de = ext2_next_entry(de); /* skip ".." */ } for (; (char*)de <= limit; de = ext2_next_entry(de)) { if (!de->inode) continue; if (de->name[0] == '.' && !sai->sai_ls_all) { /* skip hidden files */ sai->sai_skip_hidden++; continue; } /* don't stat-ahead first entry */ if (unlikely(!first)) { first++; continue; } l_wait_event(thread->t_ctl_waitq, sa_check_stop(sai) || sa_not_full(sai), &lwi); if (unlikely(sa_check_stop(sai))) { ext2_put_page(page); GOTO(out, rc); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -