forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/fs/ext4/namei.c
....@@ -54,6 +54,7 @@
5454 struct inode *inode,
5555 ext4_lblk_t *block)
5656 {
57
+ struct ext4_map_blocks map;
5758 struct buffer_head *bh;
5859 int err;
5960
....@@ -63,6 +64,21 @@
6364 return ERR_PTR(-ENOSPC);
6465
6566 *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
67
+ map.m_lblk = *block;
68
+ map.m_len = 1;
69
+
70
+ /*
71
+ * We're appending new directory block. Make sure the block is not
72
+ * allocated yet, otherwise we will end up corrupting the
73
+ * directory.
74
+ */
75
+ err = ext4_map_blocks(NULL, inode, &map, 0);
76
+ if (err < 0)
77
+ return ERR_PTR(err);
78
+ if (err) {
79
+ EXT4_ERROR_INODE(inode, "Logical block already allocated");
80
+ return ERR_PTR(-EFSCORRUPTED);
81
+ }
6682
6783 bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE);
6884 if (IS_ERR(bh))
....@@ -109,7 +125,17 @@
109125 struct ext4_dir_entry *dirent;
110126 int is_dx_block = 0;
111127
112
- bh = ext4_bread(NULL, inode, block, 0);
128
+ if (block >= inode->i_size >> inode->i_blkbits) {
129
+ ext4_error_inode(inode, func, line, block,
130
+ "Attempting to read directory block (%u) that is past i_size (%llu)",
131
+ block, inode->i_size);
132
+ return ERR_PTR(-EFSCORRUPTED);
133
+ }
134
+
135
+ if (ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_EIO))
136
+ bh = ERR_PTR(-EIO);
137
+ else
138
+ bh = ext4_bread(NULL, inode, block, 0);
113139 if (IS_ERR(bh)) {
114140 __ext4_warning(inode->i_sb, func, line,
115141 "inode #%lu: lblock %lu: comm %s: "
....@@ -153,21 +179,25 @@
153179 * caller is sure it should be an index block.
154180 */
155181 if (is_dx_block && type == INDEX) {
156
- if (ext4_dx_csum_verify(inode, dirent))
182
+ if (ext4_dx_csum_verify(inode, dirent) &&
183
+ !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC))
157184 set_buffer_verified(bh);
158185 else {
159
- ext4_error_inode(inode, func, line, block,
160
- "Directory index failed checksum");
186
+ ext4_error_inode_err(inode, func, line, block,
187
+ EFSBADCRC,
188
+ "Directory index failed checksum");
161189 brelse(bh);
162190 return ERR_PTR(-EFSBADCRC);
163191 }
164192 }
165193 if (!is_dx_block) {
166
- if (ext4_dirent_csum_verify(inode, dirent))
194
+ if (ext4_dirblock_csum_verify(inode, bh) &&
195
+ !ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_CRC))
167196 set_buffer_verified(bh);
168197 else {
169
- ext4_error_inode(inode, func, line, block,
170
- "Directory block failed checksum");
198
+ ext4_error_inode_err(inode, func, line, block,
199
+ EFSBADCRC,
200
+ "Directory block failed checksum");
171201 brelse(bh);
172202 return ERR_PTR(-EFSBADCRC);
173203 }
....@@ -226,13 +256,13 @@
226256 u8 unused_flags;
227257 }
228258 info;
229
- struct dx_entry entries[0];
259
+ struct dx_entry entries[];
230260 };
231261
232262 struct dx_node
233263 {
234264 struct fake_dirent fake;
235
- struct dx_entry entries[0];
265
+ struct dx_entry entries[];
236266 };
237267
238268
....@@ -295,9 +325,11 @@
295325 struct inode *dir, struct inode *inode);
296326
297327 /* checksumming functions */
298
-void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
299
- unsigned int blocksize)
328
+void ext4_initialize_dirent_tail(struct buffer_head *bh,
329
+ unsigned int blocksize)
300330 {
331
+ struct ext4_dir_entry_tail *t = EXT4_DIRENT_TAIL(bh->b_data, blocksize);
332
+
301333 memset(t, 0, sizeof(struct ext4_dir_entry_tail));
302334 t->det_rec_len = ext4_rec_len_to_disk(
303335 sizeof(struct ext4_dir_entry_tail), blocksize);
....@@ -306,17 +338,17 @@
306338
307339 /* Walk through a dirent block to find a checksum "dirent" at the tail */
308340 static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
309
- struct ext4_dir_entry *de)
341
+ struct buffer_head *bh)
310342 {
311343 struct ext4_dir_entry_tail *t;
312344
313345 #ifdef PARANOID
314346 struct ext4_dir_entry *d, *top;
315347
316
- d = de;
317
- top = (struct ext4_dir_entry *)(((void *)de) +
348
+ d = (struct ext4_dir_entry *)bh->b_data;
349
+ top = (struct ext4_dir_entry *)(bh->b_data +
318350 (EXT4_BLOCK_SIZE(inode->i_sb) -
319
- sizeof(struct ext4_dir_entry_tail)));
351
+ sizeof(struct ext4_dir_entry_tail)));
320352 while (d < top && d->rec_len)
321353 d = (struct ext4_dir_entry *)(((void *)d) +
322354 le16_to_cpu(d->rec_len));
....@@ -326,7 +358,7 @@
326358
327359 t = (struct ext4_dir_entry_tail *)d;
328360 #else
329
- t = EXT4_DIRENT_TAIL(de, EXT4_BLOCK_SIZE(inode->i_sb));
361
+ t = EXT4_DIRENT_TAIL(bh->b_data, EXT4_BLOCK_SIZE(inode->i_sb));
330362 #endif
331363
332364 if (t->det_reserved_zero1 ||
....@@ -338,8 +370,7 @@
338370 return t;
339371 }
340372
341
-static __le32 ext4_dirent_csum(struct inode *inode,
342
- struct ext4_dir_entry *dirent, int size)
373
+static __le32 ext4_dirblock_csum(struct inode *inode, void *dirent, int size)
343374 {
344375 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
345376 struct ext4_inode_info *ei = EXT4_I(inode);
....@@ -359,49 +390,49 @@
359390 "No space for directory leaf checksum. Please run e2fsck -D.");
360391 }
361392
362
-int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
393
+int ext4_dirblock_csum_verify(struct inode *inode, struct buffer_head *bh)
363394 {
364395 struct ext4_dir_entry_tail *t;
365396
366397 if (!ext4_has_metadata_csum(inode->i_sb))
367398 return 1;
368399
369
- t = get_dirent_tail(inode, dirent);
400
+ t = get_dirent_tail(inode, bh);
370401 if (!t) {
371402 warn_no_space_for_csum(inode);
372403 return 0;
373404 }
374405
375
- if (t->det_checksum != ext4_dirent_csum(inode, dirent,
376
- (void *)t - (void *)dirent))
406
+ if (t->det_checksum != ext4_dirblock_csum(inode, bh->b_data,
407
+ (char *)t - bh->b_data))
377408 return 0;
378409
379410 return 1;
380411 }
381412
382
-static void ext4_dirent_csum_set(struct inode *inode,
383
- struct ext4_dir_entry *dirent)
413
+static void ext4_dirblock_csum_set(struct inode *inode,
414
+ struct buffer_head *bh)
384415 {
385416 struct ext4_dir_entry_tail *t;
386417
387418 if (!ext4_has_metadata_csum(inode->i_sb))
388419 return;
389420
390
- t = get_dirent_tail(inode, dirent);
421
+ t = get_dirent_tail(inode, bh);
391422 if (!t) {
392423 warn_no_space_for_csum(inode);
393424 return;
394425 }
395426
396
- t->det_checksum = ext4_dirent_csum(inode, dirent,
397
- (void *)t - (void *)dirent);
427
+ t->det_checksum = ext4_dirblock_csum(inode, bh->b_data,
428
+ (char *)t - bh->b_data);
398429 }
399430
400
-int ext4_handle_dirty_dirent_node(handle_t *handle,
401
- struct inode *inode,
402
- struct buffer_head *bh)
431
+int ext4_handle_dirty_dirblock(handle_t *handle,
432
+ struct inode *inode,
433
+ struct buffer_head *bh)
403434 {
404
- ext4_dirent_csum_set(inode, (struct ext4_dir_entry *)bh->b_data);
435
+ ext4_dirblock_csum_set(inode, bh);
405436 return ext4_handle_dirty_metadata(handle, inode, bh);
406437 }
407438
....@@ -639,13 +670,7 @@
639670
640671 name = de->name;
641672 len = de->name_len;
642
- if (IS_ENCRYPTED(dir))
643
- res = fscrypt_get_encryption_info(dir);
644
- if (res) {
645
- printk(KERN_WARNING "Error setting up"
646
- " fname crypto: %d\n", res);
647
- }
648
- if (!fscrypt_has_encryption_key(dir)) {
673
+ if (!IS_ENCRYPTED(dir)) {
649674 /* Directory is not encrypted */
650675 ext4fs_dirhash(dir, de->name,
651676 de->name_len, &h);
....@@ -659,8 +684,7 @@
659684
660685 /* Directory is encrypted */
661686 res = fscrypt_fname_alloc_buffer(
662
- dir, len,
663
- &fname_crypto_str);
687
+ len, &fname_crypto_str);
664688 if (res)
665689 printk(KERN_WARNING "Error "
666690 "allocating crypto "
....@@ -756,12 +780,14 @@
756780 dx_probe(struct ext4_filename *fname, struct inode *dir,
757781 struct dx_hash_info *hinfo, struct dx_frame *frame_in)
758782 {
759
- unsigned count, indirect;
783
+ unsigned count, indirect, level, i;
760784 struct dx_entry *at, *entries, *p, *q, *m;
761785 struct dx_root *root;
762786 struct dx_frame *frame = frame_in;
763787 struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
764788 u32 hash;
789
+ ext4_lblk_t block;
790
+ ext4_lblk_t blocks[EXT4_HTREE_LEVEL];
765791
766792 memset(frame_in, 0, EXT4_HTREE_LEVEL * sizeof(frame_in[0]));
767793 frame->bh = ext4_read_dirblock(dir, 0, INDEX);
....@@ -833,6 +859,8 @@
833859 }
834860
835861 dxtrace(printk("Look up %x", hash));
862
+ level = 0;
863
+ blocks[0] = 0;
836864 while (1) {
837865 count = dx_get_count(entries);
838866 if (!count || count > dx_get_limit(entries)) {
....@@ -874,15 +902,27 @@
874902 dx_get_block(at)));
875903 frame->entries = entries;
876904 frame->at = at;
877
- if (!indirect--)
905
+
906
+ block = dx_get_block(at);
907
+ for (i = 0; i <= level; i++) {
908
+ if (blocks[i] == block) {
909
+ ext4_warning_inode(dir,
910
+ "dx entry: tree cycle block %u points back to block %u",
911
+ blocks[level], block);
912
+ goto fail;
913
+ }
914
+ }
915
+ if (++level > indirect)
878916 return frame;
917
+ blocks[level] = block;
879918 frame++;
880
- frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
919
+ frame->bh = ext4_read_dirblock(dir, block, INDEX);
881920 if (IS_ERR(frame->bh)) {
882921 ret_err = (struct dx_frame *) frame->bh;
883922 frame->bh = NULL;
884923 goto fail;
885924 }
925
+
886926 entries = ((struct dx_node *) frame->bh->b_data)->entries;
887927
888928 if (dx_get_limit(entries) != dx_node_limit(dir)) {
....@@ -1027,22 +1067,21 @@
10271067 dir->i_sb->s_blocksize -
10281068 ext4_dir_rec_len(0,
10291069 csum ? NULL : dir));
1030
-#ifdef CONFIG_FS_ENCRYPTION
10311070 /* Check if the directory is encrypted */
10321071 if (IS_ENCRYPTED(dir)) {
1033
- err = fscrypt_get_encryption_info(dir);
1072
+ err = fscrypt_prepare_readdir(dir);
10341073 if (err < 0) {
10351074 brelse(bh);
10361075 return err;
10371076 }
1038
- err = fscrypt_fname_alloc_buffer(dir, EXT4_NAME_LEN,
1039
- &fname_crypto_str);
1077
+ err = fscrypt_fname_alloc_buffer(EXT4_NAME_LEN,
1078
+ &fname_crypto_str);
10401079 if (err < 0) {
10411080 brelse(bh);
10421081 return err;
10431082 }
10441083 }
1045
-#endif
1084
+
10461085 for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
10471086 if (ext4_check_dir_entry(dir, NULL, de, bh,
10481087 bh->b_data, bh->b_size, block,
....@@ -1100,9 +1139,7 @@
11001139 }
11011140 errout:
11021141 brelse(bh);
1103
-#ifdef CONFIG_FS_ENCRYPTION
11041142 fscrypt_fname_free_buffer(&fname_crypto_str);
1105
-#endif
11061143 return count;
11071144 }
11081145
....@@ -1143,10 +1180,10 @@
11431180 hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
11441181 if (ext4_has_inline_data(dir)) {
11451182 int has_inline_data = 1;
1146
- count = htree_inlinedir_to_tree(dir_file, dir, 0,
1147
- &hinfo, start_hash,
1148
- start_minor_hash,
1149
- &has_inline_data);
1183
+ count = ext4_inlinedir_to_tree(dir_file, dir, 0,
1184
+ &hinfo, start_hash,
1185
+ start_minor_hash,
1186
+ &has_inline_data);
11501187 if (has_inline_data) {
11511188 *next_hash = ~0;
11521189 return count;
....@@ -1354,7 +1391,7 @@
13541391 /* Handle invalid character sequence as either an error
13551392 * or as an opaque byte sequence.
13561393 */
1357
- if (sb_has_enc_strict_mode(sb))
1394
+ if (sb_has_strict_encoding(sb))
13581395 ret = -EINVAL;
13591396 else if (name->len != entry.len)
13601397 ret = 1;
....@@ -1373,7 +1410,8 @@
13731410 struct dx_hash_info *hinfo = &name->hinfo;
13741411 int len;
13751412
1376
- if (!needs_casefold(dir)) {
1413
+ if (!IS_CASEFOLDED(dir) || !dir->i_sb->s_encoding ||
1414
+ (IS_ENCRYPTED(dir) && !fscrypt_has_encryption_key(dir))) {
13771415 cf_name->name = NULL;
13781416 return 0;
13791417 }
....@@ -1424,7 +1462,8 @@
14241462 #endif
14251463
14261464 #ifdef CONFIG_UNICODE
1427
- if (needs_casefold(parent)) {
1465
+ if (parent->i_sb->s_encoding && IS_CASEFOLDED(parent) &&
1466
+ (!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) {
14281467 if (fname->cf_name.name) {
14291468 struct qstr cf = {.name = fname->cf_name.name,
14301469 .len = fname->cf_name.len};
....@@ -1461,10 +1500,10 @@
14611500
14621501 de = (struct ext4_dir_entry_2 *)search_buf;
14631502 dlimit = search_buf + buf_size;
1464
- while ((char *) de < dlimit) {
1503
+ while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) {
14651504 /* this code is executed quadratically often */
14661505 /* do minimal checking `by hand' */
1467
- if ((char *) de + de->name_len <= dlimit &&
1506
+ if (de->name + de->name_len <= dlimit &&
14681507 ext4_match(dir, fname, de)) {
14691508 /* found a match - just to be sure, do
14701509 * a full check */
....@@ -1606,8 +1645,9 @@
16061645 goto next;
16071646 wait_on_buffer(bh);
16081647 if (!buffer_uptodate(bh)) {
1609
- EXT4_ERROR_INODE(dir, "reading directory lblock %lu",
1610
- (unsigned long) block);
1648
+ EXT4_ERROR_INODE_ERR(dir, EIO,
1649
+ "reading directory lblock %lu",
1650
+ (unsigned long) block);
16111651 brelse(bh);
16121652 ret = ERR_PTR(-EIO);
16131653 goto cleanup_and_exit;
....@@ -1615,10 +1655,10 @@
16151655 if (!buffer_verified(bh) &&
16161656 !is_dx_internal_node(dir, block,
16171657 (struct ext4_dir_entry *)bh->b_data) &&
1618
- !ext4_dirent_csum_verify(dir,
1619
- (struct ext4_dir_entry *)bh->b_data)) {
1620
- EXT4_ERROR_INODE(dir, "checksumming directory "
1621
- "block %lu", (unsigned long)block);
1658
+ !ext4_dirblock_csum_verify(dir, bh)) {
1659
+ EXT4_ERROR_INODE_ERR(dir, EFSBADCRC,
1660
+ "checksumming directory "
1661
+ "block %lu", (unsigned long)block);
16221662 brelse(bh);
16231663 ret = ERR_PTR(-EFSBADCRC);
16241664 goto cleanup_and_exit;
....@@ -1690,7 +1730,7 @@
16901730 struct buffer_head *bh;
16911731
16921732 err = ext4_fname_prepare_lookup(dir, dentry, &fname);
1693
- generic_set_encrypted_ci_d_ops(dir, dentry);
1733
+ generic_set_encrypted_ci_d_ops(dentry);
16941734 if (err == -ENOENT)
16951735 return NULL;
16961736 if (err)
....@@ -1768,7 +1808,7 @@
17681808
17691809 bh = ext4_lookup_entry(dir, dentry, &de);
17701810 if (IS_ERR(bh))
1771
- return (struct dentry *) bh;
1811
+ return ERR_CAST(bh);
17721812 inode = NULL;
17731813 if (bh) {
17741814 __u32 ino = le32_to_cpu(de->inode);
....@@ -1823,7 +1863,7 @@
18231863
18241864 bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL, NULL);
18251865 if (IS_ERR(bh))
1826
- return (struct dentry *) bh;
1866
+ return ERR_CAST(bh);
18271867 if (!bh)
18281868 return ERR_PTR(-ENOENT);
18291869 ino = le32_to_cpu(de->inode);
....@@ -1900,14 +1940,14 @@
19001940 struct dx_hash_info *hinfo, ext4_lblk_t *newblock)
19011941 {
19021942 unsigned blocksize = dir->i_sb->s_blocksize;
1903
- unsigned count, continued;
1943
+ unsigned continued;
1944
+ int count;
19041945 struct buffer_head *bh2;
19051946 u32 hash2;
19061947 struct dx_map_entry *map;
19071948 char *data1 = (*bh)->b_data, *data2;
19081949 unsigned split, move, size;
19091950 struct ext4_dir_entry_2 *de = NULL, *de2;
1910
- struct ext4_dir_entry_tail *t;
19111951 int csum_size = 0;
19121952 int err = 0, i;
19131953
....@@ -1978,11 +2018,8 @@
19782018 (char *) de2,
19792019 blocksize);
19802020 if (csum_size) {
1981
- t = EXT4_DIRENT_TAIL(data2, blocksize);
1982
- initialize_dirent_tail(t, blocksize);
1983
-
1984
- t = EXT4_DIRENT_TAIL(data1, blocksize);
1985
- initialize_dirent_tail(t, blocksize);
2021
+ ext4_initialize_dirent_tail(*bh, blocksize);
2022
+ ext4_initialize_dirent_tail(bh2, blocksize);
19862023 }
19872024
19882025 dxtrace(dx_show_leaf(dir, hinfo, (struct ext4_dir_entry_2 *) data1,
....@@ -1996,7 +2033,7 @@
19962033 de = de2;
19972034 }
19982035 dx_insert_block(frame, hash2 + continued, *newblock);
1999
- err = ext4_handle_dirty_dirent_node(handle, dir, bh2);
2036
+ err = ext4_handle_dirty_dirblock(handle, dir, bh2);
20002037 if (err)
20012038 goto journal_error;
20022039 err = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
....@@ -2097,7 +2134,7 @@
20972134 {
20982135 unsigned int blocksize = dir->i_sb->s_blocksize;
20992136 int csum_size = 0;
2100
- int err;
2137
+ int err, err2;
21012138
21022139 if (ext4_has_metadata_csum(inode->i_sb))
21032140 csum_size = sizeof(struct ext4_dir_entry_tail);
....@@ -2132,12 +2169,12 @@
21322169 dir->i_mtime = dir->i_ctime = current_time(dir);
21332170 ext4_update_dx_flag(dir);
21342171 inode_inc_iversion(dir);
2135
- ext4_mark_inode_dirty(handle, dir);
2172
+ err2 = ext4_mark_inode_dirty(handle, dir);
21362173 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
2137
- err = ext4_handle_dirty_dirent_node(handle, dir, bh);
2174
+ err = ext4_handle_dirty_dirblock(handle, dir, bh);
21382175 if (err)
21392176 ext4_std_error(dir->i_sb, err);
2140
- return 0;
2177
+ return err ? err : err2;
21412178 }
21422179
21432180 /*
....@@ -2153,8 +2190,7 @@
21532190 struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
21542191 struct dx_entry *entries;
21552192 struct ext4_dir_entry_2 *de, *de2;
2156
- struct ext4_dir_entry_tail *t;
2157
- char *data1, *top;
2193
+ char *data2, *top;
21582194 unsigned len;
21592195 int retval;
21602196 unsigned blocksize;
....@@ -2194,21 +2230,26 @@
21942230 return PTR_ERR(bh2);
21952231 }
21962232 ext4_set_inode_flag(dir, EXT4_INODE_INDEX);
2197
- data1 = bh2->b_data;
2233
+ data2 = bh2->b_data;
21982234
2199
- memcpy (data1, de, len);
2200
- de = (struct ext4_dir_entry_2 *) data1;
2201
- top = data1 + len;
2202
- while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top)
2235
+ memcpy(data2, de, len);
2236
+ de = (struct ext4_dir_entry_2 *) data2;
2237
+ top = data2 + len;
2238
+ while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) {
2239
+ if (ext4_check_dir_entry(dir, NULL, de, bh2, data2, len, block,
2240
+ (data2 + (blocksize - csum_size) -
2241
+ (char *) de))) {
2242
+ brelse(bh2);
2243
+ brelse(bh);
2244
+ return -EFSCORRUPTED;
2245
+ }
22032246 de = de2;
2204
- de->rec_len = ext4_rec_len_to_disk(data1 + (blocksize - csum_size) -
2205
- (char *) de,
2206
- blocksize);
2207
-
2208
- if (csum_size) {
2209
- t = EXT4_DIRENT_TAIL(data1, blocksize);
2210
- initialize_dirent_tail(t, blocksize);
22112247 }
2248
+ de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) -
2249
+ (char *) de, blocksize);
2250
+
2251
+ if (csum_size)
2252
+ ext4_initialize_dirent_tail(bh2, blocksize);
22122253
22132254 /* Initialize the root; the dot dirents already exist */
22142255 de = (struct ext4_dir_entry_2 *) (&root->dotdot);
....@@ -2247,7 +2288,7 @@
22472288 retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
22482289 if (retval)
22492290 goto out_frames;
2250
- retval = ext4_handle_dirty_dirent_node(handle, dir, bh2);
2291
+ retval = ext4_handle_dirty_dirblock(handle, dir, bh2);
22512292 if (retval)
22522293 goto out_frames;
22532294
....@@ -2287,7 +2328,6 @@
22872328 struct inode *dir = d_inode(dentry->d_parent);
22882329 struct buffer_head *bh = NULL;
22892330 struct ext4_dir_entry_2 *de;
2290
- struct ext4_dir_entry_tail *t;
22912331 struct super_block *sb;
22922332 struct ext4_filename fname;
22932333 int retval;
....@@ -2304,14 +2344,14 @@
23042344 if (!dentry->d_name.len)
23052345 return -EINVAL;
23062346
2347
+ if (fscrypt_is_nokey_name(dentry))
2348
+ return -ENOKEY;
2349
+
23072350 #ifdef CONFIG_UNICODE
2308
- if (sb_has_enc_strict_mode(sb) && IS_CASEFOLDED(dir) &&
2351
+ if (sb_has_strict_encoding(sb) && IS_CASEFOLDED(dir) &&
23092352 sb->s_encoding && utf8_validate(sb->s_encoding, &dentry->d_name))
23102353 return -EINVAL;
23112354 #endif
2312
-
2313
- if (fscrypt_is_nokey_name(dentry))
2314
- return -ENOKEY;
23152355
23162356 retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
23172357 if (retval)
....@@ -2340,7 +2380,9 @@
23402380 }
23412381 ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
23422382 dx_fallback++;
2343
- ext4_mark_inode_dirty(handle, dir);
2383
+ retval = ext4_mark_inode_dirty(handle, dir);
2384
+ if (unlikely(retval))
2385
+ goto out;
23442386 }
23452387 blocks = dir->i_size >> sb->s_blocksize_bits;
23462388 for (block = 0; block < blocks; block++) {
....@@ -2380,10 +2422,8 @@
23802422 de->inode = 0;
23812423 de->rec_len = ext4_rec_len_to_disk(blocksize - csum_size, blocksize);
23822424
2383
- if (csum_size) {
2384
- t = EXT4_DIRENT_TAIL(bh->b_data, blocksize);
2385
- initialize_dirent_tail(t, blocksize);
2386
- }
2425
+ if (csum_size)
2426
+ ext4_initialize_dirent_tail(bh, blocksize);
23872427
23882428 retval = add_dirent_to_buf(handle, &fname, dir, inode, de, block, bh);
23892429 out:
....@@ -2573,8 +2613,7 @@
25732613 * ext4_generic_delete_entry deletes a directory entry by merging it
25742614 * with the previous entry
25752615 */
2576
-int ext4_generic_delete_entry(handle_t *handle,
2577
- struct inode *dir,
2616
+int ext4_generic_delete_entry(struct inode *dir,
25782617 struct ext4_dir_entry_2 *de_del,
25792618 ext4_lblk_t lblk,
25802619 struct buffer_head *bh,
....@@ -2637,14 +2676,13 @@
26372676 if (unlikely(err))
26382677 goto out;
26392678
2640
- err = ext4_generic_delete_entry(handle, dir, de_del, lblk,
2641
- bh, bh->b_data,
2679
+ err = ext4_generic_delete_entry(dir, de_del, lblk, bh, bh->b_data,
26422680 dir->i_sb->s_blocksize, csum_size);
26432681 if (err)
26442682 goto out;
26452683
26462684 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
2647
- err = ext4_handle_dirty_dirent_node(handle, dir, bh);
2685
+ err = ext4_handle_dirty_dirblock(handle, dir, bh);
26482686 if (unlikely(err))
26492687 goto out;
26502688
....@@ -2666,7 +2704,7 @@
26662704 * for checking S_ISDIR(inode) (since the INODE_INDEX feature will not be set
26672705 * on regular files) and to avoid creating huge/slow non-HTREE directories.
26682706 */
2669
-static void ext4_inc_count(handle_t *handle, struct inode *inode)
2707
+static void ext4_inc_count(struct inode *inode)
26702708 {
26712709 inc_nlink(inode);
26722710 if (is_dx(inode) &&
....@@ -2678,25 +2716,36 @@
26782716 * If a directory had nlink == 1, then we should let it be 1. This indicates
26792717 * directory has >EXT4_LINK_MAX subdirs.
26802718 */
2681
-static void ext4_dec_count(handle_t *handle, struct inode *inode)
2719
+static void ext4_dec_count(struct inode *inode)
26822720 {
26832721 if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
26842722 drop_nlink(inode);
26852723 }
26862724
26872725
2726
+/*
2727
+ * Add non-directory inode to a directory. On success, the inode reference is
2728
+ * consumed by dentry is instantiation. This is also indicated by clearing of
2729
+ * *inodep pointer. On failure, the caller is responsible for dropping the
2730
+ * inode reference in the safe context.
2731
+ */
26882732 static int ext4_add_nondir(handle_t *handle,
2689
- struct dentry *dentry, struct inode *inode)
2733
+ struct dentry *dentry, struct inode **inodep)
26902734 {
2735
+ struct inode *dir = d_inode(dentry->d_parent);
2736
+ struct inode *inode = *inodep;
26912737 int err = ext4_add_entry(handle, dentry, inode);
26922738 if (!err) {
2693
- ext4_mark_inode_dirty(handle, inode);
2739
+ err = ext4_mark_inode_dirty(handle, inode);
2740
+ if (IS_DIRSYNC(dir))
2741
+ ext4_handle_sync(handle);
26942742 d_instantiate_new(dentry, inode);
2695
- return 0;
2743
+ *inodep = NULL;
2744
+ return err;
26962745 }
26972746 drop_nlink(inode);
2747
+ ext4_orphan_add(handle, inode);
26982748 unlock_new_inode(inode);
2699
- iput(inode);
27002749 return err;
27012750 }
27022751
....@@ -2730,12 +2779,14 @@
27302779 inode->i_op = &ext4_file_inode_operations;
27312780 inode->i_fop = &ext4_file_operations;
27322781 ext4_set_aops(inode);
2733
- err = ext4_add_nondir(handle, dentry, inode);
2734
- if (!err && IS_DIRSYNC(dir))
2735
- ext4_handle_sync(handle);
2782
+ err = ext4_add_nondir(handle, dentry, &inode);
2783
+ if (!err)
2784
+ ext4_fc_track_create(handle, dentry);
27362785 }
27372786 if (handle)
27382787 ext4_journal_stop(handle);
2788
+ if (!IS_ERR_OR_NULL(inode))
2789
+ iput(inode);
27392790 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
27402791 goto retry;
27412792 return err;
....@@ -2762,12 +2813,14 @@
27622813 if (!IS_ERR(inode)) {
27632814 init_special_inode(inode, inode->i_mode, rdev);
27642815 inode->i_op = &ext4_special_inode_operations;
2765
- err = ext4_add_nondir(handle, dentry, inode);
2766
- if (!err && IS_DIRSYNC(dir))
2767
- ext4_handle_sync(handle);
2816
+ err = ext4_add_nondir(handle, dentry, &inode);
2817
+ if (!err)
2818
+ ext4_fc_track_create(handle, dentry);
27682819 }
27692820 if (handle)
27702821 ext4_journal_stop(handle);
2822
+ if (!IS_ERR_OR_NULL(inode))
2823
+ iput(inode);
27712824 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
27722825 goto retry;
27732826 return err;
....@@ -2842,12 +2895,11 @@
28422895 return ext4_next_entry(de, blocksize);
28432896 }
28442897
2845
-static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
2898
+int ext4_init_new_dir(handle_t *handle, struct inode *dir,
28462899 struct inode *inode)
28472900 {
28482901 struct buffer_head *dir_block = NULL;
28492902 struct ext4_dir_entry_2 *de;
2850
- struct ext4_dir_entry_tail *t;
28512903 ext4_lblk_t block = 0;
28522904 unsigned int blocksize = dir->i_sb->s_blocksize;
28532905 int csum_size = 0;
....@@ -2871,13 +2923,11 @@
28712923 de = (struct ext4_dir_entry_2 *)dir_block->b_data;
28722924 ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0);
28732925 set_nlink(inode, 2);
2874
- if (csum_size) {
2875
- t = EXT4_DIRENT_TAIL(dir_block->b_data, blocksize);
2876
- initialize_dirent_tail(t, blocksize);
2877
- }
2926
+ if (csum_size)
2927
+ ext4_initialize_dirent_tail(dir_block, blocksize);
28782928
28792929 BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
2880
- err = ext4_handle_dirty_dirent_node(handle, inode, dir_block);
2930
+ err = ext4_handle_dirty_dirblock(handle, inode, dir_block);
28812931 if (err)
28822932 goto out;
28832933 set_buffer_verified(dir_block);
....@@ -2890,7 +2940,7 @@
28902940 {
28912941 handle_t *handle;
28922942 struct inode *inode;
2893
- int err, credits, retries = 0;
2943
+ int err, err2 = 0, credits, retries = 0;
28942944
28952945 if (EXT4_DIR_LINK_MAX(dir))
28962946 return -EMLINK;
....@@ -2921,23 +2971,30 @@
29212971 if (err) {
29222972 out_clear_inode:
29232973 clear_nlink(inode);
2974
+ ext4_orphan_add(handle, inode);
29242975 unlock_new_inode(inode);
2925
- ext4_mark_inode_dirty(handle, inode);
2976
+ err2 = ext4_mark_inode_dirty(handle, inode);
2977
+ if (unlikely(err2))
2978
+ err = err2;
2979
+ ext4_journal_stop(handle);
29262980 iput(inode);
2927
- goto out_stop;
2981
+ goto out_retry;
29282982 }
2929
- ext4_inc_count(handle, dir);
2983
+ ext4_inc_count(dir);
2984
+
29302985 ext4_update_dx_flag(dir);
29312986 err = ext4_mark_inode_dirty(handle, dir);
29322987 if (err)
29332988 goto out_clear_inode;
29342989 d_instantiate_new(dentry, inode);
2990
+ ext4_fc_track_create(handle, dentry);
29352991 if (IS_DIRSYNC(dir))
29362992 ext4_handle_sync(handle);
29372993
29382994 out_stop:
29392995 if (handle)
29402996 ext4_journal_stop(handle);
2997
+out_retry:
29412998 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
29422999 goto retry;
29433000 return err;
....@@ -2966,14 +3023,14 @@
29663023 if (inode->i_size < ext4_dir_rec_len(1, NULL) +
29673024 ext4_dir_rec_len(2, NULL)) {
29683025 EXT4_ERROR_INODE(inode, "invalid size");
2969
- return true;
3026
+ return false;
29703027 }
29713028 /* The first directory block must not be a hole,
29723029 * so treat it as DIRENT_HTREE
29733030 */
29743031 bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE);
29753032 if (IS_ERR(bh))
2976
- return true;
3033
+ return false;
29773034
29783035 de = (struct ext4_dir_entry_2 *) bh->b_data;
29793036 if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, 0,
....@@ -2981,7 +3038,7 @@
29813038 le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) {
29823039 ext4_warning_inode(inode, "directory missing '.'");
29833040 brelse(bh);
2984
- return true;
3041
+ return false;
29853042 }
29863043 offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
29873044 de = ext4_next_entry(de, sb->s_blocksize);
....@@ -2990,7 +3047,7 @@
29903047 le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
29913048 ext4_warning_inode(inode, "directory missing '..'");
29923049 brelse(bh);
2993
- return true;
3050
+ return false;
29943051 }
29953052 offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
29963053 while (offset < inode->i_size) {
....@@ -3004,16 +3061,13 @@
30043061 continue;
30053062 }
30063063 if (IS_ERR(bh))
3007
- return true;
3064
+ return false;
30083065 }
30093066 de = (struct ext4_dir_entry_2 *) (bh->b_data +
30103067 (offset & (sb->s_blocksize - 1)));
30113068 if (ext4_check_dir_entry(inode, NULL, de, bh,
3012
- bh->b_data, bh->b_size, 0, offset)) {
3013
- offset = (offset | (sb->s_blocksize - 1)) + 1;
3014
- continue;
3015
- }
3016
- if (le32_to_cpu(de->inode)) {
3069
+ bh->b_data, bh->b_size, 0, offset) ||
3070
+ le32_to_cpu(de->inode)) {
30173071 brelse(bh);
30183072 return false;
30193073 }
....@@ -3263,10 +3317,13 @@
32633317 inode->i_size = 0;
32643318 ext4_orphan_add(handle, inode);
32653319 inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
3266
- ext4_mark_inode_dirty(handle, inode);
3267
- ext4_dec_count(handle, dir);
3320
+ retval = ext4_mark_inode_dirty(handle, inode);
3321
+ if (retval)
3322
+ goto end_rmdir;
3323
+ ext4_dec_count(dir);
32683324 ext4_update_dx_flag(dir);
3269
- ext4_mark_inode_dirty(handle, dir);
3325
+ ext4_fc_track_unlink(handle, dentry);
3326
+ retval = ext4_mark_inode_dirty(handle, dir);
32703327
32713328 #ifdef CONFIG_UNICODE
32723329 /* VFS negative dentries are incompatible with Encoding and
....@@ -3286,68 +3343,94 @@
32863343 return retval;
32873344 }
32883345
3289
-static int ext4_unlink(struct inode *dir, struct dentry *dentry)
3346
+int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name,
3347
+ struct inode *inode)
32903348 {
3291
- int retval;
3292
- struct inode *inode;
3349
+ int retval = -ENOENT;
32933350 struct buffer_head *bh;
32943351 struct ext4_dir_entry_2 *de;
3295
- handle_t *handle = NULL;
3352
+ int skip_remove_dentry = 0;
32963353 ext4_lblk_t lblk;
32973354
3298
- if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
3299
- return -EIO;
3300
-
3301
- trace_ext4_unlink_enter(dir, dentry);
3302
- /* Initialize quotas before so that eventual writes go
3303
- * in separate transaction */
3304
- retval = dquot_initialize(dir);
3305
- if (retval)
3306
- return retval;
3307
- retval = dquot_initialize(d_inode(dentry));
3308
- if (retval)
3309
- return retval;
3310
-
3311
- retval = -ENOENT;
3312
- bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, &lblk);
3355
+ bh = ext4_find_entry(dir, d_name, &de, NULL, &lblk);
33133356 if (IS_ERR(bh))
33143357 return PTR_ERR(bh);
3358
+
33153359 if (!bh)
3316
- goto end_unlink;
3360
+ return -ENOENT;
33173361
3318
- inode = d_inode(dentry);
3319
-
3320
- retval = -EFSCORRUPTED;
3321
- if (le32_to_cpu(de->inode) != inode->i_ino)
3322
- goto end_unlink;
3323
-
3324
- handle = ext4_journal_start(dir, EXT4_HT_DIR,
3325
- EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
3326
- if (IS_ERR(handle)) {
3327
- retval = PTR_ERR(handle);
3328
- handle = NULL;
3329
- goto end_unlink;
3362
+ if (le32_to_cpu(de->inode) != inode->i_ino) {
3363
+ /*
3364
+ * It's okay if we find dont find dentry which matches
3365
+ * the inode. That's because it might have gotten
3366
+ * renamed to a different inode number
3367
+ */
3368
+ if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
3369
+ skip_remove_dentry = 1;
3370
+ else
3371
+ goto out;
33303372 }
33313373
33323374 if (IS_DIRSYNC(dir))
33333375 ext4_handle_sync(handle);
33343376
3335
- retval = ext4_delete_entry(handle, dir, de, lblk, bh);
3336
- if (retval)
3337
- goto end_unlink;
3338
- dir->i_ctime = dir->i_mtime = current_time(dir);
3339
- ext4_update_dx_flag(dir);
3340
- ext4_mark_inode_dirty(handle, dir);
3377
+ if (!skip_remove_dentry) {
3378
+ retval = ext4_delete_entry(handle, dir, de, lblk, bh);
3379
+ if (retval)
3380
+ goto out;
3381
+ dir->i_ctime = dir->i_mtime = current_time(dir);
3382
+ ext4_update_dx_flag(dir);
3383
+ retval = ext4_mark_inode_dirty(handle, dir);
3384
+ if (retval)
3385
+ goto out;
3386
+ } else {
3387
+ retval = 0;
3388
+ }
33413389 if (inode->i_nlink == 0)
33423390 ext4_warning_inode(inode, "Deleting file '%.*s' with no links",
3343
- dentry->d_name.len, dentry->d_name.name);
3391
+ d_name->len, d_name->name);
33443392 else
33453393 drop_nlink(inode);
33463394 if (!inode->i_nlink)
33473395 ext4_orphan_add(handle, inode);
33483396 inode->i_ctime = current_time(inode);
3349
- ext4_mark_inode_dirty(handle, inode);
3397
+ retval = ext4_mark_inode_dirty(handle, inode);
33503398
3399
+out:
3400
+ brelse(bh);
3401
+ return retval;
3402
+}
3403
+
3404
+static int ext4_unlink(struct inode *dir, struct dentry *dentry)
3405
+{
3406
+ handle_t *handle;
3407
+ int retval;
3408
+
3409
+ if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
3410
+ return -EIO;
3411
+
3412
+ trace_ext4_unlink_enter(dir, dentry);
3413
+ /*
3414
+ * Initialize quotas before so that eventual writes go
3415
+ * in separate transaction
3416
+ */
3417
+ retval = dquot_initialize(dir);
3418
+ if (retval)
3419
+ goto out_trace;
3420
+ retval = dquot_initialize(d_inode(dentry));
3421
+ if (retval)
3422
+ goto out_trace;
3423
+
3424
+ handle = ext4_journal_start(dir, EXT4_HT_DIR,
3425
+ EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
3426
+ if (IS_ERR(handle)) {
3427
+ retval = PTR_ERR(handle);
3428
+ goto out_trace;
3429
+ }
3430
+
3431
+ retval = __ext4_unlink(handle, dir, &dentry->d_name, d_inode(dentry));
3432
+ if (!retval)
3433
+ ext4_fc_track_unlink(handle, dentry);
33513434 #ifdef CONFIG_UNICODE
33523435 /* VFS negative dentries are incompatible with Encoding and
33533436 * Case-insensitiveness. Eventually we'll want avoid
....@@ -3358,11 +3441,10 @@
33583441 if (IS_CASEFOLDED(dir))
33593442 d_invalidate(dentry);
33603443 #endif
3361
-
3362
-end_unlink:
3363
- brelse(bh);
33643444 if (handle)
33653445 ext4_journal_stop(handle);
3446
+
3447
+out_trace:
33663448 trace_ext4_unlink_exit(dentry, retval);
33673449 return retval;
33683450 }
....@@ -3442,7 +3524,8 @@
34423524 */
34433525 drop_nlink(inode);
34443526 err = ext4_orphan_add(handle, inode);
3445
- ext4_journal_stop(handle);
3527
+ if (handle)
3528
+ ext4_journal_stop(handle);
34463529 handle = NULL;
34473530 if (err)
34483531 goto err_drop_inode;
....@@ -3477,12 +3560,11 @@
34773560 inode->i_size = disk_link.len - 1;
34783561 }
34793562 EXT4_I(inode)->i_disksize = inode->i_size;
3480
- err = ext4_add_nondir(handle, dentry, inode);
3481
- if (!err && IS_DIRSYNC(dir))
3482
- ext4_handle_sync(handle);
3483
-
3563
+ err = ext4_add_nondir(handle, dentry, &inode);
34843564 if (handle)
34853565 ext4_journal_stop(handle);
3566
+ if (inode)
3567
+ iput(inode);
34863568 goto out_free_encrypted_link;
34873569
34883570 err_drop_inode:
....@@ -3497,12 +3579,49 @@
34973579 return err;
34983580 }
34993581
3582
+int __ext4_link(struct inode *dir, struct inode *inode, struct dentry *dentry)
3583
+{
3584
+ handle_t *handle;
3585
+ int err, retries = 0;
3586
+retry:
3587
+ handle = ext4_journal_start(dir, EXT4_HT_DIR,
3588
+ (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
3589
+ EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 1);
3590
+ if (IS_ERR(handle))
3591
+ return PTR_ERR(handle);
3592
+
3593
+ if (IS_DIRSYNC(dir))
3594
+ ext4_handle_sync(handle);
3595
+
3596
+ inode->i_ctime = current_time(inode);
3597
+ ext4_inc_count(inode);
3598
+ ihold(inode);
3599
+
3600
+ err = ext4_add_entry(handle, dentry, inode);
3601
+ if (!err) {
3602
+ err = ext4_mark_inode_dirty(handle, inode);
3603
+ /* this can happen only for tmpfile being
3604
+ * linked the first time
3605
+ */
3606
+ if (inode->i_nlink == 1)
3607
+ ext4_orphan_del(handle, inode);
3608
+ d_instantiate(dentry, inode);
3609
+ ext4_fc_track_link(handle, dentry);
3610
+ } else {
3611
+ drop_nlink(inode);
3612
+ iput(inode);
3613
+ }
3614
+ ext4_journal_stop(handle);
3615
+ if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
3616
+ goto retry;
3617
+ return err;
3618
+}
3619
+
35003620 static int ext4_link(struct dentry *old_dentry,
35013621 struct inode *dir, struct dentry *dentry)
35023622 {
3503
- handle_t *handle;
35043623 struct inode *inode = d_inode(old_dentry);
3505
- int err, retries = 0;
3624
+ int err;
35063625
35073626 if (inode->i_nlink >= EXT4_LINK_MAX)
35083627 return -EMLINK;
....@@ -3519,40 +3638,8 @@
35193638 err = dquot_initialize(dir);
35203639 if (err)
35213640 return err;
3522
-
3523
-retry:
3524
- handle = ext4_journal_start(dir, EXT4_HT_DIR,
3525
- (EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
3526
- EXT4_INDEX_EXTRA_TRANS_BLOCKS) + 1);
3527
- if (IS_ERR(handle))
3528
- return PTR_ERR(handle);
3529
-
3530
- if (IS_DIRSYNC(dir))
3531
- ext4_handle_sync(handle);
3532
-
3533
- inode->i_ctime = current_time(inode);
3534
- ext4_inc_count(handle, inode);
3535
- ihold(inode);
3536
-
3537
- err = ext4_add_entry(handle, dentry, inode);
3538
- if (!err) {
3539
- ext4_mark_inode_dirty(handle, inode);
3540
- /* this can happen only for tmpfile being
3541
- * linked the first time
3542
- */
3543
- if (inode->i_nlink == 1)
3544
- ext4_orphan_del(handle, inode);
3545
- d_instantiate(dentry, inode);
3546
- } else {
3547
- drop_nlink(inode);
3548
- iput(inode);
3549
- }
3550
- ext4_journal_stop(handle);
3551
- if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
3552
- goto retry;
3553
- return err;
3641
+ return __ext4_link(dir, inode, dentry);
35543642 }
3555
-
35563643
35573644 /*
35583645 * Try to find buffer head where contains the parent block.
....@@ -3568,6 +3655,9 @@
35683655 struct buffer_head *bh;
35693656
35703657 if (!ext4_has_inline_data(inode)) {
3658
+ struct ext4_dir_entry_2 *de;
3659
+ unsigned int offset;
3660
+
35713661 /* The first directory block must not be a hole, so
35723662 * treat it as DIRENT_HTREE
35733663 */
....@@ -3576,9 +3666,30 @@
35763666 *retval = PTR_ERR(bh);
35773667 return NULL;
35783668 }
3579
- *parent_de = ext4_next_entry(
3580
- (struct ext4_dir_entry_2 *)bh->b_data,
3581
- inode->i_sb->s_blocksize);
3669
+
3670
+ de = (struct ext4_dir_entry_2 *) bh->b_data;
3671
+ if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data,
3672
+ bh->b_size, 0, 0) ||
3673
+ le32_to_cpu(de->inode) != inode->i_ino ||
3674
+ strcmp(".", de->name)) {
3675
+ EXT4_ERROR_INODE(inode, "directory missing '.'");
3676
+ brelse(bh);
3677
+ *retval = -EFSCORRUPTED;
3678
+ return NULL;
3679
+ }
3680
+ offset = ext4_rec_len_from_disk(de->rec_len,
3681
+ inode->i_sb->s_blocksize);
3682
+ de = ext4_next_entry(de, inode->i_sb->s_blocksize);
3683
+ if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data,
3684
+ bh->b_size, 0, offset) ||
3685
+ le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
3686
+ EXT4_ERROR_INODE(inode, "directory missing '..'");
3687
+ brelse(bh);
3688
+ *retval = -EFSCORRUPTED;
3689
+ return NULL;
3690
+ }
3691
+ *parent_de = de;
3692
+
35823693 return bh;
35833694 }
35843695
....@@ -3633,9 +3744,8 @@
36333744 ent->inode,
36343745 ent->dir_bh);
36353746 } else {
3636
- retval = ext4_handle_dirty_dirent_node(handle,
3637
- ent->inode,
3638
- ent->dir_bh);
3747
+ retval = ext4_handle_dirty_dirblock(handle, ent->inode,
3748
+ ent->dir_bh);
36393749 }
36403750 } else {
36413751 retval = ext4_mark_inode_dirty(handle, ent->inode);
....@@ -3650,7 +3760,7 @@
36503760 static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
36513761 unsigned ino, unsigned file_type)
36523762 {
3653
- int retval;
3763
+ int retval, retval2;
36543764
36553765 BUFFER_TRACE(ent->bh, "get write access");
36563766 retval = ext4_journal_get_write_access(handle, ent->bh);
....@@ -3662,18 +3772,16 @@
36623772 inode_inc_iversion(ent->dir);
36633773 ent->dir->i_ctime = ent->dir->i_mtime =
36643774 current_time(ent->dir);
3665
- ext4_mark_inode_dirty(handle, ent->dir);
3775
+ retval = ext4_mark_inode_dirty(handle, ent->dir);
36663776 BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata");
36673777 if (!ent->inlined) {
3668
- retval = ext4_handle_dirty_dirent_node(handle,
3669
- ent->dir, ent->bh);
3670
- if (unlikely(retval)) {
3671
- ext4_std_error(ent->dir->i_sb, retval);
3672
- return retval;
3778
+ retval2 = ext4_handle_dirty_dirblock(handle, ent->dir, ent->bh);
3779
+ if (unlikely(retval2)) {
3780
+ ext4_std_error(ent->dir->i_sb, retval2);
3781
+ return retval2;
36733782 }
36743783 }
3675
-
3676
- return 0;
3784
+ return retval;
36773785 }
36783786
36793787 static void ext4_resetent(handle_t *handle, struct ext4_renament *ent,
....@@ -3757,9 +3865,9 @@
37573865 {
37583866 if (ent->dir_nlink_delta) {
37593867 if (ent->dir_nlink_delta == -1)
3760
- ext4_dec_count(handle, ent->dir);
3868
+ ext4_dec_count(ent->dir);
37613869 else
3762
- ext4_inc_count(handle, ent->dir);
3870
+ ext4_inc_count(ent->dir);
37633871 ext4_mark_inode_dirty(handle, ent->dir);
37643872 }
37653873 }
....@@ -3935,7 +4043,10 @@
39354043 EXT4_FT_CHRDEV);
39364044 if (retval)
39374045 goto end_rename;
3938
- ext4_mark_inode_dirty(handle, whiteout);
4046
+ retval = ext4_mark_inode_dirty(handle, whiteout);
4047
+ if (unlikely(retval))
4048
+ goto end_rename;
4049
+
39394050 }
39404051 if (!new.bh) {
39414052 retval = ext4_add_entry(handle, new.dentry, old.inode);
....@@ -3956,7 +4067,9 @@
39564067 * rename.
39574068 */
39584069 old.inode->i_ctime = current_time(old.inode);
3959
- ext4_mark_inode_dirty(handle, old.inode);
4070
+ retval = ext4_mark_inode_dirty(handle, old.inode);
4071
+ if (unlikely(retval))
4072
+ goto end_rename;
39604073
39614074 if (!whiteout) {
39624075 /*
....@@ -3966,7 +4079,7 @@
39664079 }
39674080
39684081 if (new.inode) {
3969
- ext4_dec_count(handle, new.inode);
4082
+ ext4_dec_count(new.inode);
39704083 new.inode->i_ctime = current_time(new.inode);
39714084 }
39724085 old.dir->i_ctime = old.dir->i_mtime = current_time(old.dir);
....@@ -3976,21 +4089,45 @@
39764089 if (retval)
39774090 goto end_rename;
39784091
3979
- ext4_dec_count(handle, old.dir);
4092
+ ext4_dec_count(old.dir);
39804093 if (new.inode) {
39814094 /* checked ext4_empty_dir above, can't have another
39824095 * parent, ext4_dec_count() won't work for many-linked
39834096 * dirs */
39844097 clear_nlink(new.inode);
39854098 } else {
3986
- ext4_inc_count(handle, new.dir);
4099
+ ext4_inc_count(new.dir);
39874100 ext4_update_dx_flag(new.dir);
3988
- ext4_mark_inode_dirty(handle, new.dir);
4101
+ retval = ext4_mark_inode_dirty(handle, new.dir);
4102
+ if (unlikely(retval))
4103
+ goto end_rename;
39894104 }
39904105 }
3991
- ext4_mark_inode_dirty(handle, old.dir);
4106
+ retval = ext4_mark_inode_dirty(handle, old.dir);
4107
+ if (unlikely(retval))
4108
+ goto end_rename;
4109
+
4110
+ if (S_ISDIR(old.inode->i_mode)) {
4111
+ /*
4112
+ * We disable fast commits here that's because the
4113
+ * replay code is not yet capable of changing dot dot
4114
+ * dirents in directories.
4115
+ */
4116
+ ext4_fc_mark_ineligible(old.inode->i_sb,
4117
+ EXT4_FC_REASON_RENAME_DIR);
4118
+ } else {
4119
+ if (new.inode)
4120
+ ext4_fc_track_unlink(handle, new.dentry);
4121
+ __ext4_fc_track_link(handle, old.inode, new.dentry);
4122
+ __ext4_fc_track_unlink(handle, old.inode, old.dentry);
4123
+ if (whiteout)
4124
+ __ext4_fc_track_create(handle, whiteout, old.dentry);
4125
+ }
4126
+
39924127 if (new.inode) {
3993
- ext4_mark_inode_dirty(handle, new.inode);
4128
+ retval = ext4_mark_inode_dirty(handle, new.inode);
4129
+ if (unlikely(retval))
4130
+ goto end_rename;
39944131 if (!new.inode->i_nlink)
39954132 ext4_orphan_add(handle, new.inode);
39964133 }
....@@ -4130,9 +4267,14 @@
41304267 ctime = current_time(old.inode);
41314268 old.inode->i_ctime = ctime;
41324269 new.inode->i_ctime = ctime;
4133
- ext4_mark_inode_dirty(handle, old.inode);
4134
- ext4_mark_inode_dirty(handle, new.inode);
4135
-
4270
+ retval = ext4_mark_inode_dirty(handle, old.inode);
4271
+ if (unlikely(retval))
4272
+ goto end_rename;
4273
+ retval = ext4_mark_inode_dirty(handle, new.inode);
4274
+ if (unlikely(retval))
4275
+ goto end_rename;
4276
+ ext4_fc_mark_ineligible(new.inode->i_sb,
4277
+ EXT4_FC_REASON_CROSS_RENAME);
41364278 if (old.dir_bh) {
41374279 retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino);
41384280 if (retval)