diff options
Diffstat (limited to 'fs/ocfs2/alloc.c')
| -rw-r--r-- | fs/ocfs2/alloc.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 48aa9c7401c7..ed553c60de82 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
| 30 | #include <linux/swap.h> | 30 | #include <linux/swap.h> |
| 31 | #include <linux/quotaops.h> | 31 | #include <linux/quotaops.h> |
| 32 | #include <linux/blkdev.h> | ||
| 32 | 33 | ||
| 33 | #include <cluster/masklog.h> | 34 | #include <cluster/masklog.h> |
| 34 | 35 | ||
| @@ -7184,3 +7185,168 @@ out_commit: | |||
| 7184 | out: | 7185 | out: |
| 7185 | return ret; | 7186 | return ret; |
| 7186 | } | 7187 | } |
| 7188 | |||
| 7189 | static int ocfs2_trim_extent(struct super_block *sb, | ||
| 7190 | struct ocfs2_group_desc *gd, | ||
| 7191 | u32 start, u32 count) | ||
| 7192 | { | ||
| 7193 | u64 discard, bcount; | ||
| 7194 | |||
| 7195 | bcount = ocfs2_clusters_to_blocks(sb, count); | ||
| 7196 | discard = le64_to_cpu(gd->bg_blkno) + | ||
| 7197 | ocfs2_clusters_to_blocks(sb, start); | ||
| 7198 | |||
| 7199 | trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); | ||
| 7200 | |||
| 7201 | return sb_issue_discard(sb, discard, bcount, GFP_NOFS, 0); | ||
| 7202 | } | ||
| 7203 | |||
| 7204 | static int ocfs2_trim_group(struct super_block *sb, | ||
| 7205 | struct ocfs2_group_desc *gd, | ||
| 7206 | u32 start, u32 max, u32 minbits) | ||
| 7207 | { | ||
| 7208 | int ret = 0, count = 0, next; | ||
| 7209 | void *bitmap = gd->bg_bitmap; | ||
| 7210 | |||
| 7211 | if (le16_to_cpu(gd->bg_free_bits_count) < minbits) | ||
| 7212 | return 0; | ||
| 7213 | |||
| 7214 | trace_ocfs2_trim_group((unsigned long long)le64_to_cpu(gd->bg_blkno), | ||
| 7215 | start, max, minbits); | ||
| 7216 | |||
| 7217 | while (start < max) { | ||
| 7218 | start = ocfs2_find_next_zero_bit(bitmap, max, start); | ||
| 7219 | if (start >= max) | ||
| 7220 | break; | ||
| 7221 | next = ocfs2_find_next_bit(bitmap, max, start); | ||
| 7222 | |||
| 7223 | if ((next - start) >= minbits) { | ||
| 7224 | ret = ocfs2_trim_extent(sb, gd, | ||
| 7225 | start, next - start); | ||
| 7226 | if (ret < 0) { | ||
| 7227 | mlog_errno(ret); | ||
| 7228 | break; | ||
| 7229 | } | ||
| 7230 | count += next - start; | ||
| 7231 | } | ||
| 7232 | start = next + 1; | ||
| 7233 | |||
| 7234 | if (fatal_signal_pending(current)) { | ||
| 7235 | count = -ERESTARTSYS; | ||
| 7236 | break; | ||
| 7237 | } | ||
| 7238 | |||
| 7239 | if ((le16_to_cpu(gd->bg_free_bits_count) - count) < minbits) | ||
| 7240 | break; | ||
| 7241 | } | ||
| 7242 | |||
| 7243 | if (ret < 0) | ||
| 7244 | count = ret; | ||
| 7245 | |||
| 7246 | return count; | ||
| 7247 | } | ||
| 7248 | |||
| 7249 | int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range) | ||
| 7250 | { | ||
| 7251 | struct ocfs2_super *osb = OCFS2_SB(sb); | ||
| 7252 | u64 start, len, trimmed, first_group, last_group, group; | ||
| 7253 | int ret, cnt; | ||
| 7254 | u32 first_bit, last_bit, minlen; | ||
| 7255 | struct buffer_head *main_bm_bh = NULL; | ||
| 7256 | struct inode *main_bm_inode = NULL; | ||
| 7257 | struct buffer_head *gd_bh = NULL; | ||
| 7258 | struct ocfs2_dinode *main_bm; | ||
| 7259 | struct ocfs2_group_desc *gd = NULL; | ||
| 7260 | |||
| 7261 | start = range->start >> osb->s_clustersize_bits; | ||
| 7262 | len = range->len >> osb->s_clustersize_bits; | ||
| 7263 | minlen = range->minlen >> osb->s_clustersize_bits; | ||
| 7264 | trimmed = 0; | ||
| 7265 | |||
| 7266 | if (!len) { | ||
| 7267 | range->len = 0; | ||
| 7268 | return 0; | ||
| 7269 | } | ||
| 7270 | |||
| 7271 | if (minlen >= osb->bitmap_cpg) | ||
| 7272 | return -EINVAL; | ||
| 7273 | |||
| 7274 | main_bm_inode = ocfs2_get_system_file_inode(osb, | ||
| 7275 | GLOBAL_BITMAP_SYSTEM_INODE, | ||
| 7276 | OCFS2_INVALID_SLOT); | ||
| 7277 | if (!main_bm_inode) { | ||
| 7278 | ret = -EIO; | ||
| 7279 | mlog_errno(ret); | ||
| 7280 | goto out; | ||
| 7281 | } | ||
| 7282 | |||
| 7283 | mutex_lock(&main_bm_inode->i_mutex); | ||
| 7284 | |||
| 7285 | ret = ocfs2_inode_lock(main_bm_inode, &main_bm_bh, 0); | ||
| 7286 | if (ret < 0) { | ||
| 7287 | mlog_errno(ret); | ||
| 7288 | goto out_mutex; | ||
| 7289 | } | ||
| 7290 | main_bm = (struct ocfs2_dinode *)main_bm_bh->b_data; | ||
| 7291 | |||
| 7292 | if (start >= le32_to_cpu(main_bm->i_clusters)) { | ||
| 7293 | ret = -EINVAL; | ||
| 7294 | goto out_unlock; | ||
| 7295 | } | ||
| 7296 | |||
| 7297 | if (start + len > le32_to_cpu(main_bm->i_clusters)) | ||
| 7298 | len = le32_to_cpu(main_bm->i_clusters) - start; | ||
| 7299 | |||
| 7300 | trace_ocfs2_trim_fs(start, len, minlen); | ||
| 7301 | |||
| 7302 | /* Determine first and last group to examine based on start and len */ | ||
| 7303 | first_group = ocfs2_which_cluster_group(main_bm_inode, start); | ||
| 7304 | if (first_group == osb->first_cluster_group_blkno) | ||
| 7305 | first_bit = start; | ||
| 7306 | else | ||
| 7307 | first_bit = start - ocfs2_blocks_to_clusters(sb, first_group); | ||
| 7308 | last_group = ocfs2_which_cluster_group(main_bm_inode, start + len - 1); | ||
| 7309 | last_bit = osb->bitmap_cpg; | ||
| 7310 | |||
| 7311 | for (group = first_group; group <= last_group;) { | ||
| 7312 | if (first_bit + len >= osb->bitmap_cpg) | ||
| 7313 | last_bit = osb->bitmap_cpg; | ||
| 7314 | else | ||
| 7315 | last_bit = first_bit + len; | ||
| 7316 | |||
| 7317 | ret = ocfs2_read_group_descriptor(main_bm_inode, | ||
| 7318 | main_bm, group, | ||
| 7319 | &gd_bh); | ||
| 7320 | if (ret < 0) { | ||
| 7321 | mlog_errno(ret); | ||
| 7322 | break; | ||
| 7323 | } | ||
| 7324 | |||
| 7325 | gd = (struct ocfs2_group_desc *)gd_bh->b_data; | ||
| 7326 | cnt = ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); | ||
| 7327 | brelse(gd_bh); | ||
| 7328 | gd_bh = NULL; | ||
| 7329 | if (cnt < 0) { | ||
| 7330 | ret = cnt; | ||
| 7331 | mlog_errno(ret); | ||
| 7332 | break; | ||
| 7333 | } | ||
| 7334 | |||
| 7335 | trimmed += cnt; | ||
| 7336 | len -= osb->bitmap_cpg - first_bit; | ||
| 7337 | first_bit = 0; | ||
| 7338 | if (group == osb->first_cluster_group_blkno) | ||
| 7339 | group = ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); | ||
| 7340 | else | ||
| 7341 | group += ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); | ||
| 7342 | } | ||
| 7343 | range->len = trimmed * sb->s_blocksize; | ||
| 7344 | out_unlock: | ||
| 7345 | ocfs2_inode_unlock(main_bm_inode, 0); | ||
| 7346 | brelse(main_bm_bh); | ||
| 7347 | out_mutex: | ||
| 7348 | mutex_unlock(&main_bm_inode->i_mutex); | ||
| 7349 | iput(main_bm_inode); | ||
| 7350 | out: | ||
| 7351 | return ret; | ||
| 7352 | } | ||
