.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* -*- mode: c; c-basic-offset: 8; -*- |
---|
2 | 3 | * vim: noexpandtab sw=8 ts=8 sts=0: |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * Extent allocs and frees |
---|
7 | 8 | * |
---|
8 | 9 | * Copyright (C) 2002, 2004 Oracle. All rights reserved. |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or |
---|
11 | | - * modify it under the terms of the GNU General Public |
---|
12 | | - * License as published by the Free Software Foundation; either |
---|
13 | | - * version 2 of the License, or (at your option) any later version. |
---|
14 | | - * |
---|
15 | | - * This program is distributed in the hope that it will be useful, |
---|
16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
18 | | - * General Public License for more details. |
---|
19 | | - * |
---|
20 | | - * You should have received a copy of the GNU General Public |
---|
21 | | - * License along with this program; if not, write to the |
---|
22 | | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
23 | | - * Boston, MA 021110-1307, USA. |
---|
24 | 10 | */ |
---|
25 | 11 | |
---|
26 | 12 | #include <linux/fs.h> |
---|
.. | .. |
---|
1074 | 1060 | brelse(bhs[i]); |
---|
1075 | 1061 | bhs[i] = NULL; |
---|
1076 | 1062 | } |
---|
1077 | | - mlog_errno(status); |
---|
1078 | 1063 | } |
---|
1079 | 1064 | return status; |
---|
1080 | 1065 | } |
---|
.. | .. |
---|
2302 | 2287 | int ret = 0; |
---|
2303 | 2288 | int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits; |
---|
2304 | 2289 | |
---|
2305 | | - if (handle->h_buffer_credits < credits) |
---|
| 2290 | + if (jbd2_handle_buffer_credits(handle) < credits) |
---|
2306 | 2291 | ret = ocfs2_extend_trans(handle, |
---|
2307 | | - credits - handle->h_buffer_credits); |
---|
| 2292 | + credits - jbd2_handle_buffer_credits(handle)); |
---|
2308 | 2293 | |
---|
2309 | 2294 | return ret; |
---|
2310 | 2295 | } |
---|
.. | .. |
---|
2381 | 2366 | struct ocfs2_path *right_path, |
---|
2382 | 2367 | struct ocfs2_path **ret_left_path) |
---|
2383 | 2368 | { |
---|
2384 | | - int ret, start, orig_credits = handle->h_buffer_credits; |
---|
| 2369 | + int ret, start, orig_credits = jbd2_handle_buffer_credits(handle); |
---|
2385 | 2370 | u32 cpos; |
---|
2386 | 2371 | struct ocfs2_path *left_path = NULL; |
---|
2387 | 2372 | struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci); |
---|
.. | .. |
---|
3162 | 3147 | struct ocfs2_path *path, |
---|
3163 | 3148 | struct ocfs2_cached_dealloc_ctxt *dealloc) |
---|
3164 | 3149 | { |
---|
3165 | | - int ret, orig_credits = handle->h_buffer_credits; |
---|
| 3150 | + int ret, orig_credits = jbd2_handle_buffer_credits(handle); |
---|
3166 | 3151 | struct ocfs2_path *tmp_path = NULL, *restart_path = NULL; |
---|
3167 | 3152 | struct ocfs2_extent_block *eb; |
---|
3168 | 3153 | struct ocfs2_extent_list *el; |
---|
.. | .. |
---|
3400 | 3385 | right_path); |
---|
3401 | 3386 | |
---|
3402 | 3387 | ret = ocfs2_extend_rotate_transaction(handle, subtree_index, |
---|
3403 | | - handle->h_buffer_credits, |
---|
3404 | | - right_path); |
---|
| 3388 | + jbd2_handle_buffer_credits(handle), |
---|
| 3389 | + right_path); |
---|
3405 | 3390 | if (ret) { |
---|
3406 | 3391 | mlog_errno(ret); |
---|
3407 | 3392 | goto out; |
---|
.. | .. |
---|
3562 | 3547 | right_path); |
---|
3563 | 3548 | |
---|
3564 | 3549 | ret = ocfs2_extend_rotate_transaction(handle, subtree_index, |
---|
3565 | | - handle->h_buffer_credits, |
---|
3566 | | - left_path); |
---|
| 3550 | + jbd2_handle_buffer_credits(handle), |
---|
| 3551 | + left_path); |
---|
3567 | 3552 | if (ret) { |
---|
3568 | 3553 | mlog_errno(ret); |
---|
3569 | 3554 | goto out; |
---|
.. | .. |
---|
3637 | 3622 | le16_to_cpu(el->l_next_free_rec) == 1) { |
---|
3638 | 3623 | /* extend credit for ocfs2_remove_rightmost_path */ |
---|
3639 | 3624 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
3640 | | - handle->h_buffer_credits, |
---|
| 3625 | + jbd2_handle_buffer_credits(handle), |
---|
3641 | 3626 | right_path); |
---|
3642 | 3627 | if (ret) { |
---|
3643 | 3628 | mlog_errno(ret); |
---|
.. | .. |
---|
3683 | 3668 | if (ctxt->c_split_covers_rec && ctxt->c_has_empty_extent) { |
---|
3684 | 3669 | /* extend credit for ocfs2_remove_rightmost_path */ |
---|
3685 | 3670 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
3686 | | - handle->h_buffer_credits, |
---|
| 3671 | + jbd2_handle_buffer_credits(handle), |
---|
3687 | 3672 | path); |
---|
3688 | 3673 | if (ret) { |
---|
3689 | 3674 | mlog_errno(ret); |
---|
.. | .. |
---|
3739 | 3724 | |
---|
3740 | 3725 | /* extend credit for ocfs2_remove_rightmost_path */ |
---|
3741 | 3726 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
3742 | | - handle->h_buffer_credits, |
---|
| 3727 | + jbd2_handle_buffer_credits(handle), |
---|
3743 | 3728 | path); |
---|
3744 | 3729 | if (ret) { |
---|
3745 | 3730 | mlog_errno(ret); |
---|
.. | .. |
---|
3769 | 3754 | |
---|
3770 | 3755 | /* extend credit for ocfs2_remove_rightmost_path */ |
---|
3771 | 3756 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
3772 | | - handle->h_buffer_credits, |
---|
| 3757 | + jbd2_handle_buffer_credits(handle), |
---|
3773 | 3758 | path); |
---|
3774 | 3759 | if (ret) { |
---|
3775 | 3760 | mlog_errno(ret); |
---|
.. | .. |
---|
3813 | 3798 | if (ctxt->c_split_covers_rec) { |
---|
3814 | 3799 | /* extend credit for ocfs2_remove_rightmost_path */ |
---|
3815 | 3800 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
3816 | | - handle->h_buffer_credits, |
---|
| 3801 | + jbd2_handle_buffer_credits(handle), |
---|
3817 | 3802 | path); |
---|
3818 | 3803 | if (ret) { |
---|
3819 | 3804 | mlog_errno(ret); |
---|
.. | .. |
---|
3956 | 3941 | * above. |
---|
3957 | 3942 | * |
---|
3958 | 3943 | * This leaf needs to have space, either by the empty 1st |
---|
3959 | | - * extent record, or by virtue of an l_next_rec < l_count. |
---|
| 3944 | + * extent record, or by virtue of an l_next_free_rec < l_count. |
---|
3960 | 3945 | */ |
---|
3961 | 3946 | ocfs2_rotate_leaf(el, insert_rec); |
---|
3962 | 3947 | } |
---|
.. | .. |
---|
4722 | 4707 | struct ocfs2_alloc_context *meta_ac) |
---|
4723 | 4708 | { |
---|
4724 | 4709 | int status; |
---|
4725 | | - int uninitialized_var(free_records); |
---|
| 4710 | + int free_records; |
---|
4726 | 4711 | struct buffer_head *last_eb_bh = NULL; |
---|
4727 | 4712 | struct ocfs2_insert_type insert = {0, }; |
---|
4728 | 4713 | struct ocfs2_extent_rec rec; |
---|
.. | .. |
---|
5106 | 5091 | * rightmost extent list. |
---|
5107 | 5092 | */ |
---|
5108 | 5093 | if (path->p_tree_depth) { |
---|
5109 | | - struct ocfs2_extent_block *eb; |
---|
5110 | | - |
---|
5111 | 5094 | ret = ocfs2_read_extent_block(et->et_ci, |
---|
5112 | 5095 | ocfs2_et_get_last_eb_blk(et), |
---|
5113 | 5096 | &last_eb_bh); |
---|
.. | .. |
---|
5115 | 5098 | mlog_errno(ret); |
---|
5116 | 5099 | goto out; |
---|
5117 | 5100 | } |
---|
5118 | | - |
---|
5119 | | - eb = (struct ocfs2_extent_block *) last_eb_bh->b_data; |
---|
5120 | 5101 | } |
---|
5121 | 5102 | |
---|
5122 | 5103 | if (rec->e_cpos == split_rec->e_cpos && |
---|
.. | .. |
---|
5376 | 5357 | if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) { |
---|
5377 | 5358 | /* extend credit for ocfs2_remove_rightmost_path */ |
---|
5378 | 5359 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
5379 | | - handle->h_buffer_credits, |
---|
| 5360 | + jbd2_handle_buffer_credits(handle), |
---|
5380 | 5361 | path); |
---|
5381 | 5362 | if (ret) { |
---|
5382 | 5363 | mlog_errno(ret); |
---|
.. | .. |
---|
5445 | 5426 | } |
---|
5446 | 5427 | |
---|
5447 | 5428 | ret = ocfs2_extend_rotate_transaction(handle, 0, |
---|
5448 | | - handle->h_buffer_credits, |
---|
5449 | | - path); |
---|
| 5429 | + jbd2_handle_buffer_credits(handle), |
---|
| 5430 | + path); |
---|
5450 | 5431 | if (ret) { |
---|
5451 | 5432 | mlog_errno(ret); |
---|
5452 | 5433 | goto out; |
---|
.. | .. |
---|
6011 | 5992 | struct buffer_head *data_alloc_bh = NULL; |
---|
6012 | 5993 | struct ocfs2_dinode *di; |
---|
6013 | 5994 | struct ocfs2_truncate_log *tl; |
---|
| 5995 | + struct ocfs2_journal *journal = osb->journal; |
---|
6014 | 5996 | |
---|
6015 | 5997 | BUG_ON(inode_trylock(tl_inode)); |
---|
6016 | 5998 | |
---|
.. | .. |
---|
6028 | 6010 | num_to_flush); |
---|
6029 | 6011 | if (!num_to_flush) { |
---|
6030 | 6012 | status = 0; |
---|
| 6013 | + goto out; |
---|
| 6014 | + } |
---|
| 6015 | + |
---|
| 6016 | + /* Appending truncate log(TA) and flushing truncate log(TF) are |
---|
| 6017 | + * two separated transactions. They can be both committed but not |
---|
| 6018 | + * checkpointed. If crash occurs then, both two transaction will be |
---|
| 6019 | + * replayed with several already released to global bitmap clusters. |
---|
| 6020 | + * Then truncate log will be replayed resulting in cluster double free. |
---|
| 6021 | + */ |
---|
| 6022 | + jbd2_journal_lock_updates(journal->j_journal); |
---|
| 6023 | + status = jbd2_journal_flush(journal->j_journal); |
---|
| 6024 | + jbd2_journal_unlock_updates(journal->j_journal); |
---|
| 6025 | + if (status < 0) { |
---|
| 6026 | + mlog_errno(status); |
---|
6031 | 6027 | goto out; |
---|
6032 | 6028 | } |
---|
6033 | 6029 | |
---|
.. | .. |
---|
6209 | 6205 | if (le16_to_cpu(tl->tl_used)) { |
---|
6210 | 6206 | trace_ocfs2_truncate_log_recovery_num(le16_to_cpu(tl->tl_used)); |
---|
6211 | 6207 | |
---|
6212 | | - *tl_copy = kmalloc(tl_bh->b_size, GFP_KERNEL); |
---|
| 6208 | + /* |
---|
| 6209 | + * Assuming the write-out below goes well, this copy will be |
---|
| 6210 | + * passed back to recovery for processing. |
---|
| 6211 | + */ |
---|
| 6212 | + *tl_copy = kmemdup(tl_bh->b_data, tl_bh->b_size, GFP_KERNEL); |
---|
6213 | 6213 | if (!(*tl_copy)) { |
---|
6214 | 6214 | status = -ENOMEM; |
---|
6215 | 6215 | mlog_errno(status); |
---|
6216 | 6216 | goto bail; |
---|
6217 | 6217 | } |
---|
6218 | | - |
---|
6219 | | - /* Assuming the write-out below goes well, this copy |
---|
6220 | | - * will be passed back to recovery for processing. */ |
---|
6221 | | - memcpy(*tl_copy, tl_bh->b_data, tl_bh->b_size); |
---|
6222 | 6218 | |
---|
6223 | 6219 | /* All we need to do to clear the truncate log is set |
---|
6224 | 6220 | * tl_used. */ |
---|
.. | .. |
---|
6810 | 6806 | struct page *page, int zero, u64 *phys) |
---|
6811 | 6807 | { |
---|
6812 | 6808 | int ret, partial = 0; |
---|
| 6809 | + loff_t start_byte = ((loff_t)page->index << PAGE_SHIFT) + from; |
---|
| 6810 | + loff_t length = to - from; |
---|
6813 | 6811 | |
---|
6814 | 6812 | ret = ocfs2_map_page_blocks(page, phys, inode, from, to, 0); |
---|
6815 | 6813 | if (ret) |
---|
.. | .. |
---|
6829 | 6827 | if (ret < 0) |
---|
6830 | 6828 | mlog_errno(ret); |
---|
6831 | 6829 | else if (ocfs2_should_order_data(inode)) { |
---|
6832 | | - ret = ocfs2_jbd2_file_inode(handle, inode); |
---|
| 6830 | + ret = ocfs2_jbd2_inode_add_write(handle, inode, |
---|
| 6831 | + start_byte, length); |
---|
6833 | 6832 | if (ret < 0) |
---|
6834 | 6833 | mlog_errno(ret); |
---|
6835 | 6834 | } |
---|
.. | .. |
---|
7052 | 7051 | int need_free = 0; |
---|
7053 | 7052 | u32 bit_off, num; |
---|
7054 | 7053 | handle_t *handle; |
---|
7055 | | - u64 uninitialized_var(block); |
---|
| 7054 | + u64 block; |
---|
7056 | 7055 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
---|
7057 | 7056 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
---|
7058 | 7057 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
---|
.. | .. |
---|
7518 | 7517 | return count; |
---|
7519 | 7518 | } |
---|
7520 | 7519 | |
---|
7521 | | -int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range) |
---|
| 7520 | +static |
---|
| 7521 | +int ocfs2_trim_mainbm(struct super_block *sb, struct fstrim_range *range) |
---|
7522 | 7522 | { |
---|
7523 | 7523 | struct ocfs2_super *osb = OCFS2_SB(sb); |
---|
7524 | | - u64 start, len, trimmed, first_group, last_group, group; |
---|
| 7524 | + u64 start, len, trimmed = 0, first_group, last_group = 0, group = 0; |
---|
7525 | 7525 | int ret, cnt; |
---|
7526 | 7526 | u32 first_bit, last_bit, minlen; |
---|
7527 | 7527 | struct buffer_head *main_bm_bh = NULL; |
---|
.. | .. |
---|
7529 | 7529 | struct buffer_head *gd_bh = NULL; |
---|
7530 | 7530 | struct ocfs2_dinode *main_bm; |
---|
7531 | 7531 | struct ocfs2_group_desc *gd = NULL; |
---|
7532 | | - struct ocfs2_trim_fs_info info, *pinfo = NULL; |
---|
7533 | 7532 | |
---|
7534 | 7533 | start = range->start >> osb->s_clustersize_bits; |
---|
7535 | 7534 | len = range->len >> osb->s_clustersize_bits; |
---|
.. | .. |
---|
7538 | 7537 | if (minlen >= osb->bitmap_cpg || range->len < sb->s_blocksize) |
---|
7539 | 7538 | return -EINVAL; |
---|
7540 | 7539 | |
---|
| 7540 | + trace_ocfs2_trim_mainbm(start, len, minlen); |
---|
| 7541 | + |
---|
| 7542 | +next_group: |
---|
7541 | 7543 | main_bm_inode = ocfs2_get_system_file_inode(osb, |
---|
7542 | 7544 | GLOBAL_BITMAP_SYSTEM_INODE, |
---|
7543 | 7545 | OCFS2_INVALID_SLOT); |
---|
.. | .. |
---|
7556 | 7558 | } |
---|
7557 | 7559 | main_bm = (struct ocfs2_dinode *)main_bm_bh->b_data; |
---|
7558 | 7560 | |
---|
7559 | | - if (start >= le32_to_cpu(main_bm->i_clusters)) { |
---|
7560 | | - ret = -EINVAL; |
---|
7561 | | - goto out_unlock; |
---|
7562 | | - } |
---|
7563 | | - |
---|
7564 | | - len = range->len >> osb->s_clustersize_bits; |
---|
7565 | | - if (start + len > le32_to_cpu(main_bm->i_clusters)) |
---|
7566 | | - len = le32_to_cpu(main_bm->i_clusters) - start; |
---|
7567 | | - |
---|
7568 | | - trace_ocfs2_trim_fs(start, len, minlen); |
---|
7569 | | - |
---|
7570 | | - ocfs2_trim_fs_lock_res_init(osb); |
---|
7571 | | - ret = ocfs2_trim_fs_lock(osb, NULL, 1); |
---|
7572 | | - if (ret < 0) { |
---|
7573 | | - if (ret != -EAGAIN) { |
---|
7574 | | - mlog_errno(ret); |
---|
7575 | | - ocfs2_trim_fs_lock_res_uninit(osb); |
---|
| 7561 | + /* |
---|
| 7562 | + * Do some check before trim the first group. |
---|
| 7563 | + */ |
---|
| 7564 | + if (!group) { |
---|
| 7565 | + if (start >= le32_to_cpu(main_bm->i_clusters)) { |
---|
| 7566 | + ret = -EINVAL; |
---|
7576 | 7567 | goto out_unlock; |
---|
7577 | 7568 | } |
---|
7578 | 7569 | |
---|
7579 | | - mlog(ML_NOTICE, "Wait for trim on device (%s) to " |
---|
7580 | | - "finish, which is running from another node.\n", |
---|
7581 | | - osb->dev_str); |
---|
7582 | | - ret = ocfs2_trim_fs_lock(osb, &info, 0); |
---|
7583 | | - if (ret < 0) { |
---|
7584 | | - mlog_errno(ret); |
---|
7585 | | - ocfs2_trim_fs_lock_res_uninit(osb); |
---|
7586 | | - goto out_unlock; |
---|
7587 | | - } |
---|
| 7570 | + if (start + len > le32_to_cpu(main_bm->i_clusters)) |
---|
| 7571 | + len = le32_to_cpu(main_bm->i_clusters) - start; |
---|
7588 | 7572 | |
---|
7589 | | - if (info.tf_valid && info.tf_success && |
---|
7590 | | - info.tf_start == start && info.tf_len == len && |
---|
7591 | | - info.tf_minlen == minlen) { |
---|
7592 | | - /* Avoid sending duplicated trim to a shared device */ |
---|
7593 | | - mlog(ML_NOTICE, "The same trim on device (%s) was " |
---|
7594 | | - "just done from node (%u), return.\n", |
---|
7595 | | - osb->dev_str, info.tf_nodenum); |
---|
7596 | | - range->len = info.tf_trimlen; |
---|
7597 | | - goto out_trimunlock; |
---|
7598 | | - } |
---|
| 7573 | + /* |
---|
| 7574 | + * Determine first and last group to examine based on |
---|
| 7575 | + * start and len |
---|
| 7576 | + */ |
---|
| 7577 | + first_group = ocfs2_which_cluster_group(main_bm_inode, start); |
---|
| 7578 | + if (first_group == osb->first_cluster_group_blkno) |
---|
| 7579 | + first_bit = start; |
---|
| 7580 | + else |
---|
| 7581 | + first_bit = start - ocfs2_blocks_to_clusters(sb, |
---|
| 7582 | + first_group); |
---|
| 7583 | + last_group = ocfs2_which_cluster_group(main_bm_inode, |
---|
| 7584 | + start + len - 1); |
---|
| 7585 | + group = first_group; |
---|
7599 | 7586 | } |
---|
7600 | 7587 | |
---|
7601 | | - info.tf_nodenum = osb->node_num; |
---|
7602 | | - info.tf_start = start; |
---|
7603 | | - info.tf_len = len; |
---|
7604 | | - info.tf_minlen = minlen; |
---|
7605 | | - |
---|
7606 | | - /* Determine first and last group to examine based on start and len */ |
---|
7607 | | - first_group = ocfs2_which_cluster_group(main_bm_inode, start); |
---|
7608 | | - if (first_group == osb->first_cluster_group_blkno) |
---|
7609 | | - first_bit = start; |
---|
7610 | | - else |
---|
7611 | | - first_bit = start - ocfs2_blocks_to_clusters(sb, first_group); |
---|
7612 | | - last_group = ocfs2_which_cluster_group(main_bm_inode, start + len - 1); |
---|
7613 | | - last_bit = osb->bitmap_cpg; |
---|
7614 | | - |
---|
7615 | | - trimmed = 0; |
---|
7616 | | - for (group = first_group; group <= last_group;) { |
---|
| 7588 | + do { |
---|
7617 | 7589 | if (first_bit + len >= osb->bitmap_cpg) |
---|
7618 | 7590 | last_bit = osb->bitmap_cpg; |
---|
7619 | 7591 | else |
---|
.. | .. |
---|
7645 | 7617 | group = ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); |
---|
7646 | 7618 | else |
---|
7647 | 7619 | group += ocfs2_clusters_to_blocks(sb, osb->bitmap_cpg); |
---|
7648 | | - } |
---|
7649 | | - range->len = trimmed * sb->s_blocksize; |
---|
| 7620 | + } while (0); |
---|
7650 | 7621 | |
---|
7651 | | - info.tf_trimlen = range->len; |
---|
7652 | | - info.tf_success = (ret ? 0 : 1); |
---|
7653 | | - pinfo = &info; |
---|
7654 | | -out_trimunlock: |
---|
7655 | | - ocfs2_trim_fs_unlock(osb, pinfo); |
---|
7656 | | - ocfs2_trim_fs_lock_res_uninit(osb); |
---|
7657 | 7622 | out_unlock: |
---|
7658 | 7623 | ocfs2_inode_unlock(main_bm_inode, 0); |
---|
7659 | 7624 | brelse(main_bm_bh); |
---|
| 7625 | + main_bm_bh = NULL; |
---|
7660 | 7626 | out_mutex: |
---|
7661 | 7627 | inode_unlock(main_bm_inode); |
---|
7662 | 7628 | iput(main_bm_inode); |
---|
| 7629 | + |
---|
| 7630 | + /* |
---|
| 7631 | + * If all the groups trim are not done or failed, but we should release |
---|
| 7632 | + * main_bm related locks for avoiding the current IO starve, then go to |
---|
| 7633 | + * trim the next group |
---|
| 7634 | + */ |
---|
| 7635 | + if (ret >= 0 && group <= last_group) { |
---|
| 7636 | + cond_resched(); |
---|
| 7637 | + goto next_group; |
---|
| 7638 | + } |
---|
7663 | 7639 | out: |
---|
| 7640 | + range->len = trimmed * sb->s_blocksize; |
---|
| 7641 | + return ret; |
---|
| 7642 | +} |
---|
| 7643 | + |
---|
| 7644 | +int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range) |
---|
| 7645 | +{ |
---|
| 7646 | + int ret; |
---|
| 7647 | + struct ocfs2_super *osb = OCFS2_SB(sb); |
---|
| 7648 | + struct ocfs2_trim_fs_info info, *pinfo = NULL; |
---|
| 7649 | + |
---|
| 7650 | + ocfs2_trim_fs_lock_res_init(osb); |
---|
| 7651 | + |
---|
| 7652 | + trace_ocfs2_trim_fs(range->start, range->len, range->minlen); |
---|
| 7653 | + |
---|
| 7654 | + ret = ocfs2_trim_fs_lock(osb, NULL, 1); |
---|
| 7655 | + if (ret < 0) { |
---|
| 7656 | + if (ret != -EAGAIN) { |
---|
| 7657 | + mlog_errno(ret); |
---|
| 7658 | + ocfs2_trim_fs_lock_res_uninit(osb); |
---|
| 7659 | + return ret; |
---|
| 7660 | + } |
---|
| 7661 | + |
---|
| 7662 | + mlog(ML_NOTICE, "Wait for trim on device (%s) to " |
---|
| 7663 | + "finish, which is running from another node.\n", |
---|
| 7664 | + osb->dev_str); |
---|
| 7665 | + ret = ocfs2_trim_fs_lock(osb, &info, 0); |
---|
| 7666 | + if (ret < 0) { |
---|
| 7667 | + mlog_errno(ret); |
---|
| 7668 | + ocfs2_trim_fs_lock_res_uninit(osb); |
---|
| 7669 | + return ret; |
---|
| 7670 | + } |
---|
| 7671 | + |
---|
| 7672 | + if (info.tf_valid && info.tf_success && |
---|
| 7673 | + info.tf_start == range->start && |
---|
| 7674 | + info.tf_len == range->len && |
---|
| 7675 | + info.tf_minlen == range->minlen) { |
---|
| 7676 | + /* Avoid sending duplicated trim to a shared device */ |
---|
| 7677 | + mlog(ML_NOTICE, "The same trim on device (%s) was " |
---|
| 7678 | + "just done from node (%u), return.\n", |
---|
| 7679 | + osb->dev_str, info.tf_nodenum); |
---|
| 7680 | + range->len = info.tf_trimlen; |
---|
| 7681 | + goto out; |
---|
| 7682 | + } |
---|
| 7683 | + } |
---|
| 7684 | + |
---|
| 7685 | + info.tf_nodenum = osb->node_num; |
---|
| 7686 | + info.tf_start = range->start; |
---|
| 7687 | + info.tf_len = range->len; |
---|
| 7688 | + info.tf_minlen = range->minlen; |
---|
| 7689 | + |
---|
| 7690 | + ret = ocfs2_trim_mainbm(sb, range); |
---|
| 7691 | + |
---|
| 7692 | + info.tf_trimlen = range->len; |
---|
| 7693 | + info.tf_success = (ret < 0 ? 0 : 1); |
---|
| 7694 | + pinfo = &info; |
---|
| 7695 | +out: |
---|
| 7696 | + ocfs2_trim_fs_unlock(osb, pinfo); |
---|
| 7697 | + ocfs2_trim_fs_lock_res_uninit(osb); |
---|
7664 | 7698 | return ret; |
---|
7665 | 7699 | } |
---|