diff options
author | Dr. Tilmann Bubeck <t.bubeck@reinform.de> | 2013-04-08 12:54:05 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-04-08 12:54:05 -0400 |
commit | 393d1d1d76933886d5e1ce603214c9987589c6d5 (patch) | |
tree | 2f2368a9d787ccb8e69f61a3e5023ef9c4abfd8b /fs/ext4 | |
parent | f78ee70db40040e6f38a5134527d4760254d6683 (diff) |
ext4: implementation of a new ioctl called EXT4_IOC_SWAP_BOOT
Add a new ioctl, EXT4_IOC_SWAP_BOOT which swaps i_blocks and
associated attributes (like i_blocks, i_size, i_flags, ...) from the
specified inode with inode EXT4_BOOT_LOADER_INO (#5). This is
typically used to store a boot loader in a secure part of the
filesystem, where it can't be changed by a normal user by accident.
The data blocks of the previous boot loader will be associated with
the given inode.
This usercode program is a simple example of the usage:
int main(int argc, char *argv[])
{
int fd;
int err;
if ( argc != 2 ) {
printf("usage: ext4-swap-boot-inode FILE-TO-SWAP\n");
exit(1);
}
fd = open(argv[1], O_WRONLY);
if ( fd < 0 ) {
perror("open");
exit(1);
}
err = ioctl(fd, EXT4_IOC_SWAP_BOOT);
if ( err < 0 ) {
perror("ioctl");
exit(1);
}
close(fd);
exit(0);
}
[ Modified by Theodore Ts'o to fix a number of bugs in the original code.]
Signed-off-by: Dr. Tilmann Bubeck <t.bubeck@reinform.de>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 8 | ||||
-rw-r--r-- | fs/ext4/inode.c | 11 | ||||
-rw-r--r-- | fs/ext4/ioctl.c | 197 | ||||
-rw-r--r-- | fs/ext4/move_extent.c | 48 |
4 files changed, 238 insertions, 26 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index a0637e5057ae..d91871570982 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -616,6 +616,7 @@ enum { | |||
616 | #define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12) | 616 | #define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12) |
617 | #define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) | 617 | #define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) |
618 | #define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64) | 618 | #define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64) |
619 | #define EXT4_IOC_SWAP_BOOT _IO('f', 17) | ||
619 | 620 | ||
620 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) | 621 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) |
621 | /* | 622 | /* |
@@ -1341,6 +1342,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) | |||
1341 | return ino == EXT4_ROOT_INO || | 1342 | return ino == EXT4_ROOT_INO || |
1342 | ino == EXT4_USR_QUOTA_INO || | 1343 | ino == EXT4_USR_QUOTA_INO || |
1343 | ino == EXT4_GRP_QUOTA_INO || | 1344 | ino == EXT4_GRP_QUOTA_INO || |
1345 | ino == EXT4_BOOT_LOADER_INO || | ||
1344 | ino == EXT4_JOURNAL_INO || | 1346 | ino == EXT4_JOURNAL_INO || |
1345 | ino == EXT4_RESIZE_INO || | 1347 | ino == EXT4_RESIZE_INO || |
1346 | (ino >= EXT4_FIRST_INO(sb) && | 1348 | (ino >= EXT4_FIRST_INO(sb) && |
@@ -2624,6 +2626,12 @@ extern int ext4_ind_migrate(struct inode *inode); | |||
2624 | 2626 | ||
2625 | 2627 | ||
2626 | /* move_extent.c */ | 2628 | /* move_extent.c */ |
2629 | extern void ext4_double_down_write_data_sem(struct inode *first, | ||
2630 | struct inode *second); | ||
2631 | extern void ext4_double_up_write_data_sem(struct inode *orig_inode, | ||
2632 | struct inode *donor_inode); | ||
2633 | void ext4_inode_double_lock(struct inode *inode1, struct inode *inode2); | ||
2634 | void ext4_inode_double_unlock(struct inode *inode1, struct inode *inode2); | ||
2627 | extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, | 2635 | extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, |
2628 | __u64 start_orig, __u64 start_donor, | 2636 | __u64 start_orig, __u64 start_donor, |
2629 | __u64 len, __u64 *moved_len); | 2637 | __u64 len, __u64 *moved_len); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 769c656ea3b1..a29bfc2142ef 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4191,8 +4191,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4191 | * NeilBrown 1999oct15 | 4191 | * NeilBrown 1999oct15 |
4192 | */ | 4192 | */ |
4193 | if (inode->i_nlink == 0) { | 4193 | if (inode->i_nlink == 0) { |
4194 | if (inode->i_mode == 0 || | 4194 | if ((inode->i_mode == 0 || |
4195 | !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { | 4195 | !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) && |
4196 | ino != EXT4_BOOT_LOADER_INO) { | ||
4196 | /* this inode is deleted */ | 4197 | /* this inode is deleted */ |
4197 | ret = -ESTALE; | 4198 | ret = -ESTALE; |
4198 | goto bad_inode; | 4199 | goto bad_inode; |
@@ -4200,7 +4201,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4200 | /* The only unlinked inodes we let through here have | 4201 | /* The only unlinked inodes we let through here have |
4201 | * valid i_mode and are being read by the orphan | 4202 | * valid i_mode and are being read by the orphan |
4202 | * recovery code: that's fine, we're about to complete | 4203 | * recovery code: that's fine, we're about to complete |
4203 | * the process of deleting those. */ | 4204 | * the process of deleting those. |
4205 | * OR it is the EXT4_BOOT_LOADER_INO which is | ||
4206 | * not initialized on a new filesystem. */ | ||
4204 | } | 4207 | } |
4205 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); | 4208 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); |
4206 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); | 4209 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); |
@@ -4320,6 +4323,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4320 | else | 4323 | else |
4321 | init_special_inode(inode, inode->i_mode, | 4324 | init_special_inode(inode, inode->i_mode, |
4322 | new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); | 4325 | new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); |
4326 | } else if (ino == EXT4_BOOT_LOADER_INO) { | ||
4327 | make_bad_inode(inode); | ||
4323 | } else { | 4328 | } else { |
4324 | ret = -EIO; | 4329 | ret = -EIO; |
4325 | EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode); | 4330 | EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode); |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index a07b7bc0856a..cbc3acea6bcf 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -17,9 +17,201 @@ | |||
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include "ext4_jbd2.h" | 18 | #include "ext4_jbd2.h" |
19 | #include "ext4.h" | 19 | #include "ext4.h" |
20 | #include "ext4_extents.h" | ||
20 | 21 | ||
21 | #define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1) | 22 | #define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1) |
22 | 23 | ||
24 | /** | ||
25 | * Swap memory between @a and @b for @len bytes. | ||
26 | * | ||
27 | * @a: pointer to first memory area | ||
28 | * @b: pointer to second memory area | ||
29 | * @len: number of bytes to swap | ||
30 | * | ||
31 | */ | ||
32 | static void memswap(void *a, void *b, size_t len) | ||
33 | { | ||
34 | unsigned char *ap, *bp; | ||
35 | unsigned char tmp; | ||
36 | |||
37 | ap = (unsigned char *)a; | ||
38 | bp = (unsigned char *)b; | ||
39 | while (len-- > 0) { | ||
40 | tmp = *ap; | ||
41 | *ap = *bp; | ||
42 | *bp = tmp; | ||
43 | ap++; | ||
44 | bp++; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Swap i_data and associated attributes between @inode1 and @inode2. | ||
50 | * This function is used for the primary swap between inode1 and inode2 | ||
51 | * and also to revert this primary swap in case of errors. | ||
52 | * | ||
53 | * Therefore you have to make sure, that calling this method twice | ||
54 | * will revert all changes. | ||
55 | * | ||
56 | * @inode1: pointer to first inode | ||
57 | * @inode2: pointer to second inode | ||
58 | */ | ||
59 | static void swap_inode_data(struct inode *inode1, struct inode *inode2) | ||
60 | { | ||
61 | loff_t isize; | ||
62 | struct ext4_inode_info *ei1; | ||
63 | struct ext4_inode_info *ei2; | ||
64 | |||
65 | ei1 = EXT4_I(inode1); | ||
66 | ei2 = EXT4_I(inode2); | ||
67 | |||
68 | memswap(&inode1->i_flags, &inode2->i_flags, sizeof(inode1->i_flags)); | ||
69 | memswap(&inode1->i_version, &inode2->i_version, | ||
70 | sizeof(inode1->i_version)); | ||
71 | memswap(&inode1->i_blocks, &inode2->i_blocks, | ||
72 | sizeof(inode1->i_blocks)); | ||
73 | memswap(&inode1->i_bytes, &inode2->i_bytes, sizeof(inode1->i_bytes)); | ||
74 | memswap(&inode1->i_atime, &inode2->i_atime, sizeof(inode1->i_atime)); | ||
75 | memswap(&inode1->i_mtime, &inode2->i_mtime, sizeof(inode1->i_mtime)); | ||
76 | |||
77 | memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data)); | ||
78 | memswap(&ei1->i_flags, &ei2->i_flags, sizeof(ei1->i_flags)); | ||
79 | memswap(&ei1->i_disksize, &ei2->i_disksize, sizeof(ei1->i_disksize)); | ||
80 | memswap(&ei1->i_es_tree, &ei2->i_es_tree, sizeof(ei1->i_es_tree)); | ||
81 | memswap(&ei1->i_es_lru_nr, &ei2->i_es_lru_nr, sizeof(ei1->i_es_lru_nr)); | ||
82 | |||
83 | isize = i_size_read(inode1); | ||
84 | i_size_write(inode1, i_size_read(inode2)); | ||
85 | i_size_write(inode2, isize); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Swap the information from the given @inode and the inode | ||
90 | * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other | ||
91 | * important fields of the inodes. | ||
92 | * | ||
93 | * @sb: the super block of the filesystem | ||
94 | * @inode: the inode to swap with EXT4_BOOT_LOADER_INO | ||
95 | * | ||
96 | */ | ||
97 | static long swap_inode_boot_loader(struct super_block *sb, | ||
98 | struct inode *inode) | ||
99 | { | ||
100 | handle_t *handle; | ||
101 | int err; | ||
102 | struct inode *inode_bl; | ||
103 | struct ext4_inode_info *ei; | ||
104 | struct ext4_inode_info *ei_bl; | ||
105 | struct ext4_sb_info *sbi; | ||
106 | |||
107 | if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) { | ||
108 | err = -EINVAL; | ||
109 | goto swap_boot_out; | ||
110 | } | ||
111 | |||
112 | if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) { | ||
113 | err = -EPERM; | ||
114 | goto swap_boot_out; | ||
115 | } | ||
116 | |||
117 | sbi = EXT4_SB(sb); | ||
118 | ei = EXT4_I(inode); | ||
119 | |||
120 | inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO); | ||
121 | if (IS_ERR(inode_bl)) { | ||
122 | err = PTR_ERR(inode_bl); | ||
123 | goto swap_boot_out; | ||
124 | } | ||
125 | ei_bl = EXT4_I(inode_bl); | ||
126 | |||
127 | filemap_flush(inode->i_mapping); | ||
128 | filemap_flush(inode_bl->i_mapping); | ||
129 | |||
130 | /* Protect orig inodes against a truncate and make sure, | ||
131 | * that only 1 swap_inode_boot_loader is running. */ | ||
132 | ext4_inode_double_lock(inode, inode_bl); | ||
133 | |||
134 | truncate_inode_pages(&inode->i_data, 0); | ||
135 | truncate_inode_pages(&inode_bl->i_data, 0); | ||
136 | |||
137 | /* Wait for all existing dio workers */ | ||
138 | ext4_inode_block_unlocked_dio(inode); | ||
139 | ext4_inode_block_unlocked_dio(inode_bl); | ||
140 | inode_dio_wait(inode); | ||
141 | inode_dio_wait(inode_bl); | ||
142 | |||
143 | handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); | ||
144 | if (IS_ERR(handle)) { | ||
145 | err = -EINVAL; | ||
146 | goto swap_boot_out; | ||
147 | } | ||
148 | |||
149 | /* Protect extent tree against block allocations via delalloc */ | ||
150 | ext4_double_down_write_data_sem(inode, inode_bl); | ||
151 | |||
152 | if (inode_bl->i_nlink == 0) { | ||
153 | /* this inode has never been used as a BOOT_LOADER */ | ||
154 | set_nlink(inode_bl, 1); | ||
155 | i_uid_write(inode_bl, 0); | ||
156 | i_gid_write(inode_bl, 0); | ||
157 | inode_bl->i_flags = 0; | ||
158 | ei_bl->i_flags = 0; | ||
159 | inode_bl->i_version = 1; | ||
160 | i_size_write(inode_bl, 0); | ||
161 | inode_bl->i_mode = S_IFREG; | ||
162 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | ||
163 | EXT4_FEATURE_INCOMPAT_EXTENTS)) { | ||
164 | ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); | ||
165 | ext4_ext_tree_init(handle, inode_bl); | ||
166 | } else | ||
167 | memset(ei_bl->i_data, 0, sizeof(ei_bl->i_data)); | ||
168 | } | ||
169 | |||
170 | swap_inode_data(inode, inode_bl); | ||
171 | |||
172 | inode->i_ctime = inode_bl->i_ctime = ext4_current_time(inode); | ||
173 | |||
174 | spin_lock(&sbi->s_next_gen_lock); | ||
175 | inode->i_generation = sbi->s_next_generation++; | ||
176 | inode_bl->i_generation = sbi->s_next_generation++; | ||
177 | spin_unlock(&sbi->s_next_gen_lock); | ||
178 | |||
179 | ext4_discard_preallocations(inode); | ||
180 | |||
181 | err = ext4_mark_inode_dirty(handle, inode); | ||
182 | if (err < 0) { | ||
183 | ext4_warning(inode->i_sb, | ||
184 | "couldn't mark inode #%lu dirty (err %d)", | ||
185 | inode->i_ino, err); | ||
186 | /* Revert all changes: */ | ||
187 | swap_inode_data(inode, inode_bl); | ||
188 | } else { | ||
189 | err = ext4_mark_inode_dirty(handle, inode_bl); | ||
190 | if (err < 0) { | ||
191 | ext4_warning(inode_bl->i_sb, | ||
192 | "couldn't mark inode #%lu dirty (err %d)", | ||
193 | inode_bl->i_ino, err); | ||
194 | /* Revert all changes: */ | ||
195 | swap_inode_data(inode, inode_bl); | ||
196 | ext4_mark_inode_dirty(handle, inode); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | ext4_journal_stop(handle); | ||
201 | |||
202 | ext4_double_up_write_data_sem(inode, inode_bl); | ||
203 | |||
204 | ext4_inode_resume_unlocked_dio(inode); | ||
205 | ext4_inode_resume_unlocked_dio(inode_bl); | ||
206 | |||
207 | ext4_inode_double_unlock(inode, inode_bl); | ||
208 | |||
209 | iput(inode_bl); | ||
210 | |||
211 | swap_boot_out: | ||
212 | return err; | ||
213 | } | ||
214 | |||
23 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 215 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
24 | { | 216 | { |
25 | struct inode *inode = file_inode(filp); | 217 | struct inode *inode = file_inode(filp); |
@@ -353,6 +545,11 @@ group_add_out: | |||
353 | return err; | 545 | return err; |
354 | } | 546 | } |
355 | 547 | ||
548 | case EXT4_IOC_SWAP_BOOT: | ||
549 | if (!(filp->f_mode & FMODE_WRITE)) | ||
550 | return -EBADF; | ||
551 | return swap_inode_boot_loader(sb, inode); | ||
552 | |||
356 | case EXT4_IOC_RESIZE_FS: { | 553 | case EXT4_IOC_RESIZE_FS: { |
357 | ext4_fsblk_t n_blocks_count; | 554 | ext4_fsblk_t n_blocks_count; |
358 | struct super_block *sb = inode->i_sb; | 555 | struct super_block *sb = inode->i_sb; |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 33e1c086858b..a2e696e16331 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -144,12 +144,13 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, | |||
144 | } | 144 | } |
145 | 145 | ||
146 | /** | 146 | /** |
147 | * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem | 147 | * ext4_double_down_write_data_sem - Acquire two inodes' write lock |
148 | * of i_data_sem | ||
148 | * | 149 | * |
149 | * Acquire write lock of i_data_sem of the two inodes | 150 | * Acquire write lock of i_data_sem of the two inodes |
150 | */ | 151 | */ |
151 | static void | 152 | void |
152 | double_down_write_data_sem(struct inode *first, struct inode *second) | 153 | ext4_double_down_write_data_sem(struct inode *first, struct inode *second) |
153 | { | 154 | { |
154 | if (first < second) { | 155 | if (first < second) { |
155 | down_write(&EXT4_I(first)->i_data_sem); | 156 | down_write(&EXT4_I(first)->i_data_sem); |
@@ -162,14 +163,15 @@ double_down_write_data_sem(struct inode *first, struct inode *second) | |||
162 | } | 163 | } |
163 | 164 | ||
164 | /** | 165 | /** |
165 | * double_up_write_data_sem - Release two inodes' write lock of i_data_sem | 166 | * ext4_double_up_write_data_sem - Release two inodes' write lock of i_data_sem |
166 | * | 167 | * |
167 | * @orig_inode: original inode structure to be released its lock first | 168 | * @orig_inode: original inode structure to be released its lock first |
168 | * @donor_inode: donor inode structure to be released its lock second | 169 | * @donor_inode: donor inode structure to be released its lock second |
169 | * Release write lock of i_data_sem of two inodes (orig and donor). | 170 | * Release write lock of i_data_sem of two inodes (orig and donor). |
170 | */ | 171 | */ |
171 | static void | 172 | void |
172 | double_up_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) | 173 | ext4_double_up_write_data_sem(struct inode *orig_inode, |
174 | struct inode *donor_inode) | ||
173 | { | 175 | { |
174 | up_write(&EXT4_I(orig_inode)->i_data_sem); | 176 | up_write(&EXT4_I(orig_inode)->i_data_sem); |
175 | up_write(&EXT4_I(donor_inode)->i_data_sem); | 177 | up_write(&EXT4_I(donor_inode)->i_data_sem); |
@@ -976,7 +978,7 @@ again: | |||
976 | * necessary, just swap data blocks between orig and donor. | 978 | * necessary, just swap data blocks between orig and donor. |
977 | */ | 979 | */ |
978 | if (uninit) { | 980 | if (uninit) { |
979 | double_down_write_data_sem(orig_inode, donor_inode); | 981 | ext4_double_down_write_data_sem(orig_inode, donor_inode); |
980 | /* If any of extents in range became initialized we have to | 982 | /* If any of extents in range became initialized we have to |
981 | * fallback to data copying */ | 983 | * fallback to data copying */ |
982 | uninit = mext_check_coverage(orig_inode, orig_blk_offset, | 984 | uninit = mext_check_coverage(orig_inode, orig_blk_offset, |
@@ -990,7 +992,7 @@ again: | |||
990 | goto drop_data_sem; | 992 | goto drop_data_sem; |
991 | 993 | ||
992 | if (!uninit) { | 994 | if (!uninit) { |
993 | double_up_write_data_sem(orig_inode, donor_inode); | 995 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
994 | goto data_copy; | 996 | goto data_copy; |
995 | } | 997 | } |
996 | if ((page_has_private(pagep[0]) && | 998 | if ((page_has_private(pagep[0]) && |
@@ -1004,7 +1006,7 @@ again: | |||
1004 | donor_inode, orig_blk_offset, | 1006 | donor_inode, orig_blk_offset, |
1005 | block_len_in_page, err); | 1007 | block_len_in_page, err); |
1006 | drop_data_sem: | 1008 | drop_data_sem: |
1007 | double_up_write_data_sem(orig_inode, donor_inode); | 1009 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
1008 | goto unlock_pages; | 1010 | goto unlock_pages; |
1009 | } | 1011 | } |
1010 | data_copy: | 1012 | data_copy: |
@@ -1065,11 +1067,11 @@ repair_branches: | |||
1065 | * Extents are swapped already, but we are not able to copy data. | 1067 | * Extents are swapped already, but we are not able to copy data. |
1066 | * Try to swap extents to it's original places | 1068 | * Try to swap extents to it's original places |
1067 | */ | 1069 | */ |
1068 | double_down_write_data_sem(orig_inode, donor_inode); | 1070 | ext4_double_down_write_data_sem(orig_inode, donor_inode); |
1069 | replaced_count = mext_replace_branches(handle, donor_inode, orig_inode, | 1071 | replaced_count = mext_replace_branches(handle, donor_inode, orig_inode, |
1070 | orig_blk_offset, | 1072 | orig_blk_offset, |
1071 | block_len_in_page, &err2); | 1073 | block_len_in_page, &err2); |
1072 | double_up_write_data_sem(orig_inode, donor_inode); | 1074 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
1073 | if (replaced_count != block_len_in_page) { | 1075 | if (replaced_count != block_len_in_page) { |
1074 | EXT4_ERROR_INODE_BLOCK(orig_inode, (sector_t)(orig_blk_offset), | 1076 | EXT4_ERROR_INODE_BLOCK(orig_inode, (sector_t)(orig_blk_offset), |
1075 | "Unable to copy data block," | 1077 | "Unable to copy data block," |
@@ -1209,15 +1211,15 @@ mext_check_arguments(struct inode *orig_inode, | |||
1209 | } | 1211 | } |
1210 | 1212 | ||
1211 | /** | 1213 | /** |
1212 | * mext_inode_double_lock - Lock i_mutex on both @inode1 and @inode2 | 1214 | * ext4_inode_double_lock - Lock i_mutex on both @inode1 and @inode2 |
1213 | * | 1215 | * |
1214 | * @inode1: the inode structure | 1216 | * @inode1: the inode structure |
1215 | * @inode2: the inode structure | 1217 | * @inode2: the inode structure |
1216 | * | 1218 | * |
1217 | * Lock two inodes' i_mutex | 1219 | * Lock two inodes' i_mutex |
1218 | */ | 1220 | */ |
1219 | static void | 1221 | void |
1220 | mext_inode_double_lock(struct inode *inode1, struct inode *inode2) | 1222 | ext4_inode_double_lock(struct inode *inode1, struct inode *inode2) |
1221 | { | 1223 | { |
1222 | BUG_ON(inode1 == inode2); | 1224 | BUG_ON(inode1 == inode2); |
1223 | if (inode1 < inode2) { | 1225 | if (inode1 < inode2) { |
@@ -1230,15 +1232,15 @@ mext_inode_double_lock(struct inode *inode1, struct inode *inode2) | |||
1230 | } | 1232 | } |
1231 | 1233 | ||
1232 | /** | 1234 | /** |
1233 | * mext_inode_double_unlock - Release i_mutex on both @inode1 and @inode2 | 1235 | * ext4_inode_double_unlock - Release i_mutex on both @inode1 and @inode2 |
1234 | * | 1236 | * |
1235 | * @inode1: the inode that is released first | 1237 | * @inode1: the inode that is released first |
1236 | * @inode2: the inode that is released second | 1238 | * @inode2: the inode that is released second |
1237 | * | 1239 | * |
1238 | */ | 1240 | */ |
1239 | 1241 | ||
1240 | static void | 1242 | void |
1241 | mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) | 1243 | ext4_inode_double_unlock(struct inode *inode1, struct inode *inode2) |
1242 | { | 1244 | { |
1243 | mutex_unlock(&inode1->i_mutex); | 1245 | mutex_unlock(&inode1->i_mutex); |
1244 | mutex_unlock(&inode2->i_mutex); | 1246 | mutex_unlock(&inode2->i_mutex); |
@@ -1333,7 +1335,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1333 | return -EINVAL; | 1335 | return -EINVAL; |
1334 | } | 1336 | } |
1335 | /* Protect orig and donor inodes against a truncate */ | 1337 | /* Protect orig and donor inodes against a truncate */ |
1336 | mext_inode_double_lock(orig_inode, donor_inode); | 1338 | ext4_inode_double_lock(orig_inode, donor_inode); |
1337 | 1339 | ||
1338 | /* Wait for all existing dio workers */ | 1340 | /* Wait for all existing dio workers */ |
1339 | ext4_inode_block_unlocked_dio(orig_inode); | 1341 | ext4_inode_block_unlocked_dio(orig_inode); |
@@ -1342,7 +1344,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1342 | inode_dio_wait(donor_inode); | 1344 | inode_dio_wait(donor_inode); |
1343 | 1345 | ||
1344 | /* Protect extent tree against block allocations via delalloc */ | 1346 | /* Protect extent tree against block allocations via delalloc */ |
1345 | double_down_write_data_sem(orig_inode, donor_inode); | 1347 | ext4_double_down_write_data_sem(orig_inode, donor_inode); |
1346 | /* Check the filesystem environment whether move_extent can be done */ | 1348 | /* Check the filesystem environment whether move_extent can be done */ |
1347 | ret = mext_check_arguments(orig_inode, donor_inode, orig_start, | 1349 | ret = mext_check_arguments(orig_inode, donor_inode, orig_start, |
1348 | donor_start, &len); | 1350 | donor_start, &len); |
@@ -1466,7 +1468,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1466 | * b. racing with ->readpage, ->write_begin, and ext4_get_block | 1468 | * b. racing with ->readpage, ->write_begin, and ext4_get_block |
1467 | * in move_extent_per_page | 1469 | * in move_extent_per_page |
1468 | */ | 1470 | */ |
1469 | double_up_write_data_sem(orig_inode, donor_inode); | 1471 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
1470 | 1472 | ||
1471 | while (orig_page_offset <= seq_end_page) { | 1473 | while (orig_page_offset <= seq_end_page) { |
1472 | 1474 | ||
@@ -1500,7 +1502,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1500 | block_len_in_page = rest_blocks; | 1502 | block_len_in_page = rest_blocks; |
1501 | } | 1503 | } |
1502 | 1504 | ||
1503 | double_down_write_data_sem(orig_inode, donor_inode); | 1505 | ext4_double_down_write_data_sem(orig_inode, donor_inode); |
1504 | if (ret < 0) | 1506 | if (ret < 0) |
1505 | break; | 1507 | break; |
1506 | 1508 | ||
@@ -1538,10 +1540,10 @@ out: | |||
1538 | ext4_ext_drop_refs(holecheck_path); | 1540 | ext4_ext_drop_refs(holecheck_path); |
1539 | kfree(holecheck_path); | 1541 | kfree(holecheck_path); |
1540 | } | 1542 | } |
1541 | double_up_write_data_sem(orig_inode, donor_inode); | 1543 | ext4_double_up_write_data_sem(orig_inode, donor_inode); |
1542 | ext4_inode_resume_unlocked_dio(orig_inode); | 1544 | ext4_inode_resume_unlocked_dio(orig_inode); |
1543 | ext4_inode_resume_unlocked_dio(donor_inode); | 1545 | ext4_inode_resume_unlocked_dio(donor_inode); |
1544 | mext_inode_double_unlock(orig_inode, donor_inode); | 1546 | ext4_inode_double_unlock(orig_inode, donor_inode); |
1545 | 1547 | ||
1546 | return ret; | 1548 | return ret; |
1547 | } | 1549 | } |