⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statahead.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 3 页
字号:
                        rc = ll_statahead_one(parent, de);                        if (rc < 0) {                                ext2_put_page(page);                                GOTO(out, rc);                        }                }                ext2_put_page(page);                index++;        }        EXIT;out:        spin_lock(&lli->lli_lock);        thread->t_flags = SVC_STOPPED;        spin_unlock(&lli->lli_lock);        cfs_waitq_signal(&sai->sai_waitq);        cfs_waitq_signal(&thread->t_ctl_waitq);        ll_sai_put(sai);        dput(parent);        CDEBUG(D_READA, "statahead thread stopped, pid %d\n",               cfs_curproc_pid());        return rc;}/* called in ll_file_release() */void ll_stop_statahead(struct inode *inode, void *key){        struct ll_inode_info *lli = ll_i2info(inode);        struct ptlrpc_thread *thread;        spin_lock(&lli->lli_lock);        if (lli->lli_opendir_pid == 0 ||            unlikely(lli->lli_opendir_key != key)) {                spin_unlock(&lli->lli_lock);                return;        }        lli->lli_opendir_key = NULL;        lli->lli_opendir_pid = 0;        if (lli->lli_sai) {                struct l_wait_info lwi = { 0 };                thread = &lli->lli_sai->sai_thread;                if (!(thread->t_flags & SVC_STOPPED)) {                        thread->t_flags = SVC_STOPPING;                        spin_unlock(&lli->lli_lock);                        cfs_waitq_signal(&thread->t_ctl_waitq);                        CDEBUG(D_READA, "stopping statahead thread, pid %d\n",                               cfs_curproc_pid());                        l_wait_event(thread->t_ctl_waitq,                                     thread->t_flags & SVC_STOPPED,                                     &lwi);                } else {                        spin_unlock(&lli->lli_lock);                }                /*                 * Put the ref which was held when first statahead_enter.                 * It maybe not the last ref for some statahead requests                 * maybe inflight.                 */                ll_sai_put(lli->lli_sai);                return;        }        spin_unlock(&lli->lli_lock);}enum {        LS_NONE_FIRST_DE = 0,   /* not first dirent, or is "." */        LS_FIRST_DE,            /* the first non-hidden dirent */        LS_FIRST_DOT_DE         /* the first hidden dirent, that is ".xxx" */};static int is_first_dirent(struct inode *dir, struct dentry *dentry){        struct qstr   *d_name = &dentry->d_name;        unsigned long  npages, index = 0;        struct page   *page;        ext2_dirent   *de;        char          *kaddr, *limit;        int            rc = LS_NONE_FIRST_DE, dot_de;        ENTRY;        while (1) {                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: rc %d\n",                               dir->i_ino, dir->i_generation, 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] == '.')                                dot_de = 1;                        else                                dot_de = 0;                        if (dot_de && d_name->name[0] != '.') {                                CDEBUG(D_READA, "%.*s skip hidden file %.*s\n",                                       d_name->len, d_name->name,                                       de->name_len, de->name);                                continue;                        }                        if (d_name->len == de->name_len &&                            !strncmp(d_name->name, de->name, d_name->len))                                rc = LS_FIRST_DE + dot_de;                        else                                rc = LS_NONE_FIRST_DE;                        ext2_put_page(page);                        RETURN(rc);                }                ext2_put_page(page);                index++;        }        RETURN(rc);}/* Start statahead thread if this is the first dir entry. * Otherwise if a thread is started already, wait it until it is ahead of me. * Return value:  *  0       -- miss *  1       -- hit *  -EEXIST -- stat ahead thread started, and this is the first dentry *  -EBADFD -- statahead thread exit and not dentry available *  others  -- error */int do_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup){        struct ll_sb_info        *sbi = ll_i2sbi(dir);        struct ll_inode_info     *lli = ll_i2info(dir);        struct ll_statahead_info *sai = lli->lli_sai;        struct ll_sa_thread_args  sta;        struct l_wait_info        lwi = { 0 };        int                       rc;        ENTRY;        LASSERT(lli->lli_opendir_pid == cfs_curproc_pid());        if (sai) {                if (unlikely(sai->sai_thread.t_flags & SVC_STOPPED &&                             list_empty(&sai->sai_entries)))                        RETURN(-EBADFD);                if ((*dentryp)->d_name.name[0] == '.') {                        if (likely(sai->sai_ls_all ||                            sai->sai_miss_hidden >= sai->sai_skip_hidden)) {                                /*                                 * Hidden dentry is the first one, or statahead                                 * thread does not skip so many hidden dentries                                 * before "sai_ls_all" enabled as below.                                 */                        } else {                                if (!sai->sai_ls_all)                                        /*                                         * It maybe because hidden dentry is not                                         * the first one, "sai_ls_all" was not                                         * set, then "ls -al" missed. Enable                                         * "sai_ls_all" for such case.                                         */                                        sai->sai_ls_all = 1;                                /*                                 * Such "getattr" has been skipped before                                 * "sai_ls_all" enabled as above.                                 */                                sai->sai_miss_hidden++;                                RETURN(-ENOENT);                        }                }                if (ll_sai_entry_stated(sai)) {                        sbi->ll_sa_cached++;                } else {                        sbi->ll_sa_blocked++;                        /* thread started already, avoid double-stat */                        l_wait_event(sai->sai_waitq,                                     ll_sai_entry_stated(sai) ||                                     sai->sai_thread.t_flags & SVC_STOPPED,                                     &lwi);                }                if (lookup) {                        struct dentry *result;                        result = d_lookup((*dentryp)->d_parent,                                          &(*dentryp)->d_name);                        if (result) {                                LASSERT(result != *dentryp);                                dput(*dentryp);                                *dentryp = result;                                RETURN(1);                        }                }                /* do nothing for revalidate */                RETURN(0);        }         /* I am the "lli_opendir_pid" owner, only me can set "lli_sai". */         LASSERT(lli->lli_sai == NULL);        rc = is_first_dirent(dir, *dentryp);        if (rc == LS_NONE_FIRST_DE) {                /* It is not "ls -{a}l" operation, no need statahead for it */                spin_lock(&lli->lli_lock);                lli->lli_opendir_key = NULL;                lli->lli_opendir_pid = 0;                spin_unlock(&lli->lli_lock);                RETURN(-EBADF);        }        sai = ll_sai_alloc();        if (sai == NULL)                RETURN(-ENOMEM);                sai->sai_inode  = igrab(dir);        sai->sai_ls_all = (rc == LS_FIRST_DOT_DE);        sta.sta_parent = (*dentryp)->d_parent;        sta.sta_pid    = cfs_curproc_pid();        lli->lli_sai = sai;        rc = cfs_kernel_thread(ll_statahead_thread, &sta, 0);        if (rc < 0) {                CERROR("can't start ll_sa thread, rc: %d\n", rc);                sai->sai_thread.t_flags = SVC_STOPPED;                ll_sai_put(sai);                LASSERT(lli->lli_sai == NULL);                RETURN(rc);        }        l_wait_event(sai->sai_thread.t_ctl_waitq,                      sai->sai_thread.t_flags & (SVC_RUNNING | SVC_STOPPED),                     &lwi);        /*         * We don't stat-ahead for the first dirent since we are already in         * lookup, and -EEXIST also indicates that this is the first dirent.         */        RETURN(-EEXIST);}/* update hit/miss count */void ll_statahead_exit(struct dentry *dentry, int result){        struct dentry         *parent = dentry->d_parent;        struct ll_inode_info  *lli = ll_i2info(parent->d_inode);        struct ll_sb_info     *sbi = ll_i2sbi(parent->d_inode);        struct ll_dentry_data *ldd = ll_d2d(dentry);        if (lli->lli_opendir_pid != cfs_curproc_pid())                return;        if (lli->lli_sai) {                struct ll_statahead_info *sai = lli->lli_sai;                if (result == 1) {                        sbi->ll_sa_hit++;                        sai->sai_hit++;                        sai->sai_consecutive_miss = 0;                        sai->sai_max = min(2 * sai->sai_max, sbi->ll_sa_max);                } else {                        sbi->ll_sa_miss++;                        sai->sai_miss++;                        sai->sai_consecutive_miss++;                        if (sa_low_hit(sai) &&                            sai->sai_thread.t_flags & SVC_RUNNING) {                                sbi->ll_sa_wrong++;                                CDEBUG(D_READA, "statahead for dir %.*s hit "                                       "ratio too low: hit/miss %u/%u, "                                       "sent/replied %u/%u. stopping statahead "                                       "thread: pid %d\n",                                       parent->d_name.len, parent->d_name.name,                                       sai->sai_hit, sai->sai_miss,                                       sai->sai_sent, sai->sai_replied,                                       cfs_curproc_pid());                                spin_lock(&lli->lli_lock);                                if (!(sai->sai_thread.t_flags & SVC_STOPPED))                                        sai->sai_thread.t_flags = SVC_STOPPING;                                spin_unlock(&lli->lli_lock);                        }                }                cfs_waitq_signal(&sai->sai_thread.t_ctl_waitq);                ll_sai_entry_put(sai);                if (likely(ldd != NULL))                        ldd->lld_sa_generation = sai->sai_generation;        }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -