diff options
-rw-r--r-- | fs/inode.c | 3 | ||||
-rw-r--r-- | fs/locks.c | 44 | ||||
-rw-r--r-- | include/linux/fs.h | 11 |
3 files changed, 57 insertions, 1 deletions
diff --git a/fs/inode.c b/fs/inode.c index aa149e7262ac..f30872ade6d7 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -194,7 +194,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
194 | #ifdef CONFIG_FSNOTIFY | 194 | #ifdef CONFIG_FSNOTIFY |
195 | inode->i_fsnotify_mask = 0; | 195 | inode->i_fsnotify_mask = 0; |
196 | #endif | 196 | #endif |
197 | 197 | inode->i_flctx = NULL; | |
198 | this_cpu_inc(nr_inodes); | 198 | this_cpu_inc(nr_inodes); |
199 | 199 | ||
200 | return 0; | 200 | return 0; |
@@ -237,6 +237,7 @@ void __destroy_inode(struct inode *inode) | |||
237 | BUG_ON(inode_has_buffers(inode)); | 237 | BUG_ON(inode_has_buffers(inode)); |
238 | security_inode_free(inode); | 238 | security_inode_free(inode); |
239 | fsnotify_inode_delete(inode); | 239 | fsnotify_inode_delete(inode); |
240 | locks_free_lock_context(inode->i_flctx); | ||
240 | if (!inode->i_nlink) { | 241 | if (!inode->i_nlink) { |
241 | WARN_ON(atomic_long_read(&inode->i_sb->s_remove_count) == 0); | 242 | WARN_ON(atomic_long_read(&inode->i_sb->s_remove_count) == 0); |
242 | atomic_long_dec(&inode->i_sb->s_remove_count); | 243 | atomic_long_dec(&inode->i_sb->s_remove_count); |
diff --git a/fs/locks.c b/fs/locks.c index ae1e7cf721d6..526d5fca67c8 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -202,8 +202,49 @@ static DEFINE_HASHTABLE(blocked_hash, BLOCKED_HASH_BITS); | |||
202 | */ | 202 | */ |
203 | static DEFINE_SPINLOCK(blocked_lock_lock); | 203 | static DEFINE_SPINLOCK(blocked_lock_lock); |
204 | 204 | ||
205 | static struct kmem_cache *flctx_cache __read_mostly; | ||
205 | static struct kmem_cache *filelock_cache __read_mostly; | 206 | static struct kmem_cache *filelock_cache __read_mostly; |
206 | 207 | ||
208 | static struct file_lock_context * | ||
209 | locks_get_lock_context(struct inode *inode) | ||
210 | { | ||
211 | struct file_lock_context *new; | ||
212 | |||
213 | if (likely(inode->i_flctx)) | ||
214 | goto out; | ||
215 | |||
216 | new = kmem_cache_alloc(flctx_cache, GFP_KERNEL); | ||
217 | if (!new) | ||
218 | goto out; | ||
219 | |||
220 | INIT_LIST_HEAD(&new->flc_flock); | ||
221 | |||
222 | /* | ||
223 | * Assign the pointer if it's not already assigned. If it is, then | ||
224 | * free the context we just allocated. | ||
225 | */ | ||
226 | spin_lock(&inode->i_lock); | ||
227 | if (likely(!inode->i_flctx)) { | ||
228 | inode->i_flctx = new; | ||
229 | new = NULL; | ||
230 | } | ||
231 | spin_unlock(&inode->i_lock); | ||
232 | |||
233 | if (new) | ||
234 | kmem_cache_free(flctx_cache, new); | ||
235 | out: | ||
236 | return inode->i_flctx; | ||
237 | } | ||
238 | |||
239 | void | ||
240 | locks_free_lock_context(struct file_lock_context *ctx) | ||
241 | { | ||
242 | if (ctx) { | ||
243 | WARN_ON_ONCE(!list_empty(&ctx->flc_flock)); | ||
244 | kmem_cache_free(flctx_cache, ctx); | ||
245 | } | ||
246 | } | ||
247 | |||
207 | static void locks_init_lock_heads(struct file_lock *fl) | 248 | static void locks_init_lock_heads(struct file_lock *fl) |
208 | { | 249 | { |
209 | INIT_HLIST_NODE(&fl->fl_link); | 250 | INIT_HLIST_NODE(&fl->fl_link); |
@@ -2636,6 +2677,9 @@ static int __init filelock_init(void) | |||
2636 | { | 2677 | { |
2637 | int i; | 2678 | int i; |
2638 | 2679 | ||
2680 | flctx_cache = kmem_cache_create("file_lock_ctx", | ||
2681 | sizeof(struct file_lock_context), 0, SLAB_PANIC, NULL); | ||
2682 | |||
2639 | filelock_cache = kmem_cache_create("file_lock_cache", | 2683 | filelock_cache = kmem_cache_create("file_lock_cache", |
2640 | sizeof(struct file_lock), 0, SLAB_PANIC, NULL); | 2684 | sizeof(struct file_lock), 0, SLAB_PANIC, NULL); |
2641 | 2685 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index cd6818115162..dec0d38b05de 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -626,6 +626,7 @@ struct inode { | |||
626 | #endif | 626 | #endif |
627 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ | 627 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ |
628 | struct file_lock *i_flock; | 628 | struct file_lock *i_flock; |
629 | struct file_lock_context *i_flctx; | ||
629 | struct address_space i_data; | 630 | struct address_space i_data; |
630 | struct list_head i_devices; | 631 | struct list_head i_devices; |
631 | union { | 632 | union { |
@@ -965,6 +966,10 @@ struct file_lock { | |||
965 | } fl_u; | 966 | } fl_u; |
966 | }; | 967 | }; |
967 | 968 | ||
969 | struct file_lock_context { | ||
970 | struct list_head flc_flock; | ||
971 | }; | ||
972 | |||
968 | /* The following constant reflects the upper bound of the file/locking space */ | 973 | /* The following constant reflects the upper bound of the file/locking space */ |
969 | #ifndef OFFSET_MAX | 974 | #ifndef OFFSET_MAX |
970 | #define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1))) | 975 | #define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1))) |
@@ -991,6 +996,7 @@ extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); | |||
991 | extern int fcntl_getlease(struct file *filp); | 996 | extern int fcntl_getlease(struct file *filp); |
992 | 997 | ||
993 | /* fs/locks.c */ | 998 | /* fs/locks.c */ |
999 | void locks_free_lock_context(struct file_lock_context *ctx); | ||
994 | void locks_free_lock(struct file_lock *fl); | 1000 | void locks_free_lock(struct file_lock *fl); |
995 | extern void locks_init_lock(struct file_lock *); | 1001 | extern void locks_init_lock(struct file_lock *); |
996 | extern struct file_lock * locks_alloc_lock(void); | 1002 | extern struct file_lock * locks_alloc_lock(void); |
@@ -1048,6 +1054,11 @@ static inline int fcntl_getlease(struct file *filp) | |||
1048 | return F_UNLCK; | 1054 | return F_UNLCK; |
1049 | } | 1055 | } |
1050 | 1056 | ||
1057 | static inline void | ||
1058 | locks_free_lock_context(struct file_lock_context *ctx) | ||
1059 | { | ||
1060 | } | ||
1061 | |||
1051 | static inline void locks_init_lock(struct file_lock *fl) | 1062 | static inline void locks_init_lock(struct file_lock *fl) |
1052 | { | 1063 | { |
1053 | return; | 1064 | return; |