hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/ext4/namei.c
....@@ -341,17 +341,17 @@
341341 struct buffer_head *bh)
342342 {
343343 struct ext4_dir_entry_tail *t;
344
+ int blocksize = EXT4_BLOCK_SIZE(inode->i_sb);
344345
345346 #ifdef PARANOID
346347 struct ext4_dir_entry *d, *top;
347348
348349 d = (struct ext4_dir_entry *)bh->b_data;
349350 top = (struct ext4_dir_entry *)(bh->b_data +
350
- (EXT4_BLOCK_SIZE(inode->i_sb) -
351
- sizeof(struct ext4_dir_entry_tail)));
352
- while (d < top && d->rec_len)
351
+ (blocksize - sizeof(struct ext4_dir_entry_tail)));
352
+ while (d < top && ext4_rec_len_from_disk(d->rec_len, blocksize))
353353 d = (struct ext4_dir_entry *)(((void *)d) +
354
- le16_to_cpu(d->rec_len));
354
+ ext4_rec_len_from_disk(d->rec_len, blocksize));
355355
356356 if (d != top)
357357 return NULL;
....@@ -362,7 +362,8 @@
362362 #endif
363363
364364 if (t->det_reserved_zero1 ||
365
- le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) ||
365
+ (ext4_rec_len_from_disk(t->det_rec_len, blocksize) !=
366
+ sizeof(struct ext4_dir_entry_tail)) ||
366367 t->det_reserved_zero2 ||
367368 t->det_reserved_ft != EXT4_FT_DIR_CSUM)
368369 return NULL;
....@@ -443,13 +444,14 @@
443444 struct ext4_dir_entry *dp;
444445 struct dx_root_info *root;
445446 int count_offset;
447
+ int blocksize = EXT4_BLOCK_SIZE(inode->i_sb);
448
+ unsigned int rlen = ext4_rec_len_from_disk(dirent->rec_len, blocksize);
446449
447
- if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb))
450
+ if (rlen == blocksize)
448451 count_offset = 8;
449
- else if (le16_to_cpu(dirent->rec_len) == 12) {
452
+ else if (rlen == 12) {
450453 dp = (struct ext4_dir_entry *)(((void *)dirent) + 12);
451
- if (le16_to_cpu(dp->rec_len) !=
452
- EXT4_BLOCK_SIZE(inode->i_sb) - 12)
454
+ if (ext4_rec_len_from_disk(dp->rec_len, blocksize) != blocksize - 12)
453455 return NULL;
454456 root = (struct dx_root_info *)(((void *)dp + 12));
455457 if (root->reserved_zero ||
....@@ -1012,7 +1014,7 @@
10121014 * If the hash is 1, then continue only if the next page has a
10131015 * continuation hash of any value. This is used for readdir
10141016 * handling. Otherwise, check to see if the hash matches the
1015
- * desired contiuation hash. If it doesn't, return since
1017
+ * desired continuation hash. If it doesn't, return since
10161018 * there's no point to read in the successive index pages.
10171019 */
10181020 bhash = dx_get_hash(p->at);
....@@ -1299,11 +1301,11 @@
12991301 map_tail--;
13001302 map_tail->hash = h.hash;
13011303 map_tail->offs = ((char *) de - base)>>2;
1302
- map_tail->size = le16_to_cpu(de->rec_len);
1304
+ map_tail->size = ext4_rec_len_from_disk(de->rec_len,
1305
+ blocksize);
13031306 count++;
13041307 cond_resched();
13051308 }
1306
- /* XXX: do we need to check rec_len == 0 case? -Chris */
13071309 de = ext4_next_entry(de, blocksize);
13081310 }
13091311 return count;
....@@ -1580,11 +1582,10 @@
15801582 &has_inline_data);
15811583 if (lblk)
15821584 *lblk = 0;
1583
- if (has_inline_data) {
1584
- if (inlined)
1585
- *inlined = 1;
1585
+ if (inlined)
1586
+ *inlined = has_inline_data;
1587
+ if (has_inline_data)
15861588 goto cleanup_and_exit;
1587
- }
15881589 }
15891590
15901591 if ((namelen <= 2) && (name[0] == '.') &&
....@@ -3343,15 +3344,21 @@
33433344 return retval;
33443345 }
33453346
3346
-int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name,
3347
- struct inode *inode)
3347
+int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
3348
+ struct inode *inode,
3349
+ struct dentry *dentry /* NULL during fast_commit recovery */)
33483350 {
33493351 int retval = -ENOENT;
33503352 struct buffer_head *bh;
33513353 struct ext4_dir_entry_2 *de;
3354
+ handle_t *handle;
33523355 int skip_remove_dentry = 0;
33533356 ext4_lblk_t lblk;
33543357
3358
+ /*
3359
+ * Keep this outside the transaction; it may have to set up the
3360
+ * directory's encryption key, which isn't GFP_NOFS-safe.
3361
+ */
33553362 bh = ext4_find_entry(dir, d_name, &de, NULL, &lblk);
33563363 if (IS_ERR(bh))
33573364 return PTR_ERR(bh);
....@@ -3368,7 +3375,14 @@
33683375 if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
33693376 skip_remove_dentry = 1;
33703377 else
3371
- goto out;
3378
+ goto out_bh;
3379
+ }
3380
+
3381
+ handle = ext4_journal_start(dir, EXT4_HT_DIR,
3382
+ EXT4_DATA_TRANS_BLOCKS(dir->i_sb));
3383
+ if (IS_ERR(handle)) {
3384
+ retval = PTR_ERR(handle);
3385
+ goto out_bh;
33723386 }
33733387
33743388 if (IS_DIRSYNC(dir))
....@@ -3377,12 +3391,12 @@
33773391 if (!skip_remove_dentry) {
33783392 retval = ext4_delete_entry(handle, dir, de, lblk, bh);
33793393 if (retval)
3380
- goto out;
3394
+ goto out_handle;
33813395 dir->i_ctime = dir->i_mtime = current_time(dir);
33823396 ext4_update_dx_flag(dir);
33833397 retval = ext4_mark_inode_dirty(handle, dir);
33843398 if (retval)
3385
- goto out;
3399
+ goto out_handle;
33863400 } else {
33873401 retval = 0;
33883402 }
....@@ -3395,15 +3409,17 @@
33953409 ext4_orphan_add(handle, inode);
33963410 inode->i_ctime = current_time(inode);
33973411 retval = ext4_mark_inode_dirty(handle, inode);
3398
-
3399
-out:
3412
+ if (dentry && !retval)
3413
+ ext4_fc_track_unlink(handle, dentry);
3414
+out_handle:
3415
+ ext4_journal_stop(handle);
3416
+out_bh:
34003417 brelse(bh);
34013418 return retval;
34023419 }
34033420
34043421 static int ext4_unlink(struct inode *dir, struct dentry *dentry)
34053422 {
3406
- handle_t *handle;
34073423 int retval;
34083424
34093425 if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb))))
....@@ -3421,16 +3437,7 @@
34213437 if (retval)
34223438 goto out_trace;
34233439
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);
3440
+ retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry), dentry);
34343441 #ifdef CONFIG_UNICODE
34353442 /* VFS negative dentries are incompatible with Encoding and
34363443 * Case-insensitiveness. Eventually we'll want avoid
....@@ -3441,8 +3448,6 @@
34413448 if (IS_CASEFOLDED(dir))
34423449 d_invalidate(dentry);
34433450 #endif
3444
- if (handle)
3445
- ext4_journal_stop(handle);
34463451
34473452 out_trace:
34483453 trace_ext4_unlink_exit(dentry, retval);
....@@ -3795,8 +3800,8 @@
37953800 * so the old->de may no longer valid and need to find it again
37963801 * before reset old inode info.
37973802 */
3798
- old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL,
3799
- NULL);
3803
+ old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de,
3804
+ &old.inlined, NULL);
38003805 if (IS_ERR(old.bh))
38013806 retval = PTR_ERR(old.bh);
38023807 if (!old.bh)
....@@ -3948,6 +3953,9 @@
39483953 retval = dquot_initialize(old.dir);
39493954 if (retval)
39503955 return retval;
3956
+ retval = dquot_initialize(old.inode);
3957
+ if (retval)
3958
+ return retval;
39513959 retval = dquot_initialize(new.dir);
39523960 if (retval)
39533961 return retval;
....@@ -3960,10 +3968,11 @@
39603968 return retval;
39613969 }
39623970
3963
- old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL,
3964
- &old.lblk);
3971
+ old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de,
3972
+ &old.inlined, &old.lblk);
39653973 if (IS_ERR(old.bh))
39663974 return PTR_ERR(old.bh);
3975
+
39673976 /*
39683977 * Check for inode number is _not_ due to possible IO errors.
39693978 * We might rmdir the source, keep it as pwd of some process
....@@ -4151,6 +4160,7 @@
41514160 brelse(old.dir_bh);
41524161 brelse(old.bh);
41534162 brelse(new.bh);
4163
+
41544164 return retval;
41554165 }
41564166