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 17 #include "gfs2.h" 18 #include "incore.h" 19 #include "dir.h" 20 #include "glock.h" 21 #include "super.h" 22 #include "util.h" 23 #include "inode.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 36 static 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 = NULL; 44 int error; 45 int had_lock = 0; 46 47 if (inode) { 48 if (is_bad_inode(inode)) 49 goto invalid; 50 ip = GFS2_I(inode); 51 } 52 53 if (sdp->sd_args.ar_localcaching) 54 goto valid; 55 56 had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); 57 if (!had_lock) { 58 error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); 59 if (error) 60 goto fail; 61 } 62 63 error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip); 64 switch (error) { 65 case 0: 66 if (!inode) 67 goto invalid_gunlock; 68 break; 69 case -ENOENT: 70 if (!inode) 71 goto valid_gunlock; 72 goto invalid_gunlock; 73 default: 74 goto fail_gunlock; 75 } 76 77 valid_gunlock: 78 if (!had_lock) 79 gfs2_glock_dq_uninit(&d_gh); 80 valid: 81 dput(parent); 82 return 1; 83 84 invalid_gunlock: 85 if (!had_lock) 86 gfs2_glock_dq_uninit(&d_gh); 87 invalid: 88 if (inode && S_ISDIR(inode->i_mode)) { 89 if (have_submounts(dentry)) 90 goto valid; 91 shrink_dcache_parent(dentry); 92 } 93 d_drop(dentry); 94 dput(parent); 95 return 0; 96 97 fail_gunlock: 98 gfs2_glock_dq_uninit(&d_gh); 99 fail: 100 dput(parent); 101 return 0; 102 } 103 104 static int gfs2_dhash(struct dentry *dentry, struct qstr *str) 105 { 106 str->hash = gfs2_disk_hash(str->name, str->len); 107 return 0; 108 } 109 110 const struct dentry_operations gfs2_dops = { 111 .d_revalidate = gfs2_drevalidate, 112 .d_hash = gfs2_dhash, 113 }; 114 115