drm/rockchip: add DRM_RENDER_ALLOW
[firefly-linux-kernel-4.4.55.git] / include / linux / dcache.h
index 1a6bb81f0fe5a13d93c799cfbcd4062d0e288c28..d184e283cf81e268d0e3cd94d4fdb4d45951cad4 100644 (file)
@@ -9,8 +9,8 @@
 #include <linux/seqlock.h>
 #include <linux/cache.h>
 #include <linux/rcupdate.h>
+#include <linux/lockref.h>
 
-struct nameidata;
 struct path;
 struct vfsmount;
 
@@ -28,8 +28,10 @@ struct vfsmount;
 /* The hash is always the low bits of hash_len */
 #ifdef __LITTLE_ENDIAN
  #define HASH_LEN_DECLARE u32 hash; u32 len;
+ #define bytemask_from_count(cnt)      (~(~0ul << (cnt)*8))
 #else
  #define HASH_LEN_DECLARE u32 len; u32 hash;
+ #define bytemask_from_count(cnt)      (~(~0ul >> (cnt)*8))
 #endif
 
 /*
@@ -52,13 +54,14 @@ struct qstr {
 #define QSTR_INIT(n,l) { { { .len = l } }, .name = n }
 #define hashlen_hash(hashlen) ((u32) (hashlen))
 #define hashlen_len(hashlen)  ((u32)((hashlen) >> 32))
+#define hashlen_create(hash,len) (((u64)(len)<<32)|(u32)(hash))
 
 struct dentry_stat_t {
-       int nr_dentry;
-       int nr_unused;
-       int age_limit;          /* age in seconds */
-       int want_pages;         /* pages requested by system */
-       int dummy[2];
+       long nr_dentry;
+       long nr_unused;
+       long age_limit;          /* age in seconds */
+       long want_pages;         /* pages requested by system */
+       long dummy[2];
 };
 extern struct dentry_stat_t dentry_stat;
 
@@ -100,6 +103,8 @@ extern unsigned int full_name_hash(const unsigned char *, unsigned int);
 # endif
 #endif
 
+#define d_lock d_lockref.lock
+
 struct dentry {
        /* RCU lookup touched fields */
        unsigned int d_flags;           /* protected by d_lock */
@@ -112,23 +117,22 @@ struct dentry {
        unsigned char d_iname[DNAME_INLINE_LEN];        /* small names */
 
        /* Ref lookup also touches following */
-       unsigned int d_count;           /* protected by d_lock */
-       spinlock_t d_lock;              /* per dentry lock */
+       struct lockref d_lockref;       /* per-dentry lock and refcount */
        const struct dentry_operations *d_op;
        struct super_block *d_sb;       /* The root of the dentry tree */
        unsigned long d_time;           /* used by d_revalidate */
        void *d_fsdata;                 /* fs-specific data */
 
        struct list_head d_lru;         /* LRU list */
+       struct list_head d_child;       /* child of parent list */
+       struct list_head d_subdirs;     /* our children */
        /*
-        * d_child and d_rcu can share memory
+        * d_alias and d_rcu can share memory
         */
        union {
-               struct list_head d_child;       /* child of parent list */
+               struct hlist_node d_alias;      /* inode alias list */
                struct rcu_head d_rcu;
        } d_u;
-       struct list_head d_subdirs;     /* our children */
-       struct hlist_node d_alias;      /* inode alias list */
 };
 
 /*
@@ -146,10 +150,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 *);
@@ -158,6 +160,9 @@ struct dentry_operations {
        char *(*d_dname)(struct dentry *, char *, int);
        struct vfsmount *(*d_automount)(struct path *);
        int (*d_manage)(struct dentry *, bool);
+       struct inode *(*d_select_inode)(struct dentry *, unsigned);
+       void (*d_canonical_path)(const struct dentry *, struct path *);
+       struct dentry *(*d_real)(struct dentry *, struct inode *);
 } ____cacheline_aligned;
 
 /*
@@ -169,13 +174,13 @@ struct dentry_operations {
  */
 
 /* d_flags entries */
-#define DCACHE_OP_HASH         0x0001
-#define DCACHE_OP_COMPARE      0x0002
-#define DCACHE_OP_REVALIDATE   0x0004
-#define DCACHE_OP_DELETE       0x0008
-#define DCACHE_OP_PRUNE         0x0010
+#define DCACHE_OP_HASH                 0x00000001
+#define DCACHE_OP_COMPARE              0x00000002
+#define DCACHE_OP_REVALIDATE           0x00000004
+#define DCACHE_OP_DELETE               0x00000008
+#define DCACHE_OP_PRUNE                        0x00000010
 
-#define        DCACHE_DISCONNECTED     0x0020
+#define        DCACHE_DISCONNECTED             0x00000020
      /* This dentry is possibly not currently connected to the dcache tree, in
       * which case its parent will either be itself, or will have this flag as
       * well.  nfsd will not use a dentry with this bit set, but will first
@@ -186,43 +191,54 @@ struct dentry_operations {
       * dentry into place and return that dentry rather than the passed one,
       * typically using d_splice_alias. */
 
-#define DCACHE_REFERENCED      0x0040  /* Recently used, don't discard. */
-#define DCACHE_RCUACCESS       0x0080  /* Entry has ever been RCU-visible */
+#define DCACHE_REFERENCED              0x00000040 /* Recently used, don't discard. */
+#define DCACHE_RCUACCESS               0x00000080 /* Entry has ever been RCU-visible */
 
-#define DCACHE_CANT_MOUNT      0x0100
-#define DCACHE_GENOCIDE                0x0200
-#define DCACHE_SHRINK_LIST     0x0400
+#define DCACHE_CANT_MOUNT              0x00000100
+#define DCACHE_GENOCIDE                        0x00000200
+#define DCACHE_SHRINK_LIST             0x00000400
 
-#define DCACHE_OP_WEAK_REVALIDATE      0x0800
+#define DCACHE_OP_WEAK_REVALIDATE      0x00000800
 
-#define DCACHE_NFSFS_RENAMED   0x1000
+#define DCACHE_NFSFS_RENAMED           0x00001000
      /* this dentry has been "silly renamed" and has to be deleted on the last
       * dput() */
-#define DCACHE_COOKIE          0x2000  /* For use by dcookie subsystem */
-#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x4000
+#define DCACHE_COOKIE                  0x00002000 /* For use by dcookie subsystem */
+#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x00004000
      /* Parent inode is watched by some fsnotify listener */
 
-#define DCACHE_MOUNTED         0x10000 /* is a mountpoint */
-#define DCACHE_NEED_AUTOMOUNT  0x20000 /* handle automount on this dir */
-#define DCACHE_MANAGE_TRANSIT  0x40000 /* manage transit from this dirent */
+#define DCACHE_DENTRY_KILLED           0x00008000
+
+#define DCACHE_MOUNTED                 0x00010000 /* is a mountpoint */
+#define DCACHE_NEED_AUTOMOUNT          0x00020000 /* handle automount on this dir */
+#define DCACHE_MANAGE_TRANSIT          0x00040000 /* manage transit from this dirent */
 #define DCACHE_MANAGED_DENTRY \
        (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
 
-#define DCACHE_DENTRY_KILLED   0x100000
+#define DCACHE_LRU_LIST                        0x00080000
 
-extern seqlock_t rename_lock;
+#define DCACHE_ENTRY_TYPE              0x00700000
+#define DCACHE_MISS_TYPE               0x00000000 /* Negative dentry (maybe fallthru to nowhere) */
+#define DCACHE_WHITEOUT_TYPE           0x00100000 /* Whiteout dentry (stop pathwalk) */
+#define DCACHE_DIRECTORY_TYPE          0x00200000 /* Normal directory */
+#define DCACHE_AUTODIR_TYPE            0x00300000 /* Lookupless directory (presumed automount) */
+#define DCACHE_REGULAR_TYPE            0x00400000 /* Regular file type (or fallthru to such) */
+#define DCACHE_SPECIAL_TYPE            0x00500000 /* Other file type (or fallthru to such) */
+#define DCACHE_SYMLINK_TYPE            0x00600000 /* Symlink (or fallthru to such) */
 
-static inline int dname_external(struct dentry *dentry)
-{
-       return dentry->d_name.name != dentry->d_iname;
-}
+#define DCACHE_MAY_FREE                        0x00800000
+#define DCACHE_FALLTHRU                        0x01000000 /* Fall through to lower layer */
+#define DCACHE_OP_SELECT_INODE         0x02000000 /* Unioned entry: dcache op selects inode */
+#define DCACHE_OP_REAL                 0x08000000
+
+extern seqlock_t rename_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 struct dentry * d_materialise_unique(struct dentry *, struct inode *);
+extern int d_instantiate_no_diralias(struct dentry *, struct inode *);
 extern void __d_drop(struct dentry *dentry);
 extern void d_drop(struct dentry *dentry);
 extern void d_delete(struct dentry *);
@@ -235,10 +251,11 @@ extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
 extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
 extern struct dentry *d_find_any_alias(struct inode *inode);
 extern struct dentry * d_obtain_alias(struct inode *);
+extern struct dentry * d_obtain_root(struct inode *);
 extern void shrink_dcache_sb(struct super_block *);
 extern void shrink_dcache_parent(struct dentry *);
 extern void shrink_dcache_for_umount(struct super_block *);
-extern int d_invalidate(struct dentry *);
+extern void d_invalidate(struct dentry *);
 
 /* only used at mount-time */
 extern struct dentry * d_make_root(struct inode *);
@@ -246,6 +263,8 @@ extern struct dentry * d_make_root(struct inode *);
 /* <clickety>-<click> the ramfs-type tree */
 extern void d_genocide(struct dentry *);
 
+extern void d_tmpfile(struct dentry *, struct inode *);
+
 extern struct dentry *d_find_alias(struct inode *);
 extern void d_prune_aliases(struct inode *);
 
@@ -293,6 +312,7 @@ extern void dentry_update_name_case(struct dentry *, struct qstr *);
 
 /* used for rename() and baskets */
 extern void d_move(struct dentry *, struct dentry *);
+extern void d_exchange(struct dentry *, struct dentry *);
 extern struct dentry *d_ancestor(struct dentry *, struct dentry *);
 
 /* appendix may either be NULL or be used for transname suffixes */
@@ -300,38 +320,19 @@ 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
- * @dentry: dentry to take a ref on
- * @seq: seqcount to verify against
- * Returns: 0 on failure, else 1.
- *
- * __d_rcu_to_refcount operates on a dentry,seq pair that was returned
- * by __d_lookup_rcu, to get a reference on an rcu-walk dentry.
- */
-static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq)
+static inline unsigned d_count(const struct dentry *dentry)
 {
-       int ret = 0;
-
-       assert_spin_locked(&dentry->d_lock);
-       if (!read_seqcount_retry(&dentry->d_seq, seq)) {
-               ret = 1;
-               dentry->d_count++;
-       }
-
-       return ret;
+       return dentry->d_lockref.count;
 }
 
-/* validate "insecure" dentry pointer */
-extern int d_validate(struct dentry *, struct dentry *);
-
 /*
  * helper function for dentry_operations.d_dname() members
  */
-extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern __printf(4, 5)
+char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+extern char *simple_dname(struct dentry *, char *, int);
 
 extern char *__d_path(const struct path *, const struct path *, char *, int);
 extern char *d_absolute_path(const struct path *, char *, int);
@@ -352,17 +353,14 @@ extern char *dentry_path(struct dentry *, char *, int);
 static inline struct dentry *dget_dlock(struct dentry *dentry)
 {
        if (dentry)
-               dentry->d_count++;
+               dentry->d_lockref.count++;
        return dentry;
 }
 
 static inline struct dentry *dget(struct dentry *dentry)
 {
-       if (dentry) {
-               spin_lock(&dentry->d_lock);
-               dget_dlock(dentry);
-               spin_unlock(&dentry->d_lock);
-       }
+       if (dentry)
+               lockref_get(&dentry->d_lockref);
        return dentry;
 }
 
@@ -375,17 +373,17 @@ extern struct dentry *dget_parent(struct dentry *dentry);
  *     Returns true if the dentry passed is not currently hashed.
  */
  
-static inline int d_unhashed(struct dentry *dentry)
+static inline int d_unhashed(const struct dentry *dentry)
 {
        return hlist_bl_unhashed(&dentry->d_hash);
 }
 
-static inline int d_unlinked(struct dentry *dentry)
+static inline int d_unlinked(const struct dentry *dentry)
 {
        return d_unhashed(dentry) && !IS_ROOT(dentry);
 }
 
-static inline int cant_mount(struct dentry *dentry)
+static inline int cant_mount(const struct dentry *dentry)
 {
        return (dentry->d_flags & DCACHE_CANT_MOUNT);
 }
@@ -399,16 +397,212 @@ static inline void dont_mount(struct dentry *dentry)
 
 extern void dput(struct dentry *);
 
-static inline bool d_managed(struct dentry *dentry)
+static inline bool d_managed(const struct dentry *dentry)
 {
        return dentry->d_flags & DCACHE_MANAGED_DENTRY;
 }
 
-static inline bool d_mountpoint(struct dentry *dentry)
+static inline bool d_mountpoint(const struct dentry *dentry)
 {
        return dentry->d_flags & DCACHE_MOUNTED;
 }
 
+/*
+ * Directory cache entry type accessor functions.
+ */
+static inline unsigned __d_entry_type(const struct dentry *dentry)
+{
+       return dentry->d_flags & DCACHE_ENTRY_TYPE;
+}
+
+static inline bool d_is_miss(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_MISS_TYPE;
+}
+
+static inline bool d_is_whiteout(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_WHITEOUT_TYPE;
+}
+
+static inline bool d_can_lookup(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE;
+}
+
+static inline bool d_is_autodir(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE;
+}
+
+static inline bool d_is_dir(const struct dentry *dentry)
+{
+       return d_can_lookup(dentry) || d_is_autodir(dentry);
+}
+
+static inline bool d_is_symlink(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE;
+}
+
+static inline bool d_is_reg(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_REGULAR_TYPE;
+}
+
+static inline bool d_is_special(const struct dentry *dentry)
+{
+       return __d_entry_type(dentry) == DCACHE_SPECIAL_TYPE;
+}
+
+static inline bool d_is_file(const struct dentry *dentry)
+{
+       return d_is_reg(dentry) || d_is_special(dentry);
+}
+
+static inline bool d_is_negative(const struct dentry *dentry)
+{
+       // TODO: check d_is_whiteout(dentry) also.
+       return d_is_miss(dentry);
+}
+
+static inline bool d_is_positive(const struct dentry *dentry)
+{
+       return !d_is_negative(dentry);
+}
+
+/**
+ * d_really_is_negative - Determine if a dentry is really negative (ignoring fallthroughs)
+ * @dentry: The dentry in question
+ *
+ * Returns true if the dentry represents either an absent name or a name that
+ * doesn't map to an inode (ie. ->d_inode is NULL).  The dentry could represent
+ * a true miss, a whiteout that isn't represented by a 0,0 chardev or a
+ * fallthrough marker in an opaque directory.
+ *
+ * Note!  (1) This should be used *only* by a filesystem to examine its own
+ * dentries.  It should not be used to look at some other filesystem's
+ * dentries.  (2) It should also be used in combination with d_inode() to get
+ * the inode.  (3) The dentry may have something attached to ->d_lower and the
+ * type field of the flags may be set to something other than miss or whiteout.
+ */
+static inline bool d_really_is_negative(const struct dentry *dentry)
+{
+       return dentry->d_inode == NULL;
+}
+
+/**
+ * d_really_is_positive - Determine if a dentry is really positive (ignoring fallthroughs)
+ * @dentry: The dentry in question
+ *
+ * Returns true if the dentry represents a name that maps to an inode
+ * (ie. ->d_inode is not NULL).  The dentry might still represent a whiteout if
+ * that is represented on medium as a 0,0 chardev.
+ *
+ * Note!  (1) This should be used *only* by a filesystem to examine its own
+ * dentries.  It should not be used to look at some other filesystem's
+ * dentries.  (2) It should also be used in combination with d_inode() to get
+ * the inode.
+ */
+static inline bool d_really_is_positive(const struct dentry *dentry)
+{
+       return dentry->d_inode != NULL;
+}
+
+static inline int simple_positive(struct dentry *dentry)
+{
+       return d_really_is_positive(dentry) && !d_unhashed(dentry);
+}
+
+extern void d_set_fallthru(struct dentry *dentry);
+
+static inline bool d_is_fallthru(const struct dentry *dentry)
+{
+       return dentry->d_flags & DCACHE_FALLTHRU;
+}
+
+
 extern int sysctl_vfs_cache_pressure;
 
+static inline unsigned long vfs_pressure_ratio(unsigned long val)
+{
+       return mult_frac(val, sysctl_vfs_cache_pressure, 100);
+}
+
+/**
+ * d_inode - Get the actual inode of this dentry
+ * @dentry: The dentry to query
+ *
+ * This is the helper normal filesystems should use to get at their own inodes
+ * in their own dentries and ignore the layering superimposed upon them.
+ */
+static inline struct inode *d_inode(const struct dentry *dentry)
+{
+       return dentry->d_inode;
+}
+
+/**
+ * d_inode_rcu - Get the actual inode of this dentry with ACCESS_ONCE()
+ * @dentry: The dentry to query
+ *
+ * This is the helper normal filesystems should use to get at their own inodes
+ * in their own dentries and ignore the layering superimposed upon them.
+ */
+static inline struct inode *d_inode_rcu(const struct dentry *dentry)
+{
+       return ACCESS_ONCE(dentry->d_inode);
+}
+
+/**
+ * d_backing_inode - Get upper or lower inode we should be using
+ * @upper: The upper layer
+ *
+ * This is the helper that should be used to get at the inode that will be used
+ * if this dentry were to be opened as a file.  The inode may be on the upper
+ * dentry or it may be on a lower dentry pinned by the upper.
+ *
+ * Normal filesystems should not use this to access their own inodes.
+ */
+static inline struct inode *d_backing_inode(const struct dentry *upper)
+{
+       struct inode *inode = upper->d_inode;
+
+       return inode;
+}
+
+/**
+ * d_backing_dentry - Get upper or lower dentry we should be using
+ * @upper: The upper layer
+ *
+ * This is the helper that should be used to get the dentry of the inode that
+ * will be used if this dentry were opened as a file.  It may be the upper
+ * dentry or it may be a lower dentry pinned by the upper.
+ *
+ * Normal filesystems should not use this to access their own dentries.
+ */
+static inline struct dentry *d_backing_dentry(struct dentry *upper)
+{
+       return upper;
+}
+
+static inline struct dentry *d_real(struct dentry *dentry)
+{
+       if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
+               return dentry->d_op->d_real(dentry, NULL);
+       else
+               return dentry;
+}
+
+static inline struct inode *vfs_select_inode(struct dentry *dentry,
+                                            unsigned open_flags)
+{
+       struct inode *inode = d_inode(dentry);
+
+       if (inode && unlikely(dentry->d_flags & DCACHE_OP_SELECT_INODE))
+               inode = dentry->d_op->d_select_inode(dentry, open_flags);
+
+       return inode;
+}
+
+
 #endif /* __LINUX_DCACHE_H */