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 |
