* [PATCH 1/6] btrfs: add support for processing pending changes
2014-11-14 10:33 [PULL] [PATCH 0/6] Support for 'pending changes' David Sterba
@ 2014-11-14 10:33 ` David Sterba
2015-01-20 4:24 ` Qu Wenruo
2014-11-14 10:33 ` [PATCH 2/6] btrfs: do commit in sync_fs if there are " David Sterba
` (4 subsequent siblings)
5 siblings, 1 reply; 11+ messages in thread
From: David Sterba @ 2014-11-14 10:33 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
There are some actions that modify global filesystem state but cannot be
performed at the time of request, but later at the transaction commit
time when the filesystem is in a known state.
For example enabling new incompat features on-the-fly or issuing
transaction commit from unsafe contexts (sysfs handlers).
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/ctree.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
fs/btrfs/disk-io.c | 6 ++++++
fs/btrfs/transaction.c | 16 ++++++++++++++++
fs/btrfs/transaction.h | 2 ++
4 files changed, 69 insertions(+)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fe69edda11fb..f30b061ef77d 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1402,6 +1402,11 @@ struct btrfs_fs_info {
*/
u64 last_trans_log_full_commit;
unsigned long mount_opt;
+ /*
+ * Track requests for actions that need to be done during transaction
+ * commit (like for some mount options).
+ */
+ unsigned long pending_changes;
unsigned long compress_type:4;
int commit_interval;
/*
@@ -2103,6 +2108,7 @@ struct btrfs_ioctl_defrag_range_args {
#define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
BTRFS_MOUNT_##opt)
+
#define btrfs_set_and_info(root, opt, fmt, args...) \
{ \
if (!btrfs_test_opt(root, opt)) \
@@ -2118,6 +2124,45 @@ struct btrfs_ioctl_defrag_range_args {
}
/*
+ * Requests for changes that need to be done during transaction commit.
+ *
+ * Internal mount options that are used for special handling of the real
+ * mount options (eg. cannot be set during remount and have to be set during
+ * transaction commit)
+ */
+
+#define btrfs_test_pending(info, opt) \
+ test_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
+#define btrfs_set_pending(info, opt) \
+ set_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
+#define btrfs_clear_pending(info, opt) \
+ clear_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
+
+/*
+ * Helpers for setting pending mount option changes.
+ *
+ * Expects corresponding macros
+ * BTRFS_PENDING_SET_ and CLEAR_ + short mount option name
+ */
+#define btrfs_set_pending_and_info(info, opt, fmt, args...) \
+do { \
+ if (!btrfs_raw_test_opt((info)->mount_opt, opt)) { \
+ btrfs_info((info), fmt, ##args); \
+ btrfs_set_pending((info), SET_##opt); \
+ btrfs_clear_pending((info), CLEAR_##opt); \
+ } \
+} while(0)
+
+#define btrfs_clear_pending_and_info(info, opt, fmt, args...) \
+do { \
+ if (btrfs_raw_test_opt((info)->mount_opt, opt)) { \
+ btrfs_info((info), fmt, ##args); \
+ btrfs_set_pending((info), CLEAR_##opt); \
+ btrfs_clear_pending((info), SET_##opt); \
+ } \
+} while(0)
+
+/*
* Inode flags
*/
#define BTRFS_INODE_NODATASUM (1 << 0)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1bf9f897065d..fd80c0d98421 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2834,6 +2834,12 @@ retry_root_backup:
if (btrfs_test_opt(tree_root, CHANGE_INODE_CACHE))
btrfs_set_opt(tree_root->fs_info->mount_opt, INODE_MAP_CACHE);
+ /*
+ * Mount does not set all options immediatelly, we can do it now and do
+ * not have to wait for transaction commit
+ */
+ btrfs_apply_pending_changes(fs_info);
+
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
ret = btrfsic_mount(tree_root, fs_devices,
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index dcaae3616728..7a4024a55e5c 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1850,6 +1850,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
else
btrfs_clear_opt(root->fs_info->mount_opt, INODE_MAP_CACHE);
+ btrfs_apply_pending_changes(root->fs_info);
+
/* commit_fs_roots gets rid of all the tree log roots, it is now
* safe to free the root of tree log roots
*/
@@ -2019,3 +2021,17 @@ int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root)
return (ret < 0) ? 0 : 1;
}
+
+void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info)
+{
+ unsigned long prev;
+ unsigned long bit;
+
+ prev = cmpxchg(&fs_info->pending_changes, 0, 0);
+ if (!prev)
+ return;
+
+ if (prev)
+ btrfs_warn(fs_info,
+ "unknown pending changes left 0x%lx, ignoring", prev);
+}
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index d8f40e1a5d2d..75ebcfce9d57 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -170,4 +170,6 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
int btrfs_transaction_blocked(struct btrfs_fs_info *info);
int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
void btrfs_put_transaction(struct btrfs_transaction *transaction);
+void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info);
+
#endif
--
1.8.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 1/6] btrfs: add support for processing pending changes
2014-11-14 10:33 ` [PATCH 1/6] btrfs: add support for processing pending changes David Sterba
@ 2015-01-20 4:24 ` Qu Wenruo
0 siblings, 0 replies; 11+ messages in thread
From: Qu Wenruo @ 2015-01-20 4:24 UTC (permalink / raw)
To: David Sterba, linux-btrfs
-------- Original Message --------
Subject: [PATCH 1/6] btrfs: add support for processing pending changes
From: David Sterba <dsterba@suse.cz>
To: <linux-btrfs@vger.kernel.org>
Date: 2014年11月14日 18:33
> There are some actions that modify global filesystem state but cannot be
> performed at the time of request, but later at the transaction commit
> time when the filesystem is in a known state.
>
> For example enabling new incompat features on-the-fly or issuing
> transaction commit from unsafe contexts (sysfs handlers).
>
> Signed-off-by: David Sterba <dsterba@suse.cz>
> ---
> fs/btrfs/ctree.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
> fs/btrfs/disk-io.c | 6 ++++++
> fs/btrfs/transaction.c | 16 ++++++++++++++++
> fs/btrfs/transaction.h | 2 ++
> 4 files changed, 69 insertions(+)
>
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index fe69edda11fb..f30b061ef77d 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -1402,6 +1402,11 @@ struct btrfs_fs_info {
> */
> u64 last_trans_log_full_commit;
> unsigned long mount_opt;
> + /*
> + * Track requests for actions that need to be done during transaction
> + * commit (like for some mount options).
> + */
> + unsigned long pending_changes;
> unsigned long compress_type:4;
> int commit_interval;
> /*
> @@ -2103,6 +2108,7 @@ struct btrfs_ioctl_defrag_range_args {
> #define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
> #define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
> BTRFS_MOUNT_##opt)
> +
> #define btrfs_set_and_info(root, opt, fmt, args...) \
> { \
> if (!btrfs_test_opt(root, opt)) \
> @@ -2118,6 +2124,45 @@ struct btrfs_ioctl_defrag_range_args {
> }
>
> /*
> + * Requests for changes that need to be done during transaction commit.
> + *
> + * Internal mount options that are used for special handling of the real
> + * mount options (eg. cannot be set during remount and have to be set during
> + * transaction commit)
> + */
> +
> +#define btrfs_test_pending(info, opt) \
> + test_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
> +#define btrfs_set_pending(info, opt) \
> + set_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
> +#define btrfs_clear_pending(info, opt) \
> + clear_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
> +
> +/*
> + * Helpers for setting pending mount option changes.
> + *
> + * Expects corresponding macros
> + * BTRFS_PENDING_SET_ and CLEAR_ + short mount option name
> + */
> +#define btrfs_set_pending_and_info(info, opt, fmt, args...) \
> +do { \
> + if (!btrfs_raw_test_opt((info)->mount_opt, opt)) { \
> + btrfs_info((info), fmt, ##args); \
> + btrfs_set_pending((info), SET_##opt); \
> + btrfs_clear_pending((info), CLEAR_##opt); \
> + } \
> +} while(0)
> +
> +#define btrfs_clear_pending_and_info(info, opt, fmt, args...) \
> +do { \
> + if (btrfs_raw_test_opt((info)->mount_opt, opt)) { \
> + btrfs_info((info), fmt, ##args); \
> + btrfs_set_pending((info), CLEAR_##opt); \
> + btrfs_clear_pending((info), SET_##opt); \
> + } \
> +} while(0)
> +
> +/*
> * Inode flags
> */
> #define BTRFS_INODE_NODATASUM (1 << 0)
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 1bf9f897065d..fd80c0d98421 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -2834,6 +2834,12 @@ retry_root_backup:
> if (btrfs_test_opt(tree_root, CHANGE_INODE_CACHE))
> btrfs_set_opt(tree_root->fs_info->mount_opt, INODE_MAP_CACHE);
>
> + /*
> + * Mount does not set all options immediatelly, we can do it now and do
> + * not have to wait for transaction commit
> + */
> + btrfs_apply_pending_changes(fs_info);
> +
> #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
> if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
> ret = btrfsic_mount(tree_root, fs_devices,
> diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
> index dcaae3616728..7a4024a55e5c 100644
> --- a/fs/btrfs/transaction.c
> +++ b/fs/btrfs/transaction.c
> @@ -1850,6 +1850,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
> else
> btrfs_clear_opt(root->fs_info->mount_opt, INODE_MAP_CACHE);
>
> + btrfs_apply_pending_changes(root->fs_info);
> +
> /* commit_fs_roots gets rid of all the tree log roots, it is now
> * safe to free the root of tree log roots
> */
> @@ -2019,3 +2021,17 @@ int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root)
>
> return (ret < 0) ? 0 : 1;
> }
> +
> +void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info)
> +{
> + unsigned long prev;
> + unsigned long bit;
> +
> + prev = cmpxchg(&fs_info->pending_changes, 0, 0);
Another HUGE problem here.
cmpxchg will only change the pending_changes to 0 if it's already 0.
If it not 0, it will not change pending_changes to 0.
So pending_changes will always be non-zero if set_pending....
Thanks,
Qu
> + if (!prev)
> + return;
> +
> + if (prev)
> + btrfs_warn(fs_info,
> + "unknown pending changes left 0x%lx, ignoring", prev);
> +}
> diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
> index d8f40e1a5d2d..75ebcfce9d57 100644
> --- a/fs/btrfs/transaction.h
> +++ b/fs/btrfs/transaction.h
> @@ -170,4 +170,6 @@ int btrfs_wait_marked_extents(struct btrfs_root *root,
> int btrfs_transaction_blocked(struct btrfs_fs_info *info);
> int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
> void btrfs_put_transaction(struct btrfs_transaction *transaction);
> +void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info);
> +
> #endif
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/6] btrfs: do commit in sync_fs if there are pending changes
2014-11-14 10:33 [PULL] [PATCH 0/6] Support for 'pending changes' David Sterba
2014-11-14 10:33 ` [PATCH 1/6] btrfs: add support for processing pending changes David Sterba
@ 2014-11-14 10:33 ` David Sterba
2014-11-14 10:51 ` Filipe David Manana
2014-11-14 12:34 ` [PATCH 2/6 v2] " David Sterba
2014-11-14 10:33 ` [PATCH 3/6] btrfs: switch inode_cache option handling to " David Sterba
` (3 subsequent siblings)
5 siblings, 2 replies; 11+ messages in thread
From: David Sterba @ 2014-11-14 10:33 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
If a pending change is requested, it's not processed unless there is a
transaction commit about to happen, not even after sync or SYNC_FS
ioctl. For example a remount that toggles the inode_cache option will
not take effect after sync on a quiescent filesystem.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/super.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 54bd91ece35b..1da16d59e115 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -993,9 +993,17 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
trans = btrfs_attach_transaction_barrier(root);
if (IS_ERR(trans)) {
/* no transaction, don't bother */
- if (PTR_ERR(trans) == -ENOENT)
- return 0;
- return PTR_ERR(trans);
+ if (PTR_ERR(trans) == -ENOENT) {
+ /*
+ * Exit unless we have some pending changes
+ * that need to go through commit
+ */
+ if (fs_info->pending_changes == 0)
+ return 0;
+ trans = btrfs_start_transaction(root, 0);
+ } else {
+ return PTR_ERR(trans);
+ }
}
return btrfs_commit_transaction(trans, root);
}
--
1.8.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 2/6] btrfs: do commit in sync_fs if there are pending changes
2014-11-14 10:33 ` [PATCH 2/6] btrfs: do commit in sync_fs if there are " David Sterba
@ 2014-11-14 10:51 ` Filipe David Manana
2014-11-14 12:34 ` [PATCH 2/6 v2] " David Sterba
1 sibling, 0 replies; 11+ messages in thread
From: Filipe David Manana @ 2014-11-14 10:51 UTC (permalink / raw)
To: David Sterba; +Cc: linux-btrfs@vger.kernel.org
On Fri, Nov 14, 2014 at 10:33 AM, David Sterba <dsterba@suse.cz> wrote:
> If a pending change is requested, it's not processed unless there is a
> transaction commit about to happen, not even after sync or SYNC_FS
> ioctl. For example a remount that toggles the inode_cache option will
> not take effect after sync on a quiescent filesystem.
>
> Signed-off-by: David Sterba <dsterba@suse.cz>
> ---
> fs/btrfs/super.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index 54bd91ece35b..1da16d59e115 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -993,9 +993,17 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
> trans = btrfs_attach_transaction_barrier(root);
> if (IS_ERR(trans)) {
> /* no transaction, don't bother */
> - if (PTR_ERR(trans) == -ENOENT)
> - return 0;
> - return PTR_ERR(trans);
> + if (PTR_ERR(trans) == -ENOENT) {
> + /*
> + * Exit unless we have some pending changes
> + * that need to go through commit
> + */
> + if (fs_info->pending_changes == 0)
> + return 0;
> + trans = btrfs_start_transaction(root, 0);
Missing check for IS_ERR(trans)
The rest looks good.
Thanks
> + } else {
> + return PTR_ERR(trans);
> + }
> }
> return btrfs_commit_transaction(trans, root);
> }
> --
> 1.8.4.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Filipe David Manana,
"Reasonable men adapt themselves to the world.
Unreasonable men adapt the world to themselves.
That's why all progress depends on unreasonable men."
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 2/6 v2] btrfs: do commit in sync_fs if there are pending changes
2014-11-14 10:33 ` [PATCH 2/6] btrfs: do commit in sync_fs if there are " David Sterba
2014-11-14 10:51 ` Filipe David Manana
@ 2014-11-14 12:34 ` David Sterba
2015-01-16 13:29 ` Filipe David Manana
1 sibling, 1 reply; 11+ messages in thread
From: David Sterba @ 2014-11-14 12:34 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
If a pending change is requested, it's not processed unless there is a
transaction commit about to happen, not even after sync or SYNC_FS
ioctl. For example a remount that toggles the inode_cache option will
not take effect after sync on a quiescent filesystem.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
v2: catch error from btrfs_start_transaction
fs/btrfs/super.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 54bd91ece35b..0cf589402d8d 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -993,9 +993,17 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
trans = btrfs_attach_transaction_barrier(root);
if (IS_ERR(trans)) {
/* no transaction, don't bother */
- if (PTR_ERR(trans) == -ENOENT)
- return 0;
- return PTR_ERR(trans);
+ if (PTR_ERR(trans) == -ENOENT) {
+ /*
+ * Exit unless we have some pending changes
+ * that need to go through commit
+ */
+ if (fs_info->pending_changes == 0)
+ return 0;
+ trans = btrfs_start_transaction(root, 0);
+ }
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
}
return btrfs_commit_transaction(trans, root);
}
--
2.1.3
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 2/6 v2] btrfs: do commit in sync_fs if there are pending changes
2014-11-14 12:34 ` [PATCH 2/6 v2] " David Sterba
@ 2015-01-16 13:29 ` Filipe David Manana
0 siblings, 0 replies; 11+ messages in thread
From: Filipe David Manana @ 2015-01-16 13:29 UTC (permalink / raw)
To: David Sterba; +Cc: linux-btrfs@vger.kernel.org
On Fri, Nov 14, 2014 at 12:34 PM, David Sterba <dsterba@suse.cz> wrote:
> If a pending change is requested, it's not processed unless there is a
> transaction commit about to happen, not even after sync or SYNC_FS
> ioctl. For example a remount that toggles the inode_cache option will
> not take effect after sync on a quiescent filesystem.
>
> Signed-off-by: David Sterba <dsterba@suse.cz>
> ---
>
> v2: catch error from btrfs_start_transaction
V2 didn't make it to 3.19:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6b5fe46dfa52441f49c7432b1c1b1cb767834708
>
> fs/btrfs/super.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index 54bd91ece35b..0cf589402d8d 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -993,9 +993,17 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
> trans = btrfs_attach_transaction_barrier(root);
> if (IS_ERR(trans)) {
> /* no transaction, don't bother */
> - if (PTR_ERR(trans) == -ENOENT)
> - return 0;
> - return PTR_ERR(trans);
> + if (PTR_ERR(trans) == -ENOENT) {
> + /*
> + * Exit unless we have some pending changes
> + * that need to go through commit
> + */
> + if (fs_info->pending_changes == 0)
> + return 0;
> + trans = btrfs_start_transaction(root, 0);
> + }
> + if (IS_ERR(trans))
> + return PTR_ERR(trans);
> }
> return btrfs_commit_transaction(trans, root);
> }
> --
> 2.1.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Filipe David Manana,
"Reasonable men adapt themselves to the world.
Unreasonable men adapt the world to themselves.
That's why all progress depends on unreasonable men."
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/6] btrfs: switch inode_cache option handling to pending changes
2014-11-14 10:33 [PULL] [PATCH 0/6] Support for 'pending changes' David Sterba
2014-11-14 10:33 ` [PATCH 1/6] btrfs: add support for processing pending changes David Sterba
2014-11-14 10:33 ` [PATCH 2/6] btrfs: do commit in sync_fs if there are " David Sterba
@ 2014-11-14 10:33 ` David Sterba
2014-11-14 10:33 ` [PATCH 4/6] btrfs: introduce pending action: commit David Sterba
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: David Sterba @ 2014-11-14 10:33 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
The pending mount option(s) now share namespace and bits with the normal
options, and the existing one for (inode_cache) is unset unconditionally
at each transaction commit.
Introduce a separate namespace for pending changes and enhance the
descriptions of the intended change to use separate bits for each
action.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/ctree.h | 4 +++-
fs/btrfs/disk-io.c | 4 ----
fs/btrfs/inode-map.c | 2 +-
fs/btrfs/super.c | 4 ++--
fs/btrfs/transaction.c | 19 ++++++++++++-------
5 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f30b061ef77d..1c9157e4ab0c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2098,7 +2098,6 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)
#define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22)
#define BTRFS_MOUNT_RESCAN_UUID_TREE (1 << 23)
-#define BTRFS_MOUNT_CHANGE_INODE_CACHE (1 << 24)
#define BTRFS_DEFAULT_COMMIT_INTERVAL (30)
#define BTRFS_DEFAULT_MAX_INLINE (8192)
@@ -2131,6 +2130,9 @@ struct btrfs_ioctl_defrag_range_args {
* transaction commit)
*/
+#define BTRFS_PENDING_SET_INODE_MAP_CACHE (0)
+#define BTRFS_PENDING_CLEAR_INODE_MAP_CACHE (1)
+
#define btrfs_test_pending(info, opt) \
test_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
#define btrfs_set_pending(info, opt) \
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index fd80c0d98421..6b406e3f3abe 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2830,10 +2830,6 @@ retry_root_backup:
btrfs_set_opt(fs_info->mount_opt, SSD);
}
- /* Set the real inode map cache flag */
- if (btrfs_test_opt(tree_root, CHANGE_INODE_CACHE))
- btrfs_set_opt(tree_root->fs_info->mount_opt, INODE_MAP_CACHE);
-
/*
* Mount does not set all options immediatelly, we can do it now and do
* not have to wait for transaction commit
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index 83d646bd2e4b..4ebd5ebb1ea1 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -178,7 +178,7 @@ static void start_caching(struct btrfs_root *root)
root->root_key.objectid);
if (IS_ERR(tsk)) {
btrfs_warn(root->fs_info, "failed to start inode caching task");
- btrfs_clear_and_info(root, CHANGE_INODE_CACHE,
+ btrfs_clear_pending_and_info(root->fs_info, INODE_MAP_CACHE,
"disabling inode map caching");
}
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 1da16d59e115..65c75d9e9750 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -642,11 +642,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
"disabling disk space caching");
break;
case Opt_inode_cache:
- btrfs_set_and_info(root, CHANGE_INODE_CACHE,
+ btrfs_set_pending_and_info(info, INODE_MAP_CACHE,
"enabling inode map caching");
break;
case Opt_noinode_cache:
- btrfs_clear_and_info(root, CHANGE_INODE_CACHE,
+ btrfs_clear_pending_and_info(info, INODE_MAP_CACHE,
"disabling inode map caching");
break;
case Opt_clear_cache:
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 7a4024a55e5c..703238ed7337 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1842,14 +1842,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
}
/*
- * Since the transaction is done, we should set the inode map cache flag
- * before any other comming transaction.
+ * Since the transaction is done, we can apply the pending changes
+ * before the next transaction.
*/
- if (btrfs_test_opt(root, CHANGE_INODE_CACHE))
- btrfs_set_opt(root->fs_info->mount_opt, INODE_MAP_CACHE);
- else
- btrfs_clear_opt(root->fs_info->mount_opt, INODE_MAP_CACHE);
-
btrfs_apply_pending_changes(root->fs_info);
/* commit_fs_roots gets rid of all the tree log roots, it is now
@@ -2031,6 +2026,16 @@ void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info)
if (!prev)
return;
+ bit = 1 << BTRFS_PENDING_SET_INODE_MAP_CACHE;
+ if (prev & bit)
+ btrfs_set_opt(fs_info->mount_opt, INODE_MAP_CACHE);
+ prev &= ~bit;
+
+ bit = 1 << BTRFS_PENDING_CLEAR_INODE_MAP_CACHE;
+ if (prev & bit)
+ btrfs_clear_opt(fs_info->mount_opt, INODE_MAP_CACHE);
+ prev &= ~bit;
+
if (prev)
btrfs_warn(fs_info,
"unknown pending changes left 0x%lx, ignoring", prev);
--
1.8.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 4/6] btrfs: introduce pending action: commit
2014-11-14 10:33 [PULL] [PATCH 0/6] Support for 'pending changes' David Sterba
` (2 preceding siblings ...)
2014-11-14 10:33 ` [PATCH 3/6] btrfs: switch inode_cache option handling to " David Sterba
@ 2014-11-14 10:33 ` David Sterba
2014-11-14 10:33 ` [PATCH 5/6] btrfs: move commit out of sysfs when changing features David Sterba
2014-11-14 10:33 ` [PATCH 6/6] btrfs: move commit out of sysfs when changing label David Sterba
5 siblings, 0 replies; 11+ messages in thread
From: David Sterba @ 2014-11-14 10:33 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
In some contexts, like in sysfs handlers, we don't want to trigger a
transaction commit. It's a heavy operation, we don't know what external
locks may be taken. Instead, make it possible to finish the operation
through sync syscall or SYNC_FS ioctl.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/ctree.h | 1 +
fs/btrfs/transaction.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 1c9157e4ab0c..817fc19b8159 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2132,6 +2132,7 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_PENDING_SET_INODE_MAP_CACHE (0)
#define BTRFS_PENDING_CLEAR_INODE_MAP_CACHE (1)
+#define BTRFS_PENDING_COMMIT (2)
#define btrfs_test_pending(info, opt) \
test_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 703238ed7337..9d8e2b8d12b4 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -2036,6 +2036,11 @@ void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info)
btrfs_clear_opt(fs_info->mount_opt, INODE_MAP_CACHE);
prev &= ~bit;
+ bit = 1 << BTRFS_PENDING_COMMIT;
+ if (prev & bit)
+ btrfs_debug(fs_info, "pending commit done");
+ prev &= ~bit;
+
if (prev)
btrfs_warn(fs_info,
"unknown pending changes left 0x%lx, ignoring", prev);
--
1.8.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5/6] btrfs: move commit out of sysfs when changing features
2014-11-14 10:33 [PULL] [PATCH 0/6] Support for 'pending changes' David Sterba
` (3 preceding siblings ...)
2014-11-14 10:33 ` [PATCH 4/6] btrfs: introduce pending action: commit David Sterba
@ 2014-11-14 10:33 ` David Sterba
2014-11-14 10:33 ` [PATCH 6/6] btrfs: move commit out of sysfs when changing label David Sterba
5 siblings, 0 replies; 11+ messages in thread
From: David Sterba @ 2014-11-14 10:33 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/sysfs.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index b2e7bb4393f6..226f7261533a 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -111,7 +111,6 @@ static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info;
struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
- struct btrfs_trans_handle *trans;
u64 features, set, clear;
unsigned long val;
int ret;
@@ -153,10 +152,6 @@ static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
btrfs_info(fs_info, "%s %s feature flag",
val ? "Setting" : "Clearing", fa->kobj_attr.attr.name);
- trans = btrfs_start_transaction(fs_info->fs_root, 0);
- if (IS_ERR(trans))
- return PTR_ERR(trans);
-
spin_lock(&fs_info->super_lock);
features = get_features(fs_info, fa->feature_set);
if (val)
@@ -166,9 +161,11 @@ static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
set_features(fs_info, fa->feature_set, features);
spin_unlock(&fs_info->super_lock);
- ret = btrfs_commit_transaction(trans, fs_info->fs_root);
- if (ret)
- return ret;
+ /*
+ * We don't want to do full transaction commit from inside sysfs
+ */
+ btrfs_set_pending(fs_info, COMMIT);
+ wake_up_process(fs_info->transaction_kthread);
return count;
}
--
1.8.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 6/6] btrfs: move commit out of sysfs when changing label
2014-11-14 10:33 [PULL] [PATCH 0/6] Support for 'pending changes' David Sterba
` (4 preceding siblings ...)
2014-11-14 10:33 ` [PATCH 5/6] btrfs: move commit out of sysfs when changing features David Sterba
@ 2014-11-14 10:33 ` David Sterba
5 siblings, 0 replies; 11+ messages in thread
From: David Sterba @ 2014-11-14 10:33 UTC (permalink / raw)
To: linux-btrfs; +Cc: David Sterba
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/sysfs.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 226f7261533a..92db3f648df4 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -369,9 +369,6 @@ static ssize_t btrfs_label_store(struct kobject *kobj,
const char *buf, size_t len)
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- struct btrfs_trans_handle *trans;
- struct btrfs_root *root = fs_info->fs_root;
- int ret;
size_t p_len;
if (fs_info->sb->s_flags & MS_RDONLY)
@@ -386,20 +383,18 @@ static ssize_t btrfs_label_store(struct kobject *kobj,
if (p_len >= BTRFS_LABEL_SIZE)
return -EINVAL;
- trans = btrfs_start_transaction(root, 0);
- if (IS_ERR(trans))
- return PTR_ERR(trans);
-
- spin_lock(&root->fs_info->super_lock);
+ spin_lock(&fs_info->super_lock);
memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE);
memcpy(fs_info->super_copy->label, buf, p_len);
- spin_unlock(&root->fs_info->super_lock);
- ret = btrfs_commit_transaction(trans, root);
+ spin_unlock(&fs_info->super_lock);
- if (!ret)
- return len;
+ /*
+ * We don't want to do full transaction commit from inside sysfs
+ */
+ btrfs_set_pending(fs_info, COMMIT);
+ wake_up_process(fs_info->transaction_kthread);
- return ret;
+ return len;
}
BTRFS_ATTR_RW(label, btrfs_label_show, btrfs_label_store);
--
1.8.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread