Re: [PATCH v4 2/3] Btrfs: rescan for qgroups

2013-05-01 Thread Jan Schmidt


On 01.05.2013 13:42, Wang Shilong wrote:
> Hi Jan,
> 
>> Hi Wang,
>>
>> On 01.05.2013 09:29, Wang Shilong wrote:
>>> Hello Jan,
>>>
 If qgroup tracking is out of sync, a rescan operation can be started. It
 iterates the complete extent tree and recalculates all qgroup tracking 
 data.
 This is an expensive operation and should not be used unless required.

 A filesystem under rescan can still be umounted. The rescan continues on 
 the
 next mount.  Status information is provided with a separate ioctl while a
 rescan operation is in progress.

 Signed-off-by: Jan Schmidt 
 ---
 fs/btrfs/ctree.h   |   17 ++-
 fs/btrfs/disk-io.c |5 +
 fs/btrfs/ioctl.c   |   83 ++--
 fs/btrfs/qgroup.c  |  318 
 ++--
 include/uapi/linux/btrfs.h |   12 ++-
 5 files changed, 400 insertions(+), 35 deletions(-)

 diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
 index 412c306..e4f28a6 100644
 --- a/fs/btrfs/ctree.h
 +++ b/fs/btrfs/ctree.h
 @@ -1021,9 +1021,9 @@ struct btrfs_block_group_item {
 */
 #define BTRFS_QGROUP_STATUS_FLAG_ON(1ULL << 0)
 /*
 - * SCANNING is set during the initialization phase
 + * RESCAN is set during the initialization phase
 */
 -#define BTRFS_QGROUP_STATUS_FLAG_SCANNING (1ULL << 1)
 +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN   (1ULL << 1)
 /*
 * Some qgroup entries are known to be out of date,
 * either because the configuration has changed in a way that
 @@ -1052,7 +1052,7 @@ struct btrfs_qgroup_status_item {
 * only used during scanning to record the progress
 * of the scan. It contains a logical address
 */
 -  __le64 scan;
 +  __le64 rescan;
 } __attribute__ ((__packed__));

 struct btrfs_qgroup_info_item {
 @@ -1603,6 +1603,11 @@ struct btrfs_fs_info {
/* used by btrfs_qgroup_record_ref for an efficient tree traversal */
u64 qgroup_seq;

 +  /* qgroup rescan items */
 +  struct mutex qgroup_rescan_lock; /* protects the progress item */
 +  struct btrfs_key qgroup_rescan_progress;
 +  struct btrfs_workers qgroup_rescan_workers;
 +
/* filesystem state */
unsigned long fs_state;

 @@ -2888,8 +2893,8 @@ BTRFS_SETGET_FUNCS(qgroup_status_version, struct 
 btrfs_qgroup_status_item,
   version, 64);
 BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
   flags, 64);
 -BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
 - scan, 64);
 +BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
 + rescan, 64);

 /* btrfs_qgroup_info_item */
 BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
 @@ -3834,7 +3839,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle 
 *trans,
   struct btrfs_fs_info *fs_info);
 int btrfs_quota_disable(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info);
 -int btrfs_quota_rescan(struct btrfs_fs_info *fs_info);
 +int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
 int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
  struct btrfs_fs_info *fs_info, u64 src, u64 dst);
 int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
 diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
 index 7717363..63e9348 100644
 --- a/fs/btrfs/disk-io.c
 +++ b/fs/btrfs/disk-io.c
 @@ -2010,6 +2010,7 @@ static void btrfs_stop_all_workers(struct 
 btrfs_fs_info *fs_info)
btrfs_stop_workers(&fs_info->caching_workers);
btrfs_stop_workers(&fs_info->readahead_workers);
btrfs_stop_workers(&fs_info->flush_workers);
 +  btrfs_stop_workers(&fs_info->qgroup_rescan_workers);
 }

 /* helper to cleanup tree roots */
 @@ -2301,6 +2302,7 @@ int open_ctree(struct super_block *sb,
fs_info->qgroup_seq = 1;
fs_info->quota_enabled = 0;
fs_info->pending_quota_state = 0;
 +  mutex_init(&fs_info->qgroup_rescan_lock);

btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
 @@ -2529,6 +2531,8 @@ int open_ctree(struct super_block *sb,
btrfs_init_workers(&fs_info->readahead_workers, "readahead",
   fs_info->thread_pool_size,
   &fs_info->generic_worker);
 +  btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1,
 + &fs_info->generic_worker);

/*
 * endios are largely parallel and should have a very
 @@ -2563,6 +2567,7 @@ int open_ctree(struct super_block *sb,
ret |= 

Re: [PATCH v4 2/3] Btrfs: rescan for qgroups

2013-05-01 Thread Wang Shilong
Hi Jan,

> Hi Wang,
> 
> On 01.05.2013 09:29, Wang Shilong wrote:
>> Hello Jan,
>> 
>>> If qgroup tracking is out of sync, a rescan operation can be started. It
>>> iterates the complete extent tree and recalculates all qgroup tracking data.
>>> This is an expensive operation and should not be used unless required.
>>> 
>>> A filesystem under rescan can still be umounted. The rescan continues on the
>>> next mount.  Status information is provided with a separate ioctl while a
>>> rescan operation is in progress.
>>> 
>>> Signed-off-by: Jan Schmidt 
>>> ---
>>> fs/btrfs/ctree.h   |   17 ++-
>>> fs/btrfs/disk-io.c |5 +
>>> fs/btrfs/ioctl.c   |   83 ++--
>>> fs/btrfs/qgroup.c  |  318 
>>> ++--
>>> include/uapi/linux/btrfs.h |   12 ++-
>>> 5 files changed, 400 insertions(+), 35 deletions(-)
>>> 
>>> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
>>> index 412c306..e4f28a6 100644
>>> --- a/fs/btrfs/ctree.h
>>> +++ b/fs/btrfs/ctree.h
>>> @@ -1021,9 +1021,9 @@ struct btrfs_block_group_item {
>>> */
>>> #define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0)
>>> /*
>>> - * SCANNING is set during the initialization phase
>>> + * RESCAN is set during the initialization phase
>>> */
>>> -#define BTRFS_QGROUP_STATUS_FLAG_SCANNING  (1ULL << 1)
>>> +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN(1ULL << 1)
>>> /*
>>> * Some qgroup entries are known to be out of date,
>>> * either because the configuration has changed in a way that
>>> @@ -1052,7 +1052,7 @@ struct btrfs_qgroup_status_item {
>>>  * only used during scanning to record the progress
>>>  * of the scan. It contains a logical address
>>>  */
>>> -   __le64 scan;
>>> +   __le64 rescan;
>>> } __attribute__ ((__packed__));
>>> 
>>> struct btrfs_qgroup_info_item {
>>> @@ -1603,6 +1603,11 @@ struct btrfs_fs_info {
>>> /* used by btrfs_qgroup_record_ref for an efficient tree traversal */
>>> u64 qgroup_seq;
>>> 
>>> +   /* qgroup rescan items */
>>> +   struct mutex qgroup_rescan_lock; /* protects the progress item */
>>> +   struct btrfs_key qgroup_rescan_progress;
>>> +   struct btrfs_workers qgroup_rescan_workers;
>>> +
>>> /* filesystem state */
>>> unsigned long fs_state;
>>> 
>>> @@ -2888,8 +2893,8 @@ BTRFS_SETGET_FUNCS(qgroup_status_version, struct 
>>> btrfs_qgroup_status_item,
>>>version, 64);
>>> BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
>>>flags, 64);
>>> -BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
>>> -  scan, 64);
>>> +BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
>>> +  rescan, 64);
>>> 
>>> /* btrfs_qgroup_info_item */
>>> BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
>>> @@ -3834,7 +3839,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle 
>>> *trans,
>>>struct btrfs_fs_info *fs_info);
>>> int btrfs_quota_disable(struct btrfs_trans_handle *trans,
>>> struct btrfs_fs_info *fs_info);
>>> -int btrfs_quota_rescan(struct btrfs_fs_info *fs_info);
>>> +int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
>>> int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
>>>   struct btrfs_fs_info *fs_info, u64 src, u64 dst);
>>> int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
>>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
>>> index 7717363..63e9348 100644
>>> --- a/fs/btrfs/disk-io.c
>>> +++ b/fs/btrfs/disk-io.c
>>> @@ -2010,6 +2010,7 @@ static void btrfs_stop_all_workers(struct 
>>> btrfs_fs_info *fs_info)
>>> btrfs_stop_workers(&fs_info->caching_workers);
>>> btrfs_stop_workers(&fs_info->readahead_workers);
>>> btrfs_stop_workers(&fs_info->flush_workers);
>>> +   btrfs_stop_workers(&fs_info->qgroup_rescan_workers);
>>> }
>>> 
>>> /* helper to cleanup tree roots */
>>> @@ -2301,6 +2302,7 @@ int open_ctree(struct super_block *sb,
>>> fs_info->qgroup_seq = 1;
>>> fs_info->quota_enabled = 0;
>>> fs_info->pending_quota_state = 0;
>>> +   mutex_init(&fs_info->qgroup_rescan_lock);
>>> 
>>> btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
>>> btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
>>> @@ -2529,6 +2531,8 @@ int open_ctree(struct super_block *sb,
>>> btrfs_init_workers(&fs_info->readahead_workers, "readahead",
>>>fs_info->thread_pool_size,
>>>&fs_info->generic_worker);
>>> +   btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1,
>>> +  &fs_info->generic_worker);
>>> 
>>> /*
>>>  * endios are largely parallel and should have a very
>>> @@ -2563,6 +2567,7 @@ int open_ctree(struct super_block *sb,
>>> ret |= btrfs_start_workers(&fs_info->caching_workers);
>>> ret |= btrfs_start_workers(&fs_info->readahead_workers);
>>> ret |= 

Re: [PATCH v4 2/3] Btrfs: rescan for qgroups

2013-05-01 Thread Jan Schmidt
Hi Wang,

On 01.05.2013 09:29, Wang Shilong wrote:
> Hello Jan,
> 
>> If qgroup tracking is out of sync, a rescan operation can be started. It
>> iterates the complete extent tree and recalculates all qgroup tracking data.
>> This is an expensive operation and should not be used unless required.
>>
>> A filesystem under rescan can still be umounted. The rescan continues on the
>> next mount.  Status information is provided with a separate ioctl while a
>> rescan operation is in progress.
>>
>> Signed-off-by: Jan Schmidt 
>> ---
>> fs/btrfs/ctree.h   |   17 ++-
>> fs/btrfs/disk-io.c |5 +
>> fs/btrfs/ioctl.c   |   83 ++--
>> fs/btrfs/qgroup.c  |  318 
>> ++--
>> include/uapi/linux/btrfs.h |   12 ++-
>> 5 files changed, 400 insertions(+), 35 deletions(-)
>>
>> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
>> index 412c306..e4f28a6 100644
>> --- a/fs/btrfs/ctree.h
>> +++ b/fs/btrfs/ctree.h
>> @@ -1021,9 +1021,9 @@ struct btrfs_block_group_item {
>>  */
>> #define BTRFS_QGROUP_STATUS_FLAG_ON  (1ULL << 0)
>> /*
>> - * SCANNING is set during the initialization phase
>> + * RESCAN is set during the initialization phase
>>  */
>> -#define BTRFS_QGROUP_STATUS_FLAG_SCANNING   (1ULL << 1)
>> +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN (1ULL << 1)
>> /*
>>  * Some qgroup entries are known to be out of date,
>>  * either because the configuration has changed in a way that
>> @@ -1052,7 +1052,7 @@ struct btrfs_qgroup_status_item {
>>   * only used during scanning to record the progress
>>   * of the scan. It contains a logical address
>>   */
>> -__le64 scan;
>> +__le64 rescan;
>> } __attribute__ ((__packed__));
>>
>> struct btrfs_qgroup_info_item {
>> @@ -1603,6 +1603,11 @@ struct btrfs_fs_info {
>>  /* used by btrfs_qgroup_record_ref for an efficient tree traversal */
>>  u64 qgroup_seq;
>>
>> +/* qgroup rescan items */
>> +struct mutex qgroup_rescan_lock; /* protects the progress item */
>> +struct btrfs_key qgroup_rescan_progress;
>> +struct btrfs_workers qgroup_rescan_workers;
>> +
>>  /* filesystem state */
>>  unsigned long fs_state;
>>
>> @@ -2888,8 +2893,8 @@ BTRFS_SETGET_FUNCS(qgroup_status_version, struct 
>> btrfs_qgroup_status_item,
>> version, 64);
>> BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
>> flags, 64);
>> -BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
>> -   scan, 64);
>> +BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
>> +   rescan, 64);
>>
>> /* btrfs_qgroup_info_item */
>> BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
>> @@ -3834,7 +3839,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle 
>> *trans,
>> struct btrfs_fs_info *fs_info);
>> int btrfs_quota_disable(struct btrfs_trans_handle *trans,
>>  struct btrfs_fs_info *fs_info);
>> -int btrfs_quota_rescan(struct btrfs_fs_info *fs_info);
>> +int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
>> int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
>>struct btrfs_fs_info *fs_info, u64 src, u64 dst);
>> int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
>> index 7717363..63e9348 100644
>> --- a/fs/btrfs/disk-io.c
>> +++ b/fs/btrfs/disk-io.c
>> @@ -2010,6 +2010,7 @@ static void btrfs_stop_all_workers(struct 
>> btrfs_fs_info *fs_info)
>>  btrfs_stop_workers(&fs_info->caching_workers);
>>  btrfs_stop_workers(&fs_info->readahead_workers);
>>  btrfs_stop_workers(&fs_info->flush_workers);
>> +btrfs_stop_workers(&fs_info->qgroup_rescan_workers);
>> }
>>
>> /* helper to cleanup tree roots */
>> @@ -2301,6 +2302,7 @@ int open_ctree(struct super_block *sb,
>>  fs_info->qgroup_seq = 1;
>>  fs_info->quota_enabled = 0;
>>  fs_info->pending_quota_state = 0;
>> +mutex_init(&fs_info->qgroup_rescan_lock);
>>
>>  btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
>>  btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
>> @@ -2529,6 +2531,8 @@ int open_ctree(struct super_block *sb,
>>  btrfs_init_workers(&fs_info->readahead_workers, "readahead",
>> fs_info->thread_pool_size,
>> &fs_info->generic_worker);
>> +btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1,
>> +   &fs_info->generic_worker);
>>
>>  /*
>>   * endios are largely parallel and should have a very
>> @@ -2563,6 +2567,7 @@ int open_ctree(struct super_block *sb,
>>  ret |= btrfs_start_workers(&fs_info->caching_workers);
>>  ret |= btrfs_start_workers(&fs_info->readahead_workers);
>>  ret |= btrfs_start_workers(&fs_info->flush_workers);
>> +ret |= btrfs_start_workers(&fs_info->

Re: [PATCH v4 2/3] Btrfs: rescan for qgroups

2013-05-01 Thread Wang Shilong
Hello Jan,

> If qgroup tracking is out of sync, a rescan operation can be started. It
> iterates the complete extent tree and recalculates all qgroup tracking data.
> This is an expensive operation and should not be used unless required.
> 
> A filesystem under rescan can still be umounted. The rescan continues on the
> next mount.  Status information is provided with a separate ioctl while a
> rescan operation is in progress.
> 
> Signed-off-by: Jan Schmidt 
> ---
> fs/btrfs/ctree.h   |   17 ++-
> fs/btrfs/disk-io.c |5 +
> fs/btrfs/ioctl.c   |   83 ++--
> fs/btrfs/qgroup.c  |  318 ++--
> include/uapi/linux/btrfs.h |   12 ++-
> 5 files changed, 400 insertions(+), 35 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 412c306..e4f28a6 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -1021,9 +1021,9 @@ struct btrfs_block_group_item {
>  */
> #define BTRFS_QGROUP_STATUS_FLAG_ON   (1ULL << 0)
> /*
> - * SCANNING is set during the initialization phase
> + * RESCAN is set during the initialization phase
>  */
> -#define BTRFS_QGROUP_STATUS_FLAG_SCANNING(1ULL << 1)
> +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN  (1ULL << 1)
> /*
>  * Some qgroup entries are known to be out of date,
>  * either because the configuration has changed in a way that
> @@ -1052,7 +1052,7 @@ struct btrfs_qgroup_status_item {
>* only used during scanning to record the progress
>* of the scan. It contains a logical address
>*/
> - __le64 scan;
> + __le64 rescan;
> } __attribute__ ((__packed__));
> 
> struct btrfs_qgroup_info_item {
> @@ -1603,6 +1603,11 @@ struct btrfs_fs_info {
>   /* used by btrfs_qgroup_record_ref for an efficient tree traversal */
>   u64 qgroup_seq;
> 
> + /* qgroup rescan items */
> + struct mutex qgroup_rescan_lock; /* protects the progress item */
> + struct btrfs_key qgroup_rescan_progress;
> + struct btrfs_workers qgroup_rescan_workers;
> +
>   /* filesystem state */
>   unsigned long fs_state;
> 
> @@ -2888,8 +2893,8 @@ BTRFS_SETGET_FUNCS(qgroup_status_version, struct 
> btrfs_qgroup_status_item,
>  version, 64);
> BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
>  flags, 64);
> -BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
> -scan, 64);
> +BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
> +rescan, 64);
> 
> /* btrfs_qgroup_info_item */
> BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
> @@ -3834,7 +3839,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
>  struct btrfs_fs_info *fs_info);
> int btrfs_quota_disable(struct btrfs_trans_handle *trans,
>   struct btrfs_fs_info *fs_info);
> -int btrfs_quota_rescan(struct btrfs_fs_info *fs_info);
> +int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
> int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
> struct btrfs_fs_info *fs_info, u64 src, u64 dst);
> int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 7717363..63e9348 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -2010,6 +2010,7 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info 
> *fs_info)
>   btrfs_stop_workers(&fs_info->caching_workers);
>   btrfs_stop_workers(&fs_info->readahead_workers);
>   btrfs_stop_workers(&fs_info->flush_workers);
> + btrfs_stop_workers(&fs_info->qgroup_rescan_workers);
> }
> 
> /* helper to cleanup tree roots */
> @@ -2301,6 +2302,7 @@ int open_ctree(struct super_block *sb,
>   fs_info->qgroup_seq = 1;
>   fs_info->quota_enabled = 0;
>   fs_info->pending_quota_state = 0;
> + mutex_init(&fs_info->qgroup_rescan_lock);
> 
>   btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
>   btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
> @@ -2529,6 +2531,8 @@ int open_ctree(struct super_block *sb,
>   btrfs_init_workers(&fs_info->readahead_workers, "readahead",
>  fs_info->thread_pool_size,
>  &fs_info->generic_worker);
> + btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1,
> +&fs_info->generic_worker);
> 
>   /*
>* endios are largely parallel and should have a very
> @@ -2563,6 +2567,7 @@ int open_ctree(struct super_block *sb,
>   ret |= btrfs_start_workers(&fs_info->caching_workers);
>   ret |= btrfs_start_workers(&fs_info->readahead_workers);
>   ret |= btrfs_start_workers(&fs_info->flush_workers);
> + ret |= btrfs_start_workers(&fs_info->qgroup_rescan_workers);
>   if (ret) {
>   err = -ENOMEM;
>   goto fail_sb_buffer;
> diff -

Re: [PATCH v4 2/3] Btrfs: rescan for qgroups

2013-04-25 Thread Wang Shilong
> If qgroup tracking is out of sync, a rescan operation can be started. It
> iterates the complete extent tree and recalculates all qgroup tracking data.
> This is an expensive operation and should not be used unless required.
> 
> A filesystem under rescan can still be umounted. The rescan continues on the
> next mount.  Status information is provided with a separate ioctl while a
> rescan operation is in progress.
> 
> Signed-off-by: Jan Schmidt 


Now it looks good to me.
Reviewed-by: Wang Shilong 

Thanks,
Wang

> ---
>  fs/btrfs/ctree.h   |   17 ++-
>  fs/btrfs/disk-io.c |5 +
>  fs/btrfs/ioctl.c   |   83 ++--
>  fs/btrfs/qgroup.c  |  318 
> ++--
>  include/uapi/linux/btrfs.h |   12 ++-
>  5 files changed, 400 insertions(+), 35 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 412c306..e4f28a6 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -1021,9 +1021,9 @@ struct btrfs_block_group_item {
>   */
>  #define BTRFS_QGROUP_STATUS_FLAG_ON  (1ULL << 0)
>  /*
> - * SCANNING is set during the initialization phase
> + * RESCAN is set during the initialization phase
>   */
> -#define BTRFS_QGROUP_STATUS_FLAG_SCANNING(1ULL << 1)
> +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN  (1ULL << 1)
>  /*
>   * Some qgroup entries are known to be out of date,
>   * either because the configuration has changed in a way that
> @@ -1052,7 +1052,7 @@ struct btrfs_qgroup_status_item {
>* only used during scanning to record the progress
>* of the scan. It contains a logical address
>*/
> - __le64 scan;
> + __le64 rescan;
>  } __attribute__ ((__packed__));
>  
>  struct btrfs_qgroup_info_item {
> @@ -1603,6 +1603,11 @@ struct btrfs_fs_info {
>   /* used by btrfs_qgroup_record_ref for an efficient tree traversal */
>   u64 qgroup_seq;
>  
> + /* qgroup rescan items */
> + struct mutex qgroup_rescan_lock; /* protects the progress item */
> + struct btrfs_key qgroup_rescan_progress;
> + struct btrfs_workers qgroup_rescan_workers;
> +
>   /* filesystem state */
>   unsigned long fs_state;
>  
> @@ -2888,8 +2893,8 @@ BTRFS_SETGET_FUNCS(qgroup_status_version, struct 
> btrfs_qgroup_status_item,
>  version, 64);
>  BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
>  flags, 64);
> -BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
> -scan, 64);
> +BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
> +rescan, 64);
>  
>  /* btrfs_qgroup_info_item */
>  BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
> @@ -3834,7 +3839,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
>  struct btrfs_fs_info *fs_info);
>  int btrfs_quota_disable(struct btrfs_trans_handle *trans,
>   struct btrfs_fs_info *fs_info);
> -int btrfs_quota_rescan(struct btrfs_fs_info *fs_info);
> +int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
>  int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
> struct btrfs_fs_info *fs_info, u64 src, u64 dst);
>  int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 7717363..63e9348 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -2010,6 +2010,7 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info 
> *fs_info)
>   btrfs_stop_workers(&fs_info->caching_workers);
>   btrfs_stop_workers(&fs_info->readahead_workers);
>   btrfs_stop_workers(&fs_info->flush_workers);
> + btrfs_stop_workers(&fs_info->qgroup_rescan_workers);
>  }
>  
>  /* helper to cleanup tree roots */
> @@ -2301,6 +2302,7 @@ int open_ctree(struct super_block *sb,
>   fs_info->qgroup_seq = 1;
>   fs_info->quota_enabled = 0;
>   fs_info->pending_quota_state = 0;
> + mutex_init(&fs_info->qgroup_rescan_lock);
>  
>   btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
>   btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
> @@ -2529,6 +2531,8 @@ int open_ctree(struct super_block *sb,
>   btrfs_init_workers(&fs_info->readahead_workers, "readahead",
>  fs_info->thread_pool_size,
>  &fs_info->generic_worker);
> + btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1,
> +&fs_info->generic_worker);
>  
>   /*
>* endios are largely parallel and should have a very
> @@ -2563,6 +2567,7 @@ int open_ctree(struct super_block *sb,
>   ret |= btrfs_start_workers(&fs_info->caching_workers);
>   ret |= btrfs_start_workers(&fs_info->readahead_workers);
>   ret |= btrfs_start_workers(&fs_info->flush_workers);
> + ret |= btrfs_start_workers(&fs_info->qgroup_rescan_workers);
> 

[PATCH v4 2/3] Btrfs: rescan for qgroups

2013-04-25 Thread Jan Schmidt
If qgroup tracking is out of sync, a rescan operation can be started. It
iterates the complete extent tree and recalculates all qgroup tracking data.
This is an expensive operation and should not be used unless required.

A filesystem under rescan can still be umounted. The rescan continues on the
next mount.  Status information is provided with a separate ioctl while a
rescan operation is in progress.

Signed-off-by: Jan Schmidt 
---
 fs/btrfs/ctree.h   |   17 ++-
 fs/btrfs/disk-io.c |5 +
 fs/btrfs/ioctl.c   |   83 ++--
 fs/btrfs/qgroup.c  |  318 ++--
 include/uapi/linux/btrfs.h |   12 ++-
 5 files changed, 400 insertions(+), 35 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 412c306..e4f28a6 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1021,9 +1021,9 @@ struct btrfs_block_group_item {
  */
 #define BTRFS_QGROUP_STATUS_FLAG_ON(1ULL << 0)
 /*
- * SCANNING is set during the initialization phase
+ * RESCAN is set during the initialization phase
  */
-#define BTRFS_QGROUP_STATUS_FLAG_SCANNING  (1ULL << 1)
+#define BTRFS_QGROUP_STATUS_FLAG_RESCAN(1ULL << 1)
 /*
  * Some qgroup entries are known to be out of date,
  * either because the configuration has changed in a way that
@@ -1052,7 +1052,7 @@ struct btrfs_qgroup_status_item {
 * only used during scanning to record the progress
 * of the scan. It contains a logical address
 */
-   __le64 scan;
+   __le64 rescan;
 } __attribute__ ((__packed__));
 
 struct btrfs_qgroup_info_item {
@@ -1603,6 +1603,11 @@ struct btrfs_fs_info {
/* used by btrfs_qgroup_record_ref for an efficient tree traversal */
u64 qgroup_seq;
 
+   /* qgroup rescan items */
+   struct mutex qgroup_rescan_lock; /* protects the progress item */
+   struct btrfs_key qgroup_rescan_progress;
+   struct btrfs_workers qgroup_rescan_workers;
+
/* filesystem state */
unsigned long fs_state;
 
@@ -2888,8 +2893,8 @@ BTRFS_SETGET_FUNCS(qgroup_status_version, struct 
btrfs_qgroup_status_item,
   version, 64);
 BTRFS_SETGET_FUNCS(qgroup_status_flags, struct btrfs_qgroup_status_item,
   flags, 64);
-BTRFS_SETGET_FUNCS(qgroup_status_scan, struct btrfs_qgroup_status_item,
-  scan, 64);
+BTRFS_SETGET_FUNCS(qgroup_status_rescan, struct btrfs_qgroup_status_item,
+  rescan, 64);
 
 /* btrfs_qgroup_info_item */
 BTRFS_SETGET_FUNCS(qgroup_info_generation, struct btrfs_qgroup_info_item,
@@ -3834,7 +3839,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
   struct btrfs_fs_info *fs_info);
 int btrfs_quota_disable(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info);
-int btrfs_quota_rescan(struct btrfs_fs_info *fs_info);
+int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
 int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
  struct btrfs_fs_info *fs_info, u64 src, u64 dst);
 int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7717363..63e9348 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2010,6 +2010,7 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info 
*fs_info)
btrfs_stop_workers(&fs_info->caching_workers);
btrfs_stop_workers(&fs_info->readahead_workers);
btrfs_stop_workers(&fs_info->flush_workers);
+   btrfs_stop_workers(&fs_info->qgroup_rescan_workers);
 }
 
 /* helper to cleanup tree roots */
@@ -2301,6 +2302,7 @@ int open_ctree(struct super_block *sb,
fs_info->qgroup_seq = 1;
fs_info->quota_enabled = 0;
fs_info->pending_quota_state = 0;
+   mutex_init(&fs_info->qgroup_rescan_lock);
 
btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
@@ -2529,6 +2531,8 @@ int open_ctree(struct super_block *sb,
btrfs_init_workers(&fs_info->readahead_workers, "readahead",
   fs_info->thread_pool_size,
   &fs_info->generic_worker);
+   btrfs_init_workers(&fs_info->qgroup_rescan_workers, "qgroup-rescan", 1,
+  &fs_info->generic_worker);
 
/*
 * endios are largely parallel and should have a very
@@ -2563,6 +2567,7 @@ int open_ctree(struct super_block *sb,
ret |= btrfs_start_workers(&fs_info->caching_workers);
ret |= btrfs_start_workers(&fs_info->readahead_workers);
ret |= btrfs_start_workers(&fs_info->flush_workers);
+   ret |= btrfs_start_workers(&fs_info->qgroup_rescan_workers);
if (ret) {
err = -ENOMEM;
goto fail_sb_buffer;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index d0af96a..5e93bb8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.