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

📄 statahead.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * *  Copyright (c) 2007 Cluster File Systems, Inc. * *   This file is part of Lustre, http://www.lustre.org. * *   Lustre is free software; you can redistribute it and/or *   modify it under the terms of version 2 of the GNU General Public *   License as published by the Free Software Foundation. * *   Lustre is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with Lustre; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/fs.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <linux/highmem.h>#include <linux/pagemap.h>#define DEBUG_SUBSYSTEM S_LLITE#include <obd_support.h>#include <lustre_lite.h>#include <lustre_dlm.h>#include <linux/lustre_version.h>#include "llite_internal.h"struct ll_sai_entry {        struct list_head        se_list;        unsigned int            se_index;        int                     se_stat;};enum {        SA_ENTRY_UNSTATED = 0,        SA_ENTRY_STATED};static unsigned int sai_generation = 0;static spinlock_t sai_generation_lock = SPIN_LOCK_UNLOCKED;static struct ll_statahead_info *ll_sai_alloc(void){        struct ll_statahead_info *sai;        OBD_ALLOC_PTR(sai);        if (!sai)                return NULL;        spin_lock(&sai_generation_lock);        sai->sai_generation = ++sai_generation;        if (unlikely(sai_generation == 0))                sai->sai_generation = ++sai_generation;        spin_unlock(&sai_generation_lock);        atomic_set(&sai->sai_refcount, 1);        sai->sai_max = LL_SA_RPC_MIN;        cfs_waitq_init(&sai->sai_waitq);        cfs_waitq_init(&sai->sai_thread.t_ctl_waitq);        CFS_INIT_LIST_HEAD(&sai->sai_entries);        return sai;}static inline struct ll_statahead_info *ll_sai_get(struct ll_statahead_info *sai){        LASSERT(sai);        atomic_inc(&sai->sai_refcount);        return sai;}static void ll_sai_put(struct ll_statahead_info *sai){        struct inode         *inode = sai->sai_inode;        struct ll_inode_info *lli = ll_i2info(inode);        ENTRY;        if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_lock)) {                struct ll_sai_entry *entry, *next;                lli->lli_sai = NULL;                spin_unlock(&lli->lli_lock);                LASSERT(sai->sai_thread.t_flags & SVC_STOPPED);                if (sai->sai_sent > sai->sai_replied)                        CDEBUG(D_READA,"statahead for dir %lu/%u does not "                              "finish: [sent:%u] [replied:%u]\n",                              inode->i_ino, inode->i_generation,                              sai->sai_sent, sai->sai_replied);                list_for_each_entry_safe(entry, next, &sai->sai_entries,                                         se_list) {                        list_del(&entry->se_list);                        OBD_FREE_PTR(entry);                }                OBD_FREE_PTR(sai);                iput(inode);        }        EXIT;}static struct ll_sai_entry *ll_sai_entry_get(struct ll_statahead_info *sai, unsigned int index, int stat){        struct ll_inode_info *lli = ll_i2info(sai->sai_inode);        struct ll_sai_entry  *entry;        ENTRY;        OBD_ALLOC_PTR(entry);        if (entry == NULL)                RETURN(ERR_PTR(-ENOMEM));                CDEBUG(D_READA, "alloc sai entry %p index %u, stat %d\n",               entry, index, stat);        entry->se_index = index;        entry->se_stat  = stat;        spin_lock(&lli->lli_lock);        list_add_tail(&entry->se_list, &sai->sai_entries);        spin_unlock(&lli->lli_lock);        RETURN(entry);}/* * inside lli_lock * return value: *  0: can not find the entry with the index *  1: it is the first entry *  2: it is not the first entry */static intll_sai_entry_set(struct ll_statahead_info *sai, unsigned int index, int stat){        struct ll_sai_entry *entry;        int                  rc = 0;        ENTRY;        if (list_empty(&sai->sai_entries))                RETURN(0);        entry = list_entry(sai->sai_entries.next, struct ll_sai_entry, se_list);        if (entry->se_index == index)                GOTO(out, rc = 1);        while (entry->se_list.next != &sai->sai_entries &&               entry->se_index < index) {                entry = list_entry(entry->se_list.next, struct ll_sai_entry,                                   se_list);                if (entry->se_index == index)                        GOTO(out, rc = 2);        }        EXIT;out:        if (rc) {                LASSERT(entry->se_stat == SA_ENTRY_UNSTATED);                entry->se_stat = stat;        }        return rc;}/* * Check whether first entry was stated already or not. * No need to hold lli_lock, for: * (1) it is me that remove entry from the list * (2) the statahead thread only add new entry to the list tail */static int ll_sai_entry_stated(struct ll_statahead_info *sai){        struct ll_sai_entry  *entry;        int                   rc = 0;        ENTRY;        if (!list_empty(&sai->sai_entries)) {                entry = list_entry(sai->sai_entries.next, struct ll_sai_entry,                                   se_list);                rc = (entry->se_stat != SA_ENTRY_UNSTATED);        }        RETURN(rc);}static void ll_sai_entry_put(struct ll_statahead_info *sai){        struct ll_inode_info *lli = ll_i2info(sai->sai_inode);        struct ll_sai_entry  *entry;        ENTRY;                spin_lock(&lli->lli_lock);        if (!list_empty(&sai->sai_entries)) {                entry = list_entry(sai->sai_entries.next,                                   struct ll_sai_entry, se_list);                list_del(&entry->se_list);                OBD_FREE_PTR(entry);        }        spin_unlock(&lli->lli_lock);        EXIT;}/* finish lookup/revalidate */static int ll_statahead_interpret(struct obd_export *exp,                                  struct ptlrpc_request *req,                                  struct md_enqueue_info *minfo,                                  int rc){        struct lookup_intent     *it = &minfo->mi_it;        struct dentry            *dentry = minfo->mi_dentry;        struct inode             *dir = dentry->d_parent->d_inode;        struct ll_inode_info     *lli = ll_i2info(dir);        struct ll_statahead_info *sai = NULL;        ENTRY;        CDEBUG(D_READA, "interpret statahead %.*s rc %d\n",               dentry->d_name.len, dentry->d_name.name, rc);        spin_lock(&lli->lli_lock);        if (unlikely(lli->lli_sai == NULL ||            lli->lli_sai->sai_generation != minfo->mi_generation)) {                spin_unlock(&lli->lli_lock);                GOTO(out_free, rc = -ESTALE);        } else {                sai = ll_sai_get(lli->lli_sai);                spin_unlock(&lli->lli_lock);        }        if (rc || dir == NULL)                GOTO(out, rc);        if (dentry->d_inode == NULL) {                /* lookup */                struct dentry    *save = dentry;                struct it_cb_data icbd = {                        .icbd_parent   = dir,                        .icbd_childp   = &dentry                };                rc = lookup_it_finish(req, DLM_REPLY_REC_OFF, it, &icbd);                if (!rc)                        /*                          * Here dentry->d_inode might be NULL,                         * because the entry may have been removed before                         * we start doing stat ahead.                         */                        ll_lookup_finish_locks(it, dentry);                if (dentry != save)                        dput(save);        } else {                /* revalidate */                struct mds_body *body;                body = lustre_msg_buf(req->rq_repmsg, DLM_REPLY_REC_OFF,                                      sizeof(*body));                if (memcmp(&minfo->mi_data.fid2, &body->fid1,                           sizeof(body->fid1))) {                        ll_unhash_aliases(dentry->d_inode);                        GOTO(out, rc = -EAGAIN);                }                rc = revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, dentry);                if (rc) {                        ll_unhash_aliases(dentry->d_inode);                        GOTO(out, rc);                }                spin_lock(&dcache_lock);                lock_dentry(dentry);                __d_drop(dentry);#ifdef DCACHE_LUSTRE_INVALID                dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;#endif                unlock_dentry(dentry);                d_rehash_cond(dentry, 0);                spin_unlock(&dcache_lock);                ll_lookup_finish_locks(it, dentry);        }        EXIT;out:        if (sai != NULL) {                int first;                sai->sai_replied++;                spin_lock(&lli->lli_lock);                first = ll_sai_entry_set(sai,                                         (unsigned int)(long)minfo->mi_cbdata,                                         SA_ENTRY_STATED);                /*                 * wake up the "ls -l" process only when the first entry                 * returned.                 */                spin_unlock(&lli->lli_lock);                if (first == 1)                        cfs_waitq_signal(&sai->sai_waitq);                else if (first == 0)                        CDEBUG(D_READA, "can't find sai entry for dir "                               "%lu/%u generation %u index %d\n",                               dir->i_ino, dir->i_generation,

⌨️ 快捷键说明

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