X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Fdcache.c;h=2ef00a9c30b9baff1cd232428a6acc2c916269f0;hp=fc2ee943b79f82c65353ee4ba0e268f18122341c;hb=32becabb43b6e8f21c030c23c01c3f02e351eaea;hpb=0d4dbdda134a9fa1e349d6c2dd10257e7638834a diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index fc2ee94..2ef00a9 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -1,22 +1,37 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (c) 2001-2003 Cluster File Systems, Inc. + * GPL HEADER START * - * This file is part of Lustre, http://www.lustre.org. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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. + * This program 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * 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. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. */ #include @@ -36,8 +51,10 @@ #include "llite_internal.h" +spinlock_t ll_lookup_lock = SPIN_LOCK_UNLOCKED; + /* should NOT be called with the dcache lock, see fs/dcache.c */ -void ll_release(struct dentry *de) +static void ll_release(struct dentry *de) { struct ll_dentry_data *lld; ENTRY; @@ -60,7 +77,6 @@ void ll_release(struct dentry *de) 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. * @@ -81,15 +97,22 @@ int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name) /* 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); + + CDEBUG(D_DENTRY,"found name %.*s(%p) - flags %d/%x - refc %d\n", + name->len, name->name, dchild, + d_mountpoint(dchild), dchild->d_flags & DCACHE_LUSTRE_INVALID, + atomic_read(&dchild->d_count)); + + /* mountpoint is always valid */ + if (d_mountpoint(dchild)) + RETURN(0); + + if (dchild->d_flags & DCACHE_LUSTRE_INVALID) RETURN(1); - } + RETURN(0); } -#endif /* should NOT be called with the dcache lock, see fs/dcache.c */ static int ll_ddelete(struct dentry *de) @@ -126,7 +149,6 @@ void ll_set_dd(struct dentry *de) OBD_ALLOC_PTR(lld); if (likely(lld != NULL)) { - cfs_waitq_init(&lld->lld_waitq); lock_dentry(de); if (likely(de->d_fsdata == NULL)) de->d_fsdata = lld; @@ -194,11 +216,13 @@ int ll_drop_dentry(struct dentry *dentry) __d_drop(dentry); unlock_dentry(dentry); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); dput(dentry); + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); return 1; } - /* disconected dentry can not be find without lookup, because we + /* 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); @@ -242,6 +266,7 @@ void ll_unhash_aliases(struct inode *inode) inode->i_ino, inode->i_generation, inode); head = &inode->i_dentry; + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); restart: tmp = head; @@ -258,23 +283,14 @@ restart: "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); + spin_unlock(&ll_lookup_lock); + EXIT; } @@ -288,7 +304,7 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request, if (!request) RETURN(0); - if (it_disposition(it, DISP_LOOKUP_NEG)) + if (it_disposition(it, DISP_LOOKUP_NEG)) RETURN(-ENOENT); rc = ll_prep_inode(&de->d_inode, request, NULL); @@ -308,7 +324,7 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry) CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n", inode, inode->i_ino, inode->i_generation); md_set_lock_data(sbi->ll_md_exp, &it->d.lustre.it_lock_handle, - inode); + inode, NULL); } /* drop lookup or getattr locks immediately */ @@ -325,7 +341,7 @@ void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft) struct lookup_intent *it = *itp; #ifdef HAVE_VFS_INTENT_PATCHES if (it) { - LASSERTF(it->it_magic == INTENT_MAGIC, + LASSERTF(it->it_magic == INTENT_MAGIC, "%p has bad intent magic: %x\n", it, it->it_magic); } @@ -372,17 +388,20 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, GOTO(out_sa, rc); } - exp = ll_i2mdexp(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); + /* need to get attributes in case root got changed from other client */ + if (de == de->d_sb->s_root) { + rc = __ll_inode_revalidate_it(de, it, MDS_INODELOCK_LOOKUP); + if (rc == 0) + rc = 1; + GOTO(out_sa, rc); + } + + exp = ll_i2mdexp(de->d_inode); OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5); ll_frob_intent(&it, &lookup_it); @@ -449,14 +468,19 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, do_lock: it->it_create_mode &= ~current->fs->umask; - it->it_flags |= O_CHECK_STALE; + it->it_create_mode |= M_CHECK_STALE; rc = md_intent_lock(exp, op_data, NULL, 0, it, lookup_flags, &req, ll_md_blocking_ast, 0); - it->it_flags &= ~O_CHECK_STALE; + it->it_create_mode &= ~M_CHECK_STALE; ll_finish_md_op_data(op_data); if (it->it_op == IT_GETATTR && !first) - ll_statahead_exit(de, rc); + /* If there are too many locks on client-side, then some + * locks taken by statahead maybe dropped automatically + * before the real "revalidate" using them. */ + ll_statahead_exit(de, req == NULL ? rc : 0); + else if (first == -EEXIST) + ll_statahead_mark(de); /* If req is NULL, then md_intent_lock only tried to do a lock match; * if all was well, it will return 1 if it found locks, 0 otherwise. */ @@ -482,8 +506,8 @@ revalidate_finish: GOTO(out, rc = 0); } - if ((it->it_op & IT_OPEN) && de->d_inode && - !S_ISREG(de->d_inode->i_mode) && + if ((it->it_op & IT_OPEN) && de->d_inode && + !S_ISREG(de->d_inode->i_mode) && !S_ISDIR(de->d_inode->i_mode)) { ll_release_openhandle(de, it); } @@ -491,12 +515,14 @@ revalidate_finish: /* unfortunately ll_intent_lock may cause a callback and revoke our * dentry */ + spin_lock(&ll_lookup_lock); spin_lock(&dcache_lock); lock_dentry(de); __d_drop(de); unlock_dentry(de); d_rehash_cond(de, 0); spin_unlock(&dcache_lock); + spin_unlock(&ll_lookup_lock); out: /* We do not free request as it may be reused during following lookup @@ -589,7 +615,9 @@ out_sa: if (it && it->it_op == IT_GETATTR && rc == 1) { first = ll_statahead_enter(de->d_parent->d_inode, &de, 0); if (!first) - ll_statahead_exit(de, rc); + ll_statahead_exit(de, 1); + else if (first == -EEXIST) + ll_statahead_mark(de); } return rc; @@ -681,7 +709,7 @@ out_sa: } #ifdef HAVE_VFS_INTENT_PATCHES -static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) +int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) { int rc; ENTRY; @@ -724,16 +752,20 @@ int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) (struct ptlrpc_request *) it->d.lustre.it_data); } else { - struct file *filp; - - nd->intent.open.file->private_data = it; - filp = lookup_instantiate_filp(nd, dentry,NULL); #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) /* 2.6.1[456] have a bug in open_namei() that forgets to check * nd->intent.open.file for error, so we need to return it as lookup's result * instead */ - if (IS_ERR(filp)) - rc = 0; + struct file *filp; + + nd->intent.open.file->private_data = it; + filp = lookup_instantiate_filp(nd, dentry,NULL); + if (IS_ERR(filp)) { + rc = PTR_ERR(filp); + } +#else + nd->intent.open.file->private_data = it; + (void)lookup_instantiate_filp(nd, dentry,NULL); #endif } #else @@ -768,53 +800,9 @@ struct dentry_operations ll_d_ops = { .d_revalidate = ll_revalidate_nd, .d_release = ll_release, .d_delete = ll_ddelete, -#ifdef DCACHE_LUSTRE_INVALID .d_compare = ll_dcompare, -#endif #if 0 .d_pin = ll_pin, .d_unpin = ll_unpin, #endif }; - -static int ll_fini_revalidate_nd(struct dentry *dentry, struct nameidata *nd) -{ - ENTRY; - /* need lookup */ - RETURN(0); -} - -struct dentry_operations ll_fini_d_ops = { - .d_revalidate = ll_fini_revalidate_nd, - .d_release = ll_release, -}; - -/* - * It is for the following race condition: - * When someone (maybe statahead thread) adds the dentry to the dentry hash - * table, the dentry's "d_op" maybe NULL, at the same time, another (maybe - * "ls -l") process finds such dentry by "do_lookup()" without "do_revalidate()" - * called. It causes statahead window lost, and maybe other issues. --Fan Yong - */ -static int ll_init_revalidate_nd(struct dentry *dentry, struct nameidata *nd) -{ - struct l_wait_info lwi = { 0 }; - struct ll_dentry_data *lld; - ENTRY; - - ll_set_dd(dentry); - lld = ll_d2d(dentry); - if (unlikely(lld == NULL)) - RETURN(-ENOMEM); - - l_wait_event(lld->lld_waitq, dentry->d_op != &ll_init_d_ops, &lwi); - if (likely(dentry->d_op == &ll_d_ops)) - RETURN(ll_revalidate_nd(dentry, nd)); - else - RETURN(dentry->d_op == &ll_fini_d_ops ? 0 : -EINVAL); -} - -struct dentry_operations ll_init_d_ops = { - .d_revalidate = ll_init_revalidate_nd, - .d_release = ll_release, -};