net: move fib_rules_unregister() under rtnl lock
[deliverable/linux.git] / fs / fs-writeback.c
index c399152de397b75dba35bafc7a13b77c86db3aa1..32a8bbd7a9ad1121f9b100da08f80500736bcebf 100644 (file)
@@ -53,6 +53,18 @@ struct wb_writeback_work {
        struct completion *done;        /* set if the caller waits */
 };
 
+/*
+ * If an inode is constantly having its pages dirtied, but then the
+ * updates stop dirtytime_expire_interval seconds in the past, it's
+ * possible for the worst case time between when an inode has its
+ * timestamps updated and when they finally get written out to be two
+ * dirtytime_expire_intervals.  We set the default to 12 hours (in
+ * seconds), which means most of the time inodes will have their
+ * timestamps written to disk after 12 hours, but in the worst case a
+ * few inodes might not their timestamps updated for 24 hours.
+ */
+unsigned int dirtytime_expire_interval = 12 * 60 * 60;
+
 /**
  * writeback_in_progress - determine whether there is writeback in progress
  * @bdi: the device's backing_dev_info structure.
@@ -253,14 +265,19 @@ static bool inode_dirtied_after(struct inode *inode, unsigned long t)
        return ret;
 }
 
+#define EXPIRE_DIRTY_ATIME 0x0001
+
 /*
  * Move expired (dirtied before work->older_than_this) dirty inodes from
  * @delaying_queue to @dispatch_queue.
  */
 static int move_expired_inodes(struct list_head *delaying_queue,
                               struct list_head *dispatch_queue,
+                              int flags,
                               struct wb_writeback_work *work)
 {
+       unsigned long *older_than_this = NULL;
+       unsigned long expire_time;
        LIST_HEAD(tmp);
        struct list_head *pos, *node;
        struct super_block *sb = NULL;
@@ -268,13 +285,21 @@ static int move_expired_inodes(struct list_head *delaying_queue,
        int do_sb_sort = 0;
        int moved = 0;
 
+       if ((flags & EXPIRE_DIRTY_ATIME) == 0)
+               older_than_this = work->older_than_this;
+       else if (!work->for_sync) {
+               expire_time = jiffies - (dirtytime_expire_interval * HZ);
+               older_than_this = &expire_time;
+       }
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
-               if (work->older_than_this &&
-                   inode_dirtied_after(inode, *work->older_than_this))
+               if (older_than_this &&
+                   inode_dirtied_after(inode, *older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
+               if (flags & EXPIRE_DIRTY_ATIME)
+                       set_bit(__I_DIRTY_TIME_EXPIRED, &inode->i_state);
                if (sb_is_blkdev_sb(inode->i_sb))
                        continue;
                if (sb && sb != inode->i_sb)
@@ -315,9 +340,12 @@ out:
 static void queue_io(struct bdi_writeback *wb, struct wb_writeback_work *work)
 {
        int moved;
+
        assert_spin_locked(&wb->list_lock);
        list_splice_init(&wb->b_more_io, &wb->b_io);
-       moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, work);
+       moved = move_expired_inodes(&wb->b_dirty, &wb->b_io, 0, work);
+       moved += move_expired_inodes(&wb->b_dirty_time, &wb->b_io,
+                                    EXPIRE_DIRTY_ATIME, work);
        trace_writeback_queue_io(wb, work, moved);
 }
 
@@ -441,6 +469,9 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
                 * updates after data IO completion.
                 */
                redirty_tail(inode, wb);
+       } else if (inode->i_state & I_DIRTY_TIME) {
+               inode->dirtied_when = jiffies;
+               list_move(&inode->i_wb_list, &wb->b_dirty_time);
        } else {
                /* The inode is clean. Remove from writeback lists. */
                list_del_init(&inode->i_wb_list);
@@ -487,7 +518,18 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
        spin_lock(&inode->i_lock);
 
        dirty = inode->i_state & I_DIRTY;
-       inode->i_state &= ~I_DIRTY;
+       if (inode->i_state & I_DIRTY_TIME) {
+               if ((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) ||
+                   unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) ||
+                   unlikely(time_after(jiffies,
+                                       (inode->dirtied_time_when +
+                                        dirtytime_expire_interval * HZ)))) {
+                       dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED;
+                       trace_writeback_lazytime(inode);
+               }
+       } else
+               inode->i_state &= ~I_DIRTY_TIME_EXPIRED;
+       inode->i_state &= ~dirty;
 
        /*
         * Paired with smp_mb() in __mark_inode_dirty().  This allows
@@ -507,8 +549,10 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 
        spin_unlock(&inode->i_lock);
 
+       if (dirty & I_DIRTY_TIME)
+               mark_inode_dirty_sync(inode);
        /* Don't write the inode if only I_DIRTY_PAGES was set */
-       if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
+       if (dirty & ~I_DIRTY_PAGES) {
                int err = write_inode(inode, wbc);
                if (ret == 0)
                        ret = err;
@@ -556,7 +600,7 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
         * make sure inode is on some writeback list and leave it there unless
         * we have completely cleaned the inode.
         */
-       if (!(inode->i_state & I_DIRTY) &&
+       if (!(inode->i_state & I_DIRTY_ALL) &&
            (wbc->sync_mode != WB_SYNC_ALL ||
             !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
                goto out;
@@ -571,7 +615,7 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
         * If inode is clean, remove it from writeback lists. Otherwise don't
         * touch it. See comment above for explanation.
         */
-       if (!(inode->i_state & I_DIRTY))
+       if (!(inode->i_state & I_DIRTY_ALL))
                list_del_init(&inode->i_wb_list);
        spin_unlock(&wb->list_lock);
        inode_sync_complete(inode);
@@ -713,7 +757,7 @@ static long writeback_sb_inodes(struct super_block *sb,
                wrote += write_chunk - wbc.nr_to_write;
                spin_lock(&wb->list_lock);
                spin_lock(&inode->i_lock);
-               if (!(inode->i_state & I_DIRTY))
+               if (!(inode->i_state & I_DIRTY_ALL))
                        wrote++;
                requeue_inode(inode, wb, &wbc);
                inode_sync_complete(inode);
@@ -743,9 +787,9 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb,
                struct inode *inode = wb_inode(wb->b_io.prev);
                struct super_block *sb = inode->i_sb;
 
-               if (!grab_super_passive(sb)) {
+               if (!trylock_super(sb)) {
                        /*
-                        * grab_super_passive() may fail consistently due to
+                        * trylock_super() may fail consistently due to
                         * s_umount being grabbed by someone else. Don't use
                         * requeue_io() to avoid busy retrying the inode/sb.
                         */
@@ -753,7 +797,7 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb,
                        continue;
                }
                wrote += writeback_sb_inodes(sb, wb, work);
-               drop_super(sb);
+               up_read(&sb->s_umount);
 
                /* refer to the same tests at the end of writeback_sb_inodes */
                if (wrote) {
@@ -1105,6 +1149,56 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)
        rcu_read_unlock();
 }
 
+/*
+ * Wake up bdi's periodically to make sure dirtytime inodes gets
+ * written back periodically.  We deliberately do *not* check the
+ * b_dirtytime list in wb_has_dirty_io(), since this would cause the
+ * kernel to be constantly waking up once there are any dirtytime
+ * inodes on the system.  So instead we define a separate delayed work
+ * function which gets called much more rarely.  (By default, only
+ * once every 12 hours.)
+ *
+ * If there is any other write activity going on in the file system,
+ * this function won't be necessary.  But if the only thing that has
+ * happened on the file system is a dirtytime inode caused by an atime
+ * update, we need this infrastructure below to make sure that inode
+ * eventually gets pushed out to disk.
+ */
+static void wakeup_dirtytime_writeback(struct work_struct *w);
+static DECLARE_DELAYED_WORK(dirtytime_work, wakeup_dirtytime_writeback);
+
+static void wakeup_dirtytime_writeback(struct work_struct *w)
+{
+       struct backing_dev_info *bdi;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
+               if (list_empty(&bdi->wb.b_dirty_time))
+                       continue;
+               bdi_wakeup_thread(bdi);
+       }
+       rcu_read_unlock();
+       schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
+}
+
+static int __init start_dirtytime_writeback(void)
+{
+       schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
+       return 0;
+}
+__initcall(start_dirtytime_writeback);
+
+int dirtytime_interval_handler(struct ctl_table *table, int write,
+                              void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret;
+
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       if (ret == 0 && write)
+               mod_delayed_work(system_wq, &dirtytime_work, 0);
+       return ret;
+}
+
 static noinline void block_dump___mark_inode_dirty(struct inode *inode)
 {
        if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
@@ -1151,16 +1245,20 @@ static noinline void block_dump___mark_inode_dirty(struct inode *inode)
  * page->mapping->host, so the page-dirtying time is recorded in the internal
  * blockdev inode.
  */
+#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
 void __mark_inode_dirty(struct inode *inode, int flags)
 {
        struct super_block *sb = inode->i_sb;
        struct backing_dev_info *bdi = NULL;
+       int dirtytime;
+
+       trace_writeback_mark_inode_dirty(inode, flags);
 
        /*
         * Don't do this for I_DIRTY_PAGES - that doesn't actually
         * dirty the inode itself
         */
-       if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
+       if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_TIME)) {
                trace_writeback_dirty_inode_start(inode, flags);
 
                if (sb->s_op->dirty_inode)
@@ -1168,6 +1266,9 @@ void __mark_inode_dirty(struct inode *inode, int flags)
 
                trace_writeback_dirty_inode(inode, flags);
        }
+       if (flags & I_DIRTY_INODE)
+               flags &= ~I_DIRTY_TIME;
+       dirtytime = flags & I_DIRTY_TIME;
 
        /*
         * Paired with smp_mb() in __writeback_single_inode() for the
@@ -1175,16 +1276,21 @@ void __mark_inode_dirty(struct inode *inode, int flags)
         */
        smp_mb();
 
-       if ((inode->i_state & flags) == flags)
+       if (((inode->i_state & flags) == flags) ||
+           (dirtytime && (inode->i_state & I_DIRTY_INODE)))
                return;
 
        if (unlikely(block_dump))
                block_dump___mark_inode_dirty(inode);
 
        spin_lock(&inode->i_lock);
+       if (dirtytime && (inode->i_state & I_DIRTY_INODE))
+               goto out_unlock_inode;
        if ((inode->i_state & flags) != flags) {
                const int was_dirty = inode->i_state & I_DIRTY;
 
+               if (flags & I_DIRTY_INODE)
+                       inode->i_state &= ~I_DIRTY_TIME;
                inode->i_state |= flags;
 
                /*
@@ -1231,8 +1337,15 @@ void __mark_inode_dirty(struct inode *inode, int flags)
                        }
 
                        inode->dirtied_when = jiffies;
-                       list_move(&inode->i_wb_list, &bdi->wb.b_dirty);
+                       if (dirtytime)
+                               inode->dirtied_time_when = jiffies;
+                       if (inode->i_state & (I_DIRTY_INODE | I_DIRTY_PAGES))
+                               list_move(&inode->i_wb_list, &bdi->wb.b_dirty);
+                       else
+                               list_move(&inode->i_wb_list,
+                                         &bdi->wb.b_dirty_time);
                        spin_unlock(&bdi->wb.list_lock);
+                       trace_writeback_dirty_inode_enqueue(inode);
 
                        if (wakeup_bdi)
                                bdi_wakeup_thread_delayed(bdi);
This page took 0.029853 seconds and 5 git commands to generate.