mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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>
This commit is contained in:
@@ -2971,7 +2971,8 @@ void __ext4_fc_track_unlink(handle_t *handle, struct inode *inode,
|
||||
void __ext4_fc_track_link(handle_t *handle, struct inode *inode,
|
||||
struct dentry *dentry);
|
||||
void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry);
|
||||
void ext4_fc_track_link(handle_t *handle, struct dentry *dentry);
|
||||
void ext4_fc_track_link(handle_t *handle, struct inode *inode,
|
||||
struct dentry *dentry);
|
||||
void __ext4_fc_track_create(handle_t *handle, struct inode *inode,
|
||||
struct dentry *dentry);
|
||||
void ext4_fc_track_create(handle_t *handle, struct dentry *dentry);
|
||||
@@ -3716,7 +3717,7 @@ extern int ext4_handle_dirty_dirblock(handle_t *handle, struct inode *inode,
|
||||
extern int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
|
||||
struct inode *inode, struct dentry *dentry);
|
||||
extern int __ext4_link(struct inode *dir, struct inode *inode,
|
||||
struct dentry *dentry);
|
||||
const struct qstr *d_name, struct dentry *dentry);
|
||||
|
||||
#define S_SHIFT 12
|
||||
static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
|
||||
|
||||
@@ -497,10 +497,9 @@ void __ext4_fc_track_link(handle_t *handle,
|
||||
trace_ext4_fc_track_link(handle, inode, dentry, ret);
|
||||
}
|
||||
|
||||
void ext4_fc_track_link(handle_t *handle, struct dentry *dentry)
|
||||
void ext4_fc_track_link(handle_t *handle, struct inode *inode,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (ext4_fc_eligible(inode->i_sb))
|
||||
__ext4_fc_track_link(handle, inode, dentry);
|
||||
}
|
||||
@@ -1431,7 +1430,6 @@ static int ext4_fc_replay_link_internal(struct super_block *sb,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct inode *dir = NULL;
|
||||
struct dentry *dentry_dir = NULL, *dentry_inode = NULL;
|
||||
struct qstr qstr_dname = QSTR_INIT(darg->dname, darg->dname_len);
|
||||
int ret = 0;
|
||||
|
||||
@@ -1442,21 +1440,7 @@ static int ext4_fc_replay_link_internal(struct super_block *sb,
|
||||
goto out;
|
||||
}
|
||||
|
||||
dentry_dir = d_obtain_alias(dir);
|
||||
if (IS_ERR(dentry_dir)) {
|
||||
ext4_debug("Failed to obtain dentry");
|
||||
dentry_dir = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dentry_inode = d_alloc(dentry_dir, &qstr_dname);
|
||||
if (!dentry_inode) {
|
||||
ext4_debug("Inode dentry not created.");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __ext4_link(dir, inode, dentry_inode);
|
||||
ret = __ext4_link(dir, inode, &qstr_dname, NULL);
|
||||
/*
|
||||
* It's possible that link already existed since data blocks
|
||||
* for the dir in question got persisted before we crashed OR
|
||||
@@ -1470,16 +1454,8 @@ static int ext4_fc_replay_link_internal(struct super_block *sb,
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (dentry_dir) {
|
||||
d_drop(dentry_dir);
|
||||
dput(dentry_dir);
|
||||
} else if (dir) {
|
||||
if (dir)
|
||||
iput(dir);
|
||||
}
|
||||
if (dentry_inode) {
|
||||
d_drop(dentry_inode);
|
||||
dput(dentry_inode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3452,7 +3452,8 @@ out_retry:
|
||||
return err;
|
||||
}
|
||||
|
||||
int __ext4_link(struct inode *dir, struct inode *inode, struct dentry *dentry)
|
||||
int __ext4_link(struct inode *dir, struct inode *inode,
|
||||
const struct qstr *d_name, struct dentry *dentry)
|
||||
{
|
||||
handle_t *handle;
|
||||
int err, retries = 0;
|
||||
@@ -3468,9 +3469,8 @@ retry:
|
||||
|
||||
inode_set_ctime_current(inode);
|
||||
ext4_inc_count(inode);
|
||||
ihold(inode);
|
||||
|
||||
err = ext4_add_entry(handle, dentry, inode);
|
||||
err = __ext4_add_entry(handle, dir, d_name, inode);
|
||||
if (!err) {
|
||||
err = ext4_mark_inode_dirty(handle, inode);
|
||||
/* this can happen only for tmpfile being
|
||||
@@ -3478,11 +3478,10 @@ retry:
|
||||
*/
|
||||
if (inode->i_nlink == 1)
|
||||
ext4_orphan_del(handle, inode);
|
||||
d_instantiate(dentry, inode);
|
||||
ext4_fc_track_link(handle, dentry);
|
||||
if (dentry)
|
||||
ext4_fc_track_link(handle, inode, dentry);
|
||||
} else {
|
||||
drop_nlink(inode);
|
||||
iput(inode);
|
||||
}
|
||||
ext4_journal_stop(handle);
|
||||
if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
|
||||
@@ -3511,9 +3510,13 @@ static int ext4_link(struct dentry *old_dentry,
|
||||
err = dquot_initialize(dir);
|
||||
if (err)
|
||||
return err;
|
||||
return __ext4_link(dir, inode, dentry);
|
||||
err = __ext4_link(dir, inode, &dentry->d_name, dentry);
|
||||
if (!err) {
|
||||
ihold(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find buffer head where contains the parent block.
|
||||
* It should be the inode block if it is inlined or the 1st block
|
||||
|
||||
Reference in New Issue
Block a user