#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/rcupdate.h>
-#include <asm/bug.h>
struct nameidata;
struct vfsmount;
* "quick string" -- eases parameter passing, but more importantly
* saves "metadata" about the string (ie length and the hash).
*
- * hash comes first so it snuggles against d_parent and d_bucket in the
+ * hash comes first so it snuggles against d_parent in the
* dentry.
*/
struct qstr {
unsigned int hash;
- const unsigned char *name;
unsigned int len;
+ const unsigned char *name;
};
struct dentry_stat_t {
* negative */
/*
* The next three fields are touched by __d_lookup. Place them here
- * so they all fit in a 16-byte range, with 16-byte alignment.
+ * so they all fit in a cache line.
*/
+ struct hlist_node d_hash; /* lookup hash list */
struct dentry *d_parent; /* parent directory */
- struct hlist_head *d_bucket; /* lookup hash bucket */
struct qstr d_name;
struct list_head d_lru; /* LRU list */
- struct list_head d_child; /* child of parent list */
+ /*
+ * d_child and d_rcu can share memory
+ */
+ union {
+ struct list_head d_child; /* child of parent list */
+ struct rcu_head d_rcu;
+ } d_u;
struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op;
struct super_block *d_sb; /* The root of the dentry tree */
- int d_mounted;
void *d_fsdata; /* fs-specific data */
- struct rcu_head d_rcu;
+#ifdef CONFIG_PROFILING
struct dcookie_struct *d_cookie; /* cookie, if any */
- struct hlist_node d_hash; /* lookup hash list */
+#endif
+ int d_mounted;
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};
* d_drop - drop a dentry
* @dentry: dentry to drop
*
- * d_drop() unhashes the entry from the parent
- * dentry hashes, so that it won't be found through
- * a VFS lookup any more. Note that this is different
- * from deleting the dentry - d_delete will try to
- * mark the dentry negative if possible, giving a
- * successful _negative_ lookup, while d_drop will
+ * d_drop() unhashes the entry from the parent dentry hashes, so that it won't
+ * be found through a VFS lookup any more. Note that this is different from
+ * deleting the dentry - d_delete will try to mark the dentry negative if
+ * possible, giving a successful _negative_ lookup, while d_drop will
* just make the cache lookup fail.
*
- * d_drop() is used mainly for stuff that wants
- * to invalidate a dentry for some reason (NFS
- * timeouts or autofs deletes).
+ * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
+ * reason (NFS timeouts or autofs deletes).
+ *
+ * __d_drop requires dentry->d_lock.
*/
static inline void __d_drop(struct dentry *dentry)
static inline void d_drop(struct dentry *dentry)
{
spin_lock(&dcache_lock);
+ spin_lock(&dentry->d_lock);
__d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
}
* These are the low-level FS interfaces to the dcache..
*/
extern void d_instantiate(struct dentry *, struct inode *);
+extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *);
extern void d_delete(struct dentry *);
/* allocate/de-allocate */
d_rehash(entry);
}
+/**
+ * d_add_unique - add dentry to hash queues without aliasing
+ * @entry: dentry to add
+ * @inode: The inode to attach to this dentry
+ *
+ * This adds the entry to the hash queues and initializes @inode.
+ * The entry was actually filled in earlier during d_alloc().
+ */
+static inline struct dentry *d_add_unique(struct dentry *entry, struct inode *inode)
+{
+ struct dentry *res;
+
+ res = d_instantiate_unique(entry, inode);
+ d_rehash(res != NULL ? res : entry);
+ return res;
+}
+
/* used for rename() and baskets */
extern void d_move(struct dentry *, struct dentry *);
}
extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *);
+extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
extern int sysctl_vfs_cache_pressure;