1b1e71b06SSteven Whitehouse /* 2b1e71b06SSteven Whitehouse * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 3b1e71b06SSteven Whitehouse * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 4b1e71b06SSteven Whitehouse * 5b1e71b06SSteven Whitehouse * This copyrighted material is made available to anyone wishing to use, 6b1e71b06SSteven Whitehouse * modify, copy, or redistribute it subject to the terms and conditions 7b1e71b06SSteven Whitehouse * of the GNU General Public License version 2. 8b1e71b06SSteven Whitehouse */ 9b1e71b06SSteven Whitehouse 10b1e71b06SSteven Whitehouse #include <linux/spinlock.h> 11b1e71b06SSteven Whitehouse #include <linux/completion.h> 12b1e71b06SSteven Whitehouse #include <linux/buffer_head.h> 13b1e71b06SSteven Whitehouse #include <linux/gfs2_ondisk.h> 1434286d66SNick Piggin #include <linux/namei.h> 15b1e71b06SSteven Whitehouse #include <linux/crc32.h> 16b1e71b06SSteven Whitehouse 17b1e71b06SSteven Whitehouse #include "gfs2.h" 18b1e71b06SSteven Whitehouse #include "incore.h" 19b1e71b06SSteven Whitehouse #include "dir.h" 20b1e71b06SSteven Whitehouse #include "glock.h" 21b1e71b06SSteven Whitehouse #include "super.h" 22b1e71b06SSteven Whitehouse #include "util.h" 23b1e71b06SSteven Whitehouse #include "inode.h" 24b1e71b06SSteven Whitehouse 25b1e71b06SSteven Whitehouse /** 26b1e71b06SSteven Whitehouse * gfs2_drevalidate - Check directory lookup consistency 27b1e71b06SSteven Whitehouse * @dentry: the mapping to check 280b728e19SAl Viro * @flags: lookup flags 29b1e71b06SSteven Whitehouse * 30b1e71b06SSteven Whitehouse * Check to make sure the lookup necessary to arrive at this inode from its 31b1e71b06SSteven Whitehouse * parent is still good. 32b1e71b06SSteven Whitehouse * 33b1e71b06SSteven Whitehouse * Returns: 1 if the dentry is ok, 0 if it isn't 34b1e71b06SSteven Whitehouse */ 35b1e71b06SSteven Whitehouse 360b728e19SAl Viro static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags) 37b1e71b06SSteven Whitehouse { 3834286d66SNick Piggin struct dentry *parent; 3934286d66SNick Piggin struct gfs2_sbd *sdp; 4034286d66SNick Piggin struct gfs2_inode *dip; 4134286d66SNick Piggin struct inode *inode; 42b1e71b06SSteven Whitehouse struct gfs2_holder d_gh; 43b1e71b06SSteven Whitehouse struct gfs2_inode *ip = NULL; 44b1e71b06SSteven Whitehouse int error; 45b1e71b06SSteven Whitehouse int had_lock = 0; 46b1e71b06SSteven Whitehouse 470b728e19SAl Viro if (flags & LOOKUP_RCU) 4834286d66SNick Piggin return -ECHILD; 4934286d66SNick Piggin 5034286d66SNick Piggin parent = dget_parent(dentry); 512b0143b5SDavid Howells sdp = GFS2_SB(d_inode(parent)); 522b0143b5SDavid Howells dip = GFS2_I(d_inode(parent)); 532b0143b5SDavid Howells inode = d_inode(dentry); 5434286d66SNick Piggin 55b1e71b06SSteven Whitehouse if (inode) { 56b1e71b06SSteven Whitehouse if (is_bad_inode(inode)) 57b1e71b06SSteven Whitehouse goto invalid; 58b1e71b06SSteven Whitehouse ip = GFS2_I(inode); 59b1e71b06SSteven Whitehouse } 60b1e71b06SSteven Whitehouse 61c2048b00SSteven Whitehouse if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) 62b1e71b06SSteven Whitehouse goto valid; 63b1e71b06SSteven Whitehouse 64b1e71b06SSteven Whitehouse had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); 65b1e71b06SSteven Whitehouse if (!had_lock) { 66b1e71b06SSteven Whitehouse error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); 67b1e71b06SSteven Whitehouse if (error) 68b1e71b06SSteven Whitehouse goto fail; 69b1e71b06SSteven Whitehouse } 70b1e71b06SSteven Whitehouse 712b0143b5SDavid Howells error = gfs2_dir_check(d_inode(parent), &dentry->d_name, ip); 72b1e71b06SSteven Whitehouse switch (error) { 73b1e71b06SSteven Whitehouse case 0: 74b1e71b06SSteven Whitehouse if (!inode) 75b1e71b06SSteven Whitehouse goto invalid_gunlock; 76b1e71b06SSteven Whitehouse break; 77b1e71b06SSteven Whitehouse case -ENOENT: 78b1e71b06SSteven Whitehouse if (!inode) 79b1e71b06SSteven Whitehouse goto valid_gunlock; 80b1e71b06SSteven Whitehouse goto invalid_gunlock; 81b1e71b06SSteven Whitehouse default: 82b1e71b06SSteven Whitehouse goto fail_gunlock; 83b1e71b06SSteven Whitehouse } 84b1e71b06SSteven Whitehouse 85b1e71b06SSteven Whitehouse valid_gunlock: 86b1e71b06SSteven Whitehouse if (!had_lock) 87b1e71b06SSteven Whitehouse gfs2_glock_dq_uninit(&d_gh); 88b1e71b06SSteven Whitehouse valid: 89b1e71b06SSteven Whitehouse dput(parent); 90b1e71b06SSteven Whitehouse return 1; 91b1e71b06SSteven Whitehouse 92b1e71b06SSteven Whitehouse invalid_gunlock: 93b1e71b06SSteven Whitehouse if (!had_lock) 94b1e71b06SSteven Whitehouse gfs2_glock_dq_uninit(&d_gh); 95b1e71b06SSteven Whitehouse invalid: 96b1e71b06SSteven Whitehouse dput(parent); 97b1e71b06SSteven Whitehouse return 0; 98b1e71b06SSteven Whitehouse 99b1e71b06SSteven Whitehouse fail_gunlock: 100b1e71b06SSteven Whitehouse gfs2_glock_dq_uninit(&d_gh); 101b1e71b06SSteven Whitehouse fail: 102b1e71b06SSteven Whitehouse dput(parent); 103b1e71b06SSteven Whitehouse return 0; 104b1e71b06SSteven Whitehouse } 105b1e71b06SSteven Whitehouse 106da53be12SLinus Torvalds static int gfs2_dhash(const struct dentry *dentry, struct qstr *str) 107b1e71b06SSteven Whitehouse { 108b1e71b06SSteven Whitehouse str->hash = gfs2_disk_hash(str->name, str->len); 109b1e71b06SSteven Whitehouse return 0; 110b1e71b06SSteven Whitehouse } 111b1e71b06SSteven Whitehouse 112fe15ce44SNick Piggin static int gfs2_dentry_delete(const struct dentry *dentry) 113970343cdSWengang Wang { 114970343cdSWengang Wang struct gfs2_inode *ginode; 115970343cdSWengang Wang 1162b0143b5SDavid Howells if (d_really_is_negative(dentry)) 117970343cdSWengang Wang return 0; 118970343cdSWengang Wang 1192b0143b5SDavid Howells ginode = GFS2_I(d_inode(dentry)); 1206df9f9a2SAndreas Gruenbacher if (!gfs2_holder_initialized(&ginode->i_iopen_gh)) 121970343cdSWengang Wang return 0; 122970343cdSWengang Wang 123970343cdSWengang Wang if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags)) 124970343cdSWengang Wang return 1; 125970343cdSWengang Wang 126970343cdSWengang Wang return 0; 127970343cdSWengang Wang } 128970343cdSWengang Wang 129b1e71b06SSteven Whitehouse const struct dentry_operations gfs2_dops = { 130b1e71b06SSteven Whitehouse .d_revalidate = gfs2_drevalidate, 131b1e71b06SSteven Whitehouse .d_hash = gfs2_dhash, 132970343cdSWengang Wang .d_delete = gfs2_dentry_delete, 133b1e71b06SSteven Whitehouse }; 134b1e71b06SSteven Whitehouse 135