diff options
author | David Sterba <dsterba@suse.cz> | 2011-10-24 08:47:58 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2011-10-24 08:47:58 -0400 |
commit | a81d3b1ba2f5faae28ba7a092c7598673fa02ac2 (patch) | |
tree | 8301fefcd9f3d45be9d0030456a86bca5b9ff061 /fs/btrfs/ioctl.c | |
parent | afd582ac8f10382002a72b4d17d9c2db328ed8b8 (diff) | |
parent | f9d9ef62cd3ecbd6cbb7957a253c1e81f69d5586 (diff) |
Merge branch 'hotfixes-20111024/josef/for-chris' into btrfs-next-stable
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 877727b28d88..33aae13cc74b 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -282,6 +282,7 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
282 | struct fstrim_range range; | 282 | struct fstrim_range range; |
283 | u64 minlen = ULLONG_MAX; | 283 | u64 minlen = ULLONG_MAX; |
284 | u64 num_devices = 0; | 284 | u64 num_devices = 0; |
285 | u64 total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
285 | int ret; | 286 | int ret; |
286 | 287 | ||
287 | if (!capable(CAP_SYS_ADMIN)) | 288 | if (!capable(CAP_SYS_ADMIN)) |
@@ -300,12 +301,15 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
300 | } | 301 | } |
301 | } | 302 | } |
302 | rcu_read_unlock(); | 303 | rcu_read_unlock(); |
304 | |||
303 | if (!num_devices) | 305 | if (!num_devices) |
304 | return -EOPNOTSUPP; | 306 | return -EOPNOTSUPP; |
305 | |||
306 | if (copy_from_user(&range, arg, sizeof(range))) | 307 | if (copy_from_user(&range, arg, sizeof(range))) |
307 | return -EFAULT; | 308 | return -EFAULT; |
309 | if (range.start > total_bytes) | ||
310 | return -EINVAL; | ||
308 | 311 | ||
312 | range.len = min(range.len, total_bytes - range.start); | ||
309 | range.minlen = max(range.minlen, minlen); | 313 | range.minlen = max(range.minlen, minlen); |
310 | ret = btrfs_trim_fs(root, &range); | 314 | ret = btrfs_trim_fs(root, &range); |
311 | if (ret < 0) | 315 | if (ret < 0) |
@@ -765,7 +769,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
765 | int ret = 1; | 769 | int ret = 1; |
766 | 770 | ||
767 | /* | 771 | /* |
768 | * make sure that once we start defragging and extent, we keep on | 772 | * make sure that once we start defragging an extent, we keep on |
769 | * defragging it | 773 | * defragging it |
770 | */ | 774 | */ |
771 | if (start < *defrag_end) | 775 | if (start < *defrag_end) |
@@ -810,7 +814,6 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
810 | * extent will force at least part of that big extent to be defragged. | 814 | * extent will force at least part of that big extent to be defragged. |
811 | */ | 815 | */ |
812 | if (ret) { | 816 | if (ret) { |
813 | *last_len += len; | ||
814 | *defrag_end = extent_map_end(em); | 817 | *defrag_end = extent_map_end(em); |
815 | } else { | 818 | } else { |
816 | *last_len = 0; | 819 | *last_len = 0; |
@@ -978,18 +981,20 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
978 | struct btrfs_super_block *disk_super; | 981 | struct btrfs_super_block *disk_super; |
979 | struct file_ra_state *ra = NULL; | 982 | struct file_ra_state *ra = NULL; |
980 | unsigned long last_index; | 983 | unsigned long last_index; |
984 | u64 isize = i_size_read(inode); | ||
981 | u64 features; | 985 | u64 features; |
982 | u64 last_len = 0; | 986 | u64 last_len = 0; |
983 | u64 skip = 0; | 987 | u64 skip = 0; |
984 | u64 defrag_end = 0; | 988 | u64 defrag_end = 0; |
985 | u64 newer_off = range->start; | 989 | u64 newer_off = range->start; |
986 | int newer_left = 0; | ||
987 | unsigned long i; | 990 | unsigned long i; |
991 | unsigned long ra_index = 0; | ||
988 | int ret; | 992 | int ret; |
989 | int defrag_count = 0; | 993 | int defrag_count = 0; |
990 | int compress_type = BTRFS_COMPRESS_ZLIB; | 994 | int compress_type = BTRFS_COMPRESS_ZLIB; |
991 | int extent_thresh = range->extent_thresh; | 995 | int extent_thresh = range->extent_thresh; |
992 | int newer_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT; | 996 | int max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT; |
997 | int cluster = max_cluster; | ||
993 | u64 new_align = ~((u64)128 * 1024 - 1); | 998 | u64 new_align = ~((u64)128 * 1024 - 1); |
994 | struct page **pages = NULL; | 999 | struct page **pages = NULL; |
995 | 1000 | ||
@@ -1003,7 +1008,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1003 | compress_type = range->compress_type; | 1008 | compress_type = range->compress_type; |
1004 | } | 1009 | } |
1005 | 1010 | ||
1006 | if (inode->i_size == 0) | 1011 | if (isize == 0) |
1007 | return 0; | 1012 | return 0; |
1008 | 1013 | ||
1009 | /* | 1014 | /* |
@@ -1019,7 +1024,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1019 | ra = &file->f_ra; | 1024 | ra = &file->f_ra; |
1020 | } | 1025 | } |
1021 | 1026 | ||
1022 | pages = kmalloc(sizeof(struct page *) * newer_cluster, | 1027 | pages = kmalloc(sizeof(struct page *) * max_cluster, |
1023 | GFP_NOFS); | 1028 | GFP_NOFS); |
1024 | if (!pages) { | 1029 | if (!pages) { |
1025 | ret = -ENOMEM; | 1030 | ret = -ENOMEM; |
@@ -1028,10 +1033,10 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1028 | 1033 | ||
1029 | /* find the last page to defrag */ | 1034 | /* find the last page to defrag */ |
1030 | if (range->start + range->len > range->start) { | 1035 | if (range->start + range->len > range->start) { |
1031 | last_index = min_t(u64, inode->i_size - 1, | 1036 | last_index = min_t(u64, isize - 1, |
1032 | range->start + range->len - 1) >> PAGE_CACHE_SHIFT; | 1037 | range->start + range->len - 1) >> PAGE_CACHE_SHIFT; |
1033 | } else { | 1038 | } else { |
1034 | last_index = (inode->i_size - 1) >> PAGE_CACHE_SHIFT; | 1039 | last_index = (isize - 1) >> PAGE_CACHE_SHIFT; |
1035 | } | 1040 | } |
1036 | 1041 | ||
1037 | if (newer_than) { | 1042 | if (newer_than) { |
@@ -1044,14 +1049,13 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1044 | * the extents in the file evenly spaced | 1049 | * the extents in the file evenly spaced |
1045 | */ | 1050 | */ |
1046 | i = (newer_off & new_align) >> PAGE_CACHE_SHIFT; | 1051 | i = (newer_off & new_align) >> PAGE_CACHE_SHIFT; |
1047 | newer_left = newer_cluster; | ||
1048 | } else | 1052 | } else |
1049 | goto out_ra; | 1053 | goto out_ra; |
1050 | } else { | 1054 | } else { |
1051 | i = range->start >> PAGE_CACHE_SHIFT; | 1055 | i = range->start >> PAGE_CACHE_SHIFT; |
1052 | } | 1056 | } |
1053 | if (!max_to_defrag) | 1057 | if (!max_to_defrag) |
1054 | max_to_defrag = last_index - 1; | 1058 | max_to_defrag = last_index; |
1055 | 1059 | ||
1056 | /* | 1060 | /* |
1057 | * make writeback starts from i, so the defrag range can be | 1061 | * make writeback starts from i, so the defrag range can be |
@@ -1085,18 +1089,31 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1085 | i = max(i + 1, next); | 1089 | i = max(i + 1, next); |
1086 | continue; | 1090 | continue; |
1087 | } | 1091 | } |
1092 | |||
1093 | if (!newer_than) { | ||
1094 | cluster = (PAGE_CACHE_ALIGN(defrag_end) >> | ||
1095 | PAGE_CACHE_SHIFT) - i; | ||
1096 | cluster = min(cluster, max_cluster); | ||
1097 | } else { | ||
1098 | cluster = max_cluster; | ||
1099 | } | ||
1100 | |||
1088 | if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) | 1101 | if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) |
1089 | BTRFS_I(inode)->force_compress = compress_type; | 1102 | BTRFS_I(inode)->force_compress = compress_type; |
1090 | 1103 | ||
1091 | btrfs_force_ra(inode->i_mapping, ra, file, i, newer_cluster); | 1104 | if (i + cluster > ra_index) { |
1105 | ra_index = max(i, ra_index); | ||
1106 | btrfs_force_ra(inode->i_mapping, ra, file, ra_index, | ||
1107 | cluster); | ||
1108 | ra_index += max_cluster; | ||
1109 | } | ||
1092 | 1110 | ||
1093 | ret = cluster_pages_for_defrag(inode, pages, i, newer_cluster); | 1111 | ret = cluster_pages_for_defrag(inode, pages, i, cluster); |
1094 | if (ret < 0) | 1112 | if (ret < 0) |
1095 | goto out_ra; | 1113 | goto out_ra; |
1096 | 1114 | ||
1097 | defrag_count += ret; | 1115 | defrag_count += ret; |
1098 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret); | 1116 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret); |
1099 | i += ret; | ||
1100 | 1117 | ||
1101 | if (newer_than) { | 1118 | if (newer_than) { |
1102 | if (newer_off == (u64)-1) | 1119 | if (newer_off == (u64)-1) |
@@ -1111,12 +1128,17 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1111 | if (!ret) { | 1128 | if (!ret) { |
1112 | range->start = newer_off; | 1129 | range->start = newer_off; |
1113 | i = (newer_off & new_align) >> PAGE_CACHE_SHIFT; | 1130 | i = (newer_off & new_align) >> PAGE_CACHE_SHIFT; |
1114 | newer_left = newer_cluster; | ||
1115 | } else { | 1131 | } else { |
1116 | break; | 1132 | break; |
1117 | } | 1133 | } |
1118 | } else { | 1134 | } else { |
1119 | i++; | 1135 | if (ret > 0) { |
1136 | i += ret; | ||
1137 | last_len += ret << PAGE_CACHE_SHIFT; | ||
1138 | } else { | ||
1139 | i++; | ||
1140 | last_len = 0; | ||
1141 | } | ||
1120 | } | 1142 | } |
1121 | } | 1143 | } |
1122 | 1144 | ||
@@ -1149,9 +1171,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1149 | btrfs_set_super_incompat_flags(disk_super, features); | 1171 | btrfs_set_super_incompat_flags(disk_super, features); |
1150 | } | 1172 | } |
1151 | 1173 | ||
1152 | if (!file) | 1174 | ret = defrag_count; |
1153 | kfree(ra); | ||
1154 | return defrag_count; | ||
1155 | 1175 | ||
1156 | out_ra: | 1176 | out_ra: |
1157 | if (!file) | 1177 | if (!file) |