diff options
author | Chao Yu <chao2.yu@samsung.com> | 2015-07-14 18:14:06 +0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-08-05 08:08:23 -0700 |
commit | 470f00e9686f0b338a457568229fe7b7d44b8e6a (patch) | |
tree | e3ada22625da1d2e1dffcc9c78c8ee764e0bad18 /fs/f2fs/inline.c | |
parent | 7a04f64d4d5367ade827d75388d66054b535e201 (diff) | |
download | linux-470f00e9686f0b338a457568229fe7b7d44b8e6a.tar.gz linux-470f00e9686f0b338a457568229fe7b7d44b8e6a.tar.bz2 linux-470f00e9686f0b338a457568229fe7b7d44b8e6a.zip |
f2fs: fix to release inode page correctly
In following call path, we will pass a locked and referenced ipage
pointer to get_new_data_page:
- init_inode_metadata
- make_empty_dir
- get_new_data_page
There are two exit paths in get_new_data_page when error occurs:
1) grab_cache_page fails, ipage will not be released;
2) f2fs_reserve_block fails, ipage will be released in callee.
So, it's not consistent for error handling in get_new_data_page.
For f2fs_reserve_block, it's not very easy to change the rule
of error handling, since it's already complicated.
Here we deside to choose an easy way to fix this issue:
If any error occur in get_new_data_page, we will ensure releasing
ipage in this function.
The same issue is in f2fs_convert_inline_dir, fix that too.
Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/inline.c')
-rw-r--r-- | fs/f2fs/inline.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index a13ffcc32992..79d18d5c1fae 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -360,6 +360,10 @@ int make_empty_inline_dir(struct inode *inode, struct inode *parent, return 0; } +/* + * NOTE: ipage is grabbed by caller, but if any error occurs, we should + * release ipage in this function. + */ static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, struct f2fs_inline_dentry *inline_dentry) { @@ -369,8 +373,10 @@ static int f2fs_convert_inline_dir(struct inode *dir, struct page *ipage, int err; page = grab_cache_page(dir->i_mapping, 0); - if (!page) + if (!page) { + f2fs_put_page(ipage, 1); return -ENOMEM; + } set_new_dnode(&dn, dir, ipage, NULL, 0); err = f2fs_reserve_block(&dn, 0); @@ -434,8 +440,9 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name, slots, NR_INLINE_DENTRY); if (bit_pos >= NR_INLINE_DENTRY) { err = f2fs_convert_inline_dir(dir, ipage, dentry_blk); - if (!err) - err = -EAGAIN; + if (err) + return err; + err = -EAGAIN; goto out; } |