linux/fs/gfs2/dentry.c
<<
>>
Prefs
   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/spinlock.h>
  11#include <linux/completion.h>
  12#include <linux/buffer_head.h>
  13#include <linux/gfs2_ondisk.h>
  14#include <linux/crc32.h>
  15
  16#include "gfs2.h"
  17#include "incore.h"
  18#include "dir.h"
  19#include "glock.h"
  20#include "super.h"
  21#include "util.h"
  22#include "inode.h"
  23
  24/**
  25 * gfs2_drevalidate - Check directory lookup consistency
  26 * @dentry: the mapping to check
  27 * @nd:
  28 *
  29 * Check to make sure the lookup necessary to arrive at this inode from its
  30 * parent is still good.
  31 *
  32 * Returns: 1 if the dentry is ok, 0 if it isn't
  33 */
  34
  35static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
  36{
  37        struct dentry *parent = dget_parent(dentry);
  38        struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode);
  39        struct gfs2_inode *dip = GFS2_I(parent->d_inode);
  40        struct inode *inode = dentry->d_inode;
  41        struct gfs2_holder d_gh;
  42        struct gfs2_inode *ip = NULL;
  43        int error;
  44        int had_lock = 0;
  45
  46        if (inode) {
  47                if (is_bad_inode(inode))
  48                        goto invalid;
  49                ip = GFS2_I(inode);
  50        }
  51
  52        if (sdp->sd_args.ar_localcaching)
  53                goto valid;
  54
  55        had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
  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_check(parent->d_inode, &dentry->d_name, ip);
  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
  76valid_gunlock:
  77        if (!had_lock)
  78                gfs2_glock_dq_uninit(&d_gh);
  79valid:
  80        dput(parent);
  81        return 1;
  82
  83invalid_gunlock:
  84        if (!had_lock)
  85                gfs2_glock_dq_uninit(&d_gh);
  86invalid:
  87        if (inode && S_ISDIR(inode->i_mode)) {
  88                if (have_submounts(dentry))
  89                        goto valid;
  90                shrink_dcache_parent(dentry);
  91        }
  92        d_drop(dentry);
  93        dput(parent);
  94        return 0;
  95
  96fail_gunlock:
  97        gfs2_glock_dq_uninit(&d_gh);
  98fail:
  99        dput(parent);
 100        return 0;
 101}
 102
 103static int gfs2_dhash(struct dentry *dentry, struct qstr *str)
 104{
 105        str->hash = gfs2_disk_hash(str->name, str->len);
 106        return 0;
 107}
 108
 109static int gfs2_dentry_delete(struct dentry *dentry)
 110{
 111        struct gfs2_inode *ginode;
 112
 113        if (!dentry->d_inode)
 114                return 0;
 115
 116        ginode = GFS2_I(dentry->d_inode);
 117        if (!ginode->i_iopen_gh.gh_gl)
 118                return 0;
 119
 120        if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags))
 121                return 1;
 122
 123        return 0;
 124}
 125
 126const struct dentry_operations gfs2_dops = {
 127        .d_revalidate = gfs2_drevalidate,
 128        .d_hash = gfs2_dhash,
 129        .d_delete = gfs2_dentry_delete,
 130};
 131
 132
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.