Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ext4: move dcache manipulation out of __ext4_link()

__ext4_link() has two callers.

- ext4_link() calls it during normal handling of the link() system
call or similar
- ext4_fc_replay_link_internal() calls it when replaying the journal
at mount time.

The former needs changes to dcache - instantiating the dentry to the
inode on success. The latter doesn't need or want any dcache
manipulation.

So move the manipulation out of __ext4_link() and do it in ext4_link()
only.

This requires:
- passing the qname from the dentry explicitly to __ext4_link.
The parent dir is already passed. The dentry is still passed
in the ext4_link() case purely for use by ext4_fc_track_link().
- passing the inode separately to ext4_fc_track_link() as the
dentry will not be instantiated yet.
- using __ext4_add_entry() in ext4_link, which doesn't need a dentry.
- moving ihold(), d_instantiate(), drop_nlink() and iput() calls out
of __ext4_link() into ext4_link().

Note that ext4_inc_count() and drop_nlink() remain in __ext4_link()
as both callers need them and they are not related to the dentry.

This substantially simplifies ext4_fc_replay_link_internal(), and
removes a use of d_alloc() which, it is planned, will be removed.

Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: NeilBrown <neil@brown.name>
Link: https://patch.msgid.link/20260320000838.3797494-4-neilb@ownmail.net
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

authored by

NeilBrown and committed by
Theodore Ts'o
52b4fea1 0f5f14f3

+18 -38
+3 -2
fs/ext4/ext4.h
··· 2971 2971 void __ext4_fc_track_link(handle_t *handle, struct inode *inode, 2972 2972 struct dentry *dentry); 2973 2973 void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry); 2974 - void ext4_fc_track_link(handle_t *handle, struct dentry *dentry); 2974 + void ext4_fc_track_link(handle_t *handle, struct inode *inode, 2975 + struct dentry *dentry); 2975 2976 void __ext4_fc_track_create(handle_t *handle, struct inode *inode, 2976 2977 struct dentry *dentry); 2977 2978 void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); ··· 3717 3716 extern int __ext4_unlink(struct inode *dir, const struct qstr *d_name, 3718 3717 struct inode *inode, struct dentry *dentry); 3719 3718 extern int __ext4_link(struct inode *dir, struct inode *inode, 3720 - struct dentry *dentry); 3719 + const struct qstr *d_name, struct dentry *dentry); 3721 3720 3722 3721 #define S_SHIFT 12 3723 3722 static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
+4 -28
fs/ext4/fast_commit.c
··· 497 497 trace_ext4_fc_track_link(handle, inode, dentry, ret); 498 498 } 499 499 500 - void ext4_fc_track_link(handle_t *handle, struct dentry *dentry) 500 + void ext4_fc_track_link(handle_t *handle, struct inode *inode, 501 + struct dentry *dentry) 501 502 { 502 - struct inode *inode = d_inode(dentry); 503 - 504 503 if (ext4_fc_eligible(inode->i_sb)) 505 504 __ext4_fc_track_link(handle, inode, dentry); 506 505 } ··· 1430 1431 struct inode *inode) 1431 1432 { 1432 1433 struct inode *dir = NULL; 1433 - struct dentry *dentry_dir = NULL, *dentry_inode = NULL; 1434 1434 struct qstr qstr_dname = QSTR_INIT(darg->dname, darg->dname_len); 1435 1435 int ret = 0; 1436 1436 ··· 1440 1442 goto out; 1441 1443 } 1442 1444 1443 - dentry_dir = d_obtain_alias(dir); 1444 - if (IS_ERR(dentry_dir)) { 1445 - ext4_debug("Failed to obtain dentry"); 1446 - dentry_dir = NULL; 1447 - goto out; 1448 - } 1449 - 1450 - dentry_inode = d_alloc(dentry_dir, &qstr_dname); 1451 - if (!dentry_inode) { 1452 - ext4_debug("Inode dentry not created."); 1453 - ret = -ENOMEM; 1454 - goto out; 1455 - } 1456 - 1457 - ret = __ext4_link(dir, inode, dentry_inode); 1445 + ret = __ext4_link(dir, inode, &qstr_dname, NULL); 1458 1446 /* 1459 1447 * It's possible that link already existed since data blocks 1460 1448 * for the dir in question got persisted before we crashed OR ··· 1454 1470 1455 1471 ret = 0; 1456 1472 out: 1457 - if (dentry_dir) { 1458 - d_drop(dentry_dir); 1459 - dput(dentry_dir); 1460 - } else if (dir) { 1473 + if (dir) 1461 1474 iput(dir); 1462 - } 1463 - if (dentry_inode) { 1464 - d_drop(dentry_inode); 1465 - dput(dentry_inode); 1466 - } 1467 1475 1468 1476 return ret; 1469 1477 }
+11 -8
fs/ext4/namei.c
··· 3452 3452 return err; 3453 3453 } 3454 3454 3455 - int __ext4_link(struct inode *dir, struct inode *inode, struct dentry *dentry) 3455 + int __ext4_link(struct inode *dir, struct inode *inode, 3456 + const struct qstr *d_name, struct dentry *dentry) 3456 3457 { 3457 3458 handle_t *handle; 3458 3459 int err, retries = 0; ··· 3469 3468 3470 3469 inode_set_ctime_current(inode); 3471 3470 ext4_inc_count(inode); 3472 - ihold(inode); 3473 3471 3474 - err = ext4_add_entry(handle, dentry, inode); 3472 + err = __ext4_add_entry(handle, dir, d_name, inode); 3475 3473 if (!err) { 3476 3474 err = ext4_mark_inode_dirty(handle, inode); 3477 3475 /* this can happen only for tmpfile being ··· 3478 3478 */ 3479 3479 if (inode->i_nlink == 1) 3480 3480 ext4_orphan_del(handle, inode); 3481 - d_instantiate(dentry, inode); 3482 - ext4_fc_track_link(handle, dentry); 3481 + if (dentry) 3482 + ext4_fc_track_link(handle, inode, dentry); 3483 3483 } else { 3484 3484 drop_nlink(inode); 3485 - iput(inode); 3486 3485 } 3487 3486 ext4_journal_stop(handle); 3488 3487 if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) ··· 3510 3511 err = dquot_initialize(dir); 3511 3512 if (err) 3512 3513 return err; 3513 - return __ext4_link(dir, inode, dentry); 3514 + err = __ext4_link(dir, inode, &dentry->d_name, dentry); 3515 + if (!err) { 3516 + ihold(inode); 3517 + d_instantiate(dentry, inode); 3518 + } 3519 + return err; 3514 3520 } 3515 - 3516 3521 /* 3517 3522 * Try to find buffer head where contains the parent block. 3518 3523 * It should be the inode block if it is inlined or the 1st block