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

📄 dcache.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * *  Copyright (c) 2001-2003 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/smp_lock.h>#include <linux/quotaops.h>#define DEBUG_SUBSYSTEM S_LLITE#include <obd_support.h>#include <lustre_lite.h>#include <lustre/lustre_idl.h>#include <lustre_dlm.h>#include <linux/lustre_version.h>#include "llite_internal.h"/* should NOT be called with the dcache lock, see fs/dcache.c */static void ll_release(struct dentry *de){        struct ll_dentry_data *lld;        ENTRY;        LASSERT(de != NULL);        lld = ll_d2d(de);        if (lld == NULL) { /* NFS copies the de->d_op methods (bug 4655) */                EXIT;                return;        }#ifndef HAVE_VFS_INTENT_PATCHES        if (lld->lld_it) {                ll_intent_release(lld->lld_it);                OBD_FREE(lld->lld_it, sizeof(*lld->lld_it));        }#endif        LASSERT(lld->lld_cwd_count == 0);        LASSERT(lld->lld_mnt_count == 0);        OBD_FREE(de->d_fsdata, sizeof(*lld));        EXIT;}#ifdef DCACHE_LUSTRE_INVALID/* Compare if two dentries are the same.  Don't match if the existing dentry * is marked DCACHE_LUSTRE_INVALID.  Returns 1 if different, 0 if the same. * * This avoids a race where ll_lookup_it() instantiates a dentry, but we get * an AST before calling d_revalidate_it().  The dentry still exists (marked * INVALID) so d_lookup() matches it, but we have no lock on it (so * lock_match() fails) and we spin around real_lookup(). */int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name){        struct dentry *dchild;        ENTRY;        if (d_name->len != name->len)                RETURN(1);        if (memcmp(d_name->name, name->name, name->len))                RETURN(1);        /* XXX: d_name must be in-dentry structure */        dchild = container_of(d_name, struct dentry, d_name); /* ugh */        if (dchild->d_flags & DCACHE_LUSTRE_INVALID) {                CDEBUG(D_DENTRY,"INVALID dentry %p not matched, was bug 3784\n",                       dchild);                RETURN(1);        }        RETURN(0);}#endif/* should NOT be called with the dcache lock, see fs/dcache.c */static int ll_ddelete(struct dentry *de){        ENTRY;        LASSERT(de);#ifndef DCACHE_LUSTRE_INVALID#define DCACHE_LUSTRE_INVALID 0#endif        CDEBUG(D_DENTRY, "%s dentry %.*s (%p, parent %p, inode %p) %s%s\n",               (de->d_flags & DCACHE_LUSTRE_INVALID ? "deleting" : "keeping"),               de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode,               d_unhashed(de) ? "" : "hashed,",               list_empty(&de->d_subdirs) ? "" : "subdirs");#if DCACHE_LUSTRE_INVALID == 0#undef DCACHE_LUSTRE_INVALID#endif        RETURN(0);}void ll_set_dd(struct dentry *de){        ENTRY;        LASSERT(de != NULL);        CDEBUG(D_DENTRY, "ldd on 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));        if (de->d_fsdata == NULL) {                struct ll_dentry_data *lld;                OBD_ALLOC(lld, sizeof(struct ll_dentry_data));                if (likely(lld != NULL)) {                        cfs_waitq_init(&lld->lld_waitq);                        lock_dentry(de);                        if (likely(de->d_fsdata == NULL))                                de->d_fsdata = lld;                        else                                OBD_FREE(lld, sizeof(struct ll_dentry_data));                        unlock_dentry(de);                }        }        EXIT;}void ll_intent_drop_lock(struct lookup_intent *it){        struct lustre_handle *handle;        if (it->it_op && it->d.lustre.it_lock_mode) {                handle = (struct lustre_handle *)&it->d.lustre.it_lock_handle;                CDEBUG(D_DLMTRACE, "releasing lock with cookie "LPX64                       " from it %p\n", handle->cookie, it);                ldlm_lock_decref(handle, it->d.lustre.it_lock_mode);                /* bug 494: intent_release may be called multiple times, from                 * this thread and we don't want to double-decref this lock */                it->d.lustre.it_lock_mode = 0;        }}void ll_intent_release(struct lookup_intent *it){        ENTRY;        ll_intent_drop_lock(it);#ifdef HAVE_VFS_INTENT_PATCHES        it->it_magic = 0;        it->it_op_release = 0;#endif        /* We are still holding extra reference on a request, need to free it */        if (it_disposition(it, DISP_ENQ_OPEN_REF)) /* open req for llfile_open*/                ptlrpc_req_finished(it->d.lustre.it_data);        if (it_disposition(it, DISP_ENQ_CREATE_REF)) /* create rec */                ptlrpc_req_finished(it->d.lustre.it_data);        if (it_disposition(it, DISP_ENQ_COMPLETE)) /* saved req from revalidate                                                    * to lookup */                ptlrpc_req_finished(it->d.lustre.it_data);        it->d.lustre.it_disposition = 0;        it->d.lustre.it_data = NULL;        EXIT;}/* Drop dentry if it is not used already, unhash otherwise.   Should be called with dcache lock held!   Returns: 1 if dentry was dropped, 0 if unhashed. */int ll_drop_dentry(struct dentry *dentry){        lock_dentry(dentry);        if (atomic_read(&dentry->d_count) == 0) {                CDEBUG(D_DENTRY, "deleting dentry %.*s (%p) parent %p "                       "inode %p\n", dentry->d_name.len,                       dentry->d_name.name, dentry, dentry->d_parent,                       dentry->d_inode);                dget_locked(dentry);                __d_drop(dentry);                unlock_dentry(dentry);                spin_unlock(&dcache_lock);                dput(dentry);                spin_lock(&dcache_lock);                return 1;        }	/* disconected dentry can not be find without lookup, because we 	 * not need his to unhash or mark invalid. */	if (dentry->d_flags & DCACHE_DISCONNECTED) {		unlock_dentry(dentry);		RETURN (0);	}#ifdef DCACHE_LUSTRE_INVALID        if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) {#else        if (!d_unhashed(dentry)) {#endif                CDEBUG(D_DENTRY, "unhashing dentry %.*s (%p) parent %p "                       "inode %p refc %d\n", dentry->d_name.len,                       dentry->d_name.name, dentry, dentry->d_parent,                       dentry->d_inode, atomic_read(&dentry->d_count));                /* actually we don't unhash the dentry, rather just                 * mark it inaccessible for to __d_lookup(). otherwise                 * sys_getcwd() could return -ENOENT -bzzz */#ifdef DCACHE_LUSTRE_INVALID                dentry->d_flags |= DCACHE_LUSTRE_INVALID;#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))                __d_drop(dentry);                if (dentry->d_inode) {                        /* Put positive dentries to orphan list */                        list_add(&dentry->d_hash,                                 &ll_i2sbi(dentry->d_inode)->ll_orphan_dentry_list);                }#endif#else                if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))                        __d_drop(dentry);#endif        }        unlock_dentry(dentry);        return 0;}void ll_unhash_aliases(struct inode *inode){        struct list_head *tmp, *head;        ENTRY;        if (inode == NULL) {                CERROR("unexpected NULL inode, tell phil\n");                return;        }        CDEBUG(D_INODE, "marking dentries for ino %lu/%u(%p) invalid\n",               inode->i_ino, inode->i_generation, inode);        head = &inode->i_dentry;        spin_lock(&dcache_lock);restart:        tmp = head;        while ((tmp = tmp->next) != head) {                struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);                if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') {                        CERROR("called on root (?) dentry=%p, inode=%p "                               "ino=%lu\n", dentry, inode, inode->i_ino);                        lustre_dump_dentry(dentry, 1);                        libcfs_debug_dumpstack(NULL);                } else if (d_mountpoint(dentry)) {                        /* For mountpoints we skip removal of the dentry                           which happens solely because we have a lock on it                           obtained when this dentry was not a mountpoint yet */                        CDEBUG(D_DENTRY, "Skippind mountpoint dentry removal "                                         "%.*s (%p) parent %p\n",                                          dentry->d_name.len,                                          dentry->d_name.name,                                          dentry, dentry->d_parent);                        continue;                }                if (ll_drop_dentry(dentry))                          goto restart;        }        spin_unlock(&dcache_lock);        EXIT;}int revalidate_it_finish(struct ptlrpc_request *request, int offset,                         struct lookup_intent *it, struct dentry *de){        int rc = 0;        ENTRY;        if (!request)                RETURN(0);        if (it_disposition(it, DISP_LOOKUP_NEG))                RETURN(-ENOENT);        rc = ll_prep_inode(ll_i2sbi(de->d_inode)->ll_osc_exp, &de->d_inode,                           request, offset, NULL);        RETURN(rc);}void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry){        LASSERT(it != NULL);        LASSERT(dentry != NULL);        if (it->d.lustre.it_lock_mode && dentry->d_inode != NULL) {                struct inode *inode = dentry->d_inode;                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);        }        /* drop lookup or getattr locks immediately */        if (it->it_op == IT_LOOKUP || it->it_op == IT_GETATTR) {#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))                /* on 2.6 there are situation when several lookups and                 * revalidations may be requested during single operation.                 * therefore, we don't release intent here -bzzz */                ll_intent_drop_lock(it);#else                ll_intent_release(it);#endif        }}void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft){        struct lookup_intent *it = *itp;#if defined(HAVE_VFS_INTENT_PATCHES)&&(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))        if (it) {                LASSERTF(it->it_magic == INTENT_MAGIC, "bad intent magic: %x\n",                         it->it_magic);        }#endif        if (!it || it->it_op == IT_GETXATTR)                it = *itp = deft;#ifdef HAVE_VFS_INTENT_PATCHES        it->it_op_release = ll_intent_release;#endif}int ll_revalidate_it(struct dentry *de, int lookup_flags,                     struct lookup_intent *it){        struct mdc_op_data op_data;        struct ptlrpc_request *req = NULL;        struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };        struct obd_export *exp;        int first = 0, rc;        ENTRY;        CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name,               LL_IT2STR(it));        if (de->d_inode == NULL) {                /* We can only use negative dentries if this is stat or lookup,                   for opens and stuff we do need to query server. */                /* If there is IT_CREAT in intent op set, then we must throw                   away this negative dentry and actually do the request to                   kernel to create whatever needs to be created (if possible)*/                if (it && (it->it_op & IT_CREAT))                        RETURN(0);#ifdef DCACHE_LUSTRE_INVALID                if (de->d_flags & DCACHE_LUSTRE_INVALID)                        RETURN(0);#endif                rc = ll_have_md_lock(de->d_parent->d_inode,                                     MDS_INODELOCK_UPDATE);                GOTO(out_sa, rc);        }        exp = ll_i2mdcexp(de->d_inode);        /* Never execute intents for mount points.         * Attributes will be fixed up in ll_inode_revalidate_it */        if (d_mountpoint(de))                GOTO(out_sa, rc = 1);        /* Root of the lustre tree. Always valid.         * Attributes will be fixed up in ll_inode_revalidate_it */        if (de == de->d_sb->s_root)                GOTO(out_sa, rc = 1);        OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);        ll_frob_intent(&it, &lookup_it);        LASSERT(it);        ll_prepare_mdc_op_data(&op_data, de->d_parent->d_inode, de->d_inode,                               de->d_name.name, de->d_name.len, 0, NULL);        if ((it->it_op == IT_OPEN) && de->d_inode) {                struct inode *inode = de->d_inode;                struct ll_inode_info *lli = ll_i2info(inode);                struct obd_client_handle **och_p;                __u64 *och_usecount;

⌨️ 快捷键说明

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