diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 11:56:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 11:56:33 -0500 |
commit | b4a45f5fe8078bfc10837dbd5b98735058bc4698 (patch) | |
tree | df6f13a27610a3ec7eb4a661448cd779a8f84c79 /include | |
parent | 01539ba2a706ab7d35fc0667dff919ade7f87d63 (diff) | |
parent | b3e19d924b6eaf2ca7d22cba99a517c5171007b6 (diff) |
Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin
* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin: (57 commits)
fs: scale mntget/mntput
fs: rename vfsmount counter helpers
fs: implement faster dentry memcmp
fs: prefetch inode data in dcache lookup
fs: improve scalability of pseudo filesystems
fs: dcache per-inode inode alias locking
fs: dcache per-bucket dcache hash locking
bit_spinlock: add required includes
kernel: add bl_list
xfs: provide simple rcu-walk ACL implementation
btrfs: provide simple rcu-walk ACL implementation
ext2,3,4: provide simple rcu-walk ACL implementation
fs: provide simple rcu-walk generic_check_acl implementation
fs: provide rcu-walk aware permission i_ops
fs: rcu-walk aware d_revalidate method
fs: cache optimise dentry and inode for rcu-walk
fs: dcache reduce branches in lookup path
fs: dcache remove d_mounted
fs: fs_struct use seqlock
fs: rcu-walk for path lookup
...
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/bit_spinlock.h | 4 | ||||
-rw-r--r-- | include/linux/coda_linux.h | 2 | ||||
-rw-r--r-- | include/linux/dcache.h | 243 | ||||
-rw-r--r-- | include/linux/fs.h | 63 | ||||
-rw-r--r-- | include/linux/fs_struct.h | 3 | ||||
-rw-r--r-- | include/linux/fsnotify.h | 2 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 11 | ||||
-rw-r--r-- | include/linux/generic_acl.h | 2 | ||||
-rw-r--r-- | include/linux/list_bl.h | 144 | ||||
-rw-r--r-- | include/linux/mount.h | 53 | ||||
-rw-r--r-- | include/linux/namei.h | 16 | ||||
-rw-r--r-- | include/linux/ncp_fs.h | 4 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 2 | ||||
-rw-r--r-- | include/linux/path.h | 2 | ||||
-rw-r--r-- | include/linux/posix_acl.h | 19 | ||||
-rw-r--r-- | include/linux/rculist_bl.h | 127 | ||||
-rw-r--r-- | include/linux/reiserfs_xattr.h | 2 | ||||
-rw-r--r-- | include/linux/security.h | 8 | ||||
-rw-r--r-- | include/linux/seqlock.h | 80 | ||||
-rw-r--r-- | include/linux/slab.h | 2 |
20 files changed, 586 insertions, 203 deletions
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h index 7113a32a86ea..e612575a2596 100644 --- a/include/linux/bit_spinlock.h +++ b/include/linux/bit_spinlock.h | |||
@@ -1,6 +1,10 @@ | |||
1 | #ifndef __LINUX_BIT_SPINLOCK_H | 1 | #ifndef __LINUX_BIT_SPINLOCK_H |
2 | #define __LINUX_BIT_SPINLOCK_H | 2 | #define __LINUX_BIT_SPINLOCK_H |
3 | 3 | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/preempt.h> | ||
6 | #include <asm/atomic.h> | ||
7 | |||
4 | /* | 8 | /* |
5 | * bit-based spin_lock() | 9 | * bit-based spin_lock() |
6 | * | 10 | * |
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h index 2e914d0771b9..4ccc59c1ea82 100644 --- a/include/linux/coda_linux.h +++ b/include/linux/coda_linux.h | |||
@@ -37,7 +37,7 @@ extern const struct file_operations coda_ioctl_operations; | |||
37 | /* operations shared over more than one file */ | 37 | /* operations shared over more than one file */ |
38 | int coda_open(struct inode *i, struct file *f); | 38 | int coda_open(struct inode *i, struct file *f); |
39 | int coda_release(struct inode *i, struct file *f); | 39 | int coda_release(struct inode *i, struct file *f); |
40 | int coda_permission(struct inode *inode, int mask); | 40 | int coda_permission(struct inode *inode, int mask, unsigned int flags); |
41 | int coda_revalidate_inode(struct dentry *); | 41 | int coda_revalidate_inode(struct dentry *); |
42 | int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 42 | int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
43 | int coda_setattr(struct dentry *, struct iattr *); | 43 | int coda_setattr(struct dentry *, struct iattr *); |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 6a4aea30aa09..bd07758943e0 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -4,7 +4,9 @@ | |||
4 | #include <asm/atomic.h> | 4 | #include <asm/atomic.h> |
5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
6 | #include <linux/rculist.h> | 6 | #include <linux/rculist.h> |
7 | #include <linux/rculist_bl.h> | ||
7 | #include <linux/spinlock.h> | 8 | #include <linux/spinlock.h> |
9 | #include <linux/seqlock.h> | ||
8 | #include <linux/cache.h> | 10 | #include <linux/cache.h> |
9 | #include <linux/rcupdate.h> | 11 | #include <linux/rcupdate.h> |
10 | 12 | ||
@@ -45,6 +47,27 @@ struct dentry_stat_t { | |||
45 | }; | 47 | }; |
46 | extern struct dentry_stat_t dentry_stat; | 48 | extern struct dentry_stat_t dentry_stat; |
47 | 49 | ||
50 | /* | ||
51 | * Compare 2 name strings, return 0 if they match, otherwise non-zero. | ||
52 | * The strings are both count bytes long, and count is non-zero. | ||
53 | */ | ||
54 | static inline int dentry_cmp(const unsigned char *cs, size_t scount, | ||
55 | const unsigned char *ct, size_t tcount) | ||
56 | { | ||
57 | int ret; | ||
58 | if (scount != tcount) | ||
59 | return 1; | ||
60 | do { | ||
61 | ret = (*cs != *ct); | ||
62 | if (ret) | ||
63 | break; | ||
64 | cs++; | ||
65 | ct++; | ||
66 | tcount--; | ||
67 | } while (tcount); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
48 | /* Name hashing routines. Initial hash value */ | 71 | /* Name hashing routines. Initial hash value */ |
49 | /* Hash courtesy of the R5 hash in reiserfs modulo sign bits */ | 72 | /* Hash courtesy of the R5 hash in reiserfs modulo sign bits */ |
50 | #define init_name_hash() 0 | 73 | #define init_name_hash() 0 |
@@ -81,25 +104,33 @@ full_name_hash(const unsigned char *name, unsigned int len) | |||
81 | * large memory footprint increase). | 104 | * large memory footprint increase). |
82 | */ | 105 | */ |
83 | #ifdef CONFIG_64BIT | 106 | #ifdef CONFIG_64BIT |
84 | #define DNAME_INLINE_LEN_MIN 32 /* 192 bytes */ | 107 | # define DNAME_INLINE_LEN 32 /* 192 bytes */ |
85 | #else | 108 | #else |
86 | #define DNAME_INLINE_LEN_MIN 40 /* 128 bytes */ | 109 | # ifdef CONFIG_SMP |
110 | # define DNAME_INLINE_LEN 36 /* 128 bytes */ | ||
111 | # else | ||
112 | # define DNAME_INLINE_LEN 40 /* 128 bytes */ | ||
113 | # endif | ||
87 | #endif | 114 | #endif |
88 | 115 | ||
89 | struct dentry { | 116 | struct dentry { |
90 | atomic_t d_count; | 117 | /* RCU lookup touched fields */ |
91 | unsigned int d_flags; /* protected by d_lock */ | 118 | unsigned int d_flags; /* protected by d_lock */ |
92 | spinlock_t d_lock; /* per dentry lock */ | 119 | seqcount_t d_seq; /* per dentry seqlock */ |
93 | int d_mounted; | 120 | struct hlist_bl_node d_hash; /* lookup hash list */ |
94 | struct inode *d_inode; /* Where the name belongs to - NULL is | ||
95 | * negative */ | ||
96 | /* | ||
97 | * The next three fields are touched by __d_lookup. Place them here | ||
98 | * so they all fit in a cache line. | ||
99 | */ | ||
100 | struct hlist_node d_hash; /* lookup hash list */ | ||
101 | struct dentry *d_parent; /* parent directory */ | 121 | struct dentry *d_parent; /* parent directory */ |
102 | struct qstr d_name; | 122 | struct qstr d_name; |
123 | struct inode *d_inode; /* Where the name belongs to - NULL is | ||
124 | * negative */ | ||
125 | unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ | ||
126 | |||
127 | /* Ref lookup also touches following */ | ||
128 | unsigned int d_count; /* protected by d_lock */ | ||
129 | spinlock_t d_lock; /* per dentry lock */ | ||
130 | const struct dentry_operations *d_op; | ||
131 | struct super_block *d_sb; /* The root of the dentry tree */ | ||
132 | unsigned long d_time; /* used by d_revalidate */ | ||
133 | void *d_fsdata; /* fs-specific data */ | ||
103 | 134 | ||
104 | struct list_head d_lru; /* LRU list */ | 135 | struct list_head d_lru; /* LRU list */ |
105 | /* | 136 | /* |
@@ -111,12 +142,6 @@ struct dentry { | |||
111 | } d_u; | 142 | } d_u; |
112 | struct list_head d_subdirs; /* our children */ | 143 | struct list_head d_subdirs; /* our children */ |
113 | struct list_head d_alias; /* inode alias list */ | 144 | struct list_head d_alias; /* inode alias list */ |
114 | unsigned long d_time; /* used by d_revalidate */ | ||
115 | const struct dentry_operations *d_op; | ||
116 | struct super_block *d_sb; /* The root of the dentry tree */ | ||
117 | void *d_fsdata; /* fs-specific data */ | ||
118 | |||
119 | unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ | ||
120 | }; | 145 | }; |
121 | 146 | ||
122 | /* | 147 | /* |
@@ -133,96 +158,61 @@ enum dentry_d_lock_class | |||
133 | 158 | ||
134 | struct dentry_operations { | 159 | struct dentry_operations { |
135 | int (*d_revalidate)(struct dentry *, struct nameidata *); | 160 | int (*d_revalidate)(struct dentry *, struct nameidata *); |
136 | int (*d_hash) (struct dentry *, struct qstr *); | 161 | int (*d_hash)(const struct dentry *, const struct inode *, |
137 | int (*d_compare) (struct dentry *, struct qstr *, struct qstr *); | 162 | struct qstr *); |
138 | int (*d_delete)(struct dentry *); | 163 | int (*d_compare)(const struct dentry *, const struct inode *, |
164 | const struct dentry *, const struct inode *, | ||
165 | unsigned int, const char *, const struct qstr *); | ||
166 | int (*d_delete)(const struct dentry *); | ||
139 | void (*d_release)(struct dentry *); | 167 | void (*d_release)(struct dentry *); |
140 | void (*d_iput)(struct dentry *, struct inode *); | 168 | void (*d_iput)(struct dentry *, struct inode *); |
141 | char *(*d_dname)(struct dentry *, char *, int); | 169 | char *(*d_dname)(struct dentry *, char *, int); |
142 | }; | 170 | } ____cacheline_aligned; |
143 | |||
144 | /* the dentry parameter passed to d_hash and d_compare is the parent | ||
145 | * directory of the entries to be compared. It is used in case these | ||
146 | * functions need any directory specific information for determining | ||
147 | * equivalency classes. Using the dentry itself might not work, as it | ||
148 | * might be a negative dentry which has no information associated with | ||
149 | * it */ | ||
150 | 171 | ||
151 | /* | 172 | /* |
152 | locking rules: | 173 | * Locking rules for dentry_operations callbacks are to be found in |
153 | big lock dcache_lock d_lock may block | 174 | * Documentation/filesystems/Locking. Keep it updated! |
154 | d_revalidate: no no no yes | 175 | * |
155 | d_hash no no no yes | 176 | * FUrther descriptions are found in Documentation/filesystems/vfs.txt. |
156 | d_compare: no yes yes no | 177 | * Keep it updated too! |
157 | d_delete: no yes no no | ||
158 | d_release: no no no yes | ||
159 | d_iput: no no no yes | ||
160 | */ | 178 | */ |
161 | 179 | ||
162 | /* d_flags entries */ | 180 | /* d_flags entries */ |
163 | #define DCACHE_AUTOFS_PENDING 0x0001 /* autofs: "under construction" */ | 181 | #define DCACHE_AUTOFS_PENDING 0x0001 /* autofs: "under construction" */ |
164 | #define DCACHE_NFSFS_RENAMED 0x0002 /* this dentry has been "silly | 182 | #define DCACHE_NFSFS_RENAMED 0x0002 |
165 | * renamed" and has to be | 183 | /* this dentry has been "silly renamed" and has to be deleted on the last |
166 | * deleted on the last dput() | 184 | * dput() */ |
167 | */ | 185 | |
168 | #define DCACHE_DISCONNECTED 0x0004 | 186 | #define DCACHE_DISCONNECTED 0x0004 |
169 | /* This dentry is possibly not currently connected to the dcache tree, | 187 | /* This dentry is possibly not currently connected to the dcache tree, in |
170 | * in which case its parent will either be itself, or will have this | 188 | * which case its parent will either be itself, or will have this flag as |
171 | * flag as well. nfsd will not use a dentry with this bit set, but will | 189 | * well. nfsd will not use a dentry with this bit set, but will first |
172 | * first endeavour to clear the bit either by discovering that it is | 190 | * endeavour to clear the bit either by discovering that it is connected, |
173 | * connected, or by performing lookup operations. Any filesystem which | 191 | * or by performing lookup operations. Any filesystem which supports |
174 | * supports nfsd_operations MUST have a lookup function which, if it finds | 192 | * nfsd_operations MUST have a lookup function which, if it finds a |
175 | * a directory inode with a DCACHE_DISCONNECTED dentry, will d_move | 193 | * directory inode with a DCACHE_DISCONNECTED dentry, will d_move that |
176 | * that dentry into place and return that dentry rather than the passed one, | 194 | * dentry into place and return that dentry rather than the passed one, |
177 | * typically using d_splice_alias. | 195 | * typically using d_splice_alias. */ |
178 | */ | ||
179 | 196 | ||
180 | #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ | 197 | #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ |
181 | #define DCACHE_UNHASHED 0x0010 | 198 | #define DCACHE_UNHASHED 0x0010 |
182 | 199 | #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 | |
183 | #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched by inotify */ | 200 | /* Parent inode is watched by inotify */ |
184 | 201 | ||
185 | #define DCACHE_COOKIE 0x0040 /* For use by dcookie subsystem */ | 202 | #define DCACHE_COOKIE 0x0040 /* For use by dcookie subsystem */ |
186 | 203 | #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 | |
187 | #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ | 204 | /* Parent inode is watched by some fsnotify listener */ |
188 | 205 | ||
189 | #define DCACHE_CANT_MOUNT 0x0100 | 206 | #define DCACHE_CANT_MOUNT 0x0100 |
207 | #define DCACHE_GENOCIDE 0x0200 | ||
208 | #define DCACHE_MOUNTED 0x0400 /* is a mountpoint */ | ||
190 | 209 | ||
191 | extern spinlock_t dcache_lock; | 210 | #define DCACHE_OP_HASH 0x1000 |
192 | extern seqlock_t rename_lock; | 211 | #define DCACHE_OP_COMPARE 0x2000 |
193 | 212 | #define DCACHE_OP_REVALIDATE 0x4000 | |
194 | /** | 213 | #define DCACHE_OP_DELETE 0x8000 |
195 | * d_drop - drop a dentry | ||
196 | * @dentry: dentry to drop | ||
197 | * | ||
198 | * d_drop() unhashes the entry from the parent dentry hashes, so that it won't | ||
199 | * be found through a VFS lookup any more. Note that this is different from | ||
200 | * deleting the dentry - d_delete will try to mark the dentry negative if | ||
201 | * possible, giving a successful _negative_ lookup, while d_drop will | ||
202 | * just make the cache lookup fail. | ||
203 | * | ||
204 | * d_drop() is used mainly for stuff that wants to invalidate a dentry for some | ||
205 | * reason (NFS timeouts or autofs deletes). | ||
206 | * | ||
207 | * __d_drop requires dentry->d_lock. | ||
208 | */ | ||
209 | |||
210 | static inline void __d_drop(struct dentry *dentry) | ||
211 | { | ||
212 | if (!(dentry->d_flags & DCACHE_UNHASHED)) { | ||
213 | dentry->d_flags |= DCACHE_UNHASHED; | ||
214 | hlist_del_rcu(&dentry->d_hash); | ||
215 | } | ||
216 | } | ||
217 | 214 | ||
218 | static inline void d_drop(struct dentry *dentry) | 215 | extern seqlock_t rename_lock; |
219 | { | ||
220 | spin_lock(&dcache_lock); | ||
221 | spin_lock(&dentry->d_lock); | ||
222 | __d_drop(dentry); | ||
223 | spin_unlock(&dentry->d_lock); | ||
224 | spin_unlock(&dcache_lock); | ||
225 | } | ||
226 | 216 | ||
227 | static inline int dname_external(struct dentry *dentry) | 217 | static inline int dname_external(struct dentry *dentry) |
228 | { | 218 | { |
@@ -235,10 +225,14 @@ static inline int dname_external(struct dentry *dentry) | |||
235 | extern void d_instantiate(struct dentry *, struct inode *); | 225 | extern void d_instantiate(struct dentry *, struct inode *); |
236 | extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); | 226 | extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); |
237 | extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); | 227 | extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); |
228 | extern void __d_drop(struct dentry *dentry); | ||
229 | extern void d_drop(struct dentry *dentry); | ||
238 | extern void d_delete(struct dentry *); | 230 | extern void d_delete(struct dentry *); |
231 | extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op); | ||
239 | 232 | ||
240 | /* allocate/de-allocate */ | 233 | /* allocate/de-allocate */ |
241 | extern struct dentry * d_alloc(struct dentry *, const struct qstr *); | 234 | extern struct dentry * d_alloc(struct dentry *, const struct qstr *); |
235 | extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *); | ||
242 | extern struct dentry * d_splice_alias(struct inode *, struct dentry *); | 236 | extern struct dentry * d_splice_alias(struct inode *, struct dentry *); |
243 | extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); | 237 | extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); |
244 | extern struct dentry * d_obtain_alias(struct inode *); | 238 | extern struct dentry * d_obtain_alias(struct inode *); |
@@ -296,14 +290,40 @@ static inline struct dentry *d_add_unique(struct dentry *entry, struct inode *in | |||
296 | return res; | 290 | return res; |
297 | } | 291 | } |
298 | 292 | ||
293 | extern void dentry_update_name_case(struct dentry *, struct qstr *); | ||
294 | |||
299 | /* used for rename() and baskets */ | 295 | /* used for rename() and baskets */ |
300 | extern void d_move(struct dentry *, struct dentry *); | 296 | extern void d_move(struct dentry *, struct dentry *); |
301 | extern struct dentry *d_ancestor(struct dentry *, struct dentry *); | 297 | extern struct dentry *d_ancestor(struct dentry *, struct dentry *); |
302 | 298 | ||
303 | /* appendix may either be NULL or be used for transname suffixes */ | 299 | /* appendix may either be NULL or be used for transname suffixes */ |
304 | extern struct dentry * d_lookup(struct dentry *, struct qstr *); | 300 | extern struct dentry *d_lookup(struct dentry *, struct qstr *); |
305 | extern struct dentry * __d_lookup(struct dentry *, struct qstr *); | 301 | extern struct dentry *d_hash_and_lookup(struct dentry *, struct qstr *); |
306 | extern struct dentry * d_hash_and_lookup(struct dentry *, struct qstr *); | 302 | extern struct dentry *__d_lookup(struct dentry *, struct qstr *); |
303 | extern struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | ||
304 | unsigned *seq, struct inode **inode); | ||
305 | |||
306 | /** | ||
307 | * __d_rcu_to_refcount - take a refcount on dentry if sequence check is ok | ||
308 | * @dentry: dentry to take a ref on | ||
309 | * @seq: seqcount to verify against | ||
310 | * @Returns: 0 on failure, else 1. | ||
311 | * | ||
312 | * __d_rcu_to_refcount operates on a dentry,seq pair that was returned | ||
313 | * by __d_lookup_rcu, to get a reference on an rcu-walk dentry. | ||
314 | */ | ||
315 | static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq) | ||
316 | { | ||
317 | int ret = 0; | ||
318 | |||
319 | assert_spin_locked(&dentry->d_lock); | ||
320 | if (!read_seqcount_retry(&dentry->d_seq, seq)) { | ||
321 | ret = 1; | ||
322 | dentry->d_count++; | ||
323 | } | ||
324 | |||
325 | return ret; | ||
326 | } | ||
307 | 327 | ||
308 | /* validate "insecure" dentry pointer */ | 328 | /* validate "insecure" dentry pointer */ |
309 | extern int d_validate(struct dentry *, struct dentry *); | 329 | extern int d_validate(struct dentry *, struct dentry *); |
@@ -316,34 +336,37 @@ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); | |||
316 | extern char *__d_path(const struct path *path, struct path *root, char *, int); | 336 | extern char *__d_path(const struct path *path, struct path *root, char *, int); |
317 | extern char *d_path(const struct path *, char *, int); | 337 | extern char *d_path(const struct path *, char *, int); |
318 | extern char *d_path_with_unreachable(const struct path *, char *, int); | 338 | extern char *d_path_with_unreachable(const struct path *, char *, int); |
319 | extern char *__dentry_path(struct dentry *, char *, int); | 339 | extern char *dentry_path_raw(struct dentry *, char *, int); |
320 | extern char *dentry_path(struct dentry *, char *, int); | 340 | extern char *dentry_path(struct dentry *, char *, int); |
321 | 341 | ||
322 | /* Allocation counts.. */ | 342 | /* Allocation counts.. */ |
323 | 343 | ||
324 | /** | 344 | /** |
325 | * dget, dget_locked - get a reference to a dentry | 345 | * dget, dget_dlock - get a reference to a dentry |
326 | * @dentry: dentry to get a reference to | 346 | * @dentry: dentry to get a reference to |
327 | * | 347 | * |
328 | * Given a dentry or %NULL pointer increment the reference count | 348 | * Given a dentry or %NULL pointer increment the reference count |
329 | * if appropriate and return the dentry. A dentry will not be | 349 | * if appropriate and return the dentry. A dentry will not be |
330 | * destroyed when it has references. dget() should never be | 350 | * destroyed when it has references. |
331 | * called for dentries with zero reference counter. For these cases | ||
332 | * (preferably none, functions in dcache.c are sufficient for normal | ||
333 | * needs and they take necessary precautions) you should hold dcache_lock | ||
334 | * and call dget_locked() instead of dget(). | ||
335 | */ | 351 | */ |
336 | 352 | static inline struct dentry *dget_dlock(struct dentry *dentry) | |
353 | { | ||
354 | if (dentry) | ||
355 | dentry->d_count++; | ||
356 | return dentry; | ||
357 | } | ||
358 | |||
337 | static inline struct dentry *dget(struct dentry *dentry) | 359 | static inline struct dentry *dget(struct dentry *dentry) |
338 | { | 360 | { |
339 | if (dentry) { | 361 | if (dentry) { |
340 | BUG_ON(!atomic_read(&dentry->d_count)); | 362 | spin_lock(&dentry->d_lock); |
341 | atomic_inc(&dentry->d_count); | 363 | dget_dlock(dentry); |
364 | spin_unlock(&dentry->d_lock); | ||
342 | } | 365 | } |
343 | return dentry; | 366 | return dentry; |
344 | } | 367 | } |
345 | 368 | ||
346 | extern struct dentry * dget_locked(struct dentry *); | 369 | extern struct dentry *dget_parent(struct dentry *dentry); |
347 | 370 | ||
348 | /** | 371 | /** |
349 | * d_unhashed - is dentry hashed | 372 | * d_unhashed - is dentry hashed |
@@ -374,21 +397,11 @@ static inline void dont_mount(struct dentry *dentry) | |||
374 | spin_unlock(&dentry->d_lock); | 397 | spin_unlock(&dentry->d_lock); |
375 | } | 398 | } |
376 | 399 | ||
377 | static inline struct dentry *dget_parent(struct dentry *dentry) | ||
378 | { | ||
379 | struct dentry *ret; | ||
380 | |||
381 | spin_lock(&dentry->d_lock); | ||
382 | ret = dget(dentry->d_parent); | ||
383 | spin_unlock(&dentry->d_lock); | ||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | extern void dput(struct dentry *); | 400 | extern void dput(struct dentry *); |
388 | 401 | ||
389 | static inline int d_mountpoint(struct dentry *dentry) | 402 | static inline int d_mountpoint(struct dentry *dentry) |
390 | { | 403 | { |
391 | return dentry->d_mounted; | 404 | return dentry->d_flags & DCACHE_MOUNTED; |
392 | } | 405 | } |
393 | 406 | ||
394 | extern struct vfsmount *lookup_mnt(struct path *); | 407 | extern struct vfsmount *lookup_mnt(struct path *); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 090f0eacde29..baf3e556ff0e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -392,6 +392,7 @@ struct inodes_stat_t { | |||
392 | #include <linux/capability.h> | 392 | #include <linux/capability.h> |
393 | #include <linux/semaphore.h> | 393 | #include <linux/semaphore.h> |
394 | #include <linux/fiemap.h> | 394 | #include <linux/fiemap.h> |
395 | #include <linux/rculist_bl.h> | ||
395 | 396 | ||
396 | #include <asm/atomic.h> | 397 | #include <asm/atomic.h> |
397 | #include <asm/byteorder.h> | 398 | #include <asm/byteorder.h> |
@@ -733,16 +734,31 @@ struct posix_acl; | |||
733 | #define ACL_NOT_CACHED ((void *)(-1)) | 734 | #define ACL_NOT_CACHED ((void *)(-1)) |
734 | 735 | ||
735 | struct inode { | 736 | struct inode { |
737 | /* RCU path lookup touches following: */ | ||
738 | umode_t i_mode; | ||
739 | uid_t i_uid; | ||
740 | gid_t i_gid; | ||
741 | const struct inode_operations *i_op; | ||
742 | struct super_block *i_sb; | ||
743 | |||
744 | spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ | ||
745 | unsigned int i_flags; | ||
746 | struct mutex i_mutex; | ||
747 | |||
748 | unsigned long i_state; | ||
749 | unsigned long dirtied_when; /* jiffies of first dirtying */ | ||
750 | |||
736 | struct hlist_node i_hash; | 751 | struct hlist_node i_hash; |
737 | struct list_head i_wb_list; /* backing dev IO list */ | 752 | struct list_head i_wb_list; /* backing dev IO list */ |
738 | struct list_head i_lru; /* inode LRU list */ | 753 | struct list_head i_lru; /* inode LRU list */ |
739 | struct list_head i_sb_list; | 754 | struct list_head i_sb_list; |
740 | struct list_head i_dentry; | 755 | union { |
756 | struct list_head i_dentry; | ||
757 | struct rcu_head i_rcu; | ||
758 | }; | ||
741 | unsigned long i_ino; | 759 | unsigned long i_ino; |
742 | atomic_t i_count; | 760 | atomic_t i_count; |
743 | unsigned int i_nlink; | 761 | unsigned int i_nlink; |
744 | uid_t i_uid; | ||
745 | gid_t i_gid; | ||
746 | dev_t i_rdev; | 762 | dev_t i_rdev; |
747 | unsigned int i_blkbits; | 763 | unsigned int i_blkbits; |
748 | u64 i_version; | 764 | u64 i_version; |
@@ -755,13 +771,8 @@ struct inode { | |||
755 | struct timespec i_ctime; | 771 | struct timespec i_ctime; |
756 | blkcnt_t i_blocks; | 772 | blkcnt_t i_blocks; |
757 | unsigned short i_bytes; | 773 | unsigned short i_bytes; |
758 | umode_t i_mode; | ||
759 | spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ | ||
760 | struct mutex i_mutex; | ||
761 | struct rw_semaphore i_alloc_sem; | 774 | struct rw_semaphore i_alloc_sem; |
762 | const struct inode_operations *i_op; | ||
763 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ | 775 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ |
764 | struct super_block *i_sb; | ||
765 | struct file_lock *i_flock; | 776 | struct file_lock *i_flock; |
766 | struct address_space *i_mapping; | 777 | struct address_space *i_mapping; |
767 | struct address_space i_data; | 778 | struct address_space i_data; |
@@ -782,11 +793,6 @@ struct inode { | |||
782 | struct hlist_head i_fsnotify_marks; | 793 | struct hlist_head i_fsnotify_marks; |
783 | #endif | 794 | #endif |
784 | 795 | ||
785 | unsigned long i_state; | ||
786 | unsigned long dirtied_when; /* jiffies of first dirtying */ | ||
787 | |||
788 | unsigned int i_flags; | ||
789 | |||
790 | #ifdef CONFIG_IMA | 796 | #ifdef CONFIG_IMA |
791 | /* protected by i_lock */ | 797 | /* protected by i_lock */ |
792 | unsigned int i_readcount; /* struct files open RO */ | 798 | unsigned int i_readcount; /* struct files open RO */ |
@@ -1372,13 +1378,13 @@ struct super_block { | |||
1372 | const struct xattr_handler **s_xattr; | 1378 | const struct xattr_handler **s_xattr; |
1373 | 1379 | ||
1374 | struct list_head s_inodes; /* all inodes */ | 1380 | struct list_head s_inodes; /* all inodes */ |
1375 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ | 1381 | struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */ |
1376 | #ifdef CONFIG_SMP | 1382 | #ifdef CONFIG_SMP |
1377 | struct list_head __percpu *s_files; | 1383 | struct list_head __percpu *s_files; |
1378 | #else | 1384 | #else |
1379 | struct list_head s_files; | 1385 | struct list_head s_files; |
1380 | #endif | 1386 | #endif |
1381 | /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */ | 1387 | /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */ |
1382 | struct list_head s_dentry_lru; /* unused dentry lru */ | 1388 | struct list_head s_dentry_lru; /* unused dentry lru */ |
1383 | int s_nr_dentry_unused; /* # of dentry on lru */ | 1389 | int s_nr_dentry_unused; /* # of dentry on lru */ |
1384 | 1390 | ||
@@ -1545,9 +1551,18 @@ struct file_operations { | |||
1545 | int (*setlease)(struct file *, long, struct file_lock **); | 1551 | int (*setlease)(struct file *, long, struct file_lock **); |
1546 | }; | 1552 | }; |
1547 | 1553 | ||
1554 | #define IPERM_FLAG_RCU 0x0001 | ||
1555 | |||
1548 | struct inode_operations { | 1556 | struct inode_operations { |
1549 | int (*create) (struct inode *,struct dentry *,int, struct nameidata *); | ||
1550 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); | 1557 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); |
1558 | void * (*follow_link) (struct dentry *, struct nameidata *); | ||
1559 | int (*permission) (struct inode *, int, unsigned int); | ||
1560 | int (*check_acl)(struct inode *, int, unsigned int); | ||
1561 | |||
1562 | int (*readlink) (struct dentry *, char __user *,int); | ||
1563 | void (*put_link) (struct dentry *, struct nameidata *, void *); | ||
1564 | |||
1565 | int (*create) (struct inode *,struct dentry *,int, struct nameidata *); | ||
1551 | int (*link) (struct dentry *,struct inode *,struct dentry *); | 1566 | int (*link) (struct dentry *,struct inode *,struct dentry *); |
1552 | int (*unlink) (struct inode *,struct dentry *); | 1567 | int (*unlink) (struct inode *,struct dentry *); |
1553 | int (*symlink) (struct inode *,struct dentry *,const char *); | 1568 | int (*symlink) (struct inode *,struct dentry *,const char *); |
@@ -1556,12 +1571,7 @@ struct inode_operations { | |||
1556 | int (*mknod) (struct inode *,struct dentry *,int,dev_t); | 1571 | int (*mknod) (struct inode *,struct dentry *,int,dev_t); |
1557 | int (*rename) (struct inode *, struct dentry *, | 1572 | int (*rename) (struct inode *, struct dentry *, |
1558 | struct inode *, struct dentry *); | 1573 | struct inode *, struct dentry *); |
1559 | int (*readlink) (struct dentry *, char __user *,int); | ||
1560 | void * (*follow_link) (struct dentry *, struct nameidata *); | ||
1561 | void (*put_link) (struct dentry *, struct nameidata *, void *); | ||
1562 | void (*truncate) (struct inode *); | 1574 | void (*truncate) (struct inode *); |
1563 | int (*permission) (struct inode *, int); | ||
1564 | int (*check_acl)(struct inode *, int); | ||
1565 | int (*setattr) (struct dentry *, struct iattr *); | 1575 | int (*setattr) (struct dentry *, struct iattr *); |
1566 | int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); | 1576 | int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); |
1567 | int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); | 1577 | int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); |
@@ -1573,7 +1583,7 @@ struct inode_operations { | |||
1573 | loff_t len); | 1583 | loff_t len); |
1574 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, | 1584 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, |
1575 | u64 len); | 1585 | u64 len); |
1576 | }; | 1586 | } ____cacheline_aligned; |
1577 | 1587 | ||
1578 | struct seq_file; | 1588 | struct seq_file; |
1579 | 1589 | ||
@@ -2158,8 +2168,8 @@ extern sector_t bmap(struct inode *, sector_t); | |||
2158 | #endif | 2168 | #endif |
2159 | extern int notify_change(struct dentry *, struct iattr *); | 2169 | extern int notify_change(struct dentry *, struct iattr *); |
2160 | extern int inode_permission(struct inode *, int); | 2170 | extern int inode_permission(struct inode *, int); |
2161 | extern int generic_permission(struct inode *, int, | 2171 | extern int generic_permission(struct inode *, int, unsigned int, |
2162 | int (*check_acl)(struct inode *, int)); | 2172 | int (*check_acl)(struct inode *, int, unsigned int)); |
2163 | 2173 | ||
2164 | static inline bool execute_ok(struct inode *inode) | 2174 | static inline bool execute_ok(struct inode *inode) |
2165 | { | 2175 | { |
@@ -2230,6 +2240,7 @@ extern void iget_failed(struct inode *); | |||
2230 | extern void end_writeback(struct inode *); | 2240 | extern void end_writeback(struct inode *); |
2231 | extern void __destroy_inode(struct inode *); | 2241 | extern void __destroy_inode(struct inode *); |
2232 | extern struct inode *new_inode(struct super_block *); | 2242 | extern struct inode *new_inode(struct super_block *); |
2243 | extern void free_inode_nonrcu(struct inode *inode); | ||
2233 | extern int should_remove_suid(struct dentry *); | 2244 | extern int should_remove_suid(struct dentry *); |
2234 | extern int file_remove_suid(struct file *); | 2245 | extern int file_remove_suid(struct file *); |
2235 | 2246 | ||
@@ -2446,6 +2457,10 @@ static inline ino_t parent_ino(struct dentry *dentry) | |||
2446 | { | 2457 | { |
2447 | ino_t res; | 2458 | ino_t res; |
2448 | 2459 | ||
2460 | /* | ||
2461 | * Don't strictly need d_lock here? If the parent ino could change | ||
2462 | * then surely we'd have a deeper race in the caller? | ||
2463 | */ | ||
2449 | spin_lock(&dentry->d_lock); | 2464 | spin_lock(&dentry->d_lock); |
2450 | res = dentry->d_parent->d_inode->i_ino; | 2465 | res = dentry->d_parent->d_inode->i_ino; |
2451 | spin_unlock(&dentry->d_lock); | 2466 | spin_unlock(&dentry->d_lock); |
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index a42b5bf02f8b..003dc0fd7347 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h | |||
@@ -2,10 +2,13 @@ | |||
2 | #define _LINUX_FS_STRUCT_H | 2 | #define _LINUX_FS_STRUCT_H |
3 | 3 | ||
4 | #include <linux/path.h> | 4 | #include <linux/path.h> |
5 | #include <linux/spinlock.h> | ||
6 | #include <linux/seqlock.h> | ||
5 | 7 | ||
6 | struct fs_struct { | 8 | struct fs_struct { |
7 | int users; | 9 | int users; |
8 | spinlock_t lock; | 10 | spinlock_t lock; |
11 | seqcount_t seq; | ||
9 | int umask; | 12 | int umask; |
10 | int in_exec; | 13 | int in_exec; |
11 | struct path root, pwd; | 14 | struct path root, pwd; |
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index b10bcdeaef76..2a53f10712b3 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | /* | 18 | /* |
19 | * fsnotify_d_instantiate - instantiate a dentry for inode | 19 | * fsnotify_d_instantiate - instantiate a dentry for inode |
20 | * Called with dcache_lock held. | ||
21 | */ | 20 | */ |
22 | static inline void fsnotify_d_instantiate(struct dentry *dentry, | 21 | static inline void fsnotify_d_instantiate(struct dentry *dentry, |
23 | struct inode *inode) | 22 | struct inode *inode) |
@@ -62,7 +61,6 @@ static inline int fsnotify_perm(struct file *file, int mask) | |||
62 | 61 | ||
63 | /* | 62 | /* |
64 | * fsnotify_d_move - dentry has been moved | 63 | * fsnotify_d_move - dentry has been moved |
65 | * Called with dcache_lock and dentry->d_lock held. | ||
66 | */ | 64 | */ |
67 | static inline void fsnotify_d_move(struct dentry *dentry) | 65 | static inline void fsnotify_d_move(struct dentry *dentry) |
68 | { | 66 | { |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 7380763595d3..69ad89b50489 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -329,9 +329,15 @@ static inline void __fsnotify_update_dcache_flags(struct dentry *dentry) | |||
329 | { | 329 | { |
330 | struct dentry *parent; | 330 | struct dentry *parent; |
331 | 331 | ||
332 | assert_spin_locked(&dcache_lock); | ||
333 | assert_spin_locked(&dentry->d_lock); | 332 | assert_spin_locked(&dentry->d_lock); |
334 | 333 | ||
334 | /* | ||
335 | * Serialisation of setting PARENT_WATCHED on the dentries is provided | ||
336 | * by d_lock. If inotify_inode_watched changes after we have taken | ||
337 | * d_lock, the following __fsnotify_update_child_dentry_flags call will | ||
338 | * find our entry, so it will spin until we complete here, and update | ||
339 | * us with the new state. | ||
340 | */ | ||
335 | parent = dentry->d_parent; | 341 | parent = dentry->d_parent; |
336 | if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode)) | 342 | if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode)) |
337 | dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED; | 343 | dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED; |
@@ -341,15 +347,12 @@ static inline void __fsnotify_update_dcache_flags(struct dentry *dentry) | |||
341 | 347 | ||
342 | /* | 348 | /* |
343 | * fsnotify_d_instantiate - instantiate a dentry for inode | 349 | * fsnotify_d_instantiate - instantiate a dentry for inode |
344 | * Called with dcache_lock held. | ||
345 | */ | 350 | */ |
346 | static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode) | 351 | static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode *inode) |
347 | { | 352 | { |
348 | if (!inode) | 353 | if (!inode) |
349 | return; | 354 | return; |
350 | 355 | ||
351 | assert_spin_locked(&dcache_lock); | ||
352 | |||
353 | spin_lock(&dentry->d_lock); | 356 | spin_lock(&dentry->d_lock); |
354 | __fsnotify_update_dcache_flags(dentry); | 357 | __fsnotify_update_dcache_flags(dentry); |
355 | spin_unlock(&dentry->d_lock); | 358 | spin_unlock(&dentry->d_lock); |
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h index 574bea4013b6..0437e377b555 100644 --- a/include/linux/generic_acl.h +++ b/include/linux/generic_acl.h | |||
@@ -10,6 +10,6 @@ extern const struct xattr_handler generic_acl_default_handler; | |||
10 | 10 | ||
11 | int generic_acl_init(struct inode *, struct inode *); | 11 | int generic_acl_init(struct inode *, struct inode *); |
12 | int generic_acl_chmod(struct inode *); | 12 | int generic_acl_chmod(struct inode *); |
13 | int generic_check_acl(struct inode *inode, int mask); | 13 | int generic_check_acl(struct inode *inode, int mask, unsigned int flags); |
14 | 14 | ||
15 | #endif /* LINUX_GENERIC_ACL_H */ | 15 | #endif /* LINUX_GENERIC_ACL_H */ |
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h new file mode 100644 index 000000000000..9ee97e7f2be4 --- /dev/null +++ b/include/linux/list_bl.h | |||
@@ -0,0 +1,144 @@ | |||
1 | #ifndef _LINUX_LIST_BL_H | ||
2 | #define _LINUX_LIST_BL_H | ||
3 | |||
4 | #include <linux/list.h> | ||
5 | |||
6 | /* | ||
7 | * Special version of lists, where head of the list has a lock in the lowest | ||
8 | * bit. This is useful for scalable hash tables without increasing memory | ||
9 | * footprint overhead. | ||
10 | * | ||
11 | * For modification operations, the 0 bit of hlist_bl_head->first | ||
12 | * pointer must be set. | ||
13 | * | ||
14 | * With some small modifications, this can easily be adapted to store several | ||
15 | * arbitrary bits (not just a single lock bit), if the need arises to store | ||
16 | * some fast and compact auxiliary data. | ||
17 | */ | ||
18 | |||
19 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) | ||
20 | #define LIST_BL_LOCKMASK 1UL | ||
21 | #else | ||
22 | #define LIST_BL_LOCKMASK 0UL | ||
23 | #endif | ||
24 | |||
25 | #ifdef CONFIG_DEBUG_LIST | ||
26 | #define LIST_BL_BUG_ON(x) BUG_ON(x) | ||
27 | #else | ||
28 | #define LIST_BL_BUG_ON(x) | ||
29 | #endif | ||
30 | |||
31 | |||
32 | struct hlist_bl_head { | ||
33 | struct hlist_bl_node *first; | ||
34 | }; | ||
35 | |||
36 | struct hlist_bl_node { | ||
37 | struct hlist_bl_node *next, **pprev; | ||
38 | }; | ||
39 | #define INIT_HLIST_BL_HEAD(ptr) \ | ||
40 | ((ptr)->first = NULL) | ||
41 | |||
42 | static inline void INIT_HLIST_BL_NODE(struct hlist_bl_node *h) | ||
43 | { | ||
44 | h->next = NULL; | ||
45 | h->pprev = NULL; | ||
46 | } | ||
47 | |||
48 | #define hlist_bl_entry(ptr, type, member) container_of(ptr,type,member) | ||
49 | |||
50 | static inline int hlist_bl_unhashed(const struct hlist_bl_node *h) | ||
51 | { | ||
52 | return !h->pprev; | ||
53 | } | ||
54 | |||
55 | static inline struct hlist_bl_node *hlist_bl_first(struct hlist_bl_head *h) | ||
56 | { | ||
57 | return (struct hlist_bl_node *) | ||
58 | ((unsigned long)h->first & ~LIST_BL_LOCKMASK); | ||
59 | } | ||
60 | |||
61 | static inline void hlist_bl_set_first(struct hlist_bl_head *h, | ||
62 | struct hlist_bl_node *n) | ||
63 | { | ||
64 | LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK); | ||
65 | LIST_BL_BUG_ON(!((unsigned long)h->first & LIST_BL_LOCKMASK)); | ||
66 | h->first = (struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK); | ||
67 | } | ||
68 | |||
69 | static inline int hlist_bl_empty(const struct hlist_bl_head *h) | ||
70 | { | ||
71 | return !((unsigned long)h->first & ~LIST_BL_LOCKMASK); | ||
72 | } | ||
73 | |||
74 | static inline void hlist_bl_add_head(struct hlist_bl_node *n, | ||
75 | struct hlist_bl_head *h) | ||
76 | { | ||
77 | struct hlist_bl_node *first = hlist_bl_first(h); | ||
78 | |||
79 | n->next = first; | ||
80 | if (first) | ||
81 | first->pprev = &n->next; | ||
82 | n->pprev = &h->first; | ||
83 | hlist_bl_set_first(h, n); | ||
84 | } | ||
85 | |||
86 | static inline void __hlist_bl_del(struct hlist_bl_node *n) | ||
87 | { | ||
88 | struct hlist_bl_node *next = n->next; | ||
89 | struct hlist_bl_node **pprev = n->pprev; | ||
90 | |||
91 | LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK); | ||
92 | |||
93 | /* pprev may be `first`, so be careful not to lose the lock bit */ | ||
94 | *pprev = (struct hlist_bl_node *) | ||
95 | ((unsigned long)next | | ||
96 | ((unsigned long)*pprev & LIST_BL_LOCKMASK)); | ||
97 | if (next) | ||
98 | next->pprev = pprev; | ||
99 | } | ||
100 | |||
101 | static inline void hlist_bl_del(struct hlist_bl_node *n) | ||
102 | { | ||
103 | __hlist_bl_del(n); | ||
104 | n->next = LIST_POISON1; | ||
105 | n->pprev = LIST_POISON2; | ||
106 | } | ||
107 | |||
108 | static inline void hlist_bl_del_init(struct hlist_bl_node *n) | ||
109 | { | ||
110 | if (!hlist_bl_unhashed(n)) { | ||
111 | __hlist_bl_del(n); | ||
112 | INIT_HLIST_BL_NODE(n); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * hlist_bl_for_each_entry - iterate over list of given type | ||
118 | * @tpos: the type * to use as a loop cursor. | ||
119 | * @pos: the &struct hlist_node to use as a loop cursor. | ||
120 | * @head: the head for your list. | ||
121 | * @member: the name of the hlist_node within the struct. | ||
122 | * | ||
123 | */ | ||
124 | #define hlist_bl_for_each_entry(tpos, pos, head, member) \ | ||
125 | for (pos = hlist_bl_first(head); \ | ||
126 | pos && \ | ||
127 | ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1;}); \ | ||
128 | pos = pos->next) | ||
129 | |||
130 | /** | ||
131 | * hlist_bl_for_each_entry_safe - iterate over list of given type safe against removal of list entry | ||
132 | * @tpos: the type * to use as a loop cursor. | ||
133 | * @pos: the &struct hlist_node to use as a loop cursor. | ||
134 | * @n: another &struct hlist_node to use as temporary storage | ||
135 | * @head: the head for your list. | ||
136 | * @member: the name of the hlist_node within the struct. | ||
137 | */ | ||
138 | #define hlist_bl_for_each_entry_safe(tpos, pos, n, head, member) \ | ||
139 | for (pos = hlist_bl_first(head); \ | ||
140 | pos && ({ n = pos->next; 1; }) && \ | ||
141 | ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1;}); \ | ||
142 | pos = n) | ||
143 | |||
144 | #endif | ||
diff --git a/include/linux/mount.h b/include/linux/mount.h index 5e7a59408dd4..1869ea24a739 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/list.h> | 13 | #include <linux/list.h> |
14 | #include <linux/nodemask.h> | 14 | #include <linux/nodemask.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/seqlock.h> | ||
16 | #include <asm/atomic.h> | 17 | #include <asm/atomic.h> |
17 | 18 | ||
18 | struct super_block; | 19 | struct super_block; |
@@ -46,12 +47,24 @@ struct mnt_namespace; | |||
46 | 47 | ||
47 | #define MNT_INTERNAL 0x4000 | 48 | #define MNT_INTERNAL 0x4000 |
48 | 49 | ||
50 | struct mnt_pcp { | ||
51 | int mnt_count; | ||
52 | int mnt_writers; | ||
53 | }; | ||
54 | |||
49 | struct vfsmount { | 55 | struct vfsmount { |
50 | struct list_head mnt_hash; | 56 | struct list_head mnt_hash; |
51 | struct vfsmount *mnt_parent; /* fs we are mounted on */ | 57 | struct vfsmount *mnt_parent; /* fs we are mounted on */ |
52 | struct dentry *mnt_mountpoint; /* dentry of mountpoint */ | 58 | struct dentry *mnt_mountpoint; /* dentry of mountpoint */ |
53 | struct dentry *mnt_root; /* root of the mounted tree */ | 59 | struct dentry *mnt_root; /* root of the mounted tree */ |
54 | struct super_block *mnt_sb; /* pointer to superblock */ | 60 | struct super_block *mnt_sb; /* pointer to superblock */ |
61 | #ifdef CONFIG_SMP | ||
62 | struct mnt_pcp __percpu *mnt_pcp; | ||
63 | atomic_t mnt_longrefs; | ||
64 | #else | ||
65 | int mnt_count; | ||
66 | int mnt_writers; | ||
67 | #endif | ||
55 | struct list_head mnt_mounts; /* list of children, anchored here */ | 68 | struct list_head mnt_mounts; /* list of children, anchored here */ |
56 | struct list_head mnt_child; /* and going through their mnt_child */ | 69 | struct list_head mnt_child; /* and going through their mnt_child */ |
57 | int mnt_flags; | 70 | int mnt_flags; |
@@ -70,57 +83,25 @@ struct vfsmount { | |||
70 | struct mnt_namespace *mnt_ns; /* containing namespace */ | 83 | struct mnt_namespace *mnt_ns; /* containing namespace */ |
71 | int mnt_id; /* mount identifier */ | 84 | int mnt_id; /* mount identifier */ |
72 | int mnt_group_id; /* peer group identifier */ | 85 | int mnt_group_id; /* peer group identifier */ |
73 | /* | ||
74 | * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount | ||
75 | * to let these frequently modified fields in a separate cache line | ||
76 | * (so that reads of mnt_flags wont ping-pong on SMP machines) | ||
77 | */ | ||
78 | atomic_t mnt_count; | ||
79 | int mnt_expiry_mark; /* true if marked for expiry */ | 86 | int mnt_expiry_mark; /* true if marked for expiry */ |
80 | int mnt_pinned; | 87 | int mnt_pinned; |
81 | int mnt_ghosts; | 88 | int mnt_ghosts; |
82 | #ifdef CONFIG_SMP | ||
83 | int __percpu *mnt_writers; | ||
84 | #else | ||
85 | int mnt_writers; | ||
86 | #endif | ||
87 | }; | 89 | }; |
88 | 90 | ||
89 | static inline int *get_mnt_writers_ptr(struct vfsmount *mnt) | ||
90 | { | ||
91 | #ifdef CONFIG_SMP | ||
92 | return mnt->mnt_writers; | ||
93 | #else | ||
94 | return &mnt->mnt_writers; | ||
95 | #endif | ||
96 | } | ||
97 | |||
98 | static inline struct vfsmount *mntget(struct vfsmount *mnt) | ||
99 | { | ||
100 | if (mnt) | ||
101 | atomic_inc(&mnt->mnt_count); | ||
102 | return mnt; | ||
103 | } | ||
104 | |||
105 | struct file; /* forward dec */ | 91 | struct file; /* forward dec */ |
106 | 92 | ||
107 | extern int mnt_want_write(struct vfsmount *mnt); | 93 | extern int mnt_want_write(struct vfsmount *mnt); |
108 | extern int mnt_want_write_file(struct file *file); | 94 | extern int mnt_want_write_file(struct file *file); |
109 | extern int mnt_clone_write(struct vfsmount *mnt); | 95 | extern int mnt_clone_write(struct vfsmount *mnt); |
110 | extern void mnt_drop_write(struct vfsmount *mnt); | 96 | extern void mnt_drop_write(struct vfsmount *mnt); |
111 | extern void mntput_no_expire(struct vfsmount *mnt); | 97 | extern void mntput(struct vfsmount *mnt); |
98 | extern struct vfsmount *mntget(struct vfsmount *mnt); | ||
99 | extern void mntput_long(struct vfsmount *mnt); | ||
100 | extern struct vfsmount *mntget_long(struct vfsmount *mnt); | ||
112 | extern void mnt_pin(struct vfsmount *mnt); | 101 | extern void mnt_pin(struct vfsmount *mnt); |
113 | extern void mnt_unpin(struct vfsmount *mnt); | 102 | extern void mnt_unpin(struct vfsmount *mnt); |
114 | extern int __mnt_is_readonly(struct vfsmount *mnt); | 103 | extern int __mnt_is_readonly(struct vfsmount *mnt); |
115 | 104 | ||
116 | static inline void mntput(struct vfsmount *mnt) | ||
117 | { | ||
118 | if (mnt) { | ||
119 | mnt->mnt_expiry_mark = 0; | ||
120 | mntput_no_expire(mnt); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | extern struct vfsmount *do_kern_mount(const char *fstype, int flags, | 105 | extern struct vfsmount *do_kern_mount(const char *fstype, int flags, |
125 | const char *name, void *data); | 106 | const char *name, void *data); |
126 | 107 | ||
diff --git a/include/linux/namei.h b/include/linux/namei.h index 05b441d93642..18d06add0a40 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -19,7 +19,10 @@ struct nameidata { | |||
19 | struct path path; | 19 | struct path path; |
20 | struct qstr last; | 20 | struct qstr last; |
21 | struct path root; | 21 | struct path root; |
22 | struct file *file; | ||
23 | struct inode *inode; /* path.dentry.d_inode */ | ||
22 | unsigned int flags; | 24 | unsigned int flags; |
25 | unsigned seq; | ||
23 | int last_type; | 26 | int last_type; |
24 | unsigned depth; | 27 | unsigned depth; |
25 | char *saved_names[MAX_NESTED_LINKS + 1]; | 28 | char *saved_names[MAX_NESTED_LINKS + 1]; |
@@ -41,14 +44,15 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; | |||
41 | * - require a directory | 44 | * - require a directory |
42 | * - ending slashes ok even for nonexistent files | 45 | * - ending slashes ok even for nonexistent files |
43 | * - internal "there are more path components" flag | 46 | * - internal "there are more path components" flag |
44 | * - locked when lookup done with dcache_lock held | ||
45 | * - dentry cache is untrusted; force a real lookup | 47 | * - dentry cache is untrusted; force a real lookup |
46 | */ | 48 | */ |
47 | #define LOOKUP_FOLLOW 1 | 49 | #define LOOKUP_FOLLOW 0x0001 |
48 | #define LOOKUP_DIRECTORY 2 | 50 | #define LOOKUP_DIRECTORY 0x0002 |
49 | #define LOOKUP_CONTINUE 4 | 51 | #define LOOKUP_CONTINUE 0x0004 |
50 | #define LOOKUP_PARENT 16 | 52 | |
51 | #define LOOKUP_REVAL 64 | 53 | #define LOOKUP_PARENT 0x0010 |
54 | #define LOOKUP_REVAL 0x0020 | ||
55 | #define LOOKUP_RCU 0x0040 | ||
52 | /* | 56 | /* |
53 | * Intent data | 57 | * Intent data |
54 | */ | 58 | */ |
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index ef663061d5ac..1c27f201c856 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h | |||
@@ -184,13 +184,13 @@ struct ncp_entry_info { | |||
184 | __u8 file_handle[6]; | 184 | __u8 file_handle[6]; |
185 | }; | 185 | }; |
186 | 186 | ||
187 | static inline struct ncp_server *NCP_SBP(struct super_block *sb) | 187 | static inline struct ncp_server *NCP_SBP(const struct super_block *sb) |
188 | { | 188 | { |
189 | return sb->s_fs_info; | 189 | return sb->s_fs_info; |
190 | } | 190 | } |
191 | 191 | ||
192 | #define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) | 192 | #define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) |
193 | static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode) | 193 | static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode) |
194 | { | 194 | { |
195 | return container_of(inode, struct ncp_inode_info, vfs_inode); | 195 | return container_of(inode, struct ncp_inode_info, vfs_inode); |
196 | } | 196 | } |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 29d504d5d1c3..0779bb8f95be 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -351,7 +351,7 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *); | |||
351 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); | 351 | extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); |
352 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); | 352 | extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); |
353 | extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 353 | extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
354 | extern int nfs_permission(struct inode *, int); | 354 | extern int nfs_permission(struct inode *, int, unsigned int); |
355 | extern int nfs_open(struct inode *, struct file *); | 355 | extern int nfs_open(struct inode *, struct file *); |
356 | extern int nfs_release(struct inode *, struct file *); | 356 | extern int nfs_release(struct inode *, struct file *); |
357 | extern int nfs_attribute_timeout(struct inode *inode); | 357 | extern int nfs_attribute_timeout(struct inode *inode); |
diff --git a/include/linux/path.h b/include/linux/path.h index edc98dec6266..a581e8c06533 100644 --- a/include/linux/path.h +++ b/include/linux/path.h | |||
@@ -10,7 +10,9 @@ struct path { | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | extern void path_get(struct path *); | 12 | extern void path_get(struct path *); |
13 | extern void path_get_long(struct path *); | ||
13 | extern void path_put(struct path *); | 14 | extern void path_put(struct path *); |
15 | extern void path_put_long(struct path *); | ||
14 | 16 | ||
15 | static inline int path_equal(const struct path *path1, const struct path *path2) | 17 | static inline int path_equal(const struct path *path1, const struct path *path2) |
16 | { | 18 | { |
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 67608161df6b..d68283a898bb 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h | |||
@@ -108,6 +108,25 @@ static inline struct posix_acl *get_cached_acl(struct inode *inode, int type) | |||
108 | return acl; | 108 | return acl; |
109 | } | 109 | } |
110 | 110 | ||
111 | static inline int negative_cached_acl(struct inode *inode, int type) | ||
112 | { | ||
113 | struct posix_acl **p, *acl; | ||
114 | switch (type) { | ||
115 | case ACL_TYPE_ACCESS: | ||
116 | p = &inode->i_acl; | ||
117 | break; | ||
118 | case ACL_TYPE_DEFAULT: | ||
119 | p = &inode->i_default_acl; | ||
120 | break; | ||
121 | default: | ||
122 | BUG(); | ||
123 | } | ||
124 | acl = ACCESS_ONCE(*p); | ||
125 | if (acl) | ||
126 | return 0; | ||
127 | return 1; | ||
128 | } | ||
129 | |||
111 | static inline void set_cached_acl(struct inode *inode, | 130 | static inline void set_cached_acl(struct inode *inode, |
112 | int type, | 131 | int type, |
113 | struct posix_acl *acl) | 132 | struct posix_acl *acl) |
diff --git a/include/linux/rculist_bl.h b/include/linux/rculist_bl.h new file mode 100644 index 000000000000..b872b493724d --- /dev/null +++ b/include/linux/rculist_bl.h | |||
@@ -0,0 +1,127 @@ | |||
1 | #ifndef _LINUX_RCULIST_BL_H | ||
2 | #define _LINUX_RCULIST_BL_H | ||
3 | |||
4 | /* | ||
5 | * RCU-protected bl list version. See include/linux/list_bl.h. | ||
6 | */ | ||
7 | #include <linux/list_bl.h> | ||
8 | #include <linux/rcupdate.h> | ||
9 | |||
10 | static inline void hlist_bl_set_first_rcu(struct hlist_bl_head *h, | ||
11 | struct hlist_bl_node *n) | ||
12 | { | ||
13 | LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK); | ||
14 | LIST_BL_BUG_ON(!((unsigned long)h->first & LIST_BL_LOCKMASK)); | ||
15 | rcu_assign_pointer(h->first, | ||
16 | (struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK)); | ||
17 | } | ||
18 | |||
19 | static inline struct hlist_bl_node *hlist_bl_first_rcu(struct hlist_bl_head *h) | ||
20 | { | ||
21 | return (struct hlist_bl_node *) | ||
22 | ((unsigned long)rcu_dereference(h->first) & ~LIST_BL_LOCKMASK); | ||
23 | } | ||
24 | |||
25 | /** | ||
26 | * hlist_bl_del_init_rcu - deletes entry from hash list with re-initialization | ||
27 | * @n: the element to delete from the hash list. | ||
28 | * | ||
29 | * Note: hlist_bl_unhashed() on the node returns true after this. It is | ||
30 | * useful for RCU based read lockfree traversal if the writer side | ||
31 | * must know if the list entry is still hashed or already unhashed. | ||
32 | * | ||
33 | * In particular, it means that we can not poison the forward pointers | ||
34 | * that may still be used for walking the hash list and we can only | ||
35 | * zero the pprev pointer so list_unhashed() will return true after | ||
36 | * this. | ||
37 | * | ||
38 | * The caller must take whatever precautions are necessary (such as | ||
39 | * holding appropriate locks) to avoid racing with another | ||
40 | * list-mutation primitive, such as hlist_bl_add_head_rcu() or | ||
41 | * hlist_bl_del_rcu(), running on this same list. However, it is | ||
42 | * perfectly legal to run concurrently with the _rcu list-traversal | ||
43 | * primitives, such as hlist_bl_for_each_entry_rcu(). | ||
44 | */ | ||
45 | static inline void hlist_bl_del_init_rcu(struct hlist_bl_node *n) | ||
46 | { | ||
47 | if (!hlist_bl_unhashed(n)) { | ||
48 | __hlist_bl_del(n); | ||
49 | n->pprev = NULL; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * hlist_bl_del_rcu - deletes entry from hash list without re-initialization | ||
55 | * @n: the element to delete from the hash list. | ||
56 | * | ||
57 | * Note: hlist_bl_unhashed() on entry does not return true after this, | ||
58 | * the entry is in an undefined state. It is useful for RCU based | ||
59 | * lockfree traversal. | ||
60 | * | ||
61 | * In particular, it means that we can not poison the forward | ||
62 | * pointers that may still be used for walking the hash list. | ||
63 | * | ||
64 | * The caller must take whatever precautions are necessary | ||
65 | * (such as holding appropriate locks) to avoid racing | ||
66 | * with another list-mutation primitive, such as hlist_bl_add_head_rcu() | ||
67 | * or hlist_bl_del_rcu(), running on this same list. | ||
68 | * However, it is perfectly legal to run concurrently with | ||
69 | * the _rcu list-traversal primitives, such as | ||
70 | * hlist_bl_for_each_entry(). | ||
71 | */ | ||
72 | static inline void hlist_bl_del_rcu(struct hlist_bl_node *n) | ||
73 | { | ||
74 | __hlist_bl_del(n); | ||
75 | n->pprev = LIST_POISON2; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * hlist_bl_add_head_rcu | ||
80 | * @n: the element to add to the hash list. | ||
81 | * @h: the list to add to. | ||
82 | * | ||
83 | * Description: | ||
84 | * Adds the specified element to the specified hlist_bl, | ||
85 | * while permitting racing traversals. | ||
86 | * | ||
87 | * The caller must take whatever precautions are necessary | ||
88 | * (such as holding appropriate locks) to avoid racing | ||
89 | * with another list-mutation primitive, such as hlist_bl_add_head_rcu() | ||
90 | * or hlist_bl_del_rcu(), running on this same list. | ||
91 | * However, it is perfectly legal to run concurrently with | ||
92 | * the _rcu list-traversal primitives, such as | ||
93 | * hlist_bl_for_each_entry_rcu(), used to prevent memory-consistency | ||
94 | * problems on Alpha CPUs. Regardless of the type of CPU, the | ||
95 | * list-traversal primitive must be guarded by rcu_read_lock(). | ||
96 | */ | ||
97 | static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n, | ||
98 | struct hlist_bl_head *h) | ||
99 | { | ||
100 | struct hlist_bl_node *first; | ||
101 | |||
102 | /* don't need hlist_bl_first_rcu because we're under lock */ | ||
103 | first = hlist_bl_first(h); | ||
104 | |||
105 | n->next = first; | ||
106 | if (first) | ||
107 | first->pprev = &n->next; | ||
108 | n->pprev = &h->first; | ||
109 | |||
110 | /* need _rcu because we can have concurrent lock free readers */ | ||
111 | hlist_bl_set_first_rcu(h, n); | ||
112 | } | ||
113 | /** | ||
114 | * hlist_bl_for_each_entry_rcu - iterate over rcu list of given type | ||
115 | * @tpos: the type * to use as a loop cursor. | ||
116 | * @pos: the &struct hlist_bl_node to use as a loop cursor. | ||
117 | * @head: the head for your list. | ||
118 | * @member: the name of the hlist_bl_node within the struct. | ||
119 | * | ||
120 | */ | ||
121 | #define hlist_bl_for_each_entry_rcu(tpos, pos, head, member) \ | ||
122 | for (pos = hlist_bl_first_rcu(head); \ | ||
123 | pos && \ | ||
124 | ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \ | ||
125 | pos = rcu_dereference_raw(pos->next)) | ||
126 | |||
127 | #endif | ||
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index b2cf2089769b..3b94c91f20a6 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h | |||
@@ -41,7 +41,7 @@ int reiserfs_xattr_init(struct super_block *sb, int mount_flags); | |||
41 | int reiserfs_lookup_privroot(struct super_block *sb); | 41 | int reiserfs_lookup_privroot(struct super_block *sb); |
42 | int reiserfs_delete_xattrs(struct inode *inode); | 42 | int reiserfs_delete_xattrs(struct inode *inode); |
43 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); | 43 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); |
44 | int reiserfs_permission(struct inode *inode, int mask); | 44 | int reiserfs_permission(struct inode *inode, int mask, unsigned int flags); |
45 | 45 | ||
46 | #ifdef CONFIG_REISERFS_FS_XATTR | 46 | #ifdef CONFIG_REISERFS_FS_XATTR |
47 | #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir) | 47 | #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir) |
diff --git a/include/linux/security.h b/include/linux/security.h index d47a4c24b3e4..1ac42475ea08 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -457,7 +457,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
457 | * called when the actual read/write operations are performed. | 457 | * called when the actual read/write operations are performed. |
458 | * @inode contains the inode structure to check. | 458 | * @inode contains the inode structure to check. |
459 | * @mask contains the permission mask. | 459 | * @mask contains the permission mask. |
460 | * @nd contains the nameidata (may be NULL). | ||
461 | * Return 0 if permission is granted. | 460 | * Return 0 if permission is granted. |
462 | * @inode_setattr: | 461 | * @inode_setattr: |
463 | * Check permission before setting file attributes. Note that the kernel | 462 | * Check permission before setting file attributes. Note that the kernel |
@@ -1713,6 +1712,7 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1713 | int security_inode_readlink(struct dentry *dentry); | 1712 | int security_inode_readlink(struct dentry *dentry); |
1714 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); | 1713 | int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd); |
1715 | int security_inode_permission(struct inode *inode, int mask); | 1714 | int security_inode_permission(struct inode *inode, int mask); |
1715 | int security_inode_exec_permission(struct inode *inode, unsigned int flags); | ||
1716 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr); | 1716 | int security_inode_setattr(struct dentry *dentry, struct iattr *attr); |
1717 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); | 1717 | int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry); |
1718 | int security_inode_setxattr(struct dentry *dentry, const char *name, | 1718 | int security_inode_setxattr(struct dentry *dentry, const char *name, |
@@ -2102,6 +2102,12 @@ static inline int security_inode_permission(struct inode *inode, int mask) | |||
2102 | return 0; | 2102 | return 0; |
2103 | } | 2103 | } |
2104 | 2104 | ||
2105 | static inline int security_inode_exec_permission(struct inode *inode, | ||
2106 | unsigned int flags) | ||
2107 | { | ||
2108 | return 0; | ||
2109 | } | ||
2110 | |||
2105 | static inline int security_inode_setattr(struct dentry *dentry, | 2111 | static inline int security_inode_setattr(struct dentry *dentry, |
2106 | struct iattr *attr) | 2112 | struct iattr *attr) |
2107 | { | 2113 | { |
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index 632205ccc25d..e98cd2e57194 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h | |||
@@ -107,7 +107,7 @@ static __always_inline int read_seqretry(const seqlock_t *sl, unsigned start) | |||
107 | { | 107 | { |
108 | smp_rmb(); | 108 | smp_rmb(); |
109 | 109 | ||
110 | return (sl->sequence != start); | 110 | return unlikely(sl->sequence != start); |
111 | } | 111 | } |
112 | 112 | ||
113 | 113 | ||
@@ -125,14 +125,25 @@ typedef struct seqcount { | |||
125 | #define SEQCNT_ZERO { 0 } | 125 | #define SEQCNT_ZERO { 0 } |
126 | #define seqcount_init(x) do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0) | 126 | #define seqcount_init(x) do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0) |
127 | 127 | ||
128 | /* Start of read using pointer to a sequence counter only. */ | 128 | /** |
129 | static inline unsigned read_seqcount_begin(const seqcount_t *s) | 129 | * __read_seqcount_begin - begin a seq-read critical section (without barrier) |
130 | * @s: pointer to seqcount_t | ||
131 | * Returns: count to be passed to read_seqcount_retry | ||
132 | * | ||
133 | * __read_seqcount_begin is like read_seqcount_begin, but has no smp_rmb() | ||
134 | * barrier. Callers should ensure that smp_rmb() or equivalent ordering is | ||
135 | * provided before actually loading any of the variables that are to be | ||
136 | * protected in this critical section. | ||
137 | * | ||
138 | * Use carefully, only in critical code, and comment how the barrier is | ||
139 | * provided. | ||
140 | */ | ||
141 | static inline unsigned __read_seqcount_begin(const seqcount_t *s) | ||
130 | { | 142 | { |
131 | unsigned ret; | 143 | unsigned ret; |
132 | 144 | ||
133 | repeat: | 145 | repeat: |
134 | ret = s->sequence; | 146 | ret = s->sequence; |
135 | smp_rmb(); | ||
136 | if (unlikely(ret & 1)) { | 147 | if (unlikely(ret & 1)) { |
137 | cpu_relax(); | 148 | cpu_relax(); |
138 | goto repeat; | 149 | goto repeat; |
@@ -140,14 +151,56 @@ repeat: | |||
140 | return ret; | 151 | return ret; |
141 | } | 152 | } |
142 | 153 | ||
143 | /* | 154 | /** |
144 | * Test if reader processed invalid data because sequence number has changed. | 155 | * read_seqcount_begin - begin a seq-read critical section |
156 | * @s: pointer to seqcount_t | ||
157 | * Returns: count to be passed to read_seqcount_retry | ||
158 | * | ||
159 | * read_seqcount_begin opens a read critical section of the given seqcount. | ||
160 | * Validity of the critical section is tested by checking read_seqcount_retry | ||
161 | * function. | ||
162 | */ | ||
163 | static inline unsigned read_seqcount_begin(const seqcount_t *s) | ||
164 | { | ||
165 | unsigned ret = __read_seqcount_begin(s); | ||
166 | smp_rmb(); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * __read_seqcount_retry - end a seq-read critical section (without barrier) | ||
172 | * @s: pointer to seqcount_t | ||
173 | * @start: count, from read_seqcount_begin | ||
174 | * Returns: 1 if retry is required, else 0 | ||
175 | * | ||
176 | * __read_seqcount_retry is like read_seqcount_retry, but has no smp_rmb() | ||
177 | * barrier. Callers should ensure that smp_rmb() or equivalent ordering is | ||
178 | * provided before actually loading any of the variables that are to be | ||
179 | * protected in this critical section. | ||
180 | * | ||
181 | * Use carefully, only in critical code, and comment how the barrier is | ||
182 | * provided. | ||
183 | */ | ||
184 | static inline int __read_seqcount_retry(const seqcount_t *s, unsigned start) | ||
185 | { | ||
186 | return unlikely(s->sequence != start); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * read_seqcount_retry - end a seq-read critical section | ||
191 | * @s: pointer to seqcount_t | ||
192 | * @start: count, from read_seqcount_begin | ||
193 | * Returns: 1 if retry is required, else 0 | ||
194 | * | ||
195 | * read_seqcount_retry closes a read critical section of the given seqcount. | ||
196 | * If the critical section was invalid, it must be ignored (and typically | ||
197 | * retried). | ||
145 | */ | 198 | */ |
146 | static inline int read_seqcount_retry(const seqcount_t *s, unsigned start) | 199 | static inline int read_seqcount_retry(const seqcount_t *s, unsigned start) |
147 | { | 200 | { |
148 | smp_rmb(); | 201 | smp_rmb(); |
149 | 202 | ||
150 | return s->sequence != start; | 203 | return __read_seqcount_retry(s, start); |
151 | } | 204 | } |
152 | 205 | ||
153 | 206 | ||
@@ -167,6 +220,19 @@ static inline void write_seqcount_end(seqcount_t *s) | |||
167 | s->sequence++; | 220 | s->sequence++; |
168 | } | 221 | } |
169 | 222 | ||
223 | /** | ||
224 | * write_seqcount_barrier - invalidate in-progress read-side seq operations | ||
225 | * @s: pointer to seqcount_t | ||
226 | * | ||
227 | * After write_seqcount_barrier, no read-side seq operations will complete | ||
228 | * successfully and see data older than this. | ||
229 | */ | ||
230 | static inline void write_seqcount_barrier(seqcount_t *s) | ||
231 | { | ||
232 | smp_wmb(); | ||
233 | s->sequence+=2; | ||
234 | } | ||
235 | |||
170 | /* | 236 | /* |
171 | * Possible sw/hw IRQ protected versions of the interfaces. | 237 | * Possible sw/hw IRQ protected versions of the interfaces. |
172 | */ | 238 | */ |
diff --git a/include/linux/slab.h b/include/linux/slab.h index 59260e21bdf5..fa9086647eb7 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h | |||
@@ -106,8 +106,6 @@ int kmem_cache_shrink(struct kmem_cache *); | |||
106 | void kmem_cache_free(struct kmem_cache *, void *); | 106 | void kmem_cache_free(struct kmem_cache *, void *); |
107 | unsigned int kmem_cache_size(struct kmem_cache *); | 107 | unsigned int kmem_cache_size(struct kmem_cache *); |
108 | const char *kmem_cache_name(struct kmem_cache *); | 108 | const char *kmem_cache_name(struct kmem_cache *); |
109 | int kern_ptr_validate(const void *ptr, unsigned long size); | ||
110 | int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr); | ||
111 | 109 | ||
112 | /* | 110 | /* |
113 | * Please use this macro to create slab caches. Simply specify the | 111 | * Please use this macro to create slab caches. Simply specify the |