forked from mirrors/linux
		
	btrfs: introduce exclusive operation BALANCE_PAUSED state
Current set of exclusive operation states is not sufficient to handle all practical use cases. In particular there is a need to be able to add a device to a filesystem that have paused balance. Currently there is no way to distinguish between a running and a paused balance. Fix this by introducing BTRFS_EXCLOP_BALANCE_PAUSED which is going to be set in 2 occasions: 1. When a filesystem is mounted with skip_balance and there is an unfinished balance it will now be into BALANCE_PAUSED instead of simply BALANCE state. 2. When a running balance is paused. Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									d96b34248c
								
							
						
					
					
						commit
						efc0e69c2f
					
				
					 3 changed files with 36 additions and 2 deletions
				
			
		| 
						 | 
					@ -611,6 +611,7 @@ enum {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum btrfs_exclusive_operation {
 | 
					enum btrfs_exclusive_operation {
 | 
				
			||||||
	BTRFS_EXCLOP_NONE,
 | 
						BTRFS_EXCLOP_NONE,
 | 
				
			||||||
 | 
						BTRFS_EXCLOP_BALANCE_PAUSED,
 | 
				
			||||||
	BTRFS_EXCLOP_BALANCE,
 | 
						BTRFS_EXCLOP_BALANCE,
 | 
				
			||||||
	BTRFS_EXCLOP_DEV_ADD,
 | 
						BTRFS_EXCLOP_DEV_ADD,
 | 
				
			||||||
	BTRFS_EXCLOP_DEV_REMOVE,
 | 
						BTRFS_EXCLOP_DEV_REMOVE,
 | 
				
			||||||
| 
						 | 
					@ -3321,6 +3322,9 @@ bool btrfs_exclop_start_try_lock(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
				 enum btrfs_exclusive_operation type);
 | 
									 enum btrfs_exclusive_operation type);
 | 
				
			||||||
void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info);
 | 
					void btrfs_exclop_start_unlock(struct btrfs_fs_info *fs_info);
 | 
				
			||||||
void btrfs_exclop_finish(struct btrfs_fs_info *fs_info);
 | 
					void btrfs_exclop_finish(struct btrfs_fs_info *fs_info);
 | 
				
			||||||
 | 
					void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
 | 
								  enum btrfs_exclusive_operation op);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* file.c */
 | 
					/* file.c */
 | 
				
			||||||
int __init btrfs_auto_defrag_init(void);
 | 
					int __init btrfs_auto_defrag_init(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -414,6 +414,29 @@ void btrfs_exclop_finish(struct btrfs_fs_info *fs_info)
 | 
				
			||||||
	sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
 | 
						sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
 | 
								  enum btrfs_exclusive_operation op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (op) {
 | 
				
			||||||
 | 
						case BTRFS_EXCLOP_BALANCE_PAUSED:
 | 
				
			||||||
 | 
							spin_lock(&fs_info->super_lock);
 | 
				
			||||||
 | 
							ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE ||
 | 
				
			||||||
 | 
							       fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD);
 | 
				
			||||||
 | 
							fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED;
 | 
				
			||||||
 | 
							spin_unlock(&fs_info->super_lock);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BTRFS_EXCLOP_BALANCE:
 | 
				
			||||||
 | 
							spin_lock(&fs_info->super_lock);
 | 
				
			||||||
 | 
							ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
 | 
				
			||||||
 | 
							fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE;
 | 
				
			||||||
 | 
							spin_unlock(&fs_info->super_lock);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							btrfs_warn(fs_info,
 | 
				
			||||||
 | 
								"invalid exclop balance operation %d requested", op);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
 | 
					static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inode *inode = file_inode(file);
 | 
						struct inode *inode = file_inode(file);
 | 
				
			||||||
| 
						 | 
					@ -4056,6 +4079,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
 | 
				
			||||||
			spin_lock(&fs_info->balance_lock);
 | 
								spin_lock(&fs_info->balance_lock);
 | 
				
			||||||
			bctl->flags |= BTRFS_BALANCE_RESUME;
 | 
								bctl->flags |= BTRFS_BALANCE_RESUME;
 | 
				
			||||||
			spin_unlock(&fs_info->balance_lock);
 | 
								spin_unlock(&fs_info->balance_lock);
 | 
				
			||||||
 | 
								btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			goto do_balance;
 | 
								goto do_balance;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4394,8 +4394,10 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
 | 
				
			||||||
	ret = __btrfs_balance(fs_info);
 | 
						ret = __btrfs_balance(fs_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&fs_info->balance_mutex);
 | 
						mutex_lock(&fs_info->balance_mutex);
 | 
				
			||||||
	if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req))
 | 
						if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req)) {
 | 
				
			||||||
		btrfs_info(fs_info, "balance: paused");
 | 
							btrfs_info(fs_info, "balance: paused");
 | 
				
			||||||
 | 
							btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Balance can be canceled by:
 | 
						 * Balance can be canceled by:
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
| 
						 | 
					@ -4471,6 +4473,10 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock(&fs_info->super_lock);
 | 
				
			||||||
 | 
						ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
 | 
				
			||||||
 | 
						fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE;
 | 
				
			||||||
 | 
						spin_unlock(&fs_info->super_lock);
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * A ro->rw remount sequence should continue with the paused balance
 | 
						 * A ro->rw remount sequence should continue with the paused balance
 | 
				
			||||||
	 * regardless of who pauses it, system or the user as of now, so set
 | 
						 * regardless of who pauses it, system or the user as of now, so set
 | 
				
			||||||
| 
						 | 
					@ -4539,7 +4545,7 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
 | 
				
			||||||
	 * is in a paused state and must have fs_info::balance_ctl properly
 | 
						 * is in a paused state and must have fs_info::balance_ctl properly
 | 
				
			||||||
	 * set up.
 | 
						 * set up.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE))
 | 
						if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED))
 | 
				
			||||||
		btrfs_warn(fs_info,
 | 
							btrfs_warn(fs_info,
 | 
				
			||||||
	"balance: cannot set exclusive op status, resume manually");
 | 
						"balance: cannot set exclusive op status, resume manually");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue