]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/dcache.c
Merge tag 'module-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg...
[karo-tx-linux.git] / fs / dcache.c
index 303ebd98bc8025ee79f3b37db00e81a04b99fad9..e9a07b2a09486c019f5967bbafae522ccc9073aa 100644 (file)
@@ -104,11 +104,11 @@ static unsigned int d_hash_shift __read_mostly;
 
 static struct hlist_bl_head *dentry_hashtable __read_mostly;
 
-static inline struct hlist_bl_head *d_hash(struct dentry *parent,
-                                       unsigned long hash)
+static inline struct hlist_bl_head *d_hash(const struct dentry *parent,
+                                       unsigned int hash)
 {
-       hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES;
-       hash = hash ^ ((hash ^ GOLDEN_RATIO_PRIME) >> D_HASHBITS);
+       hash += (unsigned long) parent / L1_CACHE_BYTES;
+       hash = hash + (hash >> D_HASHBITS);
        return dentry_hashtable + (hash & D_HASHMASK);
 }
 
@@ -137,6 +137,49 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
 }
 #endif
 
+/*
+ * Compare 2 name strings, return 0 if they match, otherwise non-zero.
+ * The strings are both count bytes long, and count is non-zero.
+ */
+static inline int dentry_cmp(const unsigned char *cs, size_t scount,
+                               const unsigned char *ct, size_t tcount)
+{
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+       unsigned long a,b,mask;
+
+       if (unlikely(scount != tcount))
+               return 1;
+
+       for (;;) {
+               a = *(unsigned long *)cs;
+               b = *(unsigned long *)ct;
+               if (tcount < sizeof(unsigned long))
+                       break;
+               if (unlikely(a != b))
+                       return 1;
+               cs += sizeof(unsigned long);
+               ct += sizeof(unsigned long);
+               tcount -= sizeof(unsigned long);
+               if (!tcount)
+                       return 0;
+       }
+       mask = ~(~0ul << tcount*8);
+       return unlikely(!!((a ^ b) & mask));
+#else
+       if (scount != tcount)
+               return 1;
+
+       do {
+               if (*cs != *ct)
+                       return 1;
+               cs++;
+               ct++;
+               tcount--;
+       } while (tcount);
+       return 0;
+#endif
+}
+
 static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
@@ -1423,30 +1466,6 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 
 EXPORT_SYMBOL(d_instantiate_unique);
 
-/**
- * d_alloc_root - allocate root dentry
- * @root_inode: inode to allocate the root for
- *
- * Allocate a root ("/") dentry for the inode given. The inode is
- * instantiated and returned. %NULL is returned if there is insufficient
- * memory or the inode passed is %NULL.
- */
-struct dentry * d_alloc_root(struct inode * root_inode)
-{
-       struct dentry *res = NULL;
-
-       if (root_inode) {
-               static const struct qstr name = { .name = "/", .len = 1 };
-
-               res = __d_alloc(root_inode->i_sb, &name);
-               if (res)
-                       d_instantiate(res, root_inode);
-       }
-       return res;
-}
-EXPORT_SYMBOL(d_alloc_root);
-
 struct dentry *d_make_root(struct inode *root_inode)
 {
        struct dentry *res = NULL;
@@ -1694,7 +1713,7 @@ EXPORT_SYMBOL(d_add_ci);
  * __d_lookup_rcu - search for a dentry (racy, store-free)
  * @parent: parent dentry
  * @name: qstr of name we wish to find
- * @seq: returns d_seq value at the point where the dentry was found
+ * @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
  *
@@ -1717,8 +1736,9 @@ EXPORT_SYMBOL(d_add_ci);
  * child is looked up. Thus, an interlocking stepping of sequence lock checks
  * is formed, giving integrity down the path walk.
  */
-struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
-                               unsigned *seq, struct inode **inode)
+struct dentry *__d_lookup_rcu(const struct dentry *parent,
+                               const struct qstr *name,
+                               unsigned *seqp, struct inode **inode)
 {
        unsigned int len = name->len;
        unsigned int hash = name->hash;
@@ -1748,6 +1768,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
         * See Documentation/filesystems/path-lookup.txt for more details.
         */
        hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
+               unsigned seq;
                struct inode *i;
                const char *tname;
                int tlen;
@@ -1756,7 +1777,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
                        continue;
 
 seqretry:
-               *seq = read_seqcount_begin(&dentry->d_seq);
+               seq = read_seqcount_begin(&dentry->d_seq);
                if (dentry->d_parent != parent)
                        continue;
                if (d_unhashed(dentry))
@@ -1771,7 +1792,7 @@ seqretry:
                 * edge of memory when walking. If we could load this
                 * atomically some other way, we could drop this check.
                 */
-               if (read_seqcount_retry(&dentry->d_seq, *seq))
+               if (read_seqcount_retry(&dentry->d_seq, seq))
                        goto seqretry;
                if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
                        if (parent->d_op->d_compare(parent, *inode,
@@ -1788,6 +1809,7 @@ seqretry:
                 * order to do anything useful with the returned dentry
                 * anyway.
                 */
+               *seqp = seq;
                *inode = i;
                return dentry;
        }