aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:56 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:28 -0500
commit44a7d7a878c9cbb74f236ea755b25b6b2e26a9a9 (patch)
treed4630a38c0d683a7e1b8823d7971753719b8a54d /include
parentfb045adb99d9b7c562dc7fef834857f78249daa1 (diff)
fs: cache optimise dentry and inode for rcu-walk
Put dentry and inode fields into top of data structure. This allows RCU path traversal to perform an RCU dentry lookup in a path walk by touching only the first 56 bytes of the dentry. We also fit in 8 bytes of inline name in the first 64 bytes, so for short names, only 64 bytes needs to be touched to perform the lookup. We should get rid of the hash->prev pointer from the first 64 bytes, and fit 16 bytes of name in there, which will take care of 81% rather than 32% of the kernel tree. inode is also rearranged so that RCU lookup will only touch a single cacheline in the inode, plus one in the i_ops structure. This is important for directory component lookups in RCU path walking. In the kernel source, directory names average is around 6 chars, so this works. When we reach the last element of the lookup, we need to lock it and take its refcount which requires another cacheline access. Align dentry and inode operations structs, so members will be at predictable offsets and we can group common operations into head of structure. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'include')
-rw-r--r--include/linux/dcache.h36
-rw-r--r--include/linux/fs.h42
2 files changed, 42 insertions, 36 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index f4b40a751f09..b1aeda077258 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -82,25 +82,33 @@ full_name_hash(const unsigned char *name, unsigned int len)
82 * large memory footprint increase). 82 * large memory footprint increase).
83 */ 83 */
84#ifdef CONFIG_64BIT 84#ifdef CONFIG_64BIT
85#define DNAME_INLINE_LEN_MIN 32 /* 192 bytes */ 85# define DNAME_INLINE_LEN 32 /* 192 bytes */
86#else 86#else
87#define DNAME_INLINE_LEN_MIN 40 /* 128 bytes */ 87# ifdef CONFIG_SMP
88# define DNAME_INLINE_LEN 36 /* 128 bytes */
89# else
90# define DNAME_INLINE_LEN 40 /* 128 bytes */
91# endif
88#endif 92#endif
89 93
90struct dentry { 94struct dentry {
91 unsigned int d_count; /* protected by d_lock */ 95 /* RCU lookup touched fields */
92 unsigned int d_flags; /* protected by d_lock */ 96 unsigned int d_flags; /* protected by d_lock */
93 spinlock_t d_lock; /* per dentry lock */
94 seqcount_t d_seq; /* per dentry seqlock */ 97 seqcount_t d_seq; /* per dentry seqlock */
95 struct inode *d_inode; /* Where the name belongs to - NULL is
96 * negative */
97 /*
98 * The next three fields are touched by __d_lookup. Place them here
99 * so they all fit in a cache line.
100 */
101 struct hlist_node d_hash; /* lookup hash list */ 98 struct hlist_node d_hash; /* lookup hash list */
102 struct dentry *d_parent; /* parent directory */ 99 struct dentry *d_parent; /* parent directory */
103 struct qstr d_name; 100 struct qstr d_name;
101 struct inode *d_inode; /* Where the name belongs to - NULL is
102 * negative */
103 unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
104
105 /* Ref lookup also touches following */
106 unsigned int d_count; /* protected by d_lock */
107 spinlock_t d_lock; /* per dentry lock */
108 const struct dentry_operations *d_op;
109 struct super_block *d_sb; /* The root of the dentry tree */
110 unsigned long d_time; /* used by d_revalidate */
111 void *d_fsdata; /* fs-specific data */
104 112
105 struct list_head d_lru; /* LRU list */ 113 struct list_head d_lru; /* LRU list */
106 /* 114 /*
@@ -112,12 +120,6 @@ struct dentry {
112 } d_u; 120 } d_u;
113 struct list_head d_subdirs; /* our children */ 121 struct list_head d_subdirs; /* our children */
114 struct list_head d_alias; /* inode alias list */ 122 struct list_head d_alias; /* inode alias list */
115 unsigned long d_time; /* used by d_revalidate */
116 const struct dentry_operations *d_op;
117 struct super_block *d_sb; /* The root of the dentry tree */
118 void *d_fsdata; /* fs-specific data */
119
120 unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
121}; 123};
122 124
123/* 125/*
@@ -143,7 +145,7 @@ struct dentry_operations {
143 void (*d_release)(struct dentry *); 145 void (*d_release)(struct dentry *);
144 void (*d_iput)(struct dentry *, struct inode *); 146 void (*d_iput)(struct dentry *, struct inode *);
145 char *(*d_dname)(struct dentry *, char *, int); 147 char *(*d_dname)(struct dentry *, char *, int);
146}; 148} ____cacheline_aligned;
147 149
148/* 150/*
149 * Locking rules for dentry_operations callbacks are to be found in 151 * Locking rules for dentry_operations callbacks are to be found in
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ea202fff44f8..a04aa96acb71 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -733,6 +733,20 @@ struct posix_acl;
733#define ACL_NOT_CACHED ((void *)(-1)) 733#define ACL_NOT_CACHED ((void *)(-1))
734 734
735struct inode { 735struct inode {
736 /* RCU path lookup touches following: */
737 umode_t i_mode;
738 uid_t i_uid;
739 gid_t i_gid;
740 const struct inode_operations *i_op;
741 struct super_block *i_sb;
742
743 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
744 unsigned int i_flags;
745 struct mutex i_mutex;
746
747 unsigned long i_state;
748 unsigned long dirtied_when; /* jiffies of first dirtying */
749
736 struct hlist_node i_hash; 750 struct hlist_node i_hash;
737 struct list_head i_wb_list; /* backing dev IO list */ 751 struct list_head i_wb_list; /* backing dev IO list */
738 struct list_head i_lru; /* inode LRU list */ 752 struct list_head i_lru; /* inode LRU list */
@@ -744,8 +758,6 @@ struct inode {
744 unsigned long i_ino; 758 unsigned long i_ino;
745 atomic_t i_count; 759 atomic_t i_count;
746 unsigned int i_nlink; 760 unsigned int i_nlink;
747 uid_t i_uid;
748 gid_t i_gid;
749 dev_t i_rdev; 761 dev_t i_rdev;
750 unsigned int i_blkbits; 762 unsigned int i_blkbits;
751 u64 i_version; 763 u64 i_version;
@@ -758,13 +770,8 @@ struct inode {
758 struct timespec i_ctime; 770 struct timespec i_ctime;
759 blkcnt_t i_blocks; 771 blkcnt_t i_blocks;
760 unsigned short i_bytes; 772 unsigned short i_bytes;
761 umode_t i_mode;
762 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
763 struct mutex i_mutex;
764 struct rw_semaphore i_alloc_sem; 773 struct rw_semaphore i_alloc_sem;
765 const struct inode_operations *i_op;
766 const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ 774 const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
767 struct super_block *i_sb;
768 struct file_lock *i_flock; 775 struct file_lock *i_flock;
769 struct address_space *i_mapping; 776 struct address_space *i_mapping;
770 struct address_space i_data; 777 struct address_space i_data;
@@ -785,11 +792,6 @@ struct inode {
785 struct hlist_head i_fsnotify_marks; 792 struct hlist_head i_fsnotify_marks;
786#endif 793#endif
787 794
788 unsigned long i_state;
789 unsigned long dirtied_when; /* jiffies of first dirtying */
790
791 unsigned int i_flags;
792
793#ifdef CONFIG_IMA 795#ifdef CONFIG_IMA
794 /* protected by i_lock */ 796 /* protected by i_lock */
795 unsigned int i_readcount; /* struct files open RO */ 797 unsigned int i_readcount; /* struct files open RO */
@@ -1549,8 +1551,15 @@ struct file_operations {
1549}; 1551};
1550 1552
1551struct inode_operations { 1553struct inode_operations {
1552 int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
1553 struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); 1554 struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
1555 void * (*follow_link) (struct dentry *, struct nameidata *);
1556 int (*permission) (struct inode *, int);
1557 int (*check_acl)(struct inode *, int);
1558
1559 int (*readlink) (struct dentry *, char __user *,int);
1560 void (*put_link) (struct dentry *, struct nameidata *, void *);
1561
1562 int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
1554 int (*link) (struct dentry *,struct inode *,struct dentry *); 1563 int (*link) (struct dentry *,struct inode *,struct dentry *);
1555 int (*unlink) (struct inode *,struct dentry *); 1564 int (*unlink) (struct inode *,struct dentry *);
1556 int (*symlink) (struct inode *,struct dentry *,const char *); 1565 int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -1559,12 +1568,7 @@ struct inode_operations {
1559 int (*mknod) (struct inode *,struct dentry *,int,dev_t); 1568 int (*mknod) (struct inode *,struct dentry *,int,dev_t);
1560 int (*rename) (struct inode *, struct dentry *, 1569 int (*rename) (struct inode *, struct dentry *,
1561 struct inode *, struct dentry *); 1570 struct inode *, struct dentry *);
1562 int (*readlink) (struct dentry *, char __user *,int);
1563 void * (*follow_link) (struct dentry *, struct nameidata *);
1564 void (*put_link) (struct dentry *, struct nameidata *, void *);
1565 void (*truncate) (struct inode *); 1571 void (*truncate) (struct inode *);
1566 int (*permission) (struct inode *, int);
1567 int (*check_acl)(struct inode *, int);
1568 int (*setattr) (struct dentry *, struct iattr *); 1572 int (*setattr) (struct dentry *, struct iattr *);
1569 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 1573 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1570 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); 1574 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -1576,7 +1580,7 @@ struct inode_operations {
1576 loff_t len); 1580 loff_t len);
1577 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, 1581 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1578 u64 len); 1582 u64 len);
1579}; 1583} ____cacheline_aligned;
1580 1584
1581struct seq_file; 1585struct seq_file;
1582 1586