From b1ad1f4efce23ad0801492c0d5ffa8c0aa6a8cdb Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 21 Nov 2002 19:32:45 -0800 Subject: [PATCH] no-buffer-head ext2 option Implements a new set of block address_space_operations which will never attach buffer_heads to file pagecache. These can be turned on for ext2 with the `nobh' mount option. During write-intensive testing on a 7G machine, total buffer_head storage remained below 0.3 megabytes. And those buffer_heads are against ZONE_NORMAL pagecache and will be reclaimed by ZONE_NORMAL memory pressure. This work is, of course, a special for the huge highmem machines. Possibly it obsoletes the buffer_heads_over_limit stuff (which doesn't work terribly well), but that code is simple, and will provide relief for other filesystems. It should be noted that the nobh_prepare_write() function and the PageMappedToDisk() infrastructure is what is needed to solve the problem of user data corruption when the filesystem which backs a sparse MAP_SHARED mapping runs out of space. We can use this code in filemap_nopage() to ensure that all mapped pages have space allocated on-disk. Deliver SIGBUS on ENOSPC. This will require a new address_space op, I expect. --- include/linux/buffer_head.h | 3 +++ include/linux/ext2_fs.h | 1 + include/linux/page-flags.h | 5 +++++ 3 files changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 8587dd6f7146..4e7a9bbf99dd 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -190,6 +190,9 @@ sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); int generic_commit_write(struct file *, struct page *, unsigned, unsigned); int block_truncate_page(struct address_space *, loff_t, get_block_t *); int file_fsync(struct file *, struct dentry *, int); +int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*); +int nobh_commit_write(struct file *, struct page *, unsigned, unsigned); +int nobh_truncate_page(struct address_space *, loff_t); #define OSYNC_METADATA (1<<0) #define OSYNC_DATA (1<<1) diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index 0d008cfb99a8..d701ba88c688 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h @@ -308,6 +308,7 @@ struct ext2_inode { #define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ +#define EXT2_MOUNT_NOBH 0x0100 /* No buffer_heads */ #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ #define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ #define EXT2_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 44480d80952f..f02449871c07 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -70,6 +70,7 @@ #define PG_chainlock 15 /* lock bit for ->pte_chain */ #define PG_direct 16 /* ->pte_chain points directly at pte */ +#define PG_mappedtodisk 17 /* Has blocks allocated on-disk */ /* * Global page accounting. One instance per CPU. Only unsigned longs are @@ -233,6 +234,10 @@ extern void get_full_page_state(struct page_state *ret); #define ClearPageDirect(page) clear_bit(PG_direct, &(page)->flags) #define TestClearPageDirect(page) test_and_clear_bit(PG_direct, &(page)->flags) +#define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) +#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) +#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) + /* * The PageSwapCache predicate doesn't use a PG_flag at this time, * but it may again do so one day. -- cgit v1.2.3