History

mm: prevent concurrent unmap_mapping_range() on the same inode

Michael Leun reported that running parallel opens on a fuse filesystem can trigger a "kernel BUG at mm/truncate.c:475" Gurudas Pai reported the same bug on NFS. The reason is, unmap_mapping_range() is not prepared for more than one concurrent invocation per inode. For example: thread1: going through a big range, stops in the middle of a vma and stores the restart address in vm_truncate_count. thread2: comes in with a small (e.g. single page) unmap request on the same vma, somewhere before restart_address, finds that the vma was already unmapped up to the restart address and happily returns without doing anything. Another scenario would be two big unmap requests, both having to restart the unmapping and each one setting vm_truncate_count to its own value. This could go on forever without any of them being able to finish. Truncate and hole punching already serialize with i_mutex. Other callers of unmap_mapping_range() do not, and it's difficult to get i_mutex protection for all callers. In particular ->d_revalidate(), which calls invalidate_inode_pages2_range() in fuse, may be called with or without i_mutex. This patch adds a new mutex to 'struct address_space' to prevent running multiple concurrent unmap_mapping_range() on the same mapping. [ We'll hopefully get rid of all this with the upcoming mm preemptibility series by Peter Zijlstra, the "mm: Remove i_mmap_mutex lockbreak" patch in particular. But that is for 2.6.39 ]

Miklos Szeredi committed 15 years ago

Commit 2aa15891 parent 78794b210 files · +23 −38Browse files

Unified · Split

10 files
  1. fs/gfs2/main.c +1 −8
  2. fs/inode.c +15 −7
  3. fs/nilfs2/btnode.c +0 −5
  4. fs/nilfs2/btnode.h +0 −1
  5. fs/nilfs2/mdt.c +2 −2
  6. fs/nilfs2/page.c +0 −13
  7. fs/nilfs2/page.h +0 −1
  8. fs/nilfs2/super.c +1 −1
  9. include/linux/fs.h +2 −0
  10. mm/memory.c +2 −0
fs/gfs2/main.c+1−8
@@ -59,14 +59,7 @@ static void gfs2_init_gl_aspace_once(void *foo) · 58 unmodified lines
59 struct address_space *mapping = (struct address_space *)(gl + 1);59 struct address_space *mapping = (struct address_space *)(gl + 1);
60 60
61 gfs2_init_glock_once(gl);61 gfs2_init_glock_once(gl);
62 memset(mapping, 0, sizeof(*mapping));62 address_space_init_once(mapping);
63 INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
64 spin_lock_init(&mapping->tree_lock);
65 spin_lock_init(&mapping->i_mmap_lock);
66 INIT_LIST_HEAD(&mapping->private_list);
67 spin_lock_init(&mapping->private_lock);
68 INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
69 INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
70}63}
71 64
72/**65/**
fs/inode.c+15−7
@@ -295,6 +295,20 @@ static void destroy_inode(struct inode *inode) · 294 unmodified lines
295 call_rcu(&inode->i_rcu, i_callback);295 call_rcu(&inode->i_rcu, i_callback);
296}296}
297 297
298void address_space_init_once(struct address_space *mapping)
299{
300 memset(mapping, 0, sizeof(*mapping));
301 INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
302 spin_lock_init(&mapping->tree_lock);
303 spin_lock_init(&mapping->i_mmap_lock);
304 INIT_LIST_HEAD(&mapping->private_list);
305 spin_lock_init(&mapping->private_lock);
306 INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
307 INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
308 mutex_init(&mapping->unmap_mutex);
309}
310EXPORT_SYMBOL(address_space_init_once);
311
298/*312/*
299 * These are initializations that only need to be done313 * These are initializations that only need to be done
300 * once, because the fields are idempotent across use314 * once, because the fields are idempotent across use
@@ -308,13 +322,7 @@ void inode_init_once(struct inode *inode) · 7 unmodified lines
308 INIT_LIST_HEAD(&inode->i_devices);322 INIT_LIST_HEAD(&inode->i_devices);
309 INIT_LIST_HEAD(&inode->i_wb_list);323 INIT_LIST_HEAD(&inode->i_wb_list);
310 INIT_LIST_HEAD(&inode->i_lru);324 INIT_LIST_HEAD(&inode->i_lru);
311 INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);325 address_space_init_once(&inode->i_data);
312 spin_lock_init(&inode->i_data.tree_lock);
313 spin_lock_init(&inode->i_data.i_mmap_lock);
314 INIT_LIST_HEAD(&inode->i_data.private_list);
315 spin_lock_init(&inode->i_data.private_lock);
316 INIT_RAW_PRIO_TREE_ROOT(&inode->i_data.i_mmap);
317 INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear);
318 i_size_ordered_init(inode);326 i_size_ordered_init(inode);
319#ifdef CONFIG_FSNOTIFY327#ifdef CONFIG_FSNOTIFY
320 INIT_HLIST_HEAD(&inode->i_fsnotify_marks);328 INIT_HLIST_HEAD(&inode->i_fsnotify_marks);
fs/nilfs2/btnode.c+0−5
@@ -35,11 +35,6 @@ · 34 unmodified lines
35#include "btnode.h"35#include "btnode.h"
36 36
37 37
38void nilfs_btnode_cache_init_once(struct address_space *btnc)
39{
40 nilfs_mapping_init_once(btnc);
41}
42
43static const struct address_space_operations def_btnode_aops = {38static const struct address_space_operations def_btnode_aops = {
44 .sync_page = block_sync_page,39 .sync_page = block_sync_page,
45};40};
fs/nilfs2/btnode.h+0−1
@@ -37,7 +37,6 @@ struct nilfs_btnode_chkey_ctxt { · 36 unmodified lines
37 struct buffer_head *newbh;37 struct buffer_head *newbh;
38};38};
39 39
40void nilfs_btnode_cache_init_once(struct address_space *);
41void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *);40void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *);
42void nilfs_btnode_cache_clear(struct address_space *);41void nilfs_btnode_cache_clear(struct address_space *);
43struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc,42struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc,
fs/nilfs2/mdt.c+2−2
@@ -454,9 +454,9 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode, · 453 unmodified lines
454 struct backing_dev_info *bdi = inode->i_sb->s_bdi;454 struct backing_dev_info *bdi = inode->i_sb->s_bdi;
455 455
456 INIT_LIST_HEAD(&shadow->frozen_buffers);456 INIT_LIST_HEAD(&shadow->frozen_buffers);
457 nilfs_mapping_init_once(&shadow->frozen_data);457 address_space_init_once(&shadow->frozen_data);
458 nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops);458 nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops);
459 nilfs_mapping_init_once(&shadow->frozen_btnodes);459 address_space_init_once(&shadow->frozen_btnodes);
460 nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops);460 nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops);
461 mi->mi_shadow = shadow;461 mi->mi_shadow = shadow;
462 return 0;462 return 0;
fs/nilfs2/page.c+0−13
@@ -492,19 +492,6 @@ unsigned nilfs_page_count_clean_buffers(struct page *page, · 491 unmodified lines
492 return nc;492 return nc;
493}493}
494 494
495void nilfs_mapping_init_once(struct address_space *mapping)
496{
497 memset(mapping, 0, sizeof(*mapping));
498 INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
499 spin_lock_init(&mapping->tree_lock);
500 INIT_LIST_HEAD(&mapping->private_list);
501 spin_lock_init(&mapping->private_lock);
502
503 spin_lock_init(&mapping->i_mmap_lock);
504 INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
505 INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
506}
507
508void nilfs_mapping_init(struct address_space *mapping,495void nilfs_mapping_init(struct address_space *mapping,
509 struct backing_dev_info *bdi,496 struct backing_dev_info *bdi,
510 const struct address_space_operations *aops)497 const struct address_space_operations *aops)
fs/nilfs2/page.h+0−1
@@ -61,7 +61,6 @@ void nilfs_free_private_page(struct page *); · 60 unmodified lines
61int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);61int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);
62void nilfs_copy_back_pages(struct address_space *, struct address_space *);62void nilfs_copy_back_pages(struct address_space *, struct address_space *);
63void nilfs_clear_dirty_pages(struct address_space *);63void nilfs_clear_dirty_pages(struct address_space *);
64void nilfs_mapping_init_once(struct address_space *mapping);
65void nilfs_mapping_init(struct address_space *mapping,64void nilfs_mapping_init(struct address_space *mapping,
66 struct backing_dev_info *bdi,65 struct backing_dev_info *bdi,
67 const struct address_space_operations *aops);66 const struct address_space_operations *aops);
fs/nilfs2/super.c+1−1
@@ -1279,7 +1279,7 @@ static void nilfs_inode_init_once(void *obj) · 1278 unmodified lines
1279#ifdef CONFIG_NILFS_XATTR1279#ifdef CONFIG_NILFS_XATTR
1280 init_rwsem(&ii->xattr_sem);1280 init_rwsem(&ii->xattr_sem);
1281#endif1281#endif
1282 nilfs_btnode_cache_init_once(&ii->i_btnode_cache);1282 address_space_init_once(&ii->i_btnode_cache);
1283 ii->i_bmap = &ii->i_bmap_data;1283 ii->i_bmap = &ii->i_bmap_data;
1284 inode_init_once(&ii->vfs_inode);1284 inode_init_once(&ii->vfs_inode);
1285}1285}
include/linux/fs.h+2−0
@@ -649,6 +649,7 @@ struct address_space { · 648 unmodified lines
649 spinlock_t private_lock; /* for use by the address_space */649 spinlock_t private_lock; /* for use by the address_space */
650 struct list_head private_list; /* ditto */650 struct list_head private_list; /* ditto */
651 struct address_space *assoc_mapping; /* ditto */651 struct address_space *assoc_mapping; /* ditto */
652 struct mutex unmap_mutex; /* to protect unmapping */
652} __attribute__((aligned(sizeof(long))));653} __attribute__((aligned(sizeof(long))));
653 /*654 /*
654 * On most architectures that alignment is already the case; but655 * On most architectures that alignment is already the case; but
@@ -2225,6 +2226,7 @@ extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); · 1570 unmodified lines
2225 2226
2226extern int inode_init_always(struct super_block *, struct inode *);2227extern int inode_init_always(struct super_block *, struct inode *);
2227extern void inode_init_once(struct inode *);2228extern void inode_init_once(struct inode *);
2229extern void address_space_init_once(struct address_space *mapping);
2228extern void ihold(struct inode * inode);2230extern void ihold(struct inode * inode);
2229extern void iput(struct inode *);2231extern void iput(struct inode *);
2230extern struct inode * igrab(struct inode *);2232extern struct inode * igrab(struct inode *);
mm/memory.c+2−0
@@ -2648,6 +2648,7 @@ void unmap_mapping_range(struct address_space *mapping, · 2647 unmodified lines
2648 details.last_index = ULONG_MAX;2648 details.last_index = ULONG_MAX;
2649 details.i_mmap_lock = &mapping->i_mmap_lock;2649 details.i_mmap_lock = &mapping->i_mmap_lock;
2650 2650
2651 mutex_lock(&mapping->unmap_mutex);
2651 spin_lock(&mapping->i_mmap_lock);2652 spin_lock(&mapping->i_mmap_lock);
2652 2653
2653 /* Protect against endless unmapping loops */2654 /* Protect against endless unmapping loops */
@@ -2664,6 +2665,7 @@ void unmap_mapping_range(struct address_space *mapping, · 10 unmodified lines
2664 if (unlikely(!list_empty(&mapping->i_mmap_nonlinear)))2665 if (unlikely(!list_empty(&mapping->i_mmap_nonlinear)))
2665 unmap_mapping_range_list(&mapping->i_mmap_nonlinear, &details);2666 unmap_mapping_range_list(&mapping->i_mmap_nonlinear, &details);
2666 spin_unlock(&mapping->i_mmap_lock);2667 spin_unlock(&mapping->i_mmap_lock);
2668 mutex_unlock(&mapping->unmap_mutex);
2667}2669}
2668EXPORT_SYMBOL(unmap_mapping_range);2670EXPORT_SYMBOL(unmap_mapping_range);
2669 2671