diff options
author | Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com> | 2009-01-05 22:38:48 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-01-05 22:38:48 -0500 |
commit | c39a7f84d7845aa95d1c7c168f38215aedcc13c2 (patch) | |
tree | 3e9d741df74eef7e6438dfd9a7ab5a32dd5a5501 | |
parent | 6b082b531228c43d454c082fc0f969da1695b060 (diff) | |
download | linux-c39a7f84d7845aa95d1c7c168f38215aedcc13c2.tar.bz2 |
ext4: provide function to release metadata pages under memory pressure
Pages in the page cache belonging to ext4 data files are released via
the ext4_releasepage() function specified in the ext4 inode's
address_space_ops. However, metadata blocks (such as indirect blocks,
directory blocks, etc) are managed via the block device
address_space_ops, and they can not be released by
try_to_free_buffers() if they have a journal head attached to them.
To address this, we supply a release_metadata function which calls
jbd2_journal_try_to_free_buffers() function to free the metadata, and
which is called by the block device's blkdev_releasepage() function.
Signed-off-by: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: linux-fsdevel@vger.kernel.org
-rw-r--r-- | fs/ext4/super.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a3321bf22311..e5ab520724da 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -907,6 +907,25 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, ext4_nfs_get_inode); } +/* + * Try to release metadata pages (indirect blocks, directories) which are + * mapped via the block device. Since these pages could have journal heads + * which would prevent try_to_free_buffers() from freeing them, we must use + * jbd2 layer's try_to_free_buffers() function to release them. + */ +static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_t wait) +{ + journal_t *journal = EXT4_SB(sb)->s_journal; + + WARN_ON(PageChecked(page)); + if (!page_has_buffers(page)) + return 0; + if (journal) + return jbd2_journal_try_to_free_buffers(journal, page, + wait & ~__GFP_WAIT); + return try_to_free_buffers(page); +} + #ifdef CONFIG_QUOTA #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) @@ -971,6 +990,7 @@ static const struct super_operations ext4_sops = { .quota_read = ext4_quota_read, .quota_write = ext4_quota_write, #endif + .bdev_try_to_free_page = bdev_try_to_free_page, }; static const struct export_operations ext4_export_ops = { |