.. | .. |
---|
| 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 | * File open, close, extend, truncate |
---|
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/capability.h> |
---|
.. | .. |
---|
208 | 194 | needs_barrier = true; |
---|
209 | 195 | err = jbd2_complete_transaction(journal, commit_tid); |
---|
210 | 196 | if (needs_barrier) { |
---|
211 | | - ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); |
---|
| 197 | + ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL); |
---|
212 | 198 | if (!err) |
---|
213 | 199 | err = ret; |
---|
214 | 200 | } |
---|
.. | .. |
---|
724 | 710 | * Thus, we need to explicitly order the zeroed pages. |
---|
725 | 711 | */ |
---|
726 | 712 | static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode, |
---|
727 | | - struct buffer_head *di_bh) |
---|
| 713 | + struct buffer_head *di_bh, |
---|
| 714 | + loff_t start_byte, |
---|
| 715 | + loff_t length) |
---|
728 | 716 | { |
---|
729 | 717 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
---|
730 | 718 | handle_t *handle = NULL; |
---|
.. | .. |
---|
740 | 728 | goto out; |
---|
741 | 729 | } |
---|
742 | 730 | |
---|
743 | | - ret = ocfs2_jbd2_file_inode(handle, inode); |
---|
| 731 | + ret = ocfs2_jbd2_inode_add_write(handle, inode, start_byte, length); |
---|
744 | 732 | if (ret < 0) { |
---|
745 | 733 | mlog_errno(ret); |
---|
746 | 734 | goto out; |
---|
.. | .. |
---|
779 | 767 | BUG_ON(abs_to > (((u64)index + 1) << PAGE_SHIFT)); |
---|
780 | 768 | BUG_ON(abs_from & (inode->i_blkbits - 1)); |
---|
781 | 769 | |
---|
782 | | - handle = ocfs2_zero_start_ordered_transaction(inode, di_bh); |
---|
| 770 | + handle = ocfs2_zero_start_ordered_transaction(inode, di_bh, |
---|
| 771 | + abs_from, |
---|
| 772 | + abs_to - abs_from); |
---|
783 | 773 | if (IS_ERR(handle)) { |
---|
784 | 774 | ret = PTR_ERR(handle); |
---|
785 | 775 | goto out; |
---|
.. | .. |
---|
1244 | 1234 | transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid)); |
---|
1245 | 1235 | if (IS_ERR(transfer_to[USRQUOTA])) { |
---|
1246 | 1236 | status = PTR_ERR(transfer_to[USRQUOTA]); |
---|
| 1237 | + transfer_to[USRQUOTA] = NULL; |
---|
1247 | 1238 | goto bail_unlock; |
---|
1248 | 1239 | } |
---|
1249 | 1240 | } |
---|
.. | .. |
---|
1253 | 1244 | transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid)); |
---|
1254 | 1245 | if (IS_ERR(transfer_to[GRPQUOTA])) { |
---|
1255 | 1246 | status = PTR_ERR(transfer_to[GRPQUOTA]); |
---|
| 1247 | + transfer_to[GRPQUOTA] = NULL; |
---|
1256 | 1248 | goto bail_unlock; |
---|
1257 | 1249 | } |
---|
1258 | 1250 | } |
---|
.. | .. |
---|
2002 | 1994 | } |
---|
2003 | 1995 | } |
---|
2004 | 1996 | |
---|
2005 | | - if (file && should_remove_suid(file->f_path.dentry)) { |
---|
| 1997 | + if (file && setattr_should_drop_suidgid(file_inode(file))) { |
---|
2006 | 1998 | ret = __ocfs2_write_remove_suid(inode, di_bh); |
---|
2007 | 1999 | if (ret) { |
---|
2008 | 2000 | mlog_errno(ret); |
---|
.. | .. |
---|
2111 | 2103 | struct ocfs2_space_resv sr; |
---|
2112 | 2104 | int change_size = 1; |
---|
2113 | 2105 | int cmd = OCFS2_IOC_RESVSP64; |
---|
| 2106 | + int ret = 0; |
---|
2114 | 2107 | |
---|
2115 | 2108 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) |
---|
2116 | 2109 | return -EOPNOTSUPP; |
---|
2117 | 2110 | if (!ocfs2_writes_unwritten_extents(osb)) |
---|
2118 | 2111 | return -EOPNOTSUPP; |
---|
2119 | 2112 | |
---|
2120 | | - if (mode & FALLOC_FL_KEEP_SIZE) |
---|
| 2113 | + if (mode & FALLOC_FL_KEEP_SIZE) { |
---|
2121 | 2114 | change_size = 0; |
---|
| 2115 | + } else { |
---|
| 2116 | + ret = inode_newsize_ok(inode, offset + len); |
---|
| 2117 | + if (ret) |
---|
| 2118 | + return ret; |
---|
| 2119 | + } |
---|
2122 | 2120 | |
---|
2123 | 2121 | if (mode & FALLOC_FL_PUNCH_HOLE) |
---|
2124 | 2122 | cmd = OCFS2_IOC_UNRESVSP64; |
---|
.. | .. |
---|
2247 | 2245 | struct dentry *dentry = file->f_path.dentry; |
---|
2248 | 2246 | struct inode *inode = d_inode(dentry); |
---|
2249 | 2247 | struct buffer_head *di_bh = NULL; |
---|
2250 | | - loff_t end; |
---|
2251 | 2248 | u32 cpos; |
---|
2252 | 2249 | u32 clusters; |
---|
2253 | 2250 | |
---|
.. | .. |
---|
2291 | 2288 | * inode. There's also the dinode i_size state which |
---|
2292 | 2289 | * can be lost via setattr during extending writes (we |
---|
2293 | 2290 | * set inode->i_size at the end of a write. */ |
---|
2294 | | - if (should_remove_suid(dentry)) { |
---|
| 2291 | + if (setattr_should_drop_suidgid(inode)) { |
---|
2295 | 2292 | if (meta_level == 0) { |
---|
2296 | 2293 | ocfs2_inode_unlock_for_extent_tree(inode, |
---|
2297 | 2294 | &di_bh, |
---|
.. | .. |
---|
2307 | 2304 | goto out_unlock; |
---|
2308 | 2305 | } |
---|
2309 | 2306 | } |
---|
2310 | | - |
---|
2311 | | - end = pos + count; |
---|
2312 | 2307 | |
---|
2313 | 2308 | ret = ocfs2_check_range_for_refcount(inode, pos, count); |
---|
2314 | 2309 | if (ret == 1) { |
---|
.. | .. |
---|
2645 | 2640 | return offset; |
---|
2646 | 2641 | } |
---|
2647 | 2642 | |
---|
2648 | | -static int ocfs2_file_clone_range(struct file *file_in, |
---|
2649 | | - loff_t pos_in, |
---|
2650 | | - struct file *file_out, |
---|
2651 | | - loff_t pos_out, |
---|
2652 | | - u64 len) |
---|
| 2643 | +static loff_t ocfs2_remap_file_range(struct file *file_in, loff_t pos_in, |
---|
| 2644 | + struct file *file_out, loff_t pos_out, |
---|
| 2645 | + loff_t len, unsigned int remap_flags) |
---|
2653 | 2646 | { |
---|
2654 | | - return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, |
---|
2655 | | - len, false); |
---|
2656 | | -} |
---|
| 2647 | + struct inode *inode_in = file_inode(file_in); |
---|
| 2648 | + struct inode *inode_out = file_inode(file_out); |
---|
| 2649 | + struct ocfs2_super *osb = OCFS2_SB(inode_in->i_sb); |
---|
| 2650 | + struct buffer_head *in_bh = NULL, *out_bh = NULL; |
---|
| 2651 | + bool same_inode = (inode_in == inode_out); |
---|
| 2652 | + loff_t remapped = 0; |
---|
| 2653 | + ssize_t ret; |
---|
2657 | 2654 | |
---|
2658 | | -static int ocfs2_file_dedupe_range(struct file *file_in, |
---|
2659 | | - loff_t pos_in, |
---|
2660 | | - struct file *file_out, |
---|
2661 | | - loff_t pos_out, |
---|
2662 | | - u64 len) |
---|
2663 | | -{ |
---|
2664 | | - return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, |
---|
2665 | | - len, true); |
---|
| 2655 | + if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) |
---|
| 2656 | + return -EINVAL; |
---|
| 2657 | + if (!ocfs2_refcount_tree(osb)) |
---|
| 2658 | + return -EOPNOTSUPP; |
---|
| 2659 | + if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) |
---|
| 2660 | + return -EROFS; |
---|
| 2661 | + |
---|
| 2662 | + /* Lock both files against IO */ |
---|
| 2663 | + ret = ocfs2_reflink_inodes_lock(inode_in, &in_bh, inode_out, &out_bh); |
---|
| 2664 | + if (ret) |
---|
| 2665 | + return ret; |
---|
| 2666 | + |
---|
| 2667 | + /* Check file eligibility and prepare for block sharing. */ |
---|
| 2668 | + ret = -EINVAL; |
---|
| 2669 | + if ((OCFS2_I(inode_in)->ip_flags & OCFS2_INODE_SYSTEM_FILE) || |
---|
| 2670 | + (OCFS2_I(inode_out)->ip_flags & OCFS2_INODE_SYSTEM_FILE)) |
---|
| 2671 | + goto out_unlock; |
---|
| 2672 | + |
---|
| 2673 | + ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, |
---|
| 2674 | + &len, remap_flags); |
---|
| 2675 | + if (ret < 0 || len == 0) |
---|
| 2676 | + goto out_unlock; |
---|
| 2677 | + |
---|
| 2678 | + /* Lock out changes to the allocation maps and remap. */ |
---|
| 2679 | + down_write(&OCFS2_I(inode_in)->ip_alloc_sem); |
---|
| 2680 | + if (!same_inode) |
---|
| 2681 | + down_write_nested(&OCFS2_I(inode_out)->ip_alloc_sem, |
---|
| 2682 | + SINGLE_DEPTH_NESTING); |
---|
| 2683 | + |
---|
| 2684 | + /* Zap any page cache for the destination file's range. */ |
---|
| 2685 | + truncate_inode_pages_range(&inode_out->i_data, |
---|
| 2686 | + round_down(pos_out, PAGE_SIZE), |
---|
| 2687 | + round_up(pos_out + len, PAGE_SIZE) - 1); |
---|
| 2688 | + |
---|
| 2689 | + remapped = ocfs2_reflink_remap_blocks(inode_in, in_bh, pos_in, |
---|
| 2690 | + inode_out, out_bh, pos_out, len); |
---|
| 2691 | + up_write(&OCFS2_I(inode_in)->ip_alloc_sem); |
---|
| 2692 | + if (!same_inode) |
---|
| 2693 | + up_write(&OCFS2_I(inode_out)->ip_alloc_sem); |
---|
| 2694 | + if (remapped < 0) { |
---|
| 2695 | + ret = remapped; |
---|
| 2696 | + mlog_errno(ret); |
---|
| 2697 | + goto out_unlock; |
---|
| 2698 | + } |
---|
| 2699 | + |
---|
| 2700 | + /* |
---|
| 2701 | + * Empty the extent map so that we may get the right extent |
---|
| 2702 | + * record from the disk. |
---|
| 2703 | + */ |
---|
| 2704 | + ocfs2_extent_map_trunc(inode_in, 0); |
---|
| 2705 | + ocfs2_extent_map_trunc(inode_out, 0); |
---|
| 2706 | + |
---|
| 2707 | + ret = ocfs2_reflink_update_dest(inode_out, out_bh, pos_out + len); |
---|
| 2708 | + if (ret) { |
---|
| 2709 | + mlog_errno(ret); |
---|
| 2710 | + goto out_unlock; |
---|
| 2711 | + } |
---|
| 2712 | + |
---|
| 2713 | +out_unlock: |
---|
| 2714 | + ocfs2_reflink_inodes_unlock(inode_in, in_bh, inode_out, out_bh); |
---|
| 2715 | + return remapped > 0 ? remapped : ret; |
---|
2666 | 2716 | } |
---|
2667 | 2717 | |
---|
2668 | 2718 | const struct inode_operations ocfs2_file_iops = { |
---|
.. | .. |
---|
2704 | 2754 | .splice_read = generic_file_splice_read, |
---|
2705 | 2755 | .splice_write = iter_file_splice_write, |
---|
2706 | 2756 | .fallocate = ocfs2_fallocate, |
---|
2707 | | - .clone_file_range = ocfs2_file_clone_range, |
---|
2708 | | - .dedupe_file_range = ocfs2_file_dedupe_range, |
---|
| 2757 | + .remap_file_range = ocfs2_remap_file_range, |
---|
2709 | 2758 | }; |
---|
2710 | 2759 | |
---|
2711 | 2760 | const struct file_operations ocfs2_dops = { |
---|
.. | .. |
---|
2751 | 2800 | .splice_read = generic_file_splice_read, |
---|
2752 | 2801 | .splice_write = iter_file_splice_write, |
---|
2753 | 2802 | .fallocate = ocfs2_fallocate, |
---|
2754 | | - .clone_file_range = ocfs2_file_clone_range, |
---|
2755 | | - .dedupe_file_range = ocfs2_file_dedupe_range, |
---|
| 2803 | + .remap_file_range = ocfs2_remap_file_range, |
---|
2756 | 2804 | }; |
---|
2757 | 2805 | |
---|
2758 | 2806 | const struct file_operations ocfs2_dops_no_plocks = { |
---|