X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fdcache.c;h=0286cc6aa5a00d30cc76991ce8822f7d1b9a3f9b;hb=93acd158c57c4c5d0fc751d46741231490c04707;hp=61fbeb59b3f2dcd799805268bbce8606017123b0;hpb=015b7752475ca95402c50a2b3eb1d8ee8b5eb4ca;p=fs%2Flustre-release.git diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 61fbeb5..0286cc6 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -1,57 +1,233 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * This code is issued under the GNU General Public License. - * See the file COPYING in this distribution + * Copyright (c) 2001-2003 Cluster File Systems, Inc. * - * Copyright (C) 2001, 2002 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 -#include +#include +#include #include #define DEBUG_SUBSYSTEM S_LLITE #include #include +#include #include -extern struct address_space_operations ll_aops; +/* should NOT be called with the dcache lock, see fs/dcache.c */ +void ll_release(struct dentry *de) +{ + ENTRY; + OBD_FREE(de->d_fsdata, sizeof(struct ll_dentry_data)); + EXIT; +} -void ll_intent_release(struct dentry *de) +void ll_set_dd(struct dentry *de) +{ + ENTRY; + LASSERT(de != NULL); + + lock_kernel(); + + if (de->d_fsdata == NULL) { + OBD_ALLOC(de->d_fsdata, sizeof(struct ll_dentry_data)); + sema_init(&ll_d2d(de)->lld_it_sem, 1); + } + + unlock_kernel(); + + EXIT; +} + +void ll_intent_release(struct dentry *de, struct lookup_intent *it) { struct lustre_handle *handle; ENTRY; - if (de->d_it == NULL) { + LASSERT(ll_d2d(de) != NULL); + mdc_put_rpc_lock(&mdc_rpc_lock, it); + + if (it->it_lock_mode) { + handle = (struct lustre_handle *)it->it_lock_handle; + if (it->it_op == IT_SETATTR) + ldlm_lock_decref_and_cancel(handle, it->it_lock_mode); + else + ldlm_lock_decref(handle, it->it_lock_mode); + + /* intent_release may be called multiple times, from + this thread and we don't want to double-decref this + lock (see bug 494) */ + it->it_lock_mode = 0; + } + + if (!de->d_it || it->it_op == IT_RELEASED_MAGIC) { EXIT; return; } - if (de->d_it->it_lock_mode) { - handle = (struct lustre_handle *)de->d_it->it_lock_handle; - if (de->d_it->it_op == IT_SETATTR) { - int rc; - ldlm_lock_decref(handle, de->d_it->it_lock_mode); - rc = ldlm_cli_cancel(handle); - if (rc < 0) - CERROR("ldlm_cli_cancel: %d\n", rc); - } else - ldlm_lock_decref(handle, de->d_it->it_lock_mode); - } - de->d_it = NULL; + + if (de->d_it == it) + LL_GET_INTENT(de, it); + else + CERROR("STRANGE intent release: %p %p\n", de->d_it, it); + EXIT; } -int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it) +extern struct dentry *ll_find_alias(struct inode *, struct dentry *); + +static int revalidate2_finish(int flag, struct ptlrpc_request *request, + struct dentry **de, struct lookup_intent *it, + int offset, obd_id ino) { + struct mds_body *body; + struct lov_mds_md *lmm = NULL; + int rc = 0; ENTRY; + if (!(flag & LL_LOOKUP_NEGATIVE)) { + body = lustre_msg_buf(request->rq_repmsg, offset); + if (body->valid & OBD_MD_FLEASIZE) + lmm = lustre_msg_buf(request->rq_repmsg, offset + 1); + ll_update_inode((*de)->d_inode, body, lmm); + mdc_lock_set_inode((struct lustre_handle *)it->it_lock_handle, + (*de)->d_inode); + } else + rc = -ENOENT; + + ptlrpc_req_finished(request); + RETURN(rc); +} + +int ll_have_md_lock(struct dentry *de) +{ + struct ll_sb_info *sbi = ll_s2sbi(de->d_sb); + struct lustre_handle lockh; + struct ldlm_res_id res_id = { .name = {0} }; + struct obd_device *obddev; + ENTRY; + + if (!de->d_inode) + RETURN(0); + + obddev = class_conn2obd(&sbi->ll_mdc_conn); + res_id.name[0] = de->d_inode->i_ino; + res_id.name[1] = de->d_inode->i_generation; + + CDEBUG(D_INFO, "trying to match res "LPU64"\n", res_id.name[0]); + + if (ldlm_lock_match(obddev->obd_namespace, LDLM_FL_BLOCK_GRANTED, + &res_id, LDLM_PLAIN, NULL, 0, LCK_PR, &lockh)) { + ldlm_lock_decref(&lockh, LCK_PR); + RETURN(1); + } + + if (ldlm_lock_match(obddev->obd_namespace, LDLM_FL_BLOCK_GRANTED, + &res_id, LDLM_PLAIN, NULL, 0, LCK_PW, &lockh)) { + ldlm_lock_decref(&lockh, LCK_PW); + RETURN(1); + } RETURN(0); } +int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it) +{ + int rc; + ENTRY; + + /* We don't want to cache negative dentries, so return 0 immediately. + * We believe that this is safe, that negative dentries cannot be + * pinned by someone else */ + if (de->d_inode == NULL) { + CDEBUG(D_INODE, "negative dentry: ret 0 to force lookup2\n"); + RETURN(0); + } + + if (it && it->it_op == IT_TRUNC) + it->it_op = IT_SETATTR; + + if (it == NULL || it->it_op == IT_GETATTR) { + /* We could just return 1 immediately, but since we should only + * be called in revalidate2 if we already have a lock, let's + * verify that. */ + struct inode *inode = de->d_inode; + struct ll_sb_info *sbi = ll_i2sbi(inode); + struct obd_device *obddev = class_conn2obd(&sbi->ll_mdc_conn); + struct ldlm_res_id res_id = + { .name = {inode->i_ino, (__u64)inode->i_generation} }; + struct lustre_handle lockh; + rc = ldlm_lock_match(obddev->obd_namespace, + LDLM_FL_BLOCK_GRANTED, &res_id, + LDLM_PLAIN, NULL, 0, LCK_PR, &lockh); + if (rc) { + de->d_flags &= ~DCACHE_LUSTRE_INVALID; + if (it && it->it_op == IT_GETATTR) { + memcpy(it->it_lock_handle, &lockh, + sizeof(lockh)); + it->it_lock_mode = LCK_PR; + LL_SAVE_INTENT(de, it); + } else { + ldlm_lock_decref(&lockh, LCK_PR); + } + RETURN(1); + } + rc = ldlm_lock_match(obddev->obd_namespace, + LDLM_FL_BLOCK_GRANTED, &res_id, + LDLM_PLAIN, NULL, 0, LCK_PW, &lockh); + if (rc) { + de->d_flags &= ~DCACHE_LUSTRE_INVALID; + if (it && it->it_op == IT_GETATTR) { + memcpy(it->it_lock_handle, &lockh, + sizeof(lockh)); + it->it_lock_mode = LCK_PW; + LL_SAVE_INTENT(de, it); + } else { + ldlm_lock_decref(&lockh, LCK_PW); + } + RETURN(1); + } + if (S_ISDIR(de->d_inode->i_mode)) + ll_invalidate_inode_pages(de->d_inode); + d_unhash_aliases(de->d_inode); + RETURN(0); + } + + rc = ll_intent_lock(de->d_parent->d_inode, &de, it, revalidate2_finish); + if (rc == -ESTALE) + RETURN(0); + if (rc < 0 && it->it_status) { + CERROR("ll_intent_lock: rc %d : it->it_status %d\n", rc, + it->it_status); + RETURN(0); + } + /* unfortunately ll_intent_lock may cause a callback and revoke our + dentry */ + spin_lock(&dcache_lock); + list_del_init(&de->d_hash); + spin_unlock(&dcache_lock); + d_rehash(de); + + RETURN(1); +} + struct dentry_operations ll_d_ops = { - d_revalidate2: ll_revalidate2, - d_intent_release: ll_intent_release + .d_revalidate2 = ll_revalidate2, + .d_intent_release = ll_intent_release, + .d_release = ll_release, };