Linux-BTRFS Archive on lore.kernel.org
 help / color / Atom feed
From: Kusanagi Kouichi <slash@ac.auone-net.jp>
To: linux-btrfs@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] btrfs: Implement lazytime
Date: Tue, 14 Jan 2020 17:53:24 +0900
Message-ID: <20200114085325045.JFBE.12086.ppp.dion.ne.jp@dmta0008.auone-net.jp> (raw)

I tested with xfstests and lazytime didn't cause any new failures.

Signed-off-by: Kusanagi Kouichi <slash@ac.auone-net.jp>
---
 fs/btrfs/delayed-inode.c |  6 ++++++
 fs/btrfs/file.c          | 11 +++++++++++
 fs/btrfs/inode.c         | 28 +++++++++++++++++++++++++---
 fs/btrfs/ioctl.c         | 14 ++++++++++++++
 fs/btrfs/super.c         |  1 +
 5 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index d3e15e1d4a91..b30b00678503 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1722,6 +1722,12 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
 				  struct btrfs_inode_item *inode_item,
 				  struct inode *inode)
 {
+	if (inode->i_sb->s_flags & SB_LAZYTIME) {
+		spin_lock(&inode->i_lock);
+		inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_TIME);
+		spin_unlock(&inode->i_lock);
+	}
+
 	btrfs_set_stack_inode_uid(inode_item, i_uid_read(inode));
 	btrfs_set_stack_inode_gid(inode_item, i_gid_read(inode));
 	btrfs_set_stack_inode_size(inode_item, BTRFS_I(inode)->disk_i_size);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 8d47c76b7bd1..36aa75f4e532 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2069,6 +2069,17 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
 	trace_btrfs_sync_file(file, datasync);
 
+	if (!datasync && inode->i_sb->s_flags & SB_LAZYTIME) {
+		while (1) {
+			ret = sync_inode_metadata(inode, 0);
+			if (ret != -EAGAIN)
+				break;
+			flush_work(&fs_info->async_reclaim_work);
+		}
+		if (ret)
+			return ret;
+	}
+
 	btrfs_init_log_ctx(&ctx, inode);
 
 	/*
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5509c41a4f43..a60aee76cc95 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3941,6 +3941,12 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 
 	btrfs_init_map_token(&token, leaf);
 
+	if (inode->i_sb->s_flags & SB_LAZYTIME) {
+		spin_lock(&inode->i_lock);
+		inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_TIME);
+		spin_unlock(&inode->i_lock);
+	}
+
 	btrfs_set_token_inode_uid(leaf, item, i_uid_read(inode), &token);
 	btrfs_set_token_inode_gid(leaf, item, i_gid_read(inode), &token);
 	btrfs_set_token_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size,
@@ -6188,6 +6194,16 @@ static int btrfs_dirty_inode(struct inode *inode)
 	return ret;
 }
 
+int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	if (work_busy(&btrfs_sb(inode->i_sb)->async_reclaim_work) & WORK_BUSY_RUNNING) {
+		mark_inode_dirty_sync(inode);
+		return -EAGAIN;
+	}
+
+	return btrfs_dirty_inode(inode);
+}
+
 /*
  * This is a copy of file_update_time.  We need this so we can return error on
  * ENOSPC for updating the inode in the case of file write and mmap writes.
@@ -6201,15 +6217,21 @@ static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
 	if (btrfs_root_readonly(root))
 		return -EROFS;
 
-	if (flags & S_VERSION)
-		dirty |= inode_maybe_inc_iversion(inode, dirty);
+	if (!(flags & S_VERSION && inode_maybe_inc_iversion(inode, dirty))) {
+		if (unlikely(!dirty))
+			return 0;
+		if (inode->i_sb->s_flags & SB_LAZYTIME &&
+		    !test_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags))
+			return generic_update_time(inode, now, flags);
+	}
+
 	if (flags & S_CTIME)
 		inode->i_ctime = *now;
 	if (flags & S_MTIME)
 		inode->i_mtime = *now;
 	if (flags & S_ATIME)
 		inode->i_atime = *now;
-	return dirty ? btrfs_dirty_inode(inode) : 0;
+	return btrfs_dirty_inode(inode);
 }
 
 /*
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 18e328ce4b54..af47b4b046de 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -799,6 +799,14 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
 	if (ret)
 		goto dec_and_free;
 
+	/* For xfstests generic/003. Is it better to fix the test? */
+	if (dir->i_sb->s_flags & SB_LAZYTIME) {
+		down_read(&dir->i_sb->s_umount);
+		if (!sb_rdonly(dir->i_sb))
+			sync_inodes_sb(dir->i_sb);
+		up_read(&dir->i_sb->s_umount);
+	}
+
 	/*
 	 * All previous writes have started writeback in NOCOW mode, so now
 	 * we force future writes to fallback to COW mode during snapshot
@@ -5497,6 +5505,12 @@ long btrfs_ioctl(struct file *file, unsigned int
 		ret = btrfs_start_delalloc_roots(fs_info, -1);
 		if (ret)
 			return ret;
+		if (inode->i_sb->s_flags & SB_LAZYTIME) {
+			down_read(&inode->i_sb->s_umount);
+			if (!sb_rdonly(inode->i_sb))
+				sync_inodes_sb(inode->i_sb);
+			up_read(&inode->i_sb->s_umount);
+		}
 		ret = btrfs_sync_fs(inode->i_sb, 1);
 		/*
 		 * The transaction thread may want to do more work,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index f452a94abdc3..ccfe9aff1394 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2281,6 +2281,7 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
 }
 
 static const struct super_operations btrfs_super_ops = {
+	.write_inode	= btrfs_write_inode,
 	.drop_inode	= btrfs_drop_inode,
 	.evict_inode	= btrfs_evict_inode,
 	.put_super	= btrfs_put_super,
-- 
2.25.0.rc2


             reply index

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-14  8:53 Kusanagi Kouichi [this message]
2020-01-14 13:44 ` Josef Bacik
2020-01-15 13:41   ` Kusanagi Kouichi
2020-01-14 21:21 ` David Sterba
2020-01-15 13:45   ` Kusanagi Kouichi
2020-01-15 16:31     ` David Sterba
2020-01-16 18:01       ` Kusanagi Kouichi

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200114085325045.JFBE.12086.ppp.dion.ne.jp@dmta0008.auone-net.jp \
    --to=slash@ac.auone-net.jp \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-BTRFS Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-btrfs/0 linux-btrfs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-btrfs linux-btrfs/ https://lore.kernel.org/linux-btrfs \
		linux-btrfs@vger.kernel.org
	public-inbox-index linux-btrfs

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-btrfs


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git