diff mbox

[v8,2/8] btrfs: Cancel filesystem balance

Message ID 1309120615-18104-3-git-send-email-hugo@carfax.org.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Hugo Mills June 26, 2011, 8:36 p.m. UTC
This patch adds an ioctl for cancelling a btrfs balance operation
mid-flight. The ioctl simply sets a flag, and the operation terminates
after the current block group move has completed.

Signed-off-by: Hugo Mills <hugo@carfax.org.uk>
---
 fs/btrfs/ctree.h   |    1 +
 fs/btrfs/ioctl.c   |   28 ++++++++++++++++++++++++++++
 fs/btrfs/ioctl.h   |    1 +
 fs/btrfs/volumes.c |    7 ++++++-
 4 files changed, 36 insertions(+), 1 deletions(-)

Comments

Li Zefan June 29, 2011, 6 a.m. UTC | #1
Hugo Mills wrote:
> This patch adds an ioctl for cancelling a btrfs balance operation
> mid-flight. The ioctl simply sets a flag, and the operation terminates
> after the current block group move has completed.
> 
> Signed-off-by: Hugo Mills <hugo@carfax.org.uk>
> ---
>  fs/btrfs/ctree.h   |    1 +
>  fs/btrfs/ioctl.c   |   28 ++++++++++++++++++++++++++++
>  fs/btrfs/ioctl.h   |    1 +
>  fs/btrfs/volumes.c |    7 ++++++-
>  4 files changed, 36 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 25aa3cf..5031085 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -876,6 +876,7 @@ struct btrfs_block_group_cache {
>  struct btrfs_balance_info {
>  	u32 expected;
>  	u32 completed;
> +	int cancel_pending;
>  };
>  
>  struct reloc_control;
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 5ddf816..d4458d0 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -2868,6 +2868,32 @@ error:
>  	return ret;
>  }
>  
> +/*
> + * Cancel a running balance operation
> + */
> +long btrfs_ioctl_balance_cancel(struct btrfs_fs_info *fs_info)
> +{
> +	int err = 0;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +
> +	spin_lock(&fs_info->balance_info_lock);
> +	if (!fs_info->balance_info) {
> +		err = -EINVAL;
> +		goto error;
> +	}
> +	if (fs_info->balance_info->cancel_pending) {
> +		err = -ECANCELED;
> +		goto error;
> +	}
> +	fs_info->balance_info->cancel_pending = 1;
> +
> +error:
> +	spin_unlock(&fs_info->balance_info_lock);
> +	return err;
> +}
> +
>  long btrfs_ioctl(struct file *file, unsigned int
>  		cmd, unsigned long arg)
>  {
> @@ -2915,6 +2941,8 @@ long btrfs_ioctl(struct file *file, unsigned int
>  		return btrfs_balance(root->fs_info->dev_root);
>  	case BTRFS_IOC_BALANCE_PROGRESS:
>  		return btrfs_ioctl_balance_progress(root->fs_info, argp);
> +	case BTRFS_IOC_BALANCE_CANCEL:
> +		return btrfs_ioctl_balance_cancel(root->fs_info);
>  	case BTRFS_IOC_CLONE:
>  		return btrfs_ioctl_clone(file, arg, 0, 0, 0);
>  	case BTRFS_IOC_CLONE_RANGE:
> diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
> index 575b25f..edcbe61 100644
> --- a/fs/btrfs/ioctl.h
> +++ b/fs/btrfs/ioctl.h
> @@ -255,4 +255,5 @@ struct btrfs_ioctl_balance_progress {
>  			       struct btrfs_ioctl_fs_info_args)
>  #define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 32, \
>  				  struct btrfs_ioctl_balance_progress)
> +#define BTRFS_IOC_BALANCE_CANCEL _IO(BTRFS_IOCTL_MAGIC, 33)
>  #endif
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 4c0a386..f38b231 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -2049,6 +2049,7 @@ int btrfs_balance(struct btrfs_root *dev_root)
>  	bal_info->expected = -1; /* One less than actually counted,
>  				    because chunk 0 is special */
>  	bal_info->completed = 0;
> +	bal_info->cancel_pending = 0;
>  	spin_unlock(&dev_root->fs_info->balance_info_lock);
>  
>  	/* step one make some room on all the devices */
> @@ -2109,7 +2110,7 @@ int btrfs_balance(struct btrfs_root *dev_root)
>  	key.offset = (u64)-1;
>  	key.type = BTRFS_CHUNK_ITEM_KEY;
>  
> -	while (1) {
> +	while (!bal_info->cancel_pending) {
>  		ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
>  		if (ret < 0)
>  			goto error;
> @@ -2149,6 +2150,10 @@ int btrfs_balance(struct btrfs_root *dev_root)
>  		       bal_info->completed, bal_info->expected);
>  	}
>  	ret = 0;
> +	if (bal_info->cancel_pending) {
> +		printk(KERN_INFO "btrfs: balance cancelled\n");
> +		ret = -EINTR;
> +	}

Why not detect if there's any pending signal in the while loop? so
we can just use Ctrl+C to cancel balance.

>  error:
>  	btrfs_free_path(path);
>  	spin_lock(&dev_root->fs_info->balance_info_lock);
--
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
David Sterba June 29, 2011, 10:43 a.m. UTC | #2
On Wed, Jun 29, 2011 at 02:00:20PM +0800, Li Zefan wrote:
> Hugo Mills wrote:
> > @@ -2149,6 +2150,10 @@ int btrfs_balance(struct btrfs_root *dev_root)
> >  		       bal_info->completed, bal_info->expected);
> >  	}
> >  	ret = 0;
> > +	if (bal_info->cancel_pending) {
> > +		printk(KERN_INFO "btrfs: balance cancelled\n");
> > +		ret = -EINTR;
> > +	}
> 
> Why not detect if there's any pending signal in the while loop? so
> we can just use Ctrl+C to cancel balance.

Balance is capable of running in background, you could not send the
Ctrl-C to such process.


david
--
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
diff mbox

Patch

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 25aa3cf..5031085 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -876,6 +876,7 @@  struct btrfs_block_group_cache {
 struct btrfs_balance_info {
 	u32 expected;
 	u32 completed;
+	int cancel_pending;
 };
 
 struct reloc_control;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 5ddf816..d4458d0 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2868,6 +2868,32 @@  error:
 	return ret;
 }
 
+/*
+ * Cancel a running balance operation
+ */
+long btrfs_ioctl_balance_cancel(struct btrfs_fs_info *fs_info)
+{
+	int err = 0;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	spin_lock(&fs_info->balance_info_lock);
+	if (!fs_info->balance_info) {
+		err = -EINVAL;
+		goto error;
+	}
+	if (fs_info->balance_info->cancel_pending) {
+		err = -ECANCELED;
+		goto error;
+	}
+	fs_info->balance_info->cancel_pending = 1;
+
+error:
+	spin_unlock(&fs_info->balance_info_lock);
+	return err;
+}
+
 long btrfs_ioctl(struct file *file, unsigned int
 		cmd, unsigned long arg)
 {
@@ -2915,6 +2941,8 @@  long btrfs_ioctl(struct file *file, unsigned int
 		return btrfs_balance(root->fs_info->dev_root);
 	case BTRFS_IOC_BALANCE_PROGRESS:
 		return btrfs_ioctl_balance_progress(root->fs_info, argp);
+	case BTRFS_IOC_BALANCE_CANCEL:
+		return btrfs_ioctl_balance_cancel(root->fs_info);
 	case BTRFS_IOC_CLONE:
 		return btrfs_ioctl_clone(file, arg, 0, 0, 0);
 	case BTRFS_IOC_CLONE_RANGE:
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index 575b25f..edcbe61 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -255,4 +255,5 @@  struct btrfs_ioctl_balance_progress {
 			       struct btrfs_ioctl_fs_info_args)
 #define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 32, \
 				  struct btrfs_ioctl_balance_progress)
+#define BTRFS_IOC_BALANCE_CANCEL _IO(BTRFS_IOCTL_MAGIC, 33)
 #endif
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4c0a386..f38b231 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2049,6 +2049,7 @@  int btrfs_balance(struct btrfs_root *dev_root)
 	bal_info->expected = -1; /* One less than actually counted,
 				    because chunk 0 is special */
 	bal_info->completed = 0;
+	bal_info->cancel_pending = 0;
 	spin_unlock(&dev_root->fs_info->balance_info_lock);
 
 	/* step one make some room on all the devices */
@@ -2109,7 +2110,7 @@  int btrfs_balance(struct btrfs_root *dev_root)
 	key.offset = (u64)-1;
 	key.type = BTRFS_CHUNK_ITEM_KEY;
 
-	while (1) {
+	while (!bal_info->cancel_pending) {
 		ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
 		if (ret < 0)
 			goto error;
@@ -2149,6 +2150,10 @@  int btrfs_balance(struct btrfs_root *dev_root)
 		       bal_info->completed, bal_info->expected);
 	}
 	ret = 0;
+	if (bal_info->cancel_pending) {
+		printk(KERN_INFO "btrfs: balance cancelled\n");
+		ret = -EINTR;
+	}
 error:
 	btrfs_free_path(path);
 	spin_lock(&dev_root->fs_info->balance_info_lock);