Don't pass inode to ->d_hash() and ->d_compare()
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 21 May 2013 22:22:44 +0000 (15:22 -0700)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:57:36 +0000 (12:57 +0400)
Instances either don't look at it at all (the majority of cases) or
only want it to find the superblock (which can be had as dentry->d_sb).
A few cases that want more are actually safe with dentry->d_inode -
the only precaution needed is the check that it hadn't been replaced with
NULL by rmdir() or by overwriting rename(), which case should be simply
treated as cache miss.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
23 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
fs/adfs/dir.c
fs/affs/namei.c
fs/cifs/dir.c
fs/dcache.c
fs/efivarfs/super.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/gfs2/dentry.c
fs/hfs/hfs_fs.h
fs/hfs/string.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/unicode.c
fs/hpfs/dentry.c
fs/isofs/inode.c
fs/isofs/namei.c
fs/jfs/namei.c
fs/namei.c
fs/ncpfs/dir.c
fs/proc/proc_sysctl.c
fs/sysv/namei.c
include/linux/dcache.h

index bdd82b2..f94a362 100644 (file)
@@ -11,10 +11,8 @@ be able to use diff(1).
 prototypes:
        int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_weak_revalidate)(struct dentry *, unsigned int);
-       int (*d_hash)(const struct dentry *, const struct inode *,
-                       struct qstr *);
-       int (*d_compare)(const struct dentry *, const struct inode *,
-                       const struct dentry *, const struct inode *,
+       int (*d_hash)(const struct dentry *, struct qstr *);
+       int (*d_compare)(const struct dentry *, const struct dentry *,
                        unsigned int, const char *, const struct qstr *);
        int (*d_delete)(struct dentry *);
        void (*d_release)(struct dentry *);
index 4a35f66..51ba44e 100644 (file)
@@ -901,10 +901,8 @@ defined:
 struct dentry_operations {
        int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_weak_revalidate)(struct dentry *, unsigned int);
-       int (*d_hash)(const struct dentry *, const struct inode *,
-                       struct qstr *);
-       int (*d_compare)(const struct dentry *, const struct inode *,
-                       const struct dentry *, const struct inode *,
+       int (*d_hash)(const struct dentry *, struct qstr *);
+       int (*d_compare)(const struct dentry *, const struct dentry *,
                        unsigned int, const char *, const struct qstr *);
        int (*d_delete)(const struct dentry *);
        void (*d_release)(struct dentry *);
@@ -949,25 +947,24 @@ struct dentry_operations {
 
   d_hash: called when the VFS adds a dentry to the hash table. The first
        dentry passed to d_hash is the parent directory that the name is
-       to be hashed into. The inode is the dentry's inode.
+       to be hashed into.
 
        Same locking and synchronisation rules as d_compare regarding
        what is safe to dereference etc.
 
   d_compare: called to compare a dentry name with a given name. The first
        dentry is the parent of the dentry to be compared, the second is
-       the parent's inode, then the dentry and inode (may be NULL) of the
-       child dentry. len and name string are properties of the dentry to be
-       compared. qstr is the name to compare it with.
+       the child dentry. len and name string are properties of the dentry
+       to be compared. qstr is the name to compare it with.
 
        Must be constant and idempotent, and should not take locks if
-       possible, and should not or store into the dentry or inodes.
-       Should not dereference pointers outside the dentry or inodes without
+       possible, and should not or store into the dentry.
+       Should not dereference pointers outside the dentry without
        lots of care (eg.  d_parent, d_inode, d_name should not be used).
 
        However, our vfsmount is pinned, and RCU held, so the dentries and
        inodes won't disappear, neither will our sb or filesystem module.
-       ->i_sb and ->d_sb may be used.
+       ->d_sb may be used.
 
        It is a tricky calling convention because it needs to be called under
        "rcu-walk", ie. without any locks or references on things.
index ade28bb..0d138c0 100644 (file)
@@ -191,8 +191,7 @@ const struct file_operations adfs_dir_operations = {
 };
 
 static int
-adfs_hash(const struct dentry *parent, const struct inode *inode,
-               struct qstr *qstr)
+adfs_hash(const struct dentry *parent, struct qstr *qstr)
 {
        const unsigned int name_len = ADFS_SB(parent->d_sb)->s_namelen;
        const unsigned char *name;
@@ -228,8 +227,7 @@ adfs_hash(const struct dentry *parent, const struct inode *inode,
  * requirements of the underlying filesystem.
  */
 static int
-adfs_compare(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+adfs_compare(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        int i;
index ff65884..c36cbb4 100644 (file)
 typedef int (*toupper_t)(int);
 
 static int      affs_toupper(int ch);
-static int      affs_hash_dentry(const struct dentry *,
-               const struct inode *, struct qstr *);
-static int       affs_compare_dentry(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int      affs_hash_dentry(const struct dentry *, struct qstr *);
+static int       affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 static int      affs_intl_toupper(int ch);
-static int      affs_intl_hash_dentry(const struct dentry *,
-               const struct inode *, struct qstr *);
-static int       affs_intl_compare_dentry(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int      affs_intl_hash_dentry(const struct dentry *, struct qstr *);
+static int       affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 
 const struct dentry_operations affs_dentry_operations = {
@@ -86,14 +80,12 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper)
 }
 
 static int
-affs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
 {
        return __affs_hash_dentry(qstr, affs_toupper);
 }
 static int
-affs_intl_hash_dentry(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
 {
        return __affs_hash_dentry(qstr, affs_intl_toupper);
 }
@@ -131,15 +123,13 @@ static inline int __affs_compare_dentry(unsigned int len,
 }
 
 static int
-affs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        return __affs_compare_dentry(len, str, name, affs_toupper);
 }
 static int
-affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        return __affs_compare_dentry(len, str, name, affs_intl_toupper);
index 5699b50..5175aeb 100644 (file)
@@ -822,8 +822,7 @@ const struct dentry_operations cifs_dentry_ops = {
 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
 };
 
-static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *q)
+static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
 {
        struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
        unsigned long hash;
@@ -838,12 +837,10 @@ static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
        return 0;
 }
 
-static int cifs_ci_compare(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int cifs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
-       struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
+       struct nls_table *codepage = CIFS_SB(parent->d_sb)->local_nls;
 
        if ((name->len == len) &&
            (nls_strnicmp(codepage, name->name, str, len) == 0))
index b692c7e..3199fe6 100644 (file)
@@ -1723,7 +1723,7 @@ EXPORT_SYMBOL(d_add_ci);
  * Do the slow-case of the dentry name compare.
  *
  * Unlike the dentry_cmp() function, we need to atomically
- * load the name, length and inode information, so that the
+ * load the name and length information, so that the
  * filesystem can rely on them, and can use the 'name' and
  * 'len' information without worrying about walking off the
  * end of memory etc.
@@ -1741,22 +1741,18 @@ enum slow_d_compare {
 
 static noinline enum slow_d_compare slow_dentry_cmp(
                const struct dentry *parent,
-               struct inode *inode,
                struct dentry *dentry,
                unsigned int seq,
                const struct qstr *name)
 {
        int tlen = dentry->d_name.len;
        const char *tname = dentry->d_name.name;
-       struct inode *i = dentry->d_inode;
 
        if (read_seqcount_retry(&dentry->d_seq, seq)) {
                cpu_relax();
                return D_COMP_SEQRETRY;
        }
-       if (parent->d_op->d_compare(parent, inode,
-                               dentry, i,
-                               tlen, tname, name))
+       if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
                return D_COMP_NOMATCH;
        return D_COMP_OK;
 }
@@ -1766,7 +1762,6 @@ static noinline enum slow_d_compare slow_dentry_cmp(
  * @parent: parent dentry
  * @name: qstr of name we wish to find
  * @seqp: returns d_seq value at the point where the dentry was found
- * @inode: returns dentry->d_inode when the inode was found valid.
  * Returns: dentry, or NULL
  *
  * __d_lookup_rcu is the dcache lookup function for rcu-walk name
@@ -1793,7 +1788,7 @@ static noinline enum slow_d_compare slow_dentry_cmp(
  */
 struct dentry *__d_lookup_rcu(const struct dentry *parent,
                                const struct qstr *name,
-                               unsigned *seqp, struct inode *inode)
+                               unsigned *seqp)
 {
        u64 hashlen = name->hash_len;
        const unsigned char *str = name->name;
@@ -1827,11 +1822,10 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
 seqretry:
                /*
                 * The dentry sequence count protects us from concurrent
-                * renames, and thus protects inode, parent and name fields.
+                * renames, and thus protects parent and name fields.
                 *
                 * The caller must perform a seqcount check in order
-                * to do anything useful with the returned dentry,
-                * including using the 'd_inode' pointer.
+                * to do anything useful with the returned dentry.
                 *
                 * NOTE! We do a "raw" seqcount_begin here. That means that
                 * we don't wait for the sequence count to stabilize if it
@@ -1845,12 +1839,12 @@ seqretry:
                        continue;
                if (d_unhashed(dentry))
                        continue;
-               *seqp = seq;
 
                if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
                        if (dentry->d_name.hash != hashlen_hash(hashlen))
                                continue;
-                       switch (slow_dentry_cmp(parent, inode, dentry, seq, name)) {
+                       *seqp = seq;
+                       switch (slow_dentry_cmp(parent, dentry, seq, name)) {
                        case D_COMP_OK:
                                return dentry;
                        case D_COMP_NOMATCH:
@@ -1862,6 +1856,7 @@ seqretry:
 
                if (dentry->d_name.hash_len != hashlen)
                        continue;
+               *seqp = seq;
                if (!dentry_cmp(dentry, str, hashlen_len(hashlen)))
                        return dentry;
        }
@@ -1959,9 +1954,7 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
                if (parent->d_flags & DCACHE_OP_COMPARE) {
                        int tlen = dentry->d_name.len;
                        const char *tname = dentry->d_name.name;
-                       if (parent->d_op->d_compare(parent, parent->d_inode,
-                                               dentry, dentry->d_inode,
-                                               tlen, tname, name))
+                       if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
                                goto next;
                } else {
                        if (dentry->d_name.len != len)
@@ -1998,7 +1991,7 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
         */
        name->hash = full_name_hash(name->name, name->len);
        if (dir->d_flags & DCACHE_OP_HASH) {
-               int err = dir->d_op->d_hash(dir, dir->d_inode, name);
+               int err = dir->d_op->d_hash(dir, name);
                if (unlikely(err < 0))
                        return ERR_PTR(err);
        }
index 141aee3..a8766b8 100644 (file)
@@ -45,8 +45,8 @@ static struct super_block *efivarfs_sb;
  * So we need to perform a case-sensitive match on part 1 and a
  * case-insensitive match on part 2.
  */
-static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
-                             const struct dentry *dentry, const struct inode *inode,
+static int efivarfs_d_compare(const struct dentry *parent,
+                             const struct dentry *dentry,
                              unsigned int len, const char *str,
                              const struct qstr *name)
 {
@@ -63,8 +63,7 @@ static int efivarfs_d_compare(const struct dentry *parent, const struct inode *p
        return strncasecmp(name->name + guid, str + guid, EFI_VARIABLE_GUID_LEN);
 }
 
-static int efivarfs_d_hash(const struct dentry *dentry,
-                          const struct inode *inode, struct qstr *qstr)
+static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr)
 {
        unsigned long hash = init_name_hash();
        const unsigned char *s = qstr->name;
@@ -108,7 +107,7 @@ static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
        q.name = name;
        q.len = strlen(name);
 
-       err = efivarfs_d_hash(NULL, NULL, &q);
+       err = efivarfs_d_hash(NULL, &q);
        if (err)
                return ERR_PTR(err);
 
index 081b759..a783b0e 100644 (file)
@@ -148,8 +148,7 @@ static int msdos_find(struct inode *dir, const unsigned char *name, int len,
  * that the existing dentry can be used. The msdos fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int msdos_hash(const struct dentry *dentry, const struct inode *inode,
-              struct qstr *qstr)
+static int msdos_hash(const struct dentry *dentry, struct qstr *qstr)
 {
        struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
        unsigned char msdos_name[MSDOS_NAME];
@@ -165,8 +164,7 @@ static int msdos_hash(const struct dentry *dentry, const struct inode *inode,
  * Compare two msdos names. If either of the names are invalid,
  * we fall back to doing the standard name comparison.
  */
-static int msdos_cmp(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int msdos_cmp(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
index 2da9520..6df8d3d 100644 (file)
@@ -107,8 +107,7 @@ static unsigned int vfat_striptail_len(const struct qstr *qstr)
  * that the existing dentry can be used. The vfat fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+static int vfat_hash(const struct dentry *dentry, struct qstr *qstr)
 {
        qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr));
        return 0;
@@ -120,8 +119,7 @@ static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
  * that the existing dentry can be used. The vfat fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+static int vfat_hashi(const struct dentry *dentry, struct qstr *qstr)
 {
        struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
        const unsigned char *name;
@@ -142,8 +140,7 @@ static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
 /*
  * Case insensitive compare of two vfat names.
  */
-static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int vfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
@@ -162,8 +159,7 @@ static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode,
 /*
  * Case sensitive compare of two vfat names.
  */
-static int vfat_cmp(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int vfat_cmp(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        unsigned int alen, blen;
index 4fddb3c..f2448ab 100644 (file)
@@ -109,8 +109,7 @@ fail:
        return 0;
 }
 
-static int gfs2_dhash(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *str)
+static int gfs2_dhash(const struct dentry *dentry, struct qstr *str)
 {
        str->hash = gfs2_disk_hash(str->name, str->len);
        return 0;
index a73b118..0524cda 100644 (file)
@@ -229,13 +229,10 @@ extern int hfs_part_find(struct super_block *, sector_t *, sector_t *);
 /* string.c */
 extern const struct dentry_operations hfs_dentry_operations;
 
-extern int hfs_hash_dentry(const struct dentry *, const struct inode *,
-               struct qstr *);
+extern int hfs_hash_dentry(const struct dentry *, struct qstr *);
 extern int hfs_strcmp(const unsigned char *, unsigned int,
                      const unsigned char *, unsigned int);
-extern int hfs_compare_dentry(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+extern int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 
 /* trans.c */
index 495a976..85b610c 100644 (file)
@@ -51,8 +51,7 @@ static unsigned char caseorder[256] = {
 /*
  * Hash a string to an integer in a case-independent way
  */
-int hfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *this)
+int hfs_hash_dentry(const struct dentry *dentry, struct qstr *this)
 {
        const unsigned char *name = this->name;
        unsigned int hash, len = this->len;
@@ -93,8 +92,7 @@ int hfs_strcmp(const unsigned char *s1, unsigned int len1,
  * Test for equality of two strings in the HFS filename character ordering.
  * return 1 on failure and 0 on success
  */
-int hfs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        const unsigned char *n1, *n2;
index 60b0a33..ede7931 100644 (file)
@@ -495,11 +495,8 @@ int hfsplus_uni2asc(struct super_block *,
                const struct hfsplus_unistr *, char *, int *);
 int hfsplus_asc2uni(struct super_block *,
                struct hfsplus_unistr *, int, const char *, int);
-int hfsplus_hash_dentry(const struct dentry *dentry,
-               const struct inode *inode, struct qstr *str);
-int hfsplus_compare_dentry(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str);
+int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 
 /* wrapper.c */
index 2c2e47d..e8ef121 100644 (file)
@@ -334,8 +334,7 @@ int hfsplus_asc2uni(struct super_block *sb,
  * Composed unicode characters are decomposed and case-folding is performed
  * if the appropriate bits are (un)set on the superblock.
  */
-int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *str)
+int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
 {
        struct super_block *sb = dentry->d_sb;
        const char *astr;
@@ -386,9 +385,7 @@ int hfsplus_hash_dentry(const struct dentry *dentry, const struct inode *inode,
  * Composed unicode characters are decomposed and case-folding is performed
  * if the appropriate bits are (un)set on the superblock.
  */
-int hfsplus_compare_dentry(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        struct super_block *sb = parent->d_sb;
index 05d4816..fa27980 100644 (file)
@@ -12,8 +12,7 @@
  * Note: the dentry argument is the parent dentry.
  */
 
-static int hpfs_hash_dentry(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+static int hpfs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
 {
        unsigned long    hash;
        int              i;
@@ -35,9 +34,7 @@ static int hpfs_hash_dentry(const struct dentry *dentry, const struct inode *ino
        return 0;
 }
 
-static int hpfs_compare_dentry(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int hpfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        unsigned al = len;
index d9b8aeb..c348d6d 100644 (file)
 
 #define BEQUIET
 
-static int isofs_hashi(const struct dentry *parent, const struct inode *inode,
-               struct qstr *qstr);
-static int isofs_hash(const struct dentry *parent, const struct inode *inode,
-               struct qstr *qstr);
+static int isofs_hashi(const struct dentry *parent, struct qstr *qstr);
+static int isofs_hash(const struct dentry *parent, struct qstr *qstr);
 static int isofs_dentry_cmpi(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+               const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 static int isofs_dentry_cmp(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+               const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 
 #ifdef CONFIG_JOLIET
-static int isofs_hashi_ms(const struct dentry *parent, const struct inode *inode,
-               struct qstr *qstr);
-static int isofs_hash_ms(const struct dentry *parent, const struct inode *inode,
-               struct qstr *qstr);
+static int isofs_hashi_ms(const struct dentry *parent, struct qstr *qstr);
+static int isofs_hash_ms(const struct dentry *parent, struct qstr *qstr);
 static int isofs_dentry_cmpi_ms(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+               const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 static int isofs_dentry_cmp_ms(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+               const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
 #endif
 
@@ -265,30 +257,26 @@ static int isofs_dentry_cmp_common(
 }
 
 static int
-isofs_hash(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+isofs_hash(const struct dentry *dentry, struct qstr *qstr)
 {
        return isofs_hash_common(dentry, qstr, 0);
 }
 
 static int
-isofs_hashi(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+isofs_hashi(const struct dentry *dentry, struct qstr *qstr)
 {
        return isofs_hashi_common(dentry, qstr, 0);
 }
 
 static int
-isofs_dentry_cmp(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmp(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        return isofs_dentry_cmp_common(len, str, name, 0, 0);
 }
 
 static int
-isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        return isofs_dentry_cmp_common(len, str, name, 0, 1);
@@ -296,30 +284,26 @@ isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
 
 #ifdef CONFIG_JOLIET
 static int
-isofs_hash_ms(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr)
 {
        return isofs_hash_common(dentry, qstr, 1);
 }
 
 static int
-isofs_hashi_ms(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+isofs_hashi_ms(const struct dentry *dentry, struct qstr *qstr)
 {
        return isofs_hashi_common(dentry, qstr, 1);
 }
 
 static int
-isofs_dentry_cmp_ms(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmp_ms(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        return isofs_dentry_cmp_common(len, str, name, 1, 0);
 }
 
 static int
-isofs_dentry_cmpi_ms(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+isofs_dentry_cmpi_ms(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        return isofs_dentry_cmp_common(len, str, name, 1, 1);
index c167028..9529564 100644 (file)
@@ -37,8 +37,7 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
 
        qstr.name = compare;
        qstr.len = dlen;
-       return dentry->d_op->d_compare(NULL, NULL, NULL, NULL,
-                       dentry->d_name.len, dentry->d_name.name, &qstr);
+       return dentry->d_op->d_compare(NULL, NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
 }
 
 /*
index 89186b7..8b19027 100644 (file)
@@ -1538,8 +1538,7 @@ const struct file_operations jfs_dir_operations = {
        .llseek         = generic_file_llseek,
 };
 
-static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode,
-               struct qstr *this)
+static int jfs_ci_hash(const struct dentry *dir, struct qstr *this)
 {
        unsigned long hash;
        int i;
@@ -1552,9 +1551,7 @@ static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode,
        return 0;
 }
 
-static int jfs_ci_compare(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int jfs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        int i, result = 1;
index 66998b0..b2beee7 100644 (file)
@@ -1352,7 +1352,7 @@ static int lookup_fast(struct nameidata *nd,
         */
        if (nd->flags & LOOKUP_RCU) {
                unsigned seq;
-               dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode);
+               dentry = __d_lookup_rcu(parent, &nd->last, &seq);
                if (!dentry)
                        goto unlazy;
 
@@ -1787,8 +1787,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        struct dentry *parent = nd->path.dentry;
                        nd->flags &= ~LOOKUP_JUMPED;
                        if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
-                               err = parent->d_op->d_hash(parent, nd->inode,
-                                                          &this);
+                               err = parent->d_op->d_hash(parent, &this);
                                if (err < 0)
                                        break;
                        }
@@ -2121,7 +2120,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
         * to use its own hash..
         */
        if (base->d_flags & DCACHE_OP_HASH) {
-               int err = base->d_op->d_hash(base, base->d_inode, &this);
+               int err = base->d_op->d_hash(base, &this);
                if (err < 0)
                        return ERR_PTR(err);
        }
index 3bc105d..3be0474 100644 (file)
@@ -73,10 +73,8 @@ const struct inode_operations ncp_dir_inode_operations =
  * Dentry operations routines
  */
 static int ncp_lookup_validate(struct dentry *, unsigned int);
-static int ncp_hash_dentry(const struct dentry *, const struct inode *,
-               struct qstr *);
-static int ncp_compare_dentry(const struct dentry *, const struct inode *,
-               const struct dentry *, const struct inode *,
+static int ncp_hash_dentry(const struct dentry *, struct qstr *);
+static int ncp_compare_dentry(const struct dentry *, const struct dentry *,
                unsigned int, const char *, const struct qstr *);
 static int ncp_delete_dentry(const struct dentry *);
 
@@ -119,11 +117,19 @@ static inline int ncp_case_sensitive(const struct inode *i)
 /*
  * Note: leave the hash unchanged if the directory
  * is case-sensitive.
+ *
+ * Accessing the parent inode can be racy under RCU pathwalking.
+ * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
+ * the callers will handle races.
  */
 static int 
-ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *this)
+ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
 {
+       struct inode *inode = ACCESS_ONCE(dentry->d_inode);
+
+       if (!inode)
+               return 0;
+
        if (!ncp_case_sensitive(inode)) {
                struct super_block *sb = dentry->d_sb;
                struct nls_table *t;
@@ -140,14 +146,24 @@ ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
        return 0;
 }
 
+/*
+ * Accessing the parent inode can be racy under RCU pathwalking.
+ * Use ACCESS_ONCE() to make sure we use _one_ particular inode,
+ * the callers will handle races.
+ */
 static int
-ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
+       struct inode *pinode;
+
        if (len != name->len)
                return 1;
 
+       pinode = ACCESS_ONCE(parent->d_inode);
+       if (!pinode)
+               return 1;
+
        if (ncp_case_sensitive(pinode))
                return strncmp(str, name->name, len);
 
index f3a570e..7129046 100644 (file)
@@ -796,15 +796,16 @@ static int sysctl_is_seen(struct ctl_table_header *p)
        return res;
 }
 
-static int proc_sys_compare(const struct dentry *parent,
-               const struct inode *pinode,
-               const struct dentry *dentry, const struct inode *inode,
+static int proc_sys_compare(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
        struct ctl_table_header *head;
+       struct inode *inode;
+
        /* Although proc doesn't have negative dentries, rcu-walk means
         * that inode here can be NULL */
        /* AV: can it, indeed? */
+       inode = ACCESS_ONCE(dentry->d_inode);
        if (!inode)
                return 1;
        if (name->len != len)
index 1c0d5f2..731b2bb 100644 (file)
@@ -27,8 +27,7 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
        return err;
 }
 
-static int sysv_hash(const struct dentry *dentry, const struct inode *inode,
-               struct qstr *qstr)
+static int sysv_hash(const struct dentry *dentry, struct qstr *qstr)
 {
        /* Truncate the name in place, avoids having to define a compare
           function. */
index 86da759..f42dbe1 100644 (file)
@@ -146,10 +146,8 @@ enum dentry_d_lock_class
 struct dentry_operations {
        int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_weak_revalidate)(struct dentry *, unsigned int);
-       int (*d_hash)(const struct dentry *, const struct inode *,
-                       struct qstr *);
-       int (*d_compare)(const struct dentry *, const struct inode *,
-                       const struct dentry *, const struct inode *,
+       int (*d_hash)(const struct dentry *, struct qstr *);
+       int (*d_compare)(const struct dentry *, const struct dentry *,
                        unsigned int, const char *, const struct qstr *);
        int (*d_delete)(const struct dentry *);
        void (*d_release)(struct dentry *);
@@ -302,8 +300,7 @@ extern struct dentry *d_lookup(const struct dentry *, const struct qstr *);
 extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *);
 extern struct dentry *__d_lookup(const struct dentry *, const struct qstr *);
 extern struct dentry *__d_lookup_rcu(const struct dentry *parent,
-                               const struct qstr *name,
-                               unsigned *seq, struct inode *inode);
+                               const struct qstr *name, unsigned *seq);
 
 /**
  * __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok