Skip to contentSkip to conversation

extent mapped page cache

RFC PATCH In review Chris Mason 6 participants 17 messages Jul 10, 2007 – Jul 27, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 extent mapped page cache

This patch aims to demonstrate one way to replace buffer heads with a few extent trees. Buffer heads provide a few different features:

1) Mapping of logical file offset to blocks on disk
2) Recording state (dirty, locked etc)
3) Providing a mechanism to access sub-page sized blocks.

This patch covers #1 and #2, I'll start on #3 a little later next week.

The file offset to disk block mapping is done in one radix tree, and the state is done in a second radix tree. Extent ranges are stored in the radix trees by inserting into the slot corresponding to the end of the range, and always using gang lookups for searching.

The basic implementation mirrors the page and buffer bits already used, but allows state bits to be set on regions smaller or larger than a single page. Eventually I would like to use this mechanism to replace my DIO locking/placeholder patch.

Ext2 is changed to use the extent mapping code when mounted with -o extentmap. DIO is not supported and readpages/writepages are not yet implemented, but this should be enough to get the basic idea across. Testing has been very very light, I'm mostly sending this out for comments and to continue the discussion started by Nick's patch set.

fs/Makefile +1 -1
diff -r 126111346f94 fs/Makefile
@@ -11,7 +11,7 @@ obj-y :=	open.o read_write.o file_table.
 		attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o \
 		pnode.o drop_caches.o splice.o sync.o utimes.o \
-		stack.o
+		stack.o extent_map.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=	buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
fs/ext2/ext2.h +3 -0
diff -r 126111346f94 fs/ext2/ext2.h
@@ -1,5 +1,6 @@
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
+#include <linux/extent_map.h>
 
 /*
  * ext2 mount options
@@ -65,6 +66,7 @@ struct ext2_inode_info {
 	struct posix_acl	*i_default_acl;
 #endif
 	rwlock_t i_meta_lock;
+	struct extent_map_tree extent_tree;
 	struct inode	vfs_inode;
 };
 
@@ -167,6 +169,7 @@ extern const struct address_space_operat
 extern const struct address_space_operations ext2_aops;
 extern const struct address_space_operations ext2_aops_xip;
 extern const struct address_space_operations ext2_nobh_aops;
+extern const struct address_space_operations ext2_extent_map_aops;
 
 /* namei.c */
 extern const struct inode_operations ext2_dir_inode_operations;
fs/ext2/inode.c +145 -1

184 lines not on this page · raw message

fs/ext2/namei.c +5 -0
diff -r 126111346f94 fs/ext2/namei.c
@@ -112,6 +112,11 @@ static int ext2_create (struct inode * d
 		if (ext2_use_xip(inode->i_sb)) {
 			inode->i_mapping->a_ops = &ext2_aops_xip;
 			inode->i_fop = &ext2_xip_file_operations;
+		} else if (test_opt(inode->i_sb, EXTENTMAP)) {
+			extent_map_tree_init(&EXT2_I(inode)->extent_tree,
+					     inode->i_mapping, GFP_NOFS);
+			inode->i_mapping->a_ops = &ext2_extent_map_aops;
+			inode->i_fop = &ext2_file_operations;
 		} else if (test_opt(inode->i_sb, NOBH)) {
 			inode->i_mapping->a_ops = &ext2_nobh_aops;
 			inode->i_fop = &ext2_file_operations;
fs/ext2/super.c +6 -1
diff -r 126111346f94 fs/ext2/super.c
@@ -319,7 +319,8 @@ enum {
 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
 	Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
-	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
+	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_extent_map,
+	Opt_user_xattr, Opt_nouser_xattr,
 	Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
 	Opt_usrquota, Opt_grpquota
 };
@@ -344,6 +345,7 @@ static match_table_t tokens = {
 	{Opt_oldalloc, "oldalloc"},
 	{Opt_orlov, "orlov"},
 	{Opt_nobh, "nobh"},
+	{Opt_extent_map, "extentmap"},
 	{Opt_user_xattr, "user_xattr"},
 	{Opt_nouser_xattr, "nouser_xattr"},
 	{Opt_acl, "acl"},
@@ -431,6 +433,9 @@ static int parse_options (char * options
 			break;
 		case Opt_nobh:
 			set_opt (sbi->s_mount_opt, NOBH);
+			break;
+		case Opt_extent_map:
+			set_opt (sbi->s_mount_opt, EXTENTMAP);
 			break;
 #ifdef CONFIG_EXT2_FS_XATTR
 		case Opt_user_xattr:
fs/extent_map.c new file +1563 -0

1,563 lines not on this page · raw message

include/linux/ext2_fs.h +1 -0
diff -r 126111346f94 include/linux/ext2_fs.h
@@ -319,6 +319,7 @@ struct ext2_inode {
 #define EXT2_MOUNT_XIP			0x010000  /* Execute in place */
 #define EXT2_MOUNT_USRQUOTA		0x020000 /* user quota */
 #define EXT2_MOUNT_GRPQUOTA		0x040000 /* group quota */
+#define EXT2_MOUNT_EXTENTMAP		0x080000  /* use extent maps */
 
 
 #define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
include/linux/extent_map.h new file +74 -0

74 lines not on this page · raw message

init/main.c +2 -0
diff -r 126111346f94 init/main.c
@@ -94,6 +94,7 @@ extern void pidmap_init(void);
 extern void pidmap_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
+extern void extent_map_init(void);
 extern void free_initmem(void);
 #ifdef	CONFIG_ACPI
 extern void acpi_early_init(void);
@@ -618,6 +619,7 @@ asmlinkage void __init start_kernel(void
 	security_init();
 	vfs_caches_init(num_physpages);
 	radix_tree_init();
+	extent_map_init();
 	signals_init();
 	/* rootfs populating might need page-writeback */
 	page_writeback_init();

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw
Quoted 2 lines · Chris Mason

This patch aims to demonstrate one way to replace buffer heads with a few extent trees...

Hi Chris,

Quite terse commentary on algorithms and data structures, but I suppose that is not a problem because Jon has a whole week to reverse engineer it for us.

What did you have in mind for subpages?

Regards,

Daniel

#2 lore raw
Quoted 4 lines · On Thu, 12 Jul 2007 00:00:28 -0700 Daniel Phillips <[email protected]> wrote:
Quoted 2 lines · Chris Mason

This patch aims to demonstrate one way to replace buffer heads with a few extent trees...

Quoted 8 lines

Hi Chris,

Quite terse commentary on algorithms and data structures, but I suppose that is not a problem because Jon has a whole week to reverse engineer it for us.

What did you have in mind for subpages?

This partially depends on input here. The goal is to have one interface that works for subpages, highmem and superpages, and for the FS maintainers to not care if the mappings come magically from clameter's work or vmap or whatever.

Given the whole extent based theme, I plan on something like this:

struct extent_ptr {
	char *ptr;
	some way to indicate size and type of map
	struct page pages[];
};

struct extent_ptr *alloc_extent_ptr(struct extent_map_tree *tree,

				    u64 start, u64 end);
void free_extent_ptr(struct extent_map_tree *tree,
                     struct extent_ptr *ptr);

And then some calls along the lines of kmap/kunmap that gives you a pointer you can use for accessing the ram. read/write calls would also be fine by me, but harder to convert filesystems to use.

The struct extent_ptr would increase the ref count on the pages, but the pages would have no back pointers to it. All dirty/locked/writeback state would go in the extent state tree and would not be stored in the struct extent_ptr.

The idea is to make a simple mapping entity, and not complicate it by storing FS specific state in there. It could be variably sized to hold an array of pages, and allocated via kmap.

-chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw

RFC PATCH 1/1 extent mapped page cache

In reply to Chris Mason
Quoted 10 lines · On Tue, 10 Jul 2007 17:03:26 -0400 Chris Mason <[email protected]> wrote:

This patch aims to demonstrate one way to replace buffer heads with a few extent trees. Buffer heads provide a few different features:

1) Mapping of logical file offset to blocks on disk
2) Recording state (dirty, locked etc)
3) Providing a mechanism to access sub-page sized blocks.

This patch covers #1 and #2, I'll start on #3 a little later next week.

Well, almost. I decided to try out an rbtree instead of the radix, which turned out to be much faster. Even though individual operations are slower, the rbtree was able to do many fewer ops to accomplish the same thing, especially for merging extents together. It also uses much less ram.

This code still has lots of room for optimization, but it comes in at around 2-5% more cpu time for ext2 streaming reads and writes. I haven't done readpages or writepages yet, so this is more or less a worst case setup. I'm comparing against ext2 with readpages and writepages disabled.

The new code has the added benefit of passing fsx-linux, and not triggering MCE's on my poor little test box.

The basic idea is to store state in byte ranges in an rbtree, and to mirror that state down into individual pages. This allows us to store arbitrary state outside of the page struct, so we could include the pid of the process that dirtied a page range for cfq purposes. The example readpage and writepage code is probably the easiest way to understand the basic API.

A separate rbtree stores a mapping of byte offset in the file to byte offset on disk. This allows the filesystem to fill in mapping information in bulk, and reduces the number of metadata lookups required to do common operations.

Because the state and mapping information are separate from the page, pages can come and go and their corresponding metadata can still be cached (the current code drops mappings as the last page corresponding to that mapping disappears).

Two patches follow, the core extent_map implementation and a sample user (ext2). This is pretty basic, implementing prepare/commit_write, read/writepage and a few other funcs to exercise the new code. Longer term, it should fit in with Nick's other extent work instead of prepare/commit_write.

My patch sets page->private to 1, really for no good reason. It is just a debugging aid I was using to make sure the page took the right path down the line. If this catches on, we might set it to a magic value so you can if (ExtentPage(page)) or just leave it as null.

-chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw

RFC PATCH 1/1 extent mapped page cache main code

Core Extentmap implementation

fs/Makefile +1 -1
diff -r 126111346f94 -r 53cabea328f7 fs/Makefile
@@ -11,7 +11,7 @@ obj-y :=	open.o read_write.o file_table.
 		attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o \
 		pnode.o drop_caches.o splice.o sync.o utimes.o \
-		stack.o
+		stack.o extent_map.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=	buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
fs/extent_map.c new file +1591 -0

1,591 lines not on this page · raw message

include/linux/extent_map.h new file +82 -0

82 lines not on this page · raw message

init/main.c +2 -0
diff -r 126111346f94 -r 53cabea328f7 init/main.c
@@ -94,6 +94,7 @@ extern void pidmap_init(void);
 extern void pidmap_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
+extern void extent_map_init(void);
 extern void free_initmem(void);
 #ifdef	CONFIG_ACPI
 extern void acpi_early_init(void);
@@ -618,6 +619,7 @@ asmlinkage void __init start_kernel(void
 	security_init();
 	vfs_caches_init(num_physpages);
 	radix_tree_init();
+	extent_map_init();
 	signals_init();
 	/* rootfs populating might need page-writeback */
 	page_writeback_init();

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw

RFC PATCH 1/1 ext2 extentmap support

In reply to Chris Mason

mount -o extentmap to use the new stuff

fs/ext2/ext2.h +3 -0
diff -r 126111346f94 -r 53cabea328f7 fs/ext2/ext2.h
@@ -1,5 +1,6 @@
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
+#include <linux/extent_map.h>
 
 /*
  * ext2 mount options
@@ -65,6 +66,7 @@ struct ext2_inode_info {
 	struct posix_acl	*i_default_acl;
 #endif
 	rwlock_t i_meta_lock;
+	struct extent_map_tree extent_tree;
 	struct inode	vfs_inode;
 };
 
@@ -167,6 +169,7 @@ extern const struct address_space_operat
 extern const struct address_space_operations ext2_aops;
 extern const struct address_space_operations ext2_aops_xip;
 extern const struct address_space_operations ext2_nobh_aops;
+extern const struct address_space_operations ext2_extent_map_aops;
 
 /* namei.c */
 extern const struct inode_operations ext2_dir_inode_operations;
fs/ext2/inode.c +157 -2

203 lines not on this page · raw message

fs/ext2/namei.c +5 -0
diff -r 126111346f94 -r 53cabea328f7 fs/ext2/namei.c
@@ -112,6 +112,11 @@ static int ext2_create (struct inode * d
 		if (ext2_use_xip(inode->i_sb)) {
 			inode->i_mapping->a_ops = &ext2_aops_xip;
 			inode->i_fop = &ext2_xip_file_operations;
+		} else if (test_opt(inode->i_sb, EXTENTMAP)) {
+			extent_map_tree_init(&EXT2_I(inode)->extent_tree,
+					     inode->i_mapping, GFP_NOFS);
+			inode->i_mapping->a_ops = &ext2_extent_map_aops;
+			inode->i_fop = &ext2_file_operations;
 		} else if (test_opt(inode->i_sb, NOBH)) {
 			inode->i_mapping->a_ops = &ext2_nobh_aops;
 			inode->i_fop = &ext2_file_operations;
fs/ext2/super.c +6 -1
diff -r 126111346f94 -r 53cabea328f7 fs/ext2/super.c
@@ -319,7 +319,8 @@ enum {
 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
 	Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
-	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
+	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_extent_map,
+	Opt_user_xattr, Opt_nouser_xattr,
 	Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
 	Opt_usrquota, Opt_grpquota
 };
@@ -344,6 +345,7 @@ static match_table_t tokens = {
 	{Opt_oldalloc, "oldalloc"},
 	{Opt_orlov, "orlov"},
 	{Opt_nobh, "nobh"},
+	{Opt_extent_map, "extentmap"},
 	{Opt_user_xattr, "user_xattr"},
 	{Opt_nouser_xattr, "nouser_xattr"},
 	{Opt_acl, "acl"},
@@ -431,6 +433,9 @@ static int parse_options (char * options
 			break;
 		case Opt_nobh:
 			set_opt (sbi->s_mount_opt, NOBH);
+			break;
+		case Opt_extent_map:
+			set_opt (sbi->s_mount_opt, EXTENTMAP);
 			break;
 #ifdef CONFIG_EXT2_FS_XATTR
 		case Opt_user_xattr:
include/linux/ext2_fs.h +1 -0
diff -r 126111346f94 -r 53cabea328f7 include/linux/ext2_fs.h
@@ -319,6 +319,7 @@ struct ext2_inode {
 #define EXT2_MOUNT_XIP			0x010000  /* Execute in place */
 #define EXT2_MOUNT_USRQUOTA		0x020000 /* user quota */
 #define EXT2_MOUNT_GRPQUOTA		0x040000 /* group quota */
+#define EXT2_MOUNT_EXTENTMAP		0x080000  /* use extent maps */
 
 
 #define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw
In reply to Chris Mason
Quoted 10 lines · Chris Mason
Quoted 7 lines · On Tue, 10 Jul 2007 17:03:26 -0400 Chris Mason <[email protected]> wrote:

This patch aims to demonstrate one way to replace buffer heads with a few extent trees. Buffer heads provide a few different features:

1) Mapping of logical file offset to blocks on disk
2) Recording state (dirty, locked etc)
3) Providing a mechanism to access sub-page sized blocks.

Quoted 8 lines
Quoted 3 lines

This patch covers #1 and #2, I'll start on #3 a little later next week.

Well, almost. I decided to try out an rbtree instead of the radix, which turned out to be much faster. Even though individual operations are slower, the rbtree was able to do many fewer ops to accomplish the same thing, especially for merging extents together. It also uses much less ram.

The problem with an rbtree is that you can't use it together with RCU to do lockless lookups. You can probably modify it to allocate nodes dynamically (like the radix tree does) and thus make it RCU-compatible, but then you risk losing the two main benefits that you list above.

Trond

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw
Quoted 20 lines · Trond Myklebust
Quoted 10 lines · Chris Mason
Quoted 7 lines · On Tue, 10 Jul 2007 17:03:26 -0400 Chris Mason <[email protected]> wrote:

This patch aims to demonstrate one way to replace buffer heads with a few extent trees. Buffer heads provide a few different features:

1) Mapping of logical file offset to blocks on disk
2) Recording state (dirty, locked etc)
3) Providing a mechanism to access sub-page sized blocks.

Quoted 8 lines
Quoted 3 lines

This patch covers #1 and #2, I'll start on #3 a little later next week.

Well, almost. I decided to try out an rbtree instead of the radix, which turned out to be much faster. Even though individual operations are slower, the rbtree was able to do many fewer ops to accomplish the same thing, especially for merging extents together. It also uses much less ram.

Quoted 4 lines

The problem with an rbtree is that you can't use it together with RCU to do lockless lookups. You can probably modify it to allocate nodes dynamically (like the radix tree does) and thus make it RCU-compatible, but then you risk losing the two main benefits that you list above.

I thought on this, and I came to the conclusion that the tree rotations used to balance binary trees are incompatible with RCU. The rotation can hide one branch. Hence I started writing a B+tree that is RCU compatible much like the Radix tree.

Current code here:
http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch

Still needs some work, but is usable.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw
Quoted 22 lines · On Tue, 24 Jul 2007 23:25:43 +0200 Peter Zijlstra <[email protected]>…
Quoted 21 lines · Trond Myklebust
Quoted 19 lines · Chris Mason
Quoted 11 lines · On Tue, 10 Jul 2007 17:03:26 -0400 Chris Mason <[email protected]> wrote:

This patch aims to demonstrate one way to replace buffer heads with a few extent trees. Buffer heads provide a few different features:

1) Mapping of logical file offset to blocks on disk
2) Recording state (dirty, locked etc)
3) Providing a mechanism to access sub-page sized blocks.

This patch covers #1 and #2, I'll start on #3 a little later next week.

Well, almost. I decided to try out an rbtree instead of the radix, which turned out to be much faster. Even though individual operations are slower, the rbtree was able to do many fewer ops to accomplish the same thing, especially for merging extents together. It also uses much less ram.

Quoted 5 lines
Quoted 5 lines

The problem with an rbtree is that you can't use it together with RCU to do lockless lookups. You can probably modify it to allocate nodes dynamically (like the radix tree does) and thus make it RCU-compatible, but then you risk losing the two main benefits that you list above.

The tree is a critical part of the patch, but it is also the easiest to rip out and replace. Basically the code stores a range by inserting an object at an index corresponding to the end of the range.

Then it does searches by looking forward from the start of the range. More or less any tree that can search and return the first key >= than the requested key will work.

So, I'd be happy to rip out the tree and replace with something else. Going completely lockless will be tricky, its something that will deep thought once the rest of the interface is sane.

-chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw
Quoted 7 lines · Chris Mason

On Tue, 24 Jul 2007 23:25:43 +0200
Peter Zijlstra <[email protected]> wrote:

The tree is a critical part of the patch, but it is also the easiest to rip out and replace. Basically the code stores a range by inserting an object at an index corresponding to the end of the range.

Quoted 7 lines

Then it does searches by looking forward from the start of the range. More or less any tree that can search and return the first key >= than the requested key will work.

So, I'd be happy to rip out the tree and replace with something else. Going completely lockless will be tricky, its something that will deep thought once the rest of the interface is sane.

Just having the other tree and managing it is what makes me a little less positive of this approach, especially using it to store pagecache state when we already have the pagecache tree.

Having another tree to store block state I think is a good idea as I said in the fsblock thread with Dave, but I haven't clicked as to why it is a big advantage to use it to manage pagecache state. (and I can see some possible disadvantages in locking and tree manipulation overhead).

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw
Quoted 21 lines · On Wed, 25 Jul 2007 04:32:17 +0200 Nick Piggin <[email protected]> wrote:
Quoted 8 lines · Chris Mason

On Tue, 24 Jul 2007 23:25:43 +0200
Peter Zijlstra <[email protected]> wrote:

The tree is a critical part of the patch, but it is also the easiest to rip out and replace. Basically the code stores a range by inserting an object at an index corresponding to the end of the range.

Quoted 7 lines

Then it does searches by looking forward from the start of the range. More or less any tree that can search and return the first key >= than the requested key will work.

So, I'd be happy to rip out the tree and replace with something else. Going completely lockless will be tricky, its something that will deep thought once the rest of the interface is sane.

Just having the other tree and managing it is what makes me a little less positive of this approach, especially using it to store pagecache state when we already have the pagecache tree.

Quoted 5 lines

Having another tree to store block state I think is a good idea as I said in the fsblock thread with Dave, but I haven't clicked as to why it is a big advantage to use it to manage pagecache state. (and I can see some possible disadvantages in locking and tree manipulation overhead).

Yes, there are definitely costs with the state tree, it will take some careful benchmarking to convince me it is a feasible solution. But, storing all the state in the pages themselves is impossible unless the block size equals the page size. So, we end up with something like fsblock/buffer heads or the state tree.

One advantage to the state tree is that it separates the state from the memory being described, allowing a simple kmap style interface that covers subpages, highmem and superpages.

It also more naturally matches the way we want to do IO, making for easy clustering.

O_DIRECT becomes a special case of readpages and writepages....the memory used for IO just comes from userland instead of the page cache.

The ability to put in additional tracking info like the process that first dirtied a range is also significant. So, I think it is worth trying.

-chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#11 lore raw
Quoted 9 lines · Chris Mason
Quoted 5 lines · On Wed, 25 Jul 2007 04:32:17 +0200 Nick Piggin <[email protected]> wrote:

Having another tree to store block state I think is a good idea as I said in the fsblock thread with Dave, but I haven't clicked as to why it is a big advantage to use it to manage pagecache state. (and I can see some possible disadvantages in locking and tree manipulation overhead).

Quoted 5 lines

Yes, there are definitely costs with the state tree, it will take some careful benchmarking to convince me it is a feasible solution. But, storing all the state in the pages themselves is impossible unless the block size equals the page size. So, we end up with something like fsblock/buffer heads or the state tree.

Yep, we have to have something.

Quoted 3 lines

One advantage to the state tree is that it separates the state from the memory being described, allowing a simple kmap style interface that covers subpages, highmem and superpages.

I suppose so, although we should have added those interfaces long ago ;) The variants in fsblock are pretty good, and you could always do an arbitrary extent (rather than block) based API using the pagecache tree if it would be helpful.

Quoted 2 lines

It also more naturally matches the way we want to do IO, making for easy clustering.

Well the pagecache tree is used to reasonable effect for that now. OK the code isn't beautiful ;). Granted, this might be an area where the seperate state tree ends up being better. We'll see.

Quoted 2 lines

O_DIRECT becomes a special case of readpages and writepages....the memory used for IO just comes from userland instead of the page cache.

Could be, although you'll probably also need to teach the mm about the state tree and/or still manipulate the pagecache tree to prevent concurrency?

But isn't the main aim of O_DIRECT to do as little locking and synchronisation with the pagecache as possible? I thought this is why your race fixing patches got put on the back burner (although they did look fairly nice from a correctness POV).

Well I'm kind of handwaving when it comes to O_DIRECT ;) It does look like this might be another advantage of the state tree (although you aren't allowed to slow down buffered IO to achieve the locking ;)).

Quoted 3 lines

The ability to put in additional tracking info like the process that first dirtied a range is also significant. So, I think it is worth trying.

Definitely, and I'm glad you are. You haven't converted me yet, but I look forward to finding the best ideas from our two approaches when the patches are further along (ext2 port of fsblock coming along, so we'll be able to have races soon :P).

Thanks,
Nick

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#12 lore raw
Quoted 9 lines · On Thu, 26 Jul 2007 03:37:28 +0200 Nick Piggin <[email protected]> wrote:
Quoted 4 lines

One advantage to the state tree is that it separates the state from the memory being described, allowing a simple kmap style interface that covers subpages, highmem and superpages.

I suppose so, although we should have added those interfaces long ago ;) The variants in fsblock are pretty good, and you could always do an arbitrary extent (rather than block) based API using the pagecache tree if it would be helpful.

Yes, you could use fsblock for the state bits and make a separate API to map the actual pages.

Quoted 9 lines
Quoted 4 lines

It also more naturally matches the way we want to do IO, making for easy clustering.

Well the pagecache tree is used to reasonable effect for that now. OK the code isn't beautiful ;). Granted, this might be an area where the seperate state tree ends up being better. We'll see.

One thing it gains us is finding the start of the cluster. Even if called by kswapd, the state tree allows writepage to find the start of the cluster and send down a big bio (provided I implement trylock to avoid various deadlocks).

Quoted 8 lines
Quoted 4 lines

O_DIRECT becomes a special case of readpages and writepages....the memory used for IO just comes from userland instead of the page cache.

Could be, although you'll probably also need to teach the mm about the state tree and/or still manipulate the pagecache tree to prevent concurrency?

Well, it isn't coded yet, but I should be able to do it from the FS specific ops.

Quoted 5 lines

But isn't the main aim of O_DIRECT to do as little locking and synchronisation with the pagecache as possible? I thought this is why your race fixing patches got put on the back burner (although they did look fairly nice from a correctness POV).

I put the placeholder patches on hold because handling a corner case where userland did O_DIRECT from a mmap'd region of the same file (Linus pointed it out to me). Basically my patches had to work in 64k chunks to avoid a deadlock in get_user_pages. With the state tree, I can allow the page to be faulted in but still properly deal with it.

Quoted 4 lines

Well I'm kind of handwaving when it comes to O_DIRECT ;) It does look like this might be another advantage of the state tree (although you aren't allowed to slow down buffered IO to achieve the locking ;)).

;) The O_DIRECT benefit is a fringe thing. I've long wanted to help clean up that code, but the real point of the patch is to make general usage faster and less complex. If I can't get there, the O_DIRECT stuff doesn't matter.

Quoted 10 lines
Quoted 5 lines

The ability to put in additional tracking info like the process that first dirtied a range is also significant. So, I think it is worth trying.

Definitely, and I'm glad you are. You haven't converted me yet, but I look forward to finding the best ideas from our two approaches when the patches are further along (ext2 port of fsblock coming along, so we'll be able to have races soon :P).

I'm sure we can find some river in Cambridge, winner gets to throw Axboe in.

-chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw
Quoted 26 lines · Chris Mason
Quoted 9 lines · On Thu, 26 Jul 2007 03:37:28 +0200 Nick Piggin <[email protected]> wrote:
Quoted 4 lines

One advantage to the state tree is that it separates the state from the memory being described, allowing a simple kmap style interface that covers subpages, highmem and superpages.

I suppose so, although we should have added those interfaces long ago ;) The variants in fsblock are pretty good, and you could always do an arbitrary extent (rather than block) based API using the pagecache tree if it would be helpful.

Yes, you could use fsblock for the state bits and make a separate API to map the actual pages.

Quoted 9 lines
Quoted 4 lines

It also more naturally matches the way we want to do IO, making for easy clustering.

Well the pagecache tree is used to reasonable effect for that now. OK the code isn't beautiful ;). Granted, this might be an area where the seperate state tree ends up being better. We'll see.

Quoted 4 lines

One thing it gains us is finding the start of the cluster. Even if called by kswapd, the state tree allows writepage to find the start of the cluster and send down a big bio (provided I implement trylock to avoid various deadlocks).

That's very true, we could potentially also do that with the block extent tree that I want to try with fsblock.

I'm looking at "cleaning up" some of these aops APIs so hopefully most of the deadlock problems go away. Should be useful to both our efforts. Will post patches hopefully when I get time to finish the draft this weekend.

Quoted 10 lines
Quoted 7 lines
Quoted 3 lines

O_DIRECT becomes a special case of readpages and writepages....the memory used for IO just comes from userland instead of the page cache.

Could be, although you'll probably also need to teach the mm about the state tree and/or still manipulate the pagecache tree to prevent concurrency?

Well, it isn't coded yet, but I should be able to do it from the FS specific ops.

Probably, if you invalidate all the pagecache in the range beforehand you should be able to do it (and I guess you want to do the invalidate anyway). Although, below deadlock issues might still bite somehwere...

Quoted 10 lines
Quoted 4 lines

But isn't the main aim of O_DIRECT to do as little locking and synchronisation with the pagecache as possible? I thought this is why your race fixing patches got put on the back burner (although they did look fairly nice from a correctness POV).

I put the placeholder patches on hold because handling a corner case where userland did O_DIRECT from a mmap'd region of the same file (Linus pointed it out to me). Basically my patches had to work in 64k chunks to avoid a deadlock in get_user_pages. With the state tree, I can allow the page to be faulted in but still properly deal with it.

Oh right, I didn't think of that one. Would you still have similar issues with the external state tree? I mean, the filesystem doesn't really know why the fault is taken. O_DIRECT read from a file into mmapped memory of the same block in the file is almost hopeless I think.

Quoted 8 lines
Quoted 3 lines

Well I'm kind of handwaving when it comes to O_DIRECT ;) It does look like this might be another advantage of the state tree (although you aren't allowed to slow down buffered IO to achieve the locking ;)).

;) The O_DIRECT benefit is a fringe thing. I've long wanted to help clean up that code, but the real point of the patch is to make general usage faster and less complex. If I can't get there, the O_DIRECT stuff doesn't matter.

Sure, although unifying code is always a plus so I like that you've got that in mind.

Quoted 11 lines
Quoted 8 lines
Quoted 3 lines

The ability to put in additional tracking info like the process that first dirtied a range is also significant. So, I think it is worth trying.

Definitely, and I'm glad you are. You haven't converted me yet, but I look forward to finding the best ideas from our two approaches when the patches are further along (ext2 port of fsblock coming along, so we'll be able to have races soon :P).

I'm sure we can find some river in Cambridge, winner gets to throw Axboe in.

Very noble of you to donate your colleage to such a worthy cause.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#14 lore raw
Quoted 96 lines · Nick Piggin
Quoted 26 lines · Chris Mason
Quoted 9 lines · On Thu, 26 Jul 2007 03:37:28 +0200 Nick Piggin <[email protected]> wrote:
Quoted 4 lines

One advantage to the state tree is that it separates the state from the memory being described, allowing a simple kmap style interface that covers subpages, highmem and superpages.

I suppose so, although we should have added those interfaces long ago ;) The variants in fsblock are pretty good, and you could always do an arbitrary extent (rather than block) based API using the pagecache tree if it would be helpful.

Yes, you could use fsblock for the state bits and make a separate API to map the actual pages.

Quoted 9 lines
Quoted 4 lines

It also more naturally matches the way we want to do IO, making for easy clustering.

Well the pagecache tree is used to reasonable effect for that now. OK the code isn't beautiful ;). Granted, this might be an area where the seperate state tree ends up being better. We'll see.

Quoted 4 lines

One thing it gains us is finding the start of the cluster. Even if called by kswapd, the state tree allows writepage to find the start of the cluster and send down a big bio (provided I implement trylock to avoid various deadlocks).

That's very true, we could potentially also do that with the block extent tree that I want to try with fsblock.

I'm looking at "cleaning up" some of these aops APIs so hopefully most of the deadlock problems go away. Should be useful to both our efforts. Will post patches hopefully when I get time to finish the draft this weekend.

Quoted 10 lines
Quoted 7 lines
Quoted 3 lines

O_DIRECT becomes a special case of readpages and writepages....the memory used for IO just comes from userland instead of the page cache.

Could be, although you'll probably also need to teach the mm about the state tree and/or still manipulate the pagecache tree to prevent concurrency?

Well, it isn't coded yet, but I should be able to do it from the FS specific ops.

Probably, if you invalidate all the pagecache in the range beforehand you should be able to do it (and I guess you want to do the invalidate anyway). Although, below deadlock issues might still bite somehwere...

Quoted 10 lines
Quoted 4 lines

But isn't the main aim of O_DIRECT to do as little locking and synchronisation with the pagecache as possible? I thought this is why your race fixing patches got put on the back burner (although they did look fairly nice from a correctness POV).

I put the placeholder patches on hold because handling a corner case where userland did O_DIRECT from a mmap'd region of the same file (Linus pointed it out to me). Basically my patches had to work in 64k chunks to avoid a deadlock in get_user_pages. With the state tree, I can allow the page to be faulted in but still properly deal with it.

Oh right, I didn't think of that one. Would you still have similar issues with the external state tree? I mean, the filesystem doesn't really know why the fault is taken. O_DIRECT read from a file into mmapped memory of the same block in the file is almost hopeless I think.

Quoted 8 lines
Quoted 3 lines

Well I'm kind of handwaving when it comes to O_DIRECT ;) It does look like this might be another advantage of the state tree (although you aren't allowed to slow down buffered IO to achieve the locking ;)).

;) The O_DIRECT benefit is a fringe thing. I've long wanted to help clean up that code, but the real point of the patch is to make general usage faster and less complex. If I can't get there, the O_DIRECT stuff doesn't matter.

Sure, although unifying code is always a plus so I like that you've got that in mind.

Quoted 9 lines
Quoted 8 lines
Quoted 3 lines

The ability to put in additional tracking info like the process that first dirtied a range is also significant. So, I think it is worth trying.

Definitely, and I'm glad you are. You haven't converted me yet, but I look forward to finding the best ideas from our two approaches when the patches are further along (ext2 port of fsblock coming along, so we'll be able to have races soon :P).

Quoted 4 lines
Quoted 2 lines

I'm sure we can find some river in Cambridge, winner gets to throw Axboe in.

Very noble of you to donate your colleage to such a worthy cause.

Cambridge = Cam + Bridge = Bridge over the river Cam

The Cam is a bit muddy though so it is not a very enjoyable experience falling/being thrown into it.

Nice for punting on though when the weather is nice. (-:

Best regards,

Anton

Signature · 10 lines
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer, http://www.linux-ntfs.org/


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#15 lore raw
In reply to Nick Piggin

On Thu, 26 Jul 2007 04:36:39 +0200
Nick Piggin <[email protected]> wrote:

[ are state trees a good idea? ]

Quoted 7 lines
Quoted 4 lines

One thing it gains us is finding the start of the cluster. Even if called by kswapd, the state tree allows writepage to find the start of the cluster and send down a big bio (provided I implement trylock to avoid various deadlocks).

That's very true, we could potentially also do that with the block extent tree that I want to try with fsblock.

If fsblock records and extent of 200MB, and writepage is called on a page in the middle of the extent, how do you walk the radix backwards to find the first dirty & up to date page in the range?

Quoted 5 lines

I'm looking at "cleaning up" some of these aops APIs so hopefully most of the deadlock problems go away. Should be useful to both our efforts. Will post patches hopefully when I get time to finish the draft this weekend.

Great

Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 5 lines

O_DIRECT becomes a special case of readpages and writepages....the memory used for IO just comes from userland instead of the page cache.

Could be, although you'll probably also need to teach the mm about the state tree and/or still manipulate the pagecache tree to prevent concurrency?

Quoted 6 lines
Quoted 2 lines

Well, it isn't coded yet, but I should be able to do it from the FS specific ops.

Probably, if you invalidate all the pagecache in the range beforehand you should be able to do it (and I guess you want to do the invalidate anyway). Although, below deadlock issues might still bite somehwere...

Well, O_DIRECT is french for deadlocks. But I shouldn't have to worry so much about evicting the pages themselves since I can tag the range.

Quoted 14 lines
Quoted 7 lines
Quoted 6 lines

But isn't the main aim of O_DIRECT to do as little locking and synchronisation with the pagecache as possible? I thought this is why your race fixing patches got put on the back burner (although they did look fairly nice from a correctness POV).

Quoted 6 lines

I put the placeholder patches on hold because handling a corner case where userland did O_DIRECT from a mmap'd region of the same file (Linus pointed it out to me). Basically my patches had to work in 64k chunks to avoid a deadlock in get_user_pages. With the state tree, I can allow the page to be faulted in but still properly deal with it.

Quoted 5 lines

Oh right, I didn't think of that one. Would you still have similar issues with the external state tree? I mean, the filesystem doesn't really know why the fault is taken. O_DIRECT read from a file into mmapped memory of the same block in the file is almost hopeless I think.

Racing is fine as long as we don't deadlock or expose garbage from disk.

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 3 lines

The ability to put in additional tracking info like the process that first dirtied a range is also significant. So, I think it is worth trying.

Definitely, and I'm glad you are. You haven't converted me yet, but I look forward to finding the best ideas from our two approaches when the patches are further along (ext2 port of fsblock coming along, so we'll be able to have races soon :P).

Quoted 4 lines
Quoted 2 lines

I'm sure we can find some river in Cambridge, winner gets to throw Axboe in.

Very noble of you to donate your colleage to such a worthy cause.

Jens is always interested in helping solve such debates. It's a fantastic service he provides to the community.

-chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#16 lore raw
Quoted 10 lines · Chris Mason

On Thu, 26 Jul 2007 04:36:39 +0200
Nick Piggin <[email protected]> wrote:

[ are state trees a good idea? ]

Quoted 5 lines
Quoted 4 lines

One thing it gains us is finding the start of the cluster. Even if called by kswapd, the state tree allows writepage to find the start of the cluster and send down a big bio (provided I implement trylock to avoid various deadlocks).

Quoted 6 lines
Quoted 2 lines

That's very true, we could potentially also do that with the block extent tree that I want to try with fsblock.

If fsblock records and extent of 200MB, and writepage is called on a page in the middle of the extent, how do you walk the radix backwards to find the first dirty & up to date page in the range?

I mean if we also have a block extent tree between fsblock and the filesystem's get_block (which I think could be a good idea).

So you would use that tree to find the block extent that you're in, then use the pagecache tree dirty tag lookup from the start of that block extent (or you could add a backward tag lookup if you just wanted to gather a small range around the given offset). I think (haven't got any code for this yet, mind you).

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

I put the placeholder patches on hold because handling a corner case where userland did O_DIRECT from a mmap'd region of the same file (Linus pointed it out to me). Basically my patches had to work in 64k chunks to avoid a deadlock in get_user_pages. With the state tree, I can allow the page to be faulted in but still properly deal with it.

Quoted 7 lines
Quoted 5 lines

Oh right, I didn't think of that one. Would you still have similar issues with the external state tree? I mean, the filesystem doesn't really know why the fault is taken. O_DIRECT read from a file into mmapped memory of the same block in the file is almost hopeless I think.

Racing is fine as long as we don't deadlock or expose garbage from disk.

Hmm, OK you're probably right. I'll have to see how it looks.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

I'm sure we can find some river in Cambridge, winner gets to throw Axboe in.

Very noble of you to donate your colleage to such a worthy cause.

Jens is always interested in helping solve such debates. It's a fantastic service he provides to the community.

;)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>