📄 namei.c
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (c) 2002, 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/mm.h>#include <linux/smp_lock.h>#include <linux/quotaops.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"/* methods *//* called from iget{4,5_locked}->find_inode() under inode_lock spinlock */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))static int ll_test_inode(struct inode *inode, unsigned long ino, void *opaque)#elsestatic int ll_test_inode(struct inode *inode, void *opaque)#endif{ static int last_ino, last_gen, last_count; struct lustre_md *md = opaque; if (!(md->body->valid & (OBD_MD_FLGENER | OBD_MD_FLID))) { CERROR("MDS body missing inum or generation\n"); return 0; } if (last_ino == md->body->ino && last_gen == md->body->generation && last_count < 500) { last_count++; } else { if (last_count > 1) CDEBUG(D_VFSTRACE, "compared %u/%u %u times\n", last_ino, last_gen, last_count); last_count = 0; last_ino = md->body->ino; last_gen = md->body->generation; CDEBUG(D_VFSTRACE, "comparing inode %p ino %lu/%u to body "LPU64"/%u\n", inode, inode->i_ino, inode->i_generation, md->body->ino, md->body->generation); }#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) if (inode->i_ino != md->body->ino) return 0;#endif if (inode->i_generation != md->body->generation) {#ifdef HAVE_EXPORT___IGET if (inode->i_state & (I_FREEING | I_CLEAR)) return 0; if (inode->i_nlink == 0) return 0; /* add "duplicate" inode into deathrow for destroy */ spin_lock(&ll_i2sbi(inode)->ll_deathrow_lock); if (list_empty(&ll_i2info(inode)->lli_dead_list)) { __iget(inode); list_add(&ll_i2info(inode)->lli_dead_list, &ll_i2sbi(inode)->ll_deathrow); } spin_unlock(&ll_i2sbi(inode)->ll_deathrow_lock);#endif return 0; } /* Apply the attributes in 'opaque' to this inode */ if (!(inode->i_state & (I_FREEING | I_CLEAR))) ll_update_inode(inode, md); return 1;}int ll_unlock(__u32 mode, struct lustre_handle *lockh){ ENTRY; ldlm_lock_decref(lockh, mode); RETURN(0);}/* Get an inode by inode number (already instantiated by the intent lookup). * Returns inode or NULL */#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))int ll_set_inode(struct inode *inode, void *opaque){ ll_read_inode2(inode, opaque); return 0;}struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *md){ struct inode *inode; LASSERT(hash != 0); inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md); if (inode) { if (inode->i_state & I_NEW) unlock_new_inode(inode); CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); } return inode;}#elsestruct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *md){ struct inode *inode; LASSERT(hash != 0); inode = iget4(sb, hash, ll_test_inode, md); if (inode) CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); return inode;}#endifstatic void ll_drop_negative_dentry(struct inode *dir){ struct dentry *dentry, *tmp_alias, *tmp_subdir; spin_lock(&dcache_lock);restart: list_for_each_entry_safe(dentry, tmp_alias, &dir->i_dentry,d_alias) { if (!list_empty(&dentry->d_subdirs)) { struct dentry *child; list_for_each_entry_safe(child, tmp_subdir, &dentry->d_subdirs, d_child) { /* XXX Print some debug here? */ if (!child->d_inode) /* Negative dentry. If we were dropping dcache lock, go throught the list again */ if (ll_drop_dentry(child)) goto restart; } } } spin_unlock(&dcache_lock);}int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, void *data, int flag){ int rc; struct lustre_handle lockh; ENTRY; switch (flag) { case LDLM_CB_BLOCKING: ldlm_lock2handle(lock, &lockh); rc = ldlm_cli_cancel(&lockh); if (rc < 0) { CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc); RETURN(rc); } break; case LDLM_CB_CANCELING: { struct inode *inode = ll_inode_from_lock(lock); __u64 bits = lock->l_policy_data.l_inodebits.bits; /* Invalidate all dentries associated with this inode */ if (inode == NULL) break; LASSERT(lock->l_flags & LDLM_FL_CANCELING); if ((bits & MDS_INODELOCK_LOOKUP) && ll_have_md_lock(inode, MDS_INODELOCK_LOOKUP)) bits &= ~MDS_INODELOCK_LOOKUP; if ((bits & MDS_INODELOCK_UPDATE) && ll_have_md_lock(inode, MDS_INODELOCK_UPDATE)) bits &= ~MDS_INODELOCK_UPDATE; if ((bits & MDS_INODELOCK_OPEN) && ll_have_md_lock(inode, MDS_INODELOCK_OPEN)) bits &= ~MDS_INODELOCK_OPEN; if (lock->l_resource->lr_name.name[0] != inode->i_ino || lock->l_resource->lr_name.name[1] != inode->i_generation) { LDLM_ERROR(lock, "data mismatch with ino %lu/%u (%p)", inode->i_ino, inode->i_generation, inode); } if (bits & MDS_INODELOCK_OPEN) { int flags = 0; switch (lock->l_req_mode) { case LCK_CW: flags = FMODE_WRITE; break; case LCK_PR: flags = FMODE_EXEC; if (!FMODE_EXEC) CERROR("open PR lock without FMODE_EXEC\n"); break; case LCK_CR: flags = FMODE_READ; break; default: CERROR("Unexpected lock mode for OPEN lock " "%d, inode %ld\n", lock->l_req_mode, inode->i_ino); } ll_mdc_real_close(inode, flags); } if (bits & MDS_INODELOCK_UPDATE) clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK, &(ll_i2info(inode)->lli_flags)); if (S_ISDIR(inode->i_mode) && (bits & MDS_INODELOCK_UPDATE)) { CDEBUG(D_INODE, "invalidating inode %lu\n", inode->i_ino); truncate_inode_pages(inode->i_mapping, 0); ll_drop_negative_dentry(inode); inode->i_version++; /* XXX: remove with inode version*/ } if (inode->i_sb->s_root && inode != inode->i_sb->s_root->d_inode && (bits & MDS_INODELOCK_LOOKUP)) ll_unhash_aliases(inode); iput(inode); break; } default: LBUG(); } RETURN(0);}int ll_mdc_cancel_unused(struct lustre_handle *conn, struct inode *inode, int flags, void *opaque){ struct ldlm_res_id res_id = { .name = {inode->i_ino, inode->i_generation} }; struct obd_device *obddev = class_conn2obd(conn); ENTRY; RETURN(ldlm_cli_cancel_unused(obddev->obd_namespace, &res_id, flags, opaque));}/* Pack the required supplementary groups into the supplied groups array. * If we don't need to use the groups from the target inode(s) then we * instead pack one or more groups from the user's supplementary group * array in case it might be useful. Not needed if doing an MDS-side upcall. */void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2){ int i; LASSERT(i1 != NULL); LASSERT(suppgids != NULL); if (in_group_p(i1->i_gid)) suppgids[0] = i1->i_gid; else suppgids[0] = -1; if (i2) { if (in_group_p(i2->i_gid)) suppgids[1] = i2->i_gid; else suppgids[1] = -1; } else { suppgids[1] = -1; } for (i = 0; i < current_ngroups; i++) { if (suppgids[0] == -1) { if (current_groups[i] != suppgids[1]) suppgids[0] = current_groups[i]; continue; } if (suppgids[1] == -1) { if (current_groups[i] != suppgids[0]) suppgids[1] = current_groups[i]; continue; } break; }}int ll_prepare_mdc_op_data(struct mdc_op_data *op_data, struct inode *i1, struct inode *i2, const char *name, int namelen, int mode, void *data){ LASSERT(i1); if (namelen > ll_i2sbi(i1)->ll_namelen) return -ENAMETOOLONG; ll_i2gids(op_data->suppgids, i1, i2); ll_inode2fid(&op_data->fid1, i1); if (i2) ll_inode2fid(&op_data->fid2, i2); else memset(&op_data->fid2, 0, sizeof(op_data->fid2)); op_data->name = name; op_data->namelen = namelen; op_data->create_mode = mode; op_data->mod_time = CURRENT_SECONDS; op_data->data = data; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -