1/* 2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4 * 5 * This copyrighted material is made available to anyone wishing to use, 6 * modify, copy, or redistribute it subject to the terms and conditions 7 * of the GNU General Public License version 2. 8 */ 9 10#include <linux/slab.h> 11#include <linux/spinlock.h> 12#include <linux/completion.h> 13#include <linux/buffer_head.h> 14#include <linux/gfs2_ondisk.h> 15#include <linux/crc32.h> 16#include <linux/lm_interface.h> 17 18#include "gfs2.h" 19#include "incore.h" 20#include "dir.h" 21#include "glock.h" 22#include "ops_dentry.h" 23#include "util.h" 24 25/** 26 * gfs2_drevalidate - Check directory lookup consistency 27 * @dentry: the mapping to check 28 * @nd: 29 * 30 * Check to make sure the lookup necessary to arrive at this inode from its 31 * parent is still good. 32 * 33 * Returns: 1 if the dentry is ok, 0 if it isn't 34 */ 35 36static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) 37{ 38 struct dentry *parent = dget_parent(dentry); 39 struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode); 40 struct gfs2_inode *dip = GFS2_I(parent->d_inode); 41 struct inode *inode = dentry->d_inode; 42 struct gfs2_holder d_gh; 43 struct gfs2_inode *ip; 44 struct gfs2_inum_host inum; 45 unsigned int type; 46 int error; 47 int had_lock=0; 48 49 if (inode && is_bad_inode(inode)) 50 goto invalid; 51 52 if (sdp->sd_args.ar_localcaching) 53 goto valid; 54 55 had_lock = gfs2_glock_is_locked_by_me(dip->i_gl); 56 if (!had_lock) { 57 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); 58 if (error) 59 goto fail; 60 } 61 62 error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type); 63 switch (error) { 64 case 0: 65 if (!inode) 66 goto invalid_gunlock; 67 break; 68 case -ENOENT: 69 if (!inode) 70 goto valid_gunlock; 71 goto invalid_gunlock; 72 default: 73 goto fail_gunlock; 74 } 75 76 ip = GFS2_I(inode); 77 78 if (!gfs2_inum_equal(&ip->i_num, &inum)) 79 goto invalid_gunlock; 80 81 if (IF2DT(ip->i_inode.i_mode) != type) { 82 gfs2_consist_inode(dip); 83 goto fail_gunlock; 84 } 85 86valid_gunlock: 87 if (!had_lock) 88 gfs2_glock_dq_uninit(&d_gh); 89valid: 90 dput(parent); 91 return 1; 92 93invalid_gunlock: 94 if (!had_lock) 95 gfs2_glock_dq_uninit(&d_gh); 96invalid: 97 if (inode && S_ISDIR(inode->i_mode)) { 98 if (have_submounts(dentry)) 99 goto valid; 100 shrink_dcache_parent(dentry); 101 } 102 d_drop(dentry); 103 dput(parent); 104 return 0; 105 106fail_gunlock: 107 gfs2_glock_dq_uninit(&d_gh); 108fail: 109 dput(parent); 110 return 0; 111} 112 113static int gfs2_dhash(struct dentry *dentry, struct qstr *str) 114{ 115 str->hash = gfs2_disk_hash(str->name, str->len); 116 return 0; 117} 118 119struct dentry_operations gfs2_dops = { 120 .d_revalidate = gfs2_drevalidate, 121 .d_hash = gfs2_dhash, 122}; 123