Skip to content

Commit

Permalink
btrfs: extend balance filter limit to take minimum and maximum
Browse files Browse the repository at this point in the history
The 'limit' filter is underdesigned, it should have been a range for
[min,max], with some relaxed semantics when one of the bounds is
missing. Besides that, using a full u64 for a single value is a waste of
bytes.

Let's fix both by extending the use of the u64 bytes for the [min,max]
range. This can be done in a backward compatible way, the range will be
interpreted only if the appropriate flag is set
(BTRFS_BALANCE_ARGS_LIMIT_RANGE).

Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
  • Loading branch information
David Sterba authored and Chris Mason committed Oct 27, 2015
1 parent 2849a85 commit 12907fc
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 3 deletions.
14 changes: 12 additions & 2 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -846,8 +846,18 @@ struct btrfs_disk_balance_args {
/* BTRFS_BALANCE_ARGS_* */
__le64 flags;

/* BTRFS_BALANCE_ARGS_LIMIT value */
__le64 limit;
/*
* BTRFS_BALANCE_ARGS_LIMIT with value 'limit'
* BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum
* and maximum
*/
union {
__le64 limit;
struct {
__le32 limit_min;
__le32 limit_max;
};
};

__le64 unused[7];
} __attribute__ ((__packed__));
Expand Down
42 changes: 42 additions & 0 deletions fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3300,6 +3300,16 @@ static int should_balance_chunk(struct btrfs_root *root,
return 0;
else
bargs->limit--;
} else if ((bargs->flags & BTRFS_BALANCE_ARGS_LIMIT_RANGE)) {
/*
* Same logic as the 'limit' filter; the minimum cannot be
* determined here because we do not have the global informatoin
* about the count of all chunks that satisfy the filters.
*/
if (bargs->limit_max == 0)
return 0;
else
bargs->limit_max--;
}

return 1;
Expand All @@ -3314,6 +3324,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
struct btrfs_device *device;
u64 old_size;
u64 size_to_free;
u64 chunk_type;
struct btrfs_chunk *chunk;
struct btrfs_path *path;
struct btrfs_key key;
Expand All @@ -3324,9 +3335,13 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
int ret;
int enospc_errors = 0;
bool counting = true;
/* The single value limit and min/max limits use the same bytes in the */
u64 limit_data = bctl->data.limit;
u64 limit_meta = bctl->meta.limit;
u64 limit_sys = bctl->sys.limit;
u32 count_data = 0;
u32 count_meta = 0;
u32 count_sys = 0;

/* step one make some room on all the devices */
devices = &fs_info->fs_devices->devices;
Expand Down Expand Up @@ -3367,6 +3382,10 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
spin_unlock(&fs_info->balance_lock);
again:
if (!counting) {
/*
* The single value limit and min/max limits use the same bytes
* in the
*/
bctl->data.limit = limit_data;
bctl->meta.limit = limit_meta;
bctl->sys.limit = limit_sys;
Expand Down Expand Up @@ -3414,6 +3433,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
}

chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
chunk_type = btrfs_chunk_type(leaf, chunk);

if (!counting) {
spin_lock(&fs_info->balance_lock);
Expand All @@ -3434,6 +3454,28 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
spin_lock(&fs_info->balance_lock);
bctl->stat.expected++;
spin_unlock(&fs_info->balance_lock);

if (chunk_type & BTRFS_BLOCK_GROUP_DATA)
count_data++;
else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM)
count_sys++;
else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA)
count_meta++;

goto loop;
}

/*
* Apply limit_min filter, no need to check if the LIMITS
* filter is used, limit_min is 0 by default
*/
if (((chunk_type & BTRFS_BLOCK_GROUP_DATA) &&
count_data < bctl->data.limit_min)
|| ((chunk_type & BTRFS_BLOCK_GROUP_METADATA) &&
count_meta < bctl->meta.limit_min)
|| ((chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) &&
count_sys < bctl->sys.limit_min)) {
mutex_unlock(&fs_info->delete_unused_bgs_mutex);
goto loop;
}

Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/volumes.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ struct map_lookup {
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4)
#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5)
#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6)

#define BTRFS_BALANCE_ARGS_MASK \
(BTRFS_BALANCE_ARGS_PROFILES | \
Expand Down
13 changes: 12 additions & 1 deletion include/uapi/linux/btrfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,18 @@ struct btrfs_balance_args {

__u64 flags;

__u64 limit; /* limit number of processed chunks */
/*
* BTRFS_BALANCE_ARGS_LIMIT with value 'limit'
* BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum
* and maximum
*/
union {
__u64 limit; /* limit number of processed chunks */
struct {
__u32 limit_min;
__u32 limit_max;
};
};
__u64 unused[7];
} __attribute__ ((__packed__));

Expand Down

0 comments on commit 12907fc

Please sign in to comment.