Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / include / linux / dcache.h
index 74f22a1..4607ee9 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 #include <linux/rcupdate.h>
-#include <asm/bug.h>
 
 struct nameidata;
 struct vfsmount;
@@ -27,12 +26,14 @@ 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 in the
+ * dentry.
  */
 struct qstr {
-       const unsigned char * name;
-       unsigned int len;
        unsigned int hash;
-       char name_str[0];
+       unsigned int len;
+       const unsigned char *name;
 };
 
 struct dentry_stat_t {
@@ -74,38 +75,46 @@ full_name_hash(const unsigned char *name, unsigned int len)
        return end_name_hash(hash);
 }
 
-#define DNAME_INLINE_LEN_MIN 24
-
 struct dcookie_struct;
+
+#define DNAME_INLINE_LEN_MIN 36
+
 struct dentry {
        atomic_t d_count;
+       unsigned int d_flags;           /* protected by d_lock */
        spinlock_t d_lock;              /* per dentry lock */
-       unsigned long d_vfs_flags;      /* moved here to be on same cacheline */
-       struct inode  * d_inode;        /* Where the name belongs to - NULL is negative */
+       struct inode *d_inode;          /* Where the name belongs to - NULL is
+                                        * negative */
+       /*
+        * The next three fields are touched by __d_lookup.  Place them here
+        * so they all fit in a cache line.
+        */
+       struct hlist_node d_hash;       /* lookup hash list */
+       struct dentry *d_parent;        /* parent directory */
+       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 */
-       unsigned int d_flags;
+       struct dentry_operations *d_op;
+       struct super_block *d_sb;       /* The root of the dentry tree */
+       void *d_fsdata;                 /* fs-specific data */
+       void *d_extra_attributes;       /* TUX-specific data */
+#ifdef CONFIG_PROFILING
+       struct dcookie_struct *d_cookie; /* cookie, if any */
+#endif
        int d_mounted;
-       void * d_fsdata;                /* fs-specific data */
-       struct rcu_head d_rcu;
-       struct dcookie_struct * d_cookie; /* cookie, if any */
-       unsigned long d_move_count;     /* to indicated moved dentry while lockless lookup */
-       struct qstr * d_qstr;           /* quick str ptr used in lockless lookup and concurrent d_move */
-       struct dentry * d_parent;       /* parent directory */
-       struct qstr d_name;
-       struct hlist_node d_hash;       /* lookup hash list */  
-       struct hlist_head * d_bucket;   /* lookup hash bucket */
-       unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
+       unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* small names */
 };
 
-#define DNAME_INLINE_LEN       (sizeof(struct dentry)-offsetof(struct dentry,d_iname))
 struct dentry_operations {
        int (*d_revalidate)(struct dentry *, struct nameidata *);
        int (*d_hash) (struct dentry *, struct qstr *);
@@ -124,13 +133,13 @@ struct dentry_operations {
 
 /*
 locking rules:
-               big lock        dcache_lock     may block
-d_revalidate:  no              no              yes
-d_hash         no              no              yes
-d_compare:     no              yes             no
-d_delete:      no              yes             no
-d_release:     no              no              yes
-d_iput:                no              no              yes
+               big lock        dcache_lock     d_lock   may block
+d_revalidate:  no              no              no       yes
+d_hash         no              no              no       yes
+d_compare:     no              yes             yes      no
+d_delete:      no              yes             no       no
+d_release:     no              no              no       yes
+d_iput:                no              no              no       yes
  */
 
 /* d_flags entries */
@@ -154,29 +163,30 @@ d_iput:           no              no              yes
 #define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
 #define DCACHE_UNHASHED                0x0010  
 
+#define DCACHE_INOTIFY_PARENT_WATCHED  0x0020 /* Parent inode is watched */
+
 extern spinlock_t dcache_lock;
 
 /**
  * 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)
 {
-       if (!(dentry->d_vfs_flags & DCACHE_UNHASHED)) {
-               dentry->d_vfs_flags |= DCACHE_UNHASHED;
+       if (!(dentry->d_flags & DCACHE_UNHASHED)) {
+               dentry->d_flags |= DCACHE_UNHASHED;
                hlist_del_rcu(&dentry->d_hash);
        }
 }
@@ -184,19 +194,22 @@ 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);
 }
 
-static inline int dname_external(struct dentry *d)
+static inline int dname_external(struct dentry *dentry)
 {
-       return d->d_name.name != d->d_iname; 
+       return dentry->d_name.name != dentry->d_iname;
 }
 
 /*
  * 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 */
@@ -207,6 +220,7 @@ extern void shrink_dcache_sb(struct super_block *);
 extern void shrink_dcache_parent(struct dentry *);
 extern void shrink_dcache_anon(struct hlist_head *);
 extern int d_invalidate(struct dentry *);
+extern void flush_dentry_attributes(void);
 
 /* only used at mount-time */
 extern struct dentry * d_alloc_root(struct inode *);
@@ -240,18 +254,40 @@ static inline void d_add(struct dentry *entry, struct inode *inode)
        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 *);
 
 /* appendix may either be NULL or be used for transname suffixes */
 extern struct dentry * d_lookup(struct dentry *, struct qstr *);
 extern struct dentry * __d_lookup(struct dentry *, struct qstr *);
+extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *);
 
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
 
+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
+                struct dentry *root, struct vfsmount *rootmnt,
+                char *buffer, int buflen);
+
 extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
-  
+
 /* Allocation counts.. */
 
 /**
@@ -287,7 +323,7 @@ extern struct dentry * dget_locked(struct dentry *);
  
 static inline int d_unhashed(struct dentry *dentry)
 {
-       return (dentry->d_vfs_flags & DCACHE_UNHASHED);
+       return (dentry->d_flags & DCACHE_UNHASHED);
 }
 
 static inline struct dentry *dget_parent(struct dentry *dentry)
@@ -308,8 +344,11 @@ static inline int d_mountpoint(struct dentry *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;
+
 #endif /* __KERNEL__ */
 
 #endif /* __LINUX_DCACHE_H */