Permalink
Checking mergeability…
Don’t worry, you can still create the pull request.
Comparing changes
Open a pull request
- 5 commits
- 5 files changed
- 0 commit comments
- 4 contributors
Commits on Mar 05, 2019
The code fails if the third section is missing (like "4.18") or is followed by anything but "." or "-". This happens for example if we're not exactly at a tag and CONFIG_LOCALVERSION_AUTO=n (which results in "4.18.5+"). Signed-off-by: Adam Borowski <kilobyte@angband.pl> Signed-off-by: David Sterba <dsterba@suse.com>
Defragging an executable conflicts both way with it being run, resulting in ETXTBSY. This either makes defrag fail or prevents the program from being executed. Kernels 4.19-rc1 and later allow defragging files you could have possibly opened rw, even if the passed descriptor is ro (commit 616d374efa23 "btrfs: allow defrag on a file opened read-only that has rw permissions"). Signed-off-by: Adam Borowski <kilobyte@angband.pl> Signed-off-by: David Sterba <dsterba@suse.com>
… extent tree In github issues, one user reports unexpected ENOSPC error if enabling datasum druing convert. After some investigation, it looks like that during ext2_saved/image creation, we could create large file extent whose size can be 128M (max data extent size). In that case, its csum block will be at least 128K. Under certain case we need to allocate extra metadata chunks to fulfill such space requirement. However we only do metadata prealloc if we're reserving extents for fs trees. (we use btrfs_root::ref_cows to determine whether we should do metadata prealloc, and that member is only set for fs trees). There is no explaination on why we only do metadata prealloc for file trees, but at least from my investigation, it could be related to avoid nested extent tree modication. At least extent reservation for csum tree shouldn't be a problem with metadata block group preallocation. So change the metadata block group preallocation check from "root->ref_cow" to "root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID", and add some comment for it. Issue: #123 Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Unified
Split
Showing
with
116 additions
and 69 deletions.
- +60 −36 cmds-fi-usage.c
- +12 −2 cmds-filesystem.c
- +36 −26 cmds-receive.c
- +6 −1 extent-tree.c
- +2 −4 fsfeatures.c
| @@ -280,28 +280,6 @@ static struct btrfs_ioctl_space_args *load_space_info(int fd, const char *path) | ||
| return sargs; | ||
| } | ||
|
|
||
| /* | ||
| * This function computes the space occupied by a *single* RAID5/RAID6 chunk. | ||
| * The computation is performed on the basis of the number of stripes | ||
| * which compose the chunk, which could be different from the number of devices | ||
| * if a disk is added later. | ||
| */ | ||
| static void get_raid56_used(struct chunk_info *chunks, int chunkcount, | ||
| u64 *raid5_used, u64 *raid6_used) | ||
| { | ||
| struct chunk_info *info_ptr = chunks; | ||
| *raid5_used = 0; | ||
| *raid6_used = 0; | ||
|
|
||
| while (chunkcount-- > 0) { | ||
| if (info_ptr->type & BTRFS_BLOCK_GROUP_RAID5) | ||
| (*raid5_used) += info_ptr->size / (info_ptr->num_stripes - 1); | ||
| if (info_ptr->type & BTRFS_BLOCK_GROUP_RAID6) | ||
| (*raid6_used) += info_ptr->size / (info_ptr->num_stripes - 2); | ||
| info_ptr++; | ||
| } | ||
| } | ||
|
|
||
| #define MIN_UNALOCATED_THRESH SZ_16M | ||
| static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo, | ||
| int chunkcount, struct device_info *devinfo, int devcount, | ||
| @@ -331,13 +309,15 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo, | ||
| double data_ratio; | ||
| double metadata_ratio; | ||
| /* logical */ | ||
| u64 raid5_used = 0; | ||
| u64 raid6_used = 0; | ||
| u64 r_data_raid56_chunks = 0; | ||
| u64 l_data_raid56_chunks = 0; | ||
| u64 r_metadata_raid56_chunks = 0; | ||
| u64 l_metadata_raid56_chunks = 0; | ||
| u64 l_global_reserve = 0; | ||
| u64 l_global_reserve_used = 0; | ||
| u64 free_estimated = 0; | ||
| u64 free_min = 0; | ||
| int max_data_ratio = 1; | ||
| double max_data_ratio = 1; | ||
| int mixed = 0; | ||
|
|
||
| sargs = load_space_info(fd, path); | ||
| @@ -359,45 +339,43 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo, | ||
| ret = 1; | ||
| goto exit; | ||
| } | ||
| get_raid56_used(chunkinfo, chunkcount, &raid5_used, &raid6_used); | ||
|
|
||
| for (i = 0; i < sargs->total_spaces; i++) { | ||
| int ratio; | ||
| u64 flags = sargs->spaces[i].flags; | ||
|
|
||
| if ((flags & (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA)) | ||
| == (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA)) { | ||
| mixed = 1; | ||
| } | ||
|
|
||
| /* | ||
| * The raid5/raid6 ratio depends by the stripes number | ||
| * used by every chunk. It is computed separately | ||
| * used by every chunk. It is computed separately, | ||
| * after we're done with this loop, so skip those. | ||
| */ | ||
| if (flags & BTRFS_BLOCK_GROUP_RAID0) | ||
| ratio = 1; | ||
| else if (flags & BTRFS_BLOCK_GROUP_RAID1) | ||
| ratio = 2; | ||
| else if (flags & BTRFS_BLOCK_GROUP_RAID5) | ||
| ratio = 0; | ||
| continue; | ||
| else if (flags & BTRFS_BLOCK_GROUP_RAID6) | ||
| ratio = 0; | ||
| continue; | ||
| else if (flags & BTRFS_BLOCK_GROUP_DUP) | ||
| ratio = 2; | ||
| else if (flags & BTRFS_BLOCK_GROUP_RAID10) | ||
| ratio = 2; | ||
| else | ||
| ratio = 1; | ||
|
|
||
| if (!ratio) | ||
| warning("RAID56 detected, not implemented"); | ||
|
|
||
| if (ratio > max_data_ratio) | ||
| max_data_ratio = ratio; | ||
|
|
||
| if (flags & BTRFS_SPACE_INFO_GLOBAL_RSV) { | ||
| l_global_reserve = sargs->spaces[i].total_bytes; | ||
| l_global_reserve_used = sargs->spaces[i].used_bytes; | ||
| } | ||
| if ((flags & (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA)) | ||
| == (BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA)) { | ||
| mixed = 1; | ||
| } | ||
| if (flags & BTRFS_BLOCK_GROUP_DATA) { | ||
| r_data_used += sargs->spaces[i].used_bytes * ratio; | ||
| r_data_chunks += sargs->spaces[i].total_bytes * ratio; | ||
| @@ -414,6 +392,52 @@ static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo, | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| * Here we compute the space occupied by every RAID5/RAID6 chunks. | ||
| * The computation is performed on the basis of the number of stripes | ||
| * which compose each chunk, which could be different from the number of devices | ||
| * if a disk is added later, or if the disks are of different sizes.. | ||
| */ | ||
| struct chunk_info *info_ptr; | ||
| for (info_ptr = chunkinfo, i = chunkcount; i > 0; i--, info_ptr++) { | ||
| int flags = info_ptr->type; | ||
| int nparity; | ||
|
|
||
| if (flags & BTRFS_BLOCK_GROUP_RAID5) { | ||
| nparity = 1; | ||
| } | ||
| else if (flags & BTRFS_BLOCK_GROUP_RAID6) { | ||
| nparity = 2; | ||
| } | ||
| else { | ||
| // We're only interested in raid56 here | ||
| continue; | ||
| } | ||
|
|
||
| if (flags & BTRFS_BLOCK_GROUP_DATA) { | ||
| r_data_raid56_chunks += info_ptr->size / (info_ptr->num_stripes - nparity); | ||
| l_data_raid56_chunks += info_ptr->size / info_ptr->num_stripes; | ||
| } | ||
| if (flags & BTRFS_BLOCK_GROUP_METADATA) { | ||
| r_metadata_raid56_chunks += info_ptr->size / (info_ptr->num_stripes - nparity); | ||
| l_metadata_raid56_chunks += info_ptr->size / info_ptr->num_stripes; | ||
| } | ||
| } | ||
|
|
||
| if (l_data_raid56_chunks > 0) { | ||
| double ratio = (double)r_data_raid56_chunks / l_data_raid56_chunks; | ||
| r_data_used += r_data_raid56_chunks; | ||
| r_data_chunks += r_data_raid56_chunks; | ||
| l_data_chunks += l_data_raid56_chunks; | ||
| if (ratio > max_data_ratio) | ||
| max_data_ratio = ratio; | ||
| } | ||
| if (l_metadata_raid56_chunks > 0) { | ||
| r_metadata_used += r_metadata_raid56_chunks; | ||
| r_metadata_chunks += r_metadata_raid56_chunks; | ||
| l_metadata_chunks += l_metadata_raid56_chunks; | ||
| } | ||
|
|
||
| r_total_chunks = r_data_chunks + r_system_chunks; | ||
| r_total_used = r_data_used + r_system_used; | ||
| if (!mixed) { | ||
| @@ -26,6 +26,7 @@ | ||
| #include <ftw.h> | ||
| #include <mntent.h> | ||
| #include <linux/limits.h> | ||
| #include <linux/version.h> | ||
| #include <getopt.h> | ||
|
|
||
| #include <btrfsutil.h> | ||
| @@ -39,12 +40,14 @@ | ||
| #include "list_sort.h" | ||
| #include "disk-io.h" | ||
| #include "help.h" | ||
| #include "fsfeatures.h" | ||
|
|
||
| /* | ||
| * for btrfs fi show, we maintain a hash of fsids we've already printed. | ||
| * This way we don't print dups if a given FS is mounted more than once. | ||
| */ | ||
| static struct seen_fsid *seen_fsid_hash[SEEN_FSID_HASH_SIZE] = {NULL,}; | ||
| static mode_t defrag_open_mode = O_RDONLY; | ||
|
|
||
| static const char * const filesystem_cmd_group_usage[] = { | ||
| "btrfs filesystem [<group>] <command> [<args>]", | ||
| @@ -880,7 +883,7 @@ static int defrag_callback(const char *fpath, const struct stat *sb, | ||
| if ((typeflag == FTW_F) && S_ISREG(sb->st_mode)) { | ||
| if (defrag_global_verbose) | ||
| printf("%s\n", fpath); | ||
| fd = open(fpath, O_RDWR); | ||
| fd = open(fpath, defrag_open_mode); | ||
| if (fd < 0) { | ||
| goto error; | ||
| } | ||
| @@ -917,6 +920,13 @@ static int cmd_filesystem_defrag(int argc, char **argv) | ||
| int compress_type = BTRFS_COMPRESS_NONE; | ||
| DIR *dirstream; | ||
|
|
||
| /* | ||
| * Kernel 4.19+ supports defragmention of files open read-only, | ||
| * otherwise it's an ETXTBSY error | ||
| */ | ||
| if (get_running_kernel_version() < KERNEL_VERSION(4,19,0)) | ||
| defrag_open_mode = O_RDWR; | ||
|
|
||
| /* | ||
| * Kernel has a different default (256K) that is supposed to be safe, | ||
| * but it does not defragment very well. The 32M will likely lead to | ||
| @@ -1017,7 +1027,7 @@ static int cmd_filesystem_defrag(int argc, char **argv) | ||
| int defrag_err = 0; | ||
|
|
||
| dirstream = NULL; | ||
| fd = open_file_or_dir(argv[i], &dirstream); | ||
| fd = open_file_or_dir3(argv[i], &dirstream, defrag_open_mode); | ||
| if (fd < 0) { | ||
| error("cannot open %s: %m", argv[i]); | ||
| ret = -errno; | ||
Oops, something went wrong.