diff options
author | Artem Bityutskiy <artem.bityutskiy@linux.intel.com> | 2012-07-12 10:26:31 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-22 15:58:04 -0400 |
commit | 9e6c5829b07c9ba6668807631914efc557fab059 (patch) | |
tree | 4355c4b76869cf7fba0b2a60066e649e12e7fcc8 /fs/hfsplus | |
parent | 58770d7e83eede5fafbcdf54a604277d70010705 (diff) |
hfsplus: get rid of write_super
This patch makes hfsplus stop using the VFS '->write_super()' method along with
the 's_dirt' superblock flag, because they are on their way out.
The whole "superblock write-out" VFS infrastructure is served by the
'sync_supers()' kernel thread, which wakes up every 5 (by default) seconds and
writes out all dirty superblocks using the '->write_super()' call-back. But the
problem with this thread is that it wastes power by waking up the system every
5 seconds, even if there are no diry superblocks, or there are no client
file-systems which would need this (e.g., btrfs does not use
'->write_super()'). So we want to kill it completely and thus, we need to make
file-systems to stop using the '->write_super()' VFS service, and then remove
it together with the kernel thread.
Tested using fsstress from the LTP project.
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/bitmap.c | 4 | ||||
-rw-r--r-- | fs/hfsplus/dir.c | 2 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 6 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 6 | ||||
-rw-r--r-- | fs/hfsplus/super.c | 41 |
5 files changed, 43 insertions, 16 deletions
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index 1cad80c789cb..4cfbe2edd296 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c | |||
@@ -153,7 +153,7 @@ done: | |||
153 | kunmap(page); | 153 | kunmap(page); |
154 | *max = offset + (curr - pptr) * 32 + i - start; | 154 | *max = offset + (curr - pptr) * 32 + i - start; |
155 | sbi->free_blocks -= *max; | 155 | sbi->free_blocks -= *max; |
156 | sb->s_dirt = 1; | 156 | hfsplus_mark_mdb_dirty(sb); |
157 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); | 157 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); |
158 | out: | 158 | out: |
159 | mutex_unlock(&sbi->alloc_mutex); | 159 | mutex_unlock(&sbi->alloc_mutex); |
@@ -228,7 +228,7 @@ out: | |||
228 | set_page_dirty(page); | 228 | set_page_dirty(page); |
229 | kunmap(page); | 229 | kunmap(page); |
230 | sbi->free_blocks += len; | 230 | sbi->free_blocks += len; |
231 | sb->s_dirt = 1; | 231 | hfsplus_mark_mdb_dirty(sb); |
232 | mutex_unlock(&sbi->alloc_mutex); | 232 | mutex_unlock(&sbi->alloc_mutex); |
233 | 233 | ||
234 | return 0; | 234 | return 0; |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 378ea0c43f19..6b9f921ef2fa 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -316,7 +316,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
316 | inode->i_ctime = CURRENT_TIME_SEC; | 316 | inode->i_ctime = CURRENT_TIME_SEC; |
317 | mark_inode_dirty(inode); | 317 | mark_inode_dirty(inode); |
318 | sbi->file_count++; | 318 | sbi->file_count++; |
319 | dst_dir->i_sb->s_dirt = 1; | 319 | hfsplus_mark_mdb_dirty(dst_dir->i_sb); |
320 | out: | 320 | out: |
321 | mutex_unlock(&sbi->vh_mutex); | 321 | mutex_unlock(&sbi->vh_mutex); |
322 | return res; | 322 | return res; |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 66a9365041be..558dbb463a4e 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -153,8 +153,11 @@ struct hfsplus_sb_info { | |||
153 | gid_t gid; | 153 | gid_t gid; |
154 | 154 | ||
155 | int part, session; | 155 | int part, session; |
156 | |||
157 | unsigned long flags; | 156 | unsigned long flags; |
157 | |||
158 | int work_queued; /* non-zero delayed work is queued */ | ||
159 | struct delayed_work sync_work; /* FS sync delayed work */ | ||
160 | spinlock_t work_lock; /* protects sync_work and work_queued */ | ||
158 | }; | 161 | }; |
159 | 162 | ||
160 | #define HFSPLUS_SB_WRITEBACKUP 0 | 163 | #define HFSPLUS_SB_WRITEBACKUP 0 |
@@ -428,6 +431,7 @@ int hfsplus_show_options(struct seq_file *, struct dentry *); | |||
428 | 431 | ||
429 | /* super.c */ | 432 | /* super.c */ |
430 | struct inode *hfsplus_iget(struct super_block *, unsigned long); | 433 | struct inode *hfsplus_iget(struct super_block *, unsigned long); |
434 | void hfsplus_mark_mdb_dirty(struct super_block *sb); | ||
431 | 435 | ||
432 | /* tables.c */ | 436 | /* tables.c */ |
433 | extern u16 hfsplus_case_fold_table[]; | 437 | extern u16 hfsplus_case_fold_table[]; |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 7009265b746f..3d8b4a675ba0 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -431,7 +431,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode) | |||
431 | sbi->file_count++; | 431 | sbi->file_count++; |
432 | insert_inode_hash(inode); | 432 | insert_inode_hash(inode); |
433 | mark_inode_dirty(inode); | 433 | mark_inode_dirty(inode); |
434 | sb->s_dirt = 1; | 434 | hfsplus_mark_mdb_dirty(sb); |
435 | 435 | ||
436 | return inode; | 436 | return inode; |
437 | } | 437 | } |
@@ -442,7 +442,7 @@ void hfsplus_delete_inode(struct inode *inode) | |||
442 | 442 | ||
443 | if (S_ISDIR(inode->i_mode)) { | 443 | if (S_ISDIR(inode->i_mode)) { |
444 | HFSPLUS_SB(sb)->folder_count--; | 444 | HFSPLUS_SB(sb)->folder_count--; |
445 | sb->s_dirt = 1; | 445 | hfsplus_mark_mdb_dirty(sb); |
446 | return; | 446 | return; |
447 | } | 447 | } |
448 | HFSPLUS_SB(sb)->file_count--; | 448 | HFSPLUS_SB(sb)->file_count--; |
@@ -455,7 +455,7 @@ void hfsplus_delete_inode(struct inode *inode) | |||
455 | inode->i_size = 0; | 455 | inode->i_size = 0; |
456 | hfsplus_file_truncate(inode); | 456 | hfsplus_file_truncate(inode); |
457 | } | 457 | } |
458 | sb->s_dirt = 1; | 458 | hfsplus_mark_mdb_dirty(sb); |
459 | } | 459 | } |
460 | 460 | ||
461 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | 461 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index f4f3d5463061..473332098013 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -124,7 +124,7 @@ static int hfsplus_system_write_inode(struct inode *inode) | |||
124 | 124 | ||
125 | if (fork->total_size != cpu_to_be64(inode->i_size)) { | 125 | if (fork->total_size != cpu_to_be64(inode->i_size)) { |
126 | set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); | 126 | set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); |
127 | inode->i_sb->s_dirt = 1; | 127 | hfsplus_mark_mdb_dirty(inode->i_sb); |
128 | } | 128 | } |
129 | hfsplus_inode_write_fork(inode, fork); | 129 | hfsplus_inode_write_fork(inode, fork); |
130 | if (tree) | 130 | if (tree) |
@@ -173,8 +173,6 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait) | |||
173 | 173 | ||
174 | dprint(DBG_SUPER, "hfsplus_sync_fs\n"); | 174 | dprint(DBG_SUPER, "hfsplus_sync_fs\n"); |
175 | 175 | ||
176 | sb->s_dirt = 0; | ||
177 | |||
178 | /* | 176 | /* |
179 | * Explicitly write out the special metadata inodes. | 177 | * Explicitly write out the special metadata inodes. |
180 | * | 178 | * |
@@ -226,12 +224,34 @@ out: | |||
226 | return error; | 224 | return error; |
227 | } | 225 | } |
228 | 226 | ||
229 | static void hfsplus_write_super(struct super_block *sb) | 227 | static void delayed_sync_fs(struct work_struct *work) |
230 | { | 228 | { |
231 | if (!(sb->s_flags & MS_RDONLY)) | 229 | struct hfsplus_sb_info *sbi; |
232 | hfsplus_sync_fs(sb, 1); | 230 | |
233 | else | 231 | sbi = container_of(work, struct hfsplus_sb_info, sync_work.work); |
234 | sb->s_dirt = 0; | 232 | |
233 | spin_lock(&sbi->work_lock); | ||
234 | sbi->work_queued = 0; | ||
235 | spin_unlock(&sbi->work_lock); | ||
236 | |||
237 | hfsplus_sync_fs(sbi->alloc_file->i_sb, 1); | ||
238 | } | ||
239 | |||
240 | void hfsplus_mark_mdb_dirty(struct super_block *sb) | ||
241 | { | ||
242 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
243 | unsigned long delay; | ||
244 | |||
245 | if (sb->s_flags & MS_RDONLY) | ||
246 | return; | ||
247 | |||
248 | spin_lock(&sbi->work_lock); | ||
249 | if (!sbi->work_queued) { | ||
250 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
251 | queue_delayed_work(system_long_wq, &sbi->sync_work, delay); | ||
252 | sbi->work_queued = 1; | ||
253 | } | ||
254 | spin_unlock(&sbi->work_lock); | ||
235 | } | 255 | } |
236 | 256 | ||
237 | static void hfsplus_put_super(struct super_block *sb) | 257 | static void hfsplus_put_super(struct super_block *sb) |
@@ -240,6 +260,8 @@ static void hfsplus_put_super(struct super_block *sb) | |||
240 | 260 | ||
241 | dprint(DBG_SUPER, "hfsplus_put_super\n"); | 261 | dprint(DBG_SUPER, "hfsplus_put_super\n"); |
242 | 262 | ||
263 | cancel_delayed_work_sync(&sbi->sync_work); | ||
264 | |||
243 | if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { | 265 | if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { |
244 | struct hfsplus_vh *vhdr = sbi->s_vhdr; | 266 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
245 | 267 | ||
@@ -325,7 +347,6 @@ static const struct super_operations hfsplus_sops = { | |||
325 | .write_inode = hfsplus_write_inode, | 347 | .write_inode = hfsplus_write_inode, |
326 | .evict_inode = hfsplus_evict_inode, | 348 | .evict_inode = hfsplus_evict_inode, |
327 | .put_super = hfsplus_put_super, | 349 | .put_super = hfsplus_put_super, |
328 | .write_super = hfsplus_write_super, | ||
329 | .sync_fs = hfsplus_sync_fs, | 350 | .sync_fs = hfsplus_sync_fs, |
330 | .statfs = hfsplus_statfs, | 351 | .statfs = hfsplus_statfs, |
331 | .remount_fs = hfsplus_remount, | 352 | .remount_fs = hfsplus_remount, |
@@ -352,6 +373,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
352 | sb->s_fs_info = sbi; | 373 | sb->s_fs_info = sbi; |
353 | mutex_init(&sbi->alloc_mutex); | 374 | mutex_init(&sbi->alloc_mutex); |
354 | mutex_init(&sbi->vh_mutex); | 375 | mutex_init(&sbi->vh_mutex); |
376 | spin_lock_init(&sbi->work_lock); | ||
377 | INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); | ||
355 | hfsplus_fill_defaults(sbi); | 378 | hfsplus_fill_defaults(sbi); |
356 | 379 | ||
357 | err = -EINVAL; | 380 | err = -EINVAL; |