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 | } | ||