diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2024-02-03 07:17:34 +0100 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2024-02-25 08:10:32 +0100 |
commit | 9fa8e282c2bfe93338e81a620a49f5903a745231 (patch) | |
tree | f917ad4973fd6376d0139e46acd9d063b993fb34 /fs | |
parent | cifs_get_link(): bail out in unsafe case (diff) | |
download | linux-9fa8e282c2bfe93338e81a620a49f5903a745231.tar.xz linux-9fa8e282c2bfe93338e81a620a49f5903a745231.zip |
ext4_get_link(): fix breakage in RCU mode
1) errors from ext4_getblk() should not be propagated to caller
unless we are really sure that we would've gotten the same error
in non-RCU pathwalk.
2) we leak buffer_heads if ext4_getblk() is successful, but bh is
not uptodate.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/symlink.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 75bf1f88843c..645240cc0229 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c @@ -92,10 +92,12 @@ static const char *ext4_get_link(struct dentry *dentry, struct inode *inode, if (!dentry) { bh = ext4_getblk(NULL, inode, 0, EXT4_GET_BLOCKS_CACHED_NOWAIT); - if (IS_ERR(bh)) - return ERR_CAST(bh); - if (!bh || !ext4_buffer_uptodate(bh)) + if (IS_ERR(bh) || !bh) return ERR_PTR(-ECHILD); + if (!ext4_buffer_uptodate(bh)) { + brelse(bh); + return ERR_PTR(-ECHILD); + } } else { bh = ext4_bread(NULL, inode, 0, 0); if (IS_ERR(bh)) |