aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorDr. Tilmann Bubeck <t.bubeck@reinform.de>2013-04-08 12:54:05 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-04-08 12:54:05 -0400
commit393d1d1d76933886d5e1ce603214c9987589c6d5 (patch)
tree2f2368a9d787ccb8e69f61a3e5023ef9c4abfd8b /fs/ext4
parentf78ee70db40040e6f38a5134527d4760254d6683 (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.h8
-rw-r--r--fs/ext4/inode.c11
-rw-r--r--fs/ext4/ioctl.c197
-rw-r--r--fs/ext4/move_extent.c48
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 */
2629extern void ext4_double_down_write_data_sem(struct inode *first,
2630 struct inode *second);
2631extern void ext4_double_up_write_data_sem(struct inode *orig_inode,
2632 struct inode *donor_inode);
2633void ext4_inode_double_lock(struct inode *inode1, struct inode *inode2);
2634void ext4_inode_double_unlock(struct inode *inode1, struct inode *inode2);
2627extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, 2635extern 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 */
32static 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 */
59static 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 */
97static 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
211swap_boot_out:
212 return err;
213}
214
23long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 215long 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 */
151static void 152void
152double_down_write_data_sem(struct inode *first, struct inode *second) 153ext4_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 */
171static void 172void
172double_up_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) 173ext4_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 }
1010data_copy: 1012data_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 */
1219static void 1221void
1220mext_inode_double_lock(struct inode *inode1, struct inode *inode2) 1222ext4_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
1240static void 1242void
1241mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) 1243ext4_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}