aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/inode.c3
-rw-r--r--fs/locks.c44
-rw-r--r--include/linux/fs.h11
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 */
203static DEFINE_SPINLOCK(blocked_lock_lock); 203static DEFINE_SPINLOCK(blocked_lock_lock);
204 204
205static struct kmem_cache *flctx_cache __read_mostly;
205static struct kmem_cache *filelock_cache __read_mostly; 206static struct kmem_cache *filelock_cache __read_mostly;
206 207
208static struct file_lock_context *
209locks_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);
235out:
236 return inode->i_flctx;
237}
238
239void
240locks_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
207static void locks_init_lock_heads(struct file_lock *fl) 248static 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
969struct 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);
991extern int fcntl_getlease(struct file *filp); 996extern int fcntl_getlease(struct file *filp);
992 997
993/* fs/locks.c */ 998/* fs/locks.c */
999void locks_free_lock_context(struct file_lock_context *ctx);
994void locks_free_lock(struct file_lock *fl); 1000void locks_free_lock(struct file_lock *fl);
995extern void locks_init_lock(struct file_lock *); 1001extern void locks_init_lock(struct file_lock *);
996extern struct file_lock * locks_alloc_lock(void); 1002extern 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
1057static inline void
1058locks_free_lock_context(struct file_lock_context *ctx)
1059{
1060}
1061
1051static inline void locks_init_lock(struct file_lock *fl) 1062static inline void locks_init_lock(struct file_lock *fl)
1052{ 1063{
1053 return; 1064 return;