aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-07-25 11:11:59 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-08-03 17:24:44 -0400
commitf0cd2dbb6cf387c11f87265462e370bb5469299e (patch)
tree21c9b6237dd9131763654a6cd715461177701607
parentd42d1dabf34bdd5ad832cb56a7338817aad8a052 (diff)
vfs: kill write_super and sync_supers
Finally we can kill the 'sync_supers' kernel thread along with the '->write_super()' superblock operation because all the users are gone. Now every file-system is supposed to self-manage own superblock and its dirty state. The nice thing about killing this thread is that it improves power management. Indeed, 'sync_supers' is a source of monotonic system wake-ups - it woke up every 5 seconds no matter what - even if there were no dirty superblocks and even if there were no file-systems using this service (e.g., btrfs and journalled ext4 do not need it). So it was wasting power most of the time. And because the thread was in the core of the kernel, all systems had to have it. So I am quite happy to make it go away. Interestingly, this thread is a left-over from the pdflush kernel thread which was a self-forking kernel thread responsible for all the write-back in old Linux kernels. It was turned into per-block device BDI threads, and 'sync_supers' was a left-over. Thus, R.I.P, pdflush as well. Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/super.c40
-rw-r--r--include/linux/backing-dev.h1
-rw-r--r--include/linux/fs.h3
-rw-r--r--mm/backing-dev.c52
-rw-r--r--mm/page-writeback.c1
5 files changed, 0 insertions, 97 deletions
diff --git a/fs/super.c b/fs/super.c
index b05cf47463d0..0902cfa6a12e 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -537,46 +537,6 @@ void drop_super(struct super_block *sb)
537EXPORT_SYMBOL(drop_super); 537EXPORT_SYMBOL(drop_super);
538 538
539/** 539/**
540 * sync_supers - helper for periodic superblock writeback
541 *
542 * Call the write_super method if present on all dirty superblocks in
543 * the system. This is for the periodic writeback used by most older
544 * filesystems. For data integrity superblock writeback use
545 * sync_filesystems() instead.
546 *
547 * Note: check the dirty flag before waiting, so we don't
548 * hold up the sync while mounting a device. (The newly
549 * mounted device won't need syncing.)
550 */
551void sync_supers(void)
552{
553 struct super_block *sb, *p = NULL;
554
555 spin_lock(&sb_lock);
556 list_for_each_entry(sb, &super_blocks, s_list) {
557 if (hlist_unhashed(&sb->s_instances))
558 continue;
559 if (sb->s_op->write_super && sb->s_dirt) {
560 sb->s_count++;
561 spin_unlock(&sb_lock);
562
563 down_read(&sb->s_umount);
564 if (sb->s_root && sb->s_dirt && (sb->s_flags & MS_BORN))
565 sb->s_op->write_super(sb);
566 up_read(&sb->s_umount);
567
568 spin_lock(&sb_lock);
569 if (p)
570 __put_super(p);
571 p = sb;
572 }
573 }
574 if (p)
575 __put_super(p);
576 spin_unlock(&sb_lock);
577}
578
579/**
580 * iterate_supers - call function for all active superblocks 540 * iterate_supers - call function for all active superblocks
581 * @f: function to call 541 * @f: function to call
582 * @arg: argument to pass to it 542 * @arg: argument to pass to it
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index c97c6b9cd38e..2a9a9abc9126 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -124,7 +124,6 @@ void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
124void bdi_start_background_writeback(struct backing_dev_info *bdi); 124void bdi_start_background_writeback(struct backing_dev_info *bdi);
125int bdi_writeback_thread(void *data); 125int bdi_writeback_thread(void *data);
126int bdi_has_dirty_io(struct backing_dev_info *bdi); 126int bdi_has_dirty_io(struct backing_dev_info *bdi);
127void bdi_arm_supers_timer(void);
128void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); 127void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi);
129void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2); 128void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2);
130 129
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 38dba16c4176..aa110476a95b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1491,7 +1491,6 @@ struct sb_writers {
1491struct super_block { 1491struct super_block {
1492 struct list_head s_list; /* Keep this first */ 1492 struct list_head s_list; /* Keep this first */
1493 dev_t s_dev; /* search index; _not_ kdev_t */ 1493 dev_t s_dev; /* search index; _not_ kdev_t */
1494 unsigned char s_dirt;
1495 unsigned char s_blocksize_bits; 1494 unsigned char s_blocksize_bits;
1496 unsigned long s_blocksize; 1495 unsigned long s_blocksize;
1497 loff_t s_maxbytes; /* Max file size */ 1496 loff_t s_maxbytes; /* Max file size */
@@ -1861,7 +1860,6 @@ struct super_operations {
1861 int (*drop_inode) (struct inode *); 1860 int (*drop_inode) (struct inode *);
1862 void (*evict_inode) (struct inode *); 1861 void (*evict_inode) (struct inode *);
1863 void (*put_super) (struct super_block *); 1862 void (*put_super) (struct super_block *);
1864 void (*write_super) (struct super_block *);
1865 int (*sync_fs)(struct super_block *sb, int wait); 1863 int (*sync_fs)(struct super_block *sb, int wait);
1866 int (*freeze_fs) (struct super_block *); 1864 int (*freeze_fs) (struct super_block *);
1867 int (*unfreeze_fs) (struct super_block *); 1865 int (*unfreeze_fs) (struct super_block *);
@@ -2397,7 +2395,6 @@ extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
2397 int datasync); 2395 int datasync);
2398extern int vfs_fsync(struct file *file, int datasync); 2396extern int vfs_fsync(struct file *file, int datasync);
2399extern int generic_write_sync(struct file *file, loff_t pos, loff_t count); 2397extern int generic_write_sync(struct file *file, loff_t pos, loff_t count);
2400extern void sync_supers(void);
2401extern void emergency_sync(void); 2398extern void emergency_sync(void);
2402extern void emergency_remount(void); 2399extern void emergency_remount(void);
2403#ifdef CONFIG_BLOCK 2400#ifdef CONFIG_BLOCK
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 6b4718e2ee34..b41823cc05e6 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -39,12 +39,6 @@ DEFINE_SPINLOCK(bdi_lock);
39LIST_HEAD(bdi_list); 39LIST_HEAD(bdi_list);
40LIST_HEAD(bdi_pending_list); 40LIST_HEAD(bdi_pending_list);
41 41
42static struct task_struct *sync_supers_tsk;
43static struct timer_list sync_supers_timer;
44
45static int bdi_sync_supers(void *);
46static void sync_supers_timer_fn(unsigned long);
47
48void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2) 42void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)
49{ 43{
50 if (wb1 < wb2) { 44 if (wb1 < wb2) {
@@ -250,12 +244,6 @@ static int __init default_bdi_init(void)
250{ 244{
251 int err; 245 int err;
252 246
253 sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers");
254 BUG_ON(IS_ERR(sync_supers_tsk));
255
256 setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0);
257 bdi_arm_supers_timer();
258
259 err = bdi_init(&default_backing_dev_info); 247 err = bdi_init(&default_backing_dev_info);
260 if (!err) 248 if (!err)
261 bdi_register(&default_backing_dev_info, NULL, "default"); 249 bdi_register(&default_backing_dev_info, NULL, "default");
@@ -270,46 +258,6 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi)
270 return wb_has_dirty_io(&bdi->wb); 258 return wb_has_dirty_io(&bdi->wb);
271} 259}
272 260
273/*
274 * kupdated() used to do this. We cannot do it from the bdi_forker_thread()
275 * or we risk deadlocking on ->s_umount. The longer term solution would be
276 * to implement sync_supers_bdi() or similar and simply do it from the
277 * bdi writeback thread individually.
278 */
279static int bdi_sync_supers(void *unused)
280{
281 set_user_nice(current, 0);
282
283 while (!kthread_should_stop()) {
284 set_current_state(TASK_INTERRUPTIBLE);
285 schedule();
286
287 /*
288 * Do this periodically, like kupdated() did before.
289 */
290 sync_supers();
291 }
292
293 return 0;
294}
295
296void bdi_arm_supers_timer(void)
297{
298 unsigned long next;
299
300 if (!dirty_writeback_interval)
301 return;
302
303 next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies;
304 mod_timer(&sync_supers_timer, round_jiffies_up(next));
305}
306
307static void sync_supers_timer_fn(unsigned long unused)
308{
309 wake_up_process(sync_supers_tsk);
310 bdi_arm_supers_timer();
311}
312
313static void wakeup_timer_fn(unsigned long data) 261static void wakeup_timer_fn(unsigned long data)
314{ 262{
315 struct backing_dev_info *bdi = (struct backing_dev_info *)data; 263 struct backing_dev_info *bdi = (struct backing_dev_info *)data;
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index e5363f34e025..5ad5ce23c1e0 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1532,7 +1532,6 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write,
1532 void __user *buffer, size_t *length, loff_t *ppos) 1532 void __user *buffer, size_t *length, loff_t *ppos)
1533{ 1533{
1534 proc_dointvec(table, write, buffer, length, ppos); 1534 proc_dointvec(table, write, buffer, length, ppos);
1535 bdi_arm_supers_timer();
1536 return 0; 1535 return 0;
1537} 1536}
1538 1537