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

📄 namei.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 4 页
字号:
static void ll_d_add(struct dentry *de, struct inode *inode){        CDEBUG(D_DENTRY, "adding inode %p to dentry %p\n", inode, de);        /* d_instantiate */        if (!list_empty(&de->d_alias)) {                spin_unlock(&dcache_lock);                CERROR("dentry %.*s %p alias next %p, prev %p\n",                       de->d_name.len, de->d_name.name, de,                       de->d_alias.next, de->d_alias.prev);                LBUG();        }        if (inode)                list_add(&de->d_alias, &inode->i_dentry);        de->d_inode = inode;        /* d_rehash */        if (!d_unhashed(de)) {                spin_unlock(&dcache_lock);                CERROR("dentry %.*s %p hash next %p\n",                       de->d_name.len, de->d_name.name, de, de->d_hash.next);                LBUG();        }        d_rehash_cond(de, 0);}/* Search "inode"'s alias list for a dentry that has the same name and parent * as de.  If found, return it.  If not found, return de. * Lustre can't use d_add_unique because don't unhash aliases for directory * in ll_revalidate_it.  After revaliadate inode will be have hashed aliases * and it triggers BUG_ON in d_instantiate_unique (bug #10954). */static struct dentry *ll_find_alias(struct inode *inode, struct dentry *de){        struct list_head *tmp;        struct dentry *dentry;        struct dentry *last_discon = NULL;        spin_lock(&dcache_lock);        list_for_each(tmp, &inode->i_dentry) {                dentry = list_entry(tmp, struct dentry, d_alias);                /* We are called here with 'de' already on the aliases list. */                if (unlikely(dentry == de)) {                        CERROR("whoops\n");                        continue;                }                if (dentry->d_flags & DCACHE_DISCONNECTED) {                        LASSERT(last_discon == NULL);                        last_discon = dentry;                        continue;                }                if (dentry->d_parent != de->d_parent)                        continue;                if (dentry->d_name.hash != de->d_name.hash)                        continue;                if (dentry->d_name.len != de->d_name.len)                        continue;                if (memcmp(dentry->d_name.name, de->d_name.name,                           de->d_name.len) != 0)                        continue;                dget_locked(dentry);                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); /* avoid taking dcache_lock inside */                spin_unlock(&dcache_lock);                iput(inode);                CDEBUG(D_DENTRY, "alias dentry %.*s (%p) parent %p inode %p "                       "refc %d\n", de->d_name.len, de->d_name.name, de,                       de->d_parent, de->d_inode, atomic_read(&de->d_count));                return dentry;        }        if (last_discon) {                 CDEBUG(D_DENTRY, "Reuse disconnected dentry %p inode %p "                        "refc %d\n", last_discon, last_discon->d_inode,                        atomic_read(&last_discon->d_count));                 dget_locked(last_discon);                 spin_unlock(&dcache_lock);                 d_rehash(de);                 d_move(last_discon, de);                 iput(inode);                 return last_discon;        }        ll_d_add(de, inode);        spin_unlock(&dcache_lock);        return de;}int lookup_it_finish(struct ptlrpc_request *request, int offset,                     struct lookup_intent *it, void *data){        struct it_cb_data *icbd = data;        struct dentry **de = icbd->icbd_childp;        struct inode *parent = icbd->icbd_parent;        struct ll_sb_info *sbi = ll_i2sbi(parent);        struct inode *inode = NULL;        int set = 0, rc;        ENTRY;        lock_dentry(*de);        if (likely((*de)->d_op != &ll_d_ops)) {                (*de)->d_op = &ll_init_d_ops;                set = 1;        }        unlock_dentry(*de);        /* NB 1 request reference will be taken away by ll_intent_lock()         * when I return */        if (!it_disposition(it, DISP_LOOKUP_NEG)) {                struct dentry *save = *de;                rc = ll_prep_inode(sbi->ll_osc_exp, &inode, request, offset,                                   (*de)->d_sb);                if (rc) {                        if (set) {                                lock_dentry(*de);                                if (likely((*de)->d_op == &ll_init_d_ops)) {                                        (*de)->d_op = &ll_fini_d_ops;                                        unlock_dentry(*de);                                        smp_wmb();                                        ll_d_wakeup(*de);                                } else {                                        unlock_dentry(*de);                                }                        }                        RETURN(rc);                }                CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n",                       inode, inode->i_ino, inode->i_generation);                mdc_set_lock_data(&it->d.lustre.it_lock_handle, inode);                /* We used to query real size from OSTs here, but actually                   this is not needed. For stat() calls size would be updated                   from subsequent do_revalidate()->ll_inode_revalidate_it() in                   2.4 and                   vfs_getattr_it->ll_getattr()->ll_inode_revalidate_it() in 2.6                   Everybody else who needs correct file size would call                   ll_glimpse_size or some equivalent themselves anyway.                   Also see bug 7198. */                *de = ll_find_alias(inode, *de);                if (set && *de != save) {                        lock_dentry(save);                        if (likely(save->d_op == &ll_init_d_ops)) {                                save->d_op = &ll_fini_d_ops;                                unlock_dentry(save);                                smp_wmb();                                ll_d_wakeup(save);                        } else {                                unlock_dentry(save);                        }                }        } else {                /* Check that parent has UPDATE lock. If there is none, we                   cannot afford to hash this dentry (done by ll_d_add) as it                   might get picked up later when UPDATE lock will appear */                if (ll_have_md_lock(parent, MDS_INODELOCK_UPDATE)) {                        spin_lock(&dcache_lock);                        ll_d_add(*de, inode);                        spin_unlock(&dcache_lock);                } else {                        /* We do not want to hash the dentry if don`t have a                         * lock, but if this dentry is later used in d_move,                         * we'd hit uninitialised list head d_hash, so we just                         * do this to init d_hash field but leave dentry                         * unhashed. (bug 10796). */                        d_rehash(*de);                        d_drop(*de);                }        }        ll_set_dd(*de);        lock_dentry(*de);        if (likely((*de)->d_op == &ll_init_d_ops)) {                (*de)->d_op = &ll_d_ops;                unlock_dentry(*de);                smp_wmb();                ll_d_wakeup(*de);        } else {                (*de)->d_op = &ll_d_ops;                unlock_dentry(*de);        }        RETURN(0);}static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,                                   struct lookup_intent *it, int lookup_flags){        struct dentry *save = dentry, *retval;        struct mdc_op_data op_data;        struct it_cb_data icbd;        struct ptlrpc_request *req = NULL;        struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };        int rc;        ENTRY;        CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",               dentry->d_name.len, dentry->d_name.name, parent->i_ino,               parent->i_generation, parent, LL_IT2STR(it));        if (d_mountpoint(dentry))                CERROR("Tell Peter, lookup on mtpt, it %s\n", LL_IT2STR(it));        ll_frob_intent(&it, &lookup_it);        /* As do_lookup is called before follow_mount, root dentry may be left         * not valid, revalidate it here. */        if (parent->i_sb->s_root && (parent->i_sb->s_root->d_inode == parent) &&            (it->it_op & (IT_OPEN | IT_CREAT))) {                rc = ll_inode_revalidate_it(parent->i_sb->s_root, it);                if (rc)                        RETURN(ERR_PTR(rc));        }        if (it->it_op == IT_GETATTR) {                rc = ll_statahead_enter(parent, &dentry, 1);                if (rc >= 0) {                        ll_statahead_exit(dentry, rc);                        if (rc == 1)                                RETURN(retval = dentry);                }        }        icbd.icbd_parent = parent;        icbd.icbd_childp = &dentry;        rc = ll_prepare_mdc_op_data(&op_data, parent, NULL, dentry->d_name.name,                                    dentry->d_name.len, lookup_flags, NULL);        if (rc)                RETURN(ERR_PTR(rc));        it->it_create_mode &= ~current->fs->umask;        rc = mdc_intent_lock(ll_i2mdcexp(parent), &op_data, NULL, 0, it,                             lookup_flags, &req, ll_mdc_blocking_ast, 0);        if (rc < 0)                GOTO(out, retval = ERR_PTR(rc));        rc = lookup_it_finish(req, DLM_REPLY_REC_OFF, it, &icbd);        if (rc != 0) {                ll_intent_release(it);                GOTO(out, retval = ERR_PTR(rc));        }        if ((it->it_op & IT_OPEN) && dentry->d_inode &&            !S_ISREG(dentry->d_inode->i_mode) &&            !S_ISDIR(dentry->d_inode->i_mode)) {                ll_release_openhandle(dentry, it);        }        ll_lookup_finish_locks(it, dentry);        if (dentry == save)                GOTO(out, retval = NULL);        else                GOTO(out, retval = dentry); out:        if (req)                ptlrpc_req_finished(req);        return retval;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))#ifdef HAVE_VFS_INTENT_PATCHESstatic struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,                                   struct nameidata *nd){        struct dentry *de;        ENTRY;        if (nd && nd->flags & LOOKUP_LAST && !(nd->flags & LOOKUP_LINK_NOTLAST))                de = ll_lookup_it(parent, dentry, &nd->intent, nd->flags);        else                de = ll_lookup_it(parent, dentry, NULL, 0);        RETURN(de);}#elsestruct lookup_intent *ll_convert_intent(struct open_intent *oit,                                        int lookup_flags){        struct lookup_intent *it;        OBD_ALLOC(it, sizeof(*it));        if (!it)                return ERR_PTR(-ENOMEM);        if (lookup_flags & LOOKUP_OPEN) {                it->it_op = IT_OPEN;                if (lookup_flags & LOOKUP_CREATE)                        it->it_op |= IT_CREAT;                it->it_create_mode = oit->create_mode;                it->it_flags = oit->flags;        } else {                it->it_op = IT_GETATTR;        }#ifndef HAVE_FILE_IN_STRUCT_INTENT                /* Since there is no way to pass our intent to ll_file_open,                 * just check the file is there. Actual open will be done                 * in ll_file_open */                if (it->it_op & IT_OPEN)                        it->it_op = IT_LOOKUP;#endif        return it;}static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry,                                   struct nameidata *nd){        struct dentry *de;        ENTRY;        if (nd && !(nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))) {                struct lookup_intent *it;#if defined(HAVE_FILE_IN_STRUCT_INTENT) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))                /* Did we came here from failed revalidate just to propagate                 * its error? */                if (nd->flags & LOOKUP_OPEN)                        if (IS_ERR(nd->intent.open.file))                                RETURN((struct dentry *)nd->intent.open.file);#endif                if (ll_d2d(dentry) && ll_d2d(dentry)->lld_it) {                        it = ll_d2d(dentry)->lld_it;                        ll_d2d(dentry)->lld_it = NULL;                } else {

⌨️ 快捷键说明

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