diff options
| author | Jan Kara <jack@suse.cz> | 2012-06-12 10:20:34 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-31 01:30:13 -0400 |
| commit | 5accdf82ba25cacefd6c1867f1704beb4d244cdd (patch) | |
| tree | 7125b01d9bf0f23d5c5eaed0cbafa9a1cbe544d5 | |
| parent | d87aae2f3c8e90bd0fe03f5309b4d066b712b8ec (diff) | |
fs: Improve filesystem freezing handling
vfs_check_frozen() tests are racy since the filesystem can be frozen just after
the test is performed. Thus in write paths we can end up marking some pages or
inodes dirty even though the file system is already frozen. This creates
problems with flusher thread hanging on frozen filesystem.
Another problem is that exclusion between ->page_mkwrite() and filesystem
freezing has been handled by setting page dirty and then verifying s_frozen.
This guaranteed that either the freezing code sees the faulted page, writes it,
and writeprotects it again or we see s_frozen set and bail out of page fault.
This works to protect from page being marked writeable while filesystem
freezing is running but has an unpleasant artefact of leaving dirty (although
unmodified and writeprotected) pages on frozen filesystem resulting in similar
problems with flusher thread as the first problem.
This patch aims at providing exclusion between write paths and filesystem
freezing. We implement a writer-freeze read-write semaphore in the superblock.
Actually, there are three such semaphores because of lock ranking reasons - one
for page fault handlers (->page_mkwrite), one for all other writers, and one of
internal filesystem purposes (used e.g. to track running transactions). Write
paths which should block freezing (e.g. directory operations, ->aio_write(),
->page_mkwrite) hold reader side of the semaphore. Code freezing the filesystem
takes the writer side.
Only that we don't really want to bounce cachelines of the semaphores between
CPUs for each write happening. So we implement the reader side of the semaphore
as a per-cpu counter and the writer side is implemented using s_writers.frozen
superblock field.
[AV: microoptimize sb_start_write(); we want it fast in normal case]
BugLink: https://bugs.launchpad.net/bugs/897421
Tested-by: Kamal Mostafa <kamal@canonical.com>
Tested-by: Peter M. Petrakis <peter.petrakis@canonical.com>
Tested-by: Dann Frazier <dann.frazier@canonical.com>
Tested-by: Massimo Morana <massimo.morana@canonical.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/super.c | 251 | ||||
| -rw-r--r-- | include/linux/fs.h | 150 |
2 files changed, 373 insertions, 28 deletions
diff --git a/fs/super.c b/fs/super.c index c743fb3be4b8..0f64ecb7b1bf 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -33,12 +33,19 @@ | |||
| 33 | #include <linux/rculist_bl.h> | 33 | #include <linux/rculist_bl.h> |
| 34 | #include <linux/cleancache.h> | 34 | #include <linux/cleancache.h> |
| 35 | #include <linux/fsnotify.h> | 35 | #include <linux/fsnotify.h> |
| 36 | #include <linux/lockdep.h> | ||
| 36 | #include "internal.h" | 37 | #include "internal.h" |
| 37 | 38 | ||
| 38 | 39 | ||
| 39 | LIST_HEAD(super_blocks); | 40 | LIST_HEAD(super_blocks); |
| 40 | DEFINE_SPINLOCK(sb_lock); | 41 | DEFINE_SPINLOCK(sb_lock); |
| 41 | 42 | ||
| 43 | static char *sb_writers_name[SB_FREEZE_LEVELS] = { | ||
| 44 | "sb_writers", | ||
| 45 | "sb_pagefaults", | ||
| 46 | "sb_internal", | ||
| 47 | }; | ||
| 48 | |||
| 42 | /* | 49 | /* |
| 43 | * One thing we have to be careful of with a per-sb shrinker is that we don't | 50 | * One thing we have to be careful of with a per-sb shrinker is that we don't |
| 44 | * drop the last active reference to the superblock from within the shrinker. | 51 | * drop the last active reference to the superblock from within the shrinker. |
| @@ -102,6 +109,35 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) | |||
| 102 | return total_objects; | 109 | return total_objects; |
| 103 | } | 110 | } |
| 104 | 111 | ||
| 112 | static int init_sb_writers(struct super_block *s, struct file_system_type *type) | ||
| 113 | { | ||
| 114 | int err; | ||
| 115 | int i; | ||
| 116 | |||
| 117 | for (i = 0; i < SB_FREEZE_LEVELS; i++) { | ||
| 118 | err = percpu_counter_init(&s->s_writers.counter[i], 0); | ||
| 119 | if (err < 0) | ||
| 120 | goto err_out; | ||
| 121 | lockdep_init_map(&s->s_writers.lock_map[i], sb_writers_name[i], | ||
| 122 | &type->s_writers_key[i], 0); | ||
| 123 | } | ||
| 124 | init_waitqueue_head(&s->s_writers.wait); | ||
| 125 | init_waitqueue_head(&s->s_writers.wait_unfrozen); | ||
| 126 | return 0; | ||
| 127 | err_out: | ||
| 128 | while (--i >= 0) | ||
| 129 | percpu_counter_destroy(&s->s_writers.counter[i]); | ||
| 130 | return err; | ||
| 131 | } | ||
| 132 | |||
| 133 | static void destroy_sb_writers(struct super_block *s) | ||
| 134 | { | ||
| 135 | int i; | ||
| 136 | |||
| 137 | for (i = 0; i < SB_FREEZE_LEVELS; i++) | ||
| 138 | percpu_counter_destroy(&s->s_writers.counter[i]); | ||
| 139 | } | ||
| 140 | |||
| 105 | /** | 141 | /** |
| 106 | * alloc_super - create new superblock | 142 | * alloc_super - create new superblock |
| 107 | * @type: filesystem type superblock should belong to | 143 | * @type: filesystem type superblock should belong to |
| @@ -117,18 +153,19 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 117 | 153 | ||
| 118 | if (s) { | 154 | if (s) { |
| 119 | if (security_sb_alloc(s)) { | 155 | if (security_sb_alloc(s)) { |
| 156 | /* | ||
| 157 | * We cannot call security_sb_free() without | ||
| 158 | * security_sb_alloc() succeeding. So bail out manually | ||
| 159 | */ | ||
| 120 | kfree(s); | 160 | kfree(s); |
| 121 | s = NULL; | 161 | s = NULL; |
| 122 | goto out; | 162 | goto out; |
| 123 | } | 163 | } |
| 124 | #ifdef CONFIG_SMP | 164 | #ifdef CONFIG_SMP |
| 125 | s->s_files = alloc_percpu(struct list_head); | 165 | s->s_files = alloc_percpu(struct list_head); |
| 126 | if (!s->s_files) { | 166 | if (!s->s_files) |
| 127 | security_sb_free(s); | 167 | goto err_out; |
| 128 | kfree(s); | 168 | else { |
| 129 | s = NULL; | ||
| 130 | goto out; | ||
| 131 | } else { | ||
| 132 | int i; | 169 | int i; |
| 133 | 170 | ||
| 134 | for_each_possible_cpu(i) | 171 | for_each_possible_cpu(i) |
| @@ -137,6 +174,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 137 | #else | 174 | #else |
| 138 | INIT_LIST_HEAD(&s->s_files); | 175 | INIT_LIST_HEAD(&s->s_files); |
| 139 | #endif | 176 | #endif |
| 177 | if (init_sb_writers(s, type)) | ||
| 178 | goto err_out; | ||
| 140 | s->s_flags = flags; | 179 | s->s_flags = flags; |
| 141 | s->s_bdi = &default_backing_dev_info; | 180 | s->s_bdi = &default_backing_dev_info; |
| 142 | INIT_HLIST_NODE(&s->s_instances); | 181 | INIT_HLIST_NODE(&s->s_instances); |
| @@ -190,6 +229,16 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
| 190 | } | 229 | } |
| 191 | out: | 230 | out: |
| 192 | return s; | 231 | return s; |
| 232 | err_out: | ||
| 233 | security_sb_free(s); | ||
| 234 | #ifdef CONFIG_SMP | ||
| 235 | if (s->s_files) | ||
| 236 | free_percpu(s->s_files); | ||
| 237 | #endif | ||
| 238 | destroy_sb_writers(s); | ||
| 239 | kfree(s); | ||
| 240 | s = NULL; | ||
| 241 | goto out; | ||
| 193 | } | 242 | } |
| 194 | 243 | ||
| 195 | /** | 244 | /** |
| @@ -203,6 +252,7 @@ static inline void destroy_super(struct super_block *s) | |||
| 203 | #ifdef CONFIG_SMP | 252 | #ifdef CONFIG_SMP |
| 204 | free_percpu(s->s_files); | 253 | free_percpu(s->s_files); |
| 205 | #endif | 254 | #endif |
| 255 | destroy_sb_writers(s); | ||
| 206 | security_sb_free(s); | 256 | security_sb_free(s); |
| 207 | WARN_ON(!list_empty(&s->s_mounts)); | 257 | WARN_ON(!list_empty(&s->s_mounts)); |
| 208 | kfree(s->s_subtype); | 258 | kfree(s->s_subtype); |
| @@ -651,10 +701,11 @@ struct super_block *get_super_thawed(struct block_device *bdev) | |||
| 651 | { | 701 | { |
| 652 | while (1) { | 702 | while (1) { |
| 653 | struct super_block *s = get_super(bdev); | 703 | struct super_block *s = get_super(bdev); |
| 654 | if (!s || s->s_frozen == SB_UNFROZEN) | 704 | if (!s || s->s_writers.frozen == SB_UNFROZEN) |
| 655 | return s; | 705 | return s; |
| 656 | up_read(&s->s_umount); | 706 | up_read(&s->s_umount); |
| 657 | vfs_check_frozen(s, SB_FREEZE_WRITE); | 707 | wait_event(s->s_writers.wait_unfrozen, |
| 708 | s->s_writers.frozen == SB_UNFROZEN); | ||
| 658 | put_super(s); | 709 | put_super(s); |
| 659 | } | 710 | } |
| 660 | } | 711 | } |
| @@ -732,7 +783,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
| 732 | int retval; | 783 | int retval; |
| 733 | int remount_ro; | 784 | int remount_ro; |
| 734 | 785 | ||
| 735 | if (sb->s_frozen != SB_UNFROZEN) | 786 | if (sb->s_writers.frozen != SB_UNFROZEN) |
| 736 | return -EBUSY; | 787 | return -EBUSY; |
| 737 | 788 | ||
| 738 | #ifdef CONFIG_BLOCK | 789 | #ifdef CONFIG_BLOCK |
| @@ -1163,6 +1214,120 @@ out: | |||
| 1163 | return ERR_PTR(error); | 1214 | return ERR_PTR(error); |
| 1164 | } | 1215 | } |
| 1165 | 1216 | ||
| 1217 | /* | ||
| 1218 | * This is an internal function, please use sb_end_{write,pagefault,intwrite} | ||
| 1219 | * instead. | ||
| 1220 | */ | ||
| 1221 | void __sb_end_write(struct super_block *sb, int level) | ||
| 1222 | { | ||
| 1223 | percpu_counter_dec(&sb->s_writers.counter[level-1]); | ||
| 1224 | /* | ||
| 1225 | * Make sure s_writers are updated before we wake up waiters in | ||
| 1226 | * freeze_super(). | ||
| 1227 | */ | ||
| 1228 | smp_mb(); | ||
| 1229 | if (waitqueue_active(&sb->s_writers.wait)) | ||
| 1230 | wake_up(&sb->s_writers.wait); | ||
| 1231 | rwsem_release(&sb->s_writers.lock_map[level-1], 1, _RET_IP_); | ||
| 1232 | } | ||
| 1233 | EXPORT_SYMBOL(__sb_end_write); | ||
| 1234 | |||
| 1235 | #ifdef CONFIG_LOCKDEP | ||
| 1236 | /* | ||
| 1237 | * We want lockdep to tell us about possible deadlocks with freezing but | ||
| 1238 | * it's it bit tricky to properly instrument it. Getting a freeze protection | ||
| 1239 | * works as getting a read lock but there are subtle problems. XFS for example | ||
| 1240 | * gets freeze protection on internal level twice in some cases, which is OK | ||
| 1241 | * only because we already hold a freeze protection also on higher level. Due | ||
| 1242 | * to these cases we have to tell lockdep we are doing trylock when we | ||
| 1243 | * already hold a freeze protection for a higher freeze level. | ||
| 1244 | */ | ||
| 1245 | static void acquire_freeze_lock(struct super_block *sb, int level, bool trylock, | ||
| 1246 | unsigned long ip) | ||
| 1247 | { | ||
| 1248 | int i; | ||
| 1249 | |||
