All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] Set/get helpers speedups and cleanups
@ 2020-05-07 20:19 David Sterba
  2020-05-07 20:19 ` [PATCH 01/19] btrfs: use the token::eb for all set/get helpers David Sterba
                   ` (18 more replies)
  0 siblings, 19 replies; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

Set/get helpers are all the functions that read or write b-tree item
members, like btrfs_device_type, btrfs_set_device_type, or the variants
with token btrfs_token_device_type, defined in ctree.h with
BTRFS_SETGET_FUNCS. Most of them are implemented by btrfs_get_8/16/32/64
and btrfs_set_8/16/32/64 functions.

The helpers are used all over the place and can be seen in perf top
results quite often, though it's about 0.5-1.5%. This series simplifies
the helpers and removes function calls that do the translation from/to
the input buffers to/from the extent buffer pages.

I don't have exact number to show the speedup, watching perf top and the
same workload at least does not point to a drop, the functions are still
in the overall range 0.5-1.5%. The code cleanups result in a
straightforward code, also map_private_extent_buffer is gone!!!

David Sterba (19):
  btrfs: use the token::eb for all set/get helpers
  btrfs: drop eb parameter from set/get token helpers
  btrfs: don't use set/get token for single assignment in overwrite_item
  btrfs: don't use set/get token in leaf_space_used
  btrfs: preset set/get token with first page and drop condition
  btrfs: add separate bounds checker for set/get helpers
  btrfs: speed up btrfs_get_##bits helpers
  btrfs: speed up btrfs_get_token_##bits helpers
  btrfs: speed up btrfs_set_##bits helpers
  btrfs: speed up btrfs_set_token_##bits helpers
  btrfs: speed up and simplify generic_bin_search
  btrfs: remove unused map_private_extent_buffer
  btrfs: constify extent_buffer in the API functions
  btrfs: drop unnecessary offset_in_page in extent buffer helpers
  btrfs: optimize split page read in btrfs_get_##bits
  btrfs: optimize split page read in btrfs_get_token_##bits
  btrfs: optimize split page write in btrfs_set_##bits
  btrfs: optimize split page write in btrfs_set_token_##bits
  btrfs: update documentation of set/get helpers

 fs/btrfs/ctree.c        |  98 +++++++-----------
 fs/btrfs/ctree.h        |  58 +++++------
 fs/btrfs/extent_io.c    | 137 ++++++++-----------------
 fs/btrfs/extent_io.h    |  48 ++++-----
 fs/btrfs/inode.c        |  71 ++++++-------
 fs/btrfs/struct-funcs.c | 222 ++++++++++++++++++++--------------------
 fs/btrfs/tree-log.c     | 130 +++++++++++------------
 7 files changed, 337 insertions(+), 427 deletions(-)

-- 
2.25.0


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 01/19] btrfs: use the token::eb for all set/get helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 12:05   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers David Sterba
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The token stores a copy of the extent buffer pointer but does not make
any use of it besides sanity checks. We can use it and drop the eb
parameter from several functions, this patch only switches the use
inside the set/get helpers.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 73f7987143df..7928d310f698 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -62,12 +62,12 @@ u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,		\
 		res = get_unaligned_le##bits(p + off);			\
 		return res;						\
 	}								\
-	err = map_private_extent_buffer(eb, offset, size,		\
+	err = map_private_extent_buffer(token->eb, offset, size,	\
 					&kaddr, &map_start, &map_len);	\
 	if (err) {							\
 		__le##bits leres;					\
 									\
-		read_extent_buffer(eb, &leres, offset, size);		\
+		read_extent_buffer(token->eb, &leres, offset, size);	\
 		return le##bits##_to_cpu(leres);			\
 	}								\
 	p = kaddr + part_offset - map_start;				\
@@ -125,13 +125,13 @@ void btrfs_set_token_##bits(struct extent_buffer *eb,			\
 		put_unaligned_le##bits(val, p + off);			\
 		return;							\
 	}								\
-	err = map_private_extent_buffer(eb, offset, size,		\
+	err = map_private_extent_buffer(token->eb, offset, size,	\
 			&kaddr, &map_start, &map_len);			\
 	if (err) {							\
 		__le##bits val2;					\
 									\
 		val2 = cpu_to_le##bits(val);				\
-		write_extent_buffer(eb, &val2, offset, size);		\
+		write_extent_buffer(token->eb, &val2, offset, size);	\
 		return;							\
 	}								\
 	p = kaddr + part_offset - map_start;				\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
  2020-05-07 20:19 ` [PATCH 01/19] btrfs: use the token::eb for all set/get helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 12:09   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 03/19] btrfs: don't use set/get token for single assignment in overwrite_item David Sterba
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

Now that all set/get helpers use the eb from the token, we don't need to
pass it to many btrfs_token_*/btrfs_set_token_* helpers, saving some
stack space.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/ctree.c        |  53 ++++++++---------
 fs/btrfs/ctree.h        |  27 ++++-----
 fs/btrfs/inode.c        |  71 +++++++++++------------
 fs/btrfs/struct-funcs.c |  12 ++--
 fs/btrfs/tree-log.c     | 125 ++++++++++++++++++----------------------
 5 files changed, 130 insertions(+), 158 deletions(-)

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 6c28efe5b14a..576111cdea1d 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -3517,9 +3517,9 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr)
 	btrfs_init_map_token(&token, l);
 	start_item = btrfs_item_nr(start);
 	end_item = btrfs_item_nr(end);
-	data_len = btrfs_token_item_offset(l, start_item, &token) +
-		btrfs_token_item_size(l, start_item, &token);
-	data_len = data_len - btrfs_token_item_offset(l, end_item, &token);
+	data_len = btrfs_token_item_offset(&token, start_item) +
+		btrfs_token_item_size(&token, start_item);
+	data_len = data_len - btrfs_token_item_offset(&token, end_item);
 	data_len += sizeof(struct btrfs_item) * nr;
 	WARN_ON(data_len < 0);
 	return data_len;
@@ -3650,8 +3650,8 @@ static noinline int __push_leaf_right(struct btrfs_path *path,
 	push_space = BTRFS_LEAF_DATA_SIZE(fs_info);
 	for (i = 0; i < right_nritems; i++) {
 		item = btrfs_item_nr(i);
-		push_space -= btrfs_token_item_size(right, item, &token);
-		btrfs_set_token_item_offset(right, item, push_space, &token);
+		push_space -= btrfs_token_item_size(&token, item);
+		btrfs_set_token_item_offset(&token, item, push_space);
 	}
 
 	left_nritems -= push_items;
@@ -3859,10 +3859,9 @@ static noinline int __push_leaf_left(struct btrfs_path *path, int data_size,
 
 		item = btrfs_item_nr(i);
 
-		ioff = btrfs_token_item_offset(left, item, &token);
-		btrfs_set_token_item_offset(left, item,
-		      ioff - (BTRFS_LEAF_DATA_SIZE(fs_info) - old_left_item_size),
-		      &token);
+		ioff = btrfs_token_item_offset(&token, item);
+		btrfs_set_token_item_offset(&token, item,
+		      ioff - (BTRFS_LEAF_DATA_SIZE(fs_info) - old_left_item_size));
 	}
 	btrfs_set_header_nritems(left, old_left_nritems + push_items);
 
@@ -3892,9 +3891,8 @@ static noinline int __push_leaf_left(struct btrfs_path *path, int data_size,
 	for (i = 0; i < right_nritems; i++) {
 		item = btrfs_item_nr(i);
 
-		push_space = push_space - btrfs_token_item_size(right,
-								item, &token);
-		btrfs_set_token_item_offset(right, item, push_space, &token);
+		push_space = push_space - btrfs_token_item_size(&token, item);
+		btrfs_set_token_item_offset(&token, item, push_space);
 	}
 
 	btrfs_mark_buffer_dirty(left);
@@ -4036,9 +4034,8 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
 		struct btrfs_item *item = btrfs_item_nr(i);
 		u32 ioff;
 
-		ioff = btrfs_token_item_offset(right, item, &token);
-		btrfs_set_token_item_offset(right, item,
-					    ioff + rt_data_off, &token);
+		ioff = btrfs_token_item_offset(&token, item);
+		btrfs_set_token_item_offset(&token, item, ioff + rt_data_off);
 	}
 
 	btrfs_set_header_nritems(l, mid);
@@ -4541,9 +4538,8 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end)
 		u32 ioff;
 		item = btrfs_item_nr(i);
 
-		ioff = btrfs_token_item_offset(leaf, item, &token);
-		btrfs_set_token_item_offset(leaf, item,
-					    ioff + size_diff, &token);
+		ioff = btrfs_token_item_offset(&token, item);
+		btrfs_set_token_item_offset(&token, item, ioff + size_diff);
 	}
 
 	/* shift the data */
@@ -4640,9 +4636,8 @@ void btrfs_extend_item(struct btrfs_path *path, u32 data_size)
 		u32 ioff;
 		item = btrfs_item_nr(i);
 
-		ioff = btrfs_token_item_offset(leaf, item, &token);
-		btrfs_set_token_item_offset(leaf, item,
-					    ioff - data_size, &token);
+		ioff = btrfs_token_item_offset(&token, item);
+		btrfs_set_token_item_offset(&token, item, ioff - data_size);
 	}
 
 	/* shift the data */
@@ -4718,9 +4713,9 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
 			u32 ioff;
 
 			item = btrfs_item_nr(i);
-			ioff = btrfs_token_item_offset(leaf, item, &token);
-			btrfs_set_token_item_offset(leaf, item,
-						    ioff - total_data, &token);
+			ioff = btrfs_token_item_offset(&token, item);
+			btrfs_set_token_item_offset(&token, item,
+						    ioff - total_data);
 		}
 		/* shift the items */
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr),
@@ -4739,10 +4734,9 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
 		btrfs_cpu_key_to_disk(&disk_key, cpu_key + i);
 		btrfs_set_item_key(leaf, &disk_key, slot + i);
 		item = btrfs_item_nr(slot + i);
-		btrfs_set_token_item_offset(leaf, item,
-					    data_end - data_size[i], &token);
+		btrfs_set_token_item_offset(&token, item, data_end - data_size[i]);
 		data_end -= data_size[i];
-		btrfs_set_token_item_size(leaf, item, data_size[i], &token);
+		btrfs_set_token_item_size(&token, item, data_size[i]);
 	}
 
 	btrfs_set_header_nritems(leaf, nritems + nr);
@@ -4930,9 +4924,8 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 			u32 ioff;
 
 			item = btrfs_item_nr(i);
-			ioff = btrfs_token_item_offset(leaf, item, &token);
-			btrfs_set_token_item_offset(leaf, item,
-						    ioff + dsize, &token);
+			ioff = btrfs_token_item_offset(&token, item);
+			btrfs_set_token_item_offset(&token, item, ioff + dsize);
 		}
 
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot),
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 03ea7370aea7..054ddb5d2425 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1340,7 +1340,7 @@ do {                                                                   \
 	 BTRFS_INODE_ROOT_ITEM_INIT)
 
 struct btrfs_map_token {
-	const struct extent_buffer *eb;
+	struct extent_buffer *eb;
 	char *kaddr;
 	unsigned long offset;
 };
@@ -1376,12 +1376,11 @@ static inline void btrfs_init_map_token(struct btrfs_map_token *token,
 			   sizeof(((type *)0)->member)))
 
 #define DECLARE_BTRFS_SETGET_BITS(bits)					\
-u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,		\
-			       const void *ptr, unsigned long off,	\
-			       struct btrfs_map_token *token);		\
-void btrfs_set_token_##bits(struct extent_buffer *eb, const void *ptr,	\
-			    unsigned long off, u##bits val,		\
-			    struct btrfs_map_token *token);		\
+u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
+			       const void *ptr, unsigned long off);	\
+void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
+			    const void *ptr, unsigned long off,		\
+			    u##bits val);				\
 u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 			 const void *ptr, unsigned long off);		\
 void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,		\
@@ -1405,19 +1404,17 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, type *s,	\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
 	btrfs_set_##bits(eb, s, offsetof(type, member), val);		\
 }									\
-static inline u##bits btrfs_token_##name(const struct extent_buffer *eb,\
-					 const type *s,			\
-					 struct btrfs_map_token *token)	\
+static inline u##bits btrfs_token_##name(struct btrfs_map_token *token,	\
+					 const type *s)			\
 {									\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
-	return btrfs_get_token_##bits(eb, s, offsetof(type, member), token); \
+	return btrfs_get_token_##bits(token, s, offsetof(type, member));\
 }									\
-static inline void btrfs_set_token_##name(struct extent_buffer *eb,	\
-					  type *s, u##bits val,		\
-                                         struct btrfs_map_token *token)	\
+static inline void btrfs_set_token_##name(struct btrfs_map_token *token,\
+					  type *s, u##bits val)		\
 {									\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
-	btrfs_set_token_##bits(eb, s, offsetof(type, member), val, token); \
+	btrfs_set_token_##bits(token, s, offsetof(type, member), val);	\
 }
 
 #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)		\
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index cc94291fdd18..256eec4c85ae 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3354,43 +3354,40 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 
 	btrfs_init_map_token(&token, leaf);
 
-	btrfs_set_token_inode_uid(leaf, item, i_uid_read(inode), &token);
-	btrfs_set_token_inode_gid(leaf, item, i_gid_read(inode), &token);
-	btrfs_set_token_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size,
-				   &token);
-	btrfs_set_token_inode_mode(leaf, item, inode->i_mode, &token);
-	btrfs_set_token_inode_nlink(leaf, item, inode->i_nlink, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->atime,
-				     inode->i_atime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->atime,
-				      inode->i_atime.tv_nsec, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->mtime,
-				     inode->i_mtime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->mtime,
-				      inode->i_mtime.tv_nsec, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->ctime,
-				     inode->i_ctime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->ctime,
-				      inode->i_ctime.tv_nsec, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->otime,
-				     BTRFS_I(inode)->i_otime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->otime,
-				      BTRFS_I(inode)->i_otime.tv_nsec, &token);
-
-	btrfs_set_token_inode_nbytes(leaf, item, inode_get_bytes(inode),
-				     &token);
-	btrfs_set_token_inode_generation(leaf, item, BTRFS_I(inode)->generation,
-					 &token);
-	btrfs_set_token_inode_sequence(leaf, item, inode_peek_iversion(inode),
-				       &token);
-	btrfs_set_token_inode_transid(leaf, item, trans->transid, &token);
-	btrfs_set_token_inode_rdev(leaf, item, inode->i_rdev, &token);
-	btrfs_set_token_inode_flags(leaf, item, BTRFS_I(inode)->flags, &token);
-	btrfs_set_token_inode_block_group(leaf, item, 0, &token);
+	btrfs_set_token_inode_uid(&token, item, i_uid_read(inode));
+	btrfs_set_token_inode_gid(&token, item, i_gid_read(inode));
+	btrfs_set_token_inode_size(&token, item, BTRFS_I(inode)->disk_i_size);
+	btrfs_set_token_inode_mode(&token, item, inode->i_mode);
+	btrfs_set_token_inode_nlink(&token, item, inode->i_nlink);
+
+	btrfs_set_token_timespec_sec(&token, &item->atime,
+				     inode->i_atime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->atime,
+				      inode->i_atime.tv_nsec);
+
+	btrfs_set_token_timespec_sec(&token, &item->mtime,
+				     inode->i_mtime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->mtime,
+				      inode->i_mtime.tv_nsec);
+
+	btrfs_set_token_timespec_sec(&token, &item->ctime,
+				     inode->i_ctime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->ctime,
+				      inode->i_ctime.tv_nsec);
+
+	btrfs_set_token_timespec_sec(&token, &item->otime,
+				     BTRFS_I(inode)->i_otime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->otime,
+				      BTRFS_I(inode)->i_otime.tv_nsec);
+
+	btrfs_set_token_inode_nbytes(&token, item, inode_get_bytes(inode));
+	btrfs_set_token_inode_generation(&token, item,
+					 BTRFS_I(inode)->generation);
+	btrfs_set_token_inode_sequence(&token, item, inode_peek_iversion(inode));
+	btrfs_set_token_inode_transid(&token, item, trans->transid);
+	btrfs_set_token_inode_rdev(&token, item, inode->i_rdev);
+	btrfs_set_token_inode_flags(&token, item, BTRFS_I(inode)->flags);
+	btrfs_set_token_inode_block_group(&token, item, 0);
 }
 
 /*
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 7928d310f698..cebd0b5e4f37 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -38,9 +38,8 @@ static inline void put_unaligned_le8(u8 val, void *p)
  */
 
 #define DEFINE_BTRFS_SETGET_BITS(bits)					\
-u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,		\
-			       const void *ptr, unsigned long off,	\
-			       struct btrfs_map_token *token)		\
+u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
+			       const void *ptr, unsigned long off)	\
 {									\
 	unsigned long part_offset = (unsigned long)ptr;			\
 	unsigned long offset = part_offset + off;			\
@@ -53,7 +52,6 @@ u##bits btrfs_get_token_##bits(const struct extent_buffer *eb,		\
 	u##bits res;							\
 									\
 	ASSERT(token);							\
-	ASSERT(token->eb == eb);					\
 									\
 	if (token->kaddr && token->offset <= offset &&			\
 	   (token->offset + PAGE_SIZE >= offset + size)) {	\
@@ -101,10 +99,9 @@ u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 	res = get_unaligned_le##bits(p + off);				\
 	return res;							\
 }									\
-void btrfs_set_token_##bits(struct extent_buffer *eb,			\
+void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 			    const void *ptr, unsigned long off,		\
-			    u##bits val,				\
-			    struct btrfs_map_token *token)		\
+			    u##bits val)				\
 {									\
 	unsigned long part_offset = (unsigned long)ptr;			\
 	unsigned long offset = part_offset + off;			\
@@ -116,7 +113,6 @@ void btrfs_set_token_##bits(struct extent_buffer *eb,			\
 	int size = sizeof(u##bits);					\
 									\
 	ASSERT(token);							\
-	ASSERT(token->eb == eb);					\
 									\
 	if (token->kaddr && token->offset <= offset &&			\
 	   (token->offset + PAGE_SIZE >= offset + size)) {	\
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 39ec25518ec2..ee1c627bd618 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -509,8 +509,8 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
 				struct btrfs_map_token token;
 
 				btrfs_init_map_token(&token, dst_eb);
-				btrfs_set_token_inode_size(dst_eb, dst_item,
-							   ino_size, &token);
+				btrfs_set_token_inode_size(&token, dst_item,
+							   ino_size);
 			}
 			goto no_copy;
 		}
@@ -3852,44 +3852,41 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 		 * just to say 'this inode exists' and a logging
 		 * to say 'update this inode with these values'
 		 */
-		btrfs_set_token_inode_generation(leaf, item, 0, &token);
-		btrfs_set_token_inode_size(leaf, item, logged_isize, &token);
+		btrfs_set_token_inode_generation(&token, item, 0);
+		btrfs_set_token_inode_size(&token, item, logged_isize);
 	} else {
-		btrfs_set_token_inode_generation(leaf, item,
-						 BTRFS_I(inode)->generation,
-						 &token);
-		btrfs_set_token_inode_size(leaf, item, inode->i_size, &token);
-	}
-
-	btrfs_set_token_inode_uid(leaf, item, i_uid_read(inode), &token);
-	btrfs_set_token_inode_gid(leaf, item, i_gid_read(inode), &token);
-	btrfs_set_token_inode_mode(leaf, item, inode->i_mode, &token);
-	btrfs_set_token_inode_nlink(leaf, item, inode->i_nlink, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->atime,
-				     inode->i_atime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->atime,
-				      inode->i_atime.tv_nsec, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->mtime,
-				     inode->i_mtime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->mtime,
-				      inode->i_mtime.tv_nsec, &token);
-
-	btrfs_set_token_timespec_sec(leaf, &item->ctime,
-				     inode->i_ctime.tv_sec, &token);
-	btrfs_set_token_timespec_nsec(leaf, &item->ctime,
-				      inode->i_ctime.tv_nsec, &token);
-
-	btrfs_set_token_inode_nbytes(leaf, item, inode_get_bytes(inode),
-				     &token);
-
-	btrfs_set_token_inode_sequence(leaf, item,
-				       inode_peek_iversion(inode), &token);
-	btrfs_set_token_inode_transid(leaf, item, trans->transid, &token);
-	btrfs_set_token_inode_rdev(leaf, item, inode->i_rdev, &token);
-	btrfs_set_token_inode_flags(leaf, item, BTRFS_I(inode)->flags, &token);
-	btrfs_set_token_inode_block_group(leaf, item, 0, &token);
+		btrfs_set_token_inode_generation(&token, item,
+						 BTRFS_I(inode)->generation);
+		btrfs_set_token_inode_size(&token, item, inode->i_size);
+	}
+
+	btrfs_set_token_inode_uid(&token, item, i_uid_read(inode));
+	btrfs_set_token_inode_gid(&token, item, i_gid_read(inode));
+	btrfs_set_token_inode_mode(&token, item, inode->i_mode);
+	btrfs_set_token_inode_nlink(&token, item, inode->i_nlink);
+
+	btrfs_set_token_timespec_sec(&token, &item->atime,
+				     inode->i_atime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->atime,
+				      inode->i_atime.tv_nsec);
+
+	btrfs_set_token_timespec_sec(&token, &item->mtime,
+				     inode->i_mtime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->mtime,
+				      inode->i_mtime.tv_nsec);
+
+	btrfs_set_token_timespec_sec(&token, &item->ctime,
+				     inode->i_ctime.tv_sec);
+	btrfs_set_token_timespec_nsec(&token, &item->ctime,
+				      inode->i_ctime.tv_nsec);
+
+	btrfs_set_token_inode_nbytes(&token, item, inode_get_bytes(inode));
+
+	btrfs_set_token_inode_sequence(&token, item, inode_peek_iversion(inode));
+	btrfs_set_token_inode_transid(&token, item, trans->transid);
+	btrfs_set_token_inode_rdev(&token, item, inode->i_rdev);
+	btrfs_set_token_inode_flags(&token, item, BTRFS_I(inode)->flags);
+	btrfs_set_token_inode_block_group(&token, item, 0);
 }
 
 static int log_inode_item(struct btrfs_trans_handle *trans,
@@ -4163,43 +4160,35 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
 	fi = btrfs_item_ptr(leaf, path->slots[0],
 			    struct btrfs_file_extent_item);
 
-	btrfs_set_token_file_extent_generation(leaf, fi, trans->transid,
-					       &token);
+	btrfs_set_token_file_extent_generation(&token, fi, trans->transid);
 	if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
-		btrfs_set_token_file_extent_type(leaf, fi,
-						 BTRFS_FILE_EXTENT_PREALLOC,
-						 &token);
+		btrfs_set_token_file_extent_type(&token, fi,
+						 BTRFS_FILE_EXTENT_PREALLOC);
 	else
-		btrfs_set_token_file_extent_type(leaf, fi,
-						 BTRFS_FILE_EXTENT_REG,
-						 &token);
+		btrfs_set_token_file_extent_type(&token, fi,
+						 BTRFS_FILE_EXTENT_REG);
 
 	block_len = max(em->block_len, em->orig_block_len);
 	if (em->compress_type != BTRFS_COMPRESS_NONE) {
-		btrfs_set_token_file_extent_disk_bytenr(leaf, fi,
-							em->block_start,
-							&token);
-		btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, block_len,
-							   &token);
+		btrfs_set_token_file_extent_disk_bytenr(&token, fi,
+							em->block_start);
+		btrfs_set_token_file_extent_disk_num_bytes(&token, fi, block_len);
 	} else if (em->block_start < EXTENT_MAP_LAST_BYTE) {
-		btrfs_set_token_file_extent_disk_bytenr(leaf, fi,
+		btrfs_set_token_file_extent_disk_bytenr(&token, fi,
 							em->block_start -
-							extent_offset, &token);
-		btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, block_len,
-							   &token);
+							extent_offset);
+		btrfs_set_token_file_extent_disk_num_bytes(&token, fi, block_len);
 	} else {
-		btrfs_set_token_file_extent_disk_bytenr(leaf, fi, 0, &token);
-		btrfs_set_token_file_extent_disk_num_bytes(leaf, fi, 0,
-							   &token);
-	}
-
-	btrfs_set_token_file_extent_offset(leaf, fi, extent_offset, &token);
-	btrfs_set_token_file_extent_num_bytes(leaf, fi, em->len, &token);
-	btrfs_set_token_file_extent_ram_bytes(leaf, fi, em->ram_bytes, &token);
-	btrfs_set_token_file_extent_compression(leaf, fi, em->compress_type,
-						&token);
-	btrfs_set_token_file_extent_encryption(leaf, fi, 0, &token);
-	btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);
+		btrfs_set_token_file_extent_disk_bytenr(&token, fi, 0);
+		btrfs_set_token_file_extent_disk_num_bytes(&token, fi, 0);
+	}
+
+	btrfs_set_token_file_extent_offset(&token, fi, extent_offset);
+	btrfs_set_token_file_extent_num_bytes(&token, fi, em->len);
+	btrfs_set_token_file_extent_ram_bytes(&token, fi, em->ram_bytes);
+	btrfs_set_token_file_extent_compression(&token, fi, em->compress_type);
+	btrfs_set_token_file_extent_encryption(&token, fi, 0);
+	btrfs_set_token_file_extent_other_encoding(&token, fi, 0);
 	btrfs_mark_buffer_dirty(leaf);
 
 	btrfs_release_path(path);
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 03/19] btrfs: don't use set/get token for single assignment in overwrite_item
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
  2020-05-07 20:19 ` [PATCH 01/19] btrfs: use the token::eb for all set/get helpers David Sterba
  2020-05-07 20:19 ` [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:25   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 04/19] btrfs: don't use set/get token in leaf_space_used David Sterba
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The set/get token is supposed to cache the last page that was accessed
so it speeds up subsequential access to the eb. It does not make sense
to use that for just one change, which is the case of inode size in
overwrite_item.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/tree-log.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ee1c627bd618..60febf2082ee 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -505,13 +505,8 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
 			 */
 			if (S_ISREG(btrfs_inode_mode(eb, src_item)) &&
 			    S_ISREG(btrfs_inode_mode(dst_eb, dst_item)) &&
-			    ino_size != 0) {
-				struct btrfs_map_token token;
-
-				btrfs_init_map_token(&token, dst_eb);
-				btrfs_set_token_inode_size(&token, dst_item,
-							   ino_size);
-			}
+			    ino_size != 0)
+				btrfs_set_inode_size(dst_eb, dst_item, ino_size);
 			goto no_copy;
 		}
 
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 04/19] btrfs: don't use set/get token in leaf_space_used
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (2 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 03/19] btrfs: don't use set/get token for single assignment in overwrite_item David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:27   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 05/19] btrfs: preset set/get token with first page and drop condition David Sterba
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The token is supposed to cache the last page used by the set/get
helpers. In leaf_space_used the first and last items are accessed, it's
not likely they'd be on the same page so there's some overhead caused
updating the token address but not using it.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/ctree.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 576111cdea1d..6dbeb23c59ec 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -3507,19 +3507,17 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr)
 {
 	struct btrfs_item *start_item;
 	struct btrfs_item *end_item;
-	struct btrfs_map_token token;
 	int data_len;
 	int nritems = btrfs_header_nritems(l);
 	int end = min(nritems, start + nr) - 1;
 
 	if (!nr)
 		return 0;
-	btrfs_init_map_token(&token, l);
 	start_item = btrfs_item_nr(start);
 	end_item = btrfs_item_nr(end);
-	data_len = btrfs_token_item_offset(&token, start_item) +
-		btrfs_token_item_size(&token, start_item);
-	data_len = data_len - btrfs_token_item_offset(&token, end_item);
+	data_len = btrfs_item_offset(l, start_item) +
+		   btrfs_item_size(l, start_item);
+	data_len = data_len - btrfs_item_offset(l, end_item);
 	data_len += sizeof(struct btrfs_item) * nr;
 	WARN_ON(data_len < 0);
 	return data_len;
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 05/19] btrfs: preset set/get token with first page and drop condition
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (3 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 04/19] btrfs: don't use set/get token in leaf_space_used David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:37   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 06/19] btrfs: add separate bounds checker for set/get helpers David Sterba
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

All the set/get helpers first check if the token contains a cached
address. After first use the address is always valid, but the extra
check is done for each call.

The token initialization can optimistically set it to the first extent
buffer page, that we know always exists. Then the condition in all
btrfs_token_*/btrfs_set_token_* can be simplified by removing the
address check from the condition, but for development the assertion
still makes sure it's valid.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/ctree.h        | 3 ++-
 fs/btrfs/struct-funcs.c | 8 ++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 054ddb5d2425..fbe2f9fa9f3e 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1352,7 +1352,8 @@ static inline void btrfs_init_map_token(struct btrfs_map_token *token,
 					struct extent_buffer *eb)
 {
 	token->eb = eb;
-	token->kaddr = NULL;
+	token->kaddr = page_address(eb->pages[0]);
+	token->offset = 0;
 }
 
 /* some macros to generate set/get functions for the struct fields.  This
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index cebd0b5e4f37..cef628a5a9e0 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -52,8 +52,8 @@ u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
 	u##bits res;							\
 									\
 	ASSERT(token);							\
-									\
-	if (token->kaddr && token->offset <= offset &&			\
+	ASSERT(token->kaddr);						\
+	if (token->offset <= offset &&					\
 	   (token->offset + PAGE_SIZE >= offset + size)) {	\
 		kaddr = token->kaddr;					\
 		p = kaddr + part_offset - token->offset;		\
@@ -113,8 +113,8 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 	int size = sizeof(u##bits);					\
 									\
 	ASSERT(token);							\
-									\
-	if (token->kaddr && token->offset <= offset &&			\
+	ASSERT(token->kaddr);						\
+	if (token->offset <= offset &&					\
 	   (token->offset + PAGE_SIZE >= offset + size)) {	\
 		kaddr = token->kaddr;					\
 		p = kaddr + part_offset - token->offset;		\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 06/19] btrfs: add separate bounds checker for set/get helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (4 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 05/19] btrfs: preset set/get token with first page and drop condition David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:39   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 07/19] btrfs: speed up btrfs_get_##bits helpers David Sterba
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The bounds checking is now done in map_private_extent_buffer but that
will be removed in following patches and some sanity checks should still
be done.

There are two separate checks to see the kind of out of bounds access:
partial (start offset is in the buffer) or complete (both start and end
are out).

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index cef628a5a9e0..68c02997e60d 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -17,6 +17,27 @@ static inline void put_unaligned_le8(u8 val, void *p)
        *(u8 *)p = val;
 }
 
+static bool check_setget_bounds(const struct extent_buffer *eb,
+				const void *ptr, unsigned off, int size)
+{
+	const unsigned long member_offset = (unsigned long)ptr + off;
+
+	if (member_offset > eb->len) {
+		btrfs_warn(eb->fs_info,
+	"bad eb member start: ptr 0x%lx start %llu member offset %lu size %d",
+			(unsigned long)ptr, eb->start, member_offset, size);
+		return false;
+	}
+	if (member_offset + size > eb->len) {
+		btrfs_warn(eb->fs_info,
+	"bad eb member end: ptr 0x%lx start %llu member offset %lu size %d",
+			(unsigned long)ptr, eb->start, member_offset, size);
+		return false;
+	}
+
+	return true;
+}
+
 /*
  * this is some deeply nasty code.
  *
@@ -53,6 +74,7 @@ u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
 									\
 	ASSERT(token);							\
 	ASSERT(token->kaddr);						\
+	ASSERT(check_setget_bounds(token->eb, ptr, off, size));		\
 	if (token->offset <= offset &&					\
 	   (token->offset + PAGE_SIZE >= offset + size)) {	\
 		kaddr = token->kaddr;					\
@@ -87,6 +109,7 @@ u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 	int size = sizeof(u##bits);					\
 	u##bits res;							\
 									\
+	ASSERT(check_setget_bounds(eb, ptr, off, size));		\
 	err = map_private_extent_buffer(eb, offset, size,		\
 					&kaddr, &map_start, &map_len);	\
 	if (err) {							\
@@ -114,6 +137,7 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 									\
 	ASSERT(token);							\
 	ASSERT(token->kaddr);						\
+	ASSERT(check_setget_bounds(token->eb, ptr, off, size));		\
 	if (token->offset <= offset &&					\
 	   (token->offset + PAGE_SIZE >= offset + size)) {	\
 		kaddr = token->kaddr;					\
@@ -147,6 +171,7 @@ void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,		\
 	unsigned long map_len;						\
 	int size = sizeof(u##bits);					\
 									\
+	ASSERT(check_setget_bounds(eb, ptr, off, size));		\
 	err = map_private_extent_buffer(eb, offset, size,		\
 			&kaddr, &map_start, &map_len);			\
 	if (err) {							\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 07/19] btrfs: speed up btrfs_get_##bits helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (5 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 06/19] btrfs: add separate bounds checker for set/get helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:42   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 08/19] btrfs: speed up btrfs_get_token_##bits helpers David Sterba
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The helpers unconditionally call map_private_extent_buffer to get the
address of page containing the requested offset plus the mapping start
and length. Depending on the return value, the fast path uses unaligned
read to get data within a page, or fall back to read_extent_buffer that
can handle reads spanning more pages.

This is all wasteful. We know the number of bytes to read, 1/2/4/8 and
can find out the page. Then simply check if it's contained or the
fallback is needed.

This saves one function call to map_private_extent_buffer and several
unnecessary temporary variables.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 68c02997e60d..e6d2bd019444 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -99,28 +99,19 @@ u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
 u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 			 const void *ptr, unsigned long off)		\
 {									\
-	unsigned long part_offset = (unsigned long)ptr;			\
-	unsigned long offset = part_offset + off;			\
-	void *p;							\
-	int err;							\
-	char *kaddr;							\
-	unsigned long map_start;					\
-	unsigned long map_len;						\
-	int size = sizeof(u##bits);					\
-	u##bits res;							\
+	const unsigned long member_offset = (unsigned long)ptr + off;	\
+	const unsigned long oip = offset_in_page(member_offset);	\
+	const int size = sizeof(u##bits);				\
+	__le##bits leres;						\
 									\
 	ASSERT(check_setget_bounds(eb, ptr, off, size));		\
-	err = map_private_extent_buffer(eb, offset, size,		\
-					&kaddr, &map_start, &map_len);	\
-	if (err) {							\
-		__le##bits leres;					\
-									\
-		read_extent_buffer(eb, &leres, offset, size);		\
-		return le##bits##_to_cpu(leres);			\
+	if (oip + size <= PAGE_SIZE) {					\
+		const unsigned long idx = member_offset >> PAGE_SHIFT;	\
+		const char *kaddr = page_address(eb->pages[idx]);	\
+		return get_unaligned_le##bits(kaddr + oip);		\
 	}								\
-	p = kaddr + part_offset - map_start;				\
-	res = get_unaligned_le##bits(p + off);				\
-	return res;							\
+	read_extent_buffer(eb, &leres, member_offset, size);		\
+	return le##bits##_to_cpu(leres);				\
 }									\
 void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 			    const void *ptr, unsigned long off,		\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 08/19] btrfs: speed up btrfs_get_token_##bits helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (6 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 07/19] btrfs: speed up btrfs_get_##bits helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:46   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 09/19] btrfs: speed up btrfs_set_##bits helpers David Sterba
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The set/get token helpers either use the cached address in the token or
unconditionally call map_private_extent_buffer to get the address of
page containing the requested offset plus the mapping start and length.
Depending on the return value, the fast path uses unaligned read to get
data within a page, or fall back to read_extent_buffer that can handle
reads spanning more pages.

This is all wasteful. We know the number of bytes to read, 1/2/4/8 and
can find out the page. Then simply check if it's contained or the
fallback is needed. The token address is updated to the page, or the on
the next index, expecting that the next read will use that.

This saves one function call to map_private_extent_buffer and several
unnecessary temporary variables.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 43 +++++++++++++++--------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index e6d2bd019444..e357e0bab397 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -62,39 +62,28 @@ static bool check_setget_bounds(const struct extent_buffer *eb,
 u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
 			       const void *ptr, unsigned long off)	\
 {									\
-	unsigned long part_offset = (unsigned long)ptr;			\
-	unsigned long offset = part_offset + off;			\
-	void *p;							\
-	int err;							\
-	char *kaddr;							\
-	unsigned long map_start;					\
-	unsigned long map_len;						\
-	int size = sizeof(u##bits);					\
-	u##bits res;							\
+	const unsigned long member_offset = (unsigned long)ptr + off;	\
+	const unsigned long idx = member_offset >> PAGE_SHIFT;		\
+	const unsigned long oip = offset_in_page(member_offset);	\
+	const int size = sizeof(u##bits);				\
+	__le##bits leres;						\
 									\
 	ASSERT(token);							\
 	ASSERT(token->kaddr);						\
 	ASSERT(check_setget_bounds(token->eb, ptr, off, size));		\
-	if (token->offset <= offset &&					\
-	   (token->offset + PAGE_SIZE >= offset + size)) {	\
-		kaddr = token->kaddr;					\
-		p = kaddr + part_offset - token->offset;		\
-		res = get_unaligned_le##bits(p + off);			\
-		return res;						\
+	if (token->offset <= member_offset &&				\
+	    member_offset + size <= token->offset + PAGE_SIZE) {	\
+		return get_unaligned_le##bits(token->kaddr + oip);	\
 	}								\
-	err = map_private_extent_buffer(token->eb, offset, size,	\
-					&kaddr, &map_start, &map_len);	\
-	if (err) {							\
-		__le##bits leres;					\
-									\
-		read_extent_buffer(token->eb, &leres, offset, size);	\
-		return le##bits##_to_cpu(leres);			\
+	if (oip + size <= PAGE_SIZE) {					\
+		token->kaddr = page_address(token->eb->pages[idx]);	\
+		token->offset = idx << PAGE_SHIFT;			\
+		return get_unaligned_le##bits(token->kaddr + oip);	\
 	}								\
-	p = kaddr + part_offset - map_start;				\
-	res = get_unaligned_le##bits(p + off);				\
-	token->kaddr = kaddr;						\
-	token->offset = map_start;					\
-	return res;							\
+	token->kaddr = page_address(token->eb->pages[idx + 1]);		\
+	token->offset = (idx + 1) << PAGE_SHIFT;			\
+	read_extent_buffer(token->eb, &leres, member_offset, size);	\
+	return le##bits##_to_cpu(leres);				\
 }									\
 u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 			 const void *ptr, unsigned long off)		\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 09/19] btrfs: speed up btrfs_set_##bits helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (7 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 08/19] btrfs: speed up btrfs_get_token_##bits helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:48   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers David Sterba
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The helpers unconditionally call map_private_extent_buffer to get the
address of page containing the requested offset plus the mapping start
and length. Depending on the return value, the fast path uses unaligned
put to write data within a page, or fall back to write_extent_buffer
that can handle writes spanning more pages.

This is all wasteful. We know the number of bytes to read, 1/2/4/8 and
can find out the page. Then simply check if it's contained or the
fallback is needed.

This saves one function call to map_private_extent_buffer and several
unnecessary temporary variables.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index e357e0bab397..f8a0357d10fd 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -142,27 +142,20 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,		\
 		      unsigned long off, u##bits val)			\
 {									\
-	unsigned long part_offset = (unsigned long)ptr;			\
-	unsigned long offset = part_offset + off;			\
-	void *p;							\
-	int err;							\
-	char *kaddr;							\
-	unsigned long map_start;					\
-	unsigned long map_len;						\
-	int size = sizeof(u##bits);					\
+	const unsigned long member_offset = (unsigned long)ptr + off;	\
+	const unsigned long oip = offset_in_page(member_offset);	\
+	const int size = sizeof(u##bits);				\
+	__le##bits leres;						\
 									\
 	ASSERT(check_setget_bounds(eb, ptr, off, size));		\
-	err = map_private_extent_buffer(eb, offset, size,		\
-			&kaddr, &map_start, &map_len);			\
-	if (err) {							\
-		__le##bits val2;					\
-									\
-		val2 = cpu_to_le##bits(val);				\
-		write_extent_buffer(eb, &val2, offset, size);		\
+	if (oip + size <= PAGE_SIZE) {					\
+		const unsigned long idx = member_offset >> PAGE_SHIFT;	\
+		char *kaddr = page_address(eb->pages[idx]);		\
+		put_unaligned_le##bits(val, kaddr + oip);		\
 		return;							\
 	}								\
-	p = kaddr + part_offset - map_start;				\
-	put_unaligned_le##bits(val, p + off);				\
+	leres = cpu_to_le##bits(val);					\
+	write_extent_buffer(eb, &leres, member_offset, size);		\
 }
 
 DEFINE_BTRFS_SETGET_BITS(8)
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (8 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 09/19] btrfs: speed up btrfs_set_##bits helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 13:50   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 11/19] btrfs: speed up and simplify generic_bin_search David Sterba
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The set/get token helpers either use the cached address in the token or
unconditionally call map_private_extent_buffer to get the address of
page containing the requested offset plus the mapping start and length.
Depending on the return value, the fast path uses unaligned put to write
data within a page, or fall back to read_extent_buffer that can handle
reads spanning more pages.

This is all wasteful. We know the number of bytes to read, 1/2/4/8 and
can find out the page. Then simply check if it's contained or the
fallback is needed. The token address is updated to the page, or the on
the next index, expecting that the next write will use that.

This saves one function call to map_private_extent_buffer and several
unnecessary temporary variables.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index f8a0357d10fd..67dfd1287c3e 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -106,38 +106,30 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 			    const void *ptr, unsigned long off,		\
 			    u##bits val)				\
 {									\
-	unsigned long part_offset = (unsigned long)ptr;			\
-	unsigned long offset = part_offset + off;			\
-	void *p;							\
-	int err;							\
-	char *kaddr;							\
-	unsigned long map_start;					\
-	unsigned long map_len;						\
-	int size = sizeof(u##bits);					\
+	const unsigned long member_offset = (unsigned long)ptr + off;	\
+	const unsigned long idx = member_offset >> PAGE_SHIFT;		\
+	const unsigned long oip = offset_in_page(member_offset);	\
+	const int size = sizeof(u##bits);				\
+	__le##bits leres;						\
 									\
 	ASSERT(token);							\
 	ASSERT(token->kaddr);						\
 	ASSERT(check_setget_bounds(token->eb, ptr, off, size));		\
-	if (token->offset <= offset &&					\
-	   (token->offset + PAGE_SIZE >= offset + size)) {	\
-		kaddr = token->kaddr;					\
-		p = kaddr + part_offset - token->offset;		\
-		put_unaligned_le##bits(val, p + off);			\
+	if (token->offset <= member_offset &&				\
+	    member_offset + size <= token->offset + PAGE_SIZE) {	\
+		put_unaligned_le##bits(val, token->kaddr + oip);	\
 		return;							\
 	}								\
-	err = map_private_extent_buffer(token->eb, offset, size,	\
-			&kaddr, &map_start, &map_len);			\
-	if (err) {							\
-		__le##bits val2;					\
-									\
-		val2 = cpu_to_le##bits(val);				\
-		write_extent_buffer(token->eb, &val2, offset, size);	\
+	if (oip + size <= PAGE_SIZE) {					\
+		token->kaddr = page_address(token->eb->pages[idx]);	\
+		token->offset = idx << PAGE_SHIFT;			\
+		put_unaligned_le##bits(val, token->kaddr + oip);	\
 		return;							\
 	}								\
-	p = kaddr + part_offset - map_start;				\
-	put_unaligned_le##bits(val, p + off);				\
-	token->kaddr = kaddr;						\
-	token->offset = map_start;					\
+	token->kaddr = page_address(token->eb->pages[idx + 1]);		\
+	token->offset = (idx + 1) << PAGE_SHIFT;			\
+	leres = cpu_to_le##bits(val);					\
+	write_extent_buffer(token->eb, &leres, member_offset, size);	\
 }									\
 void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,		\
 		      unsigned long off, u##bits val)			\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 11/19] btrfs: speed up and simplify generic_bin_search
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (9 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 14:04   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 12/19] btrfs: remove unused map_private_extent_buffer David Sterba
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The bin search jumps over the extent buffer item keys, comparing
directly the bytes if the key is in one page, or storing it in a
temporary buffer in case it spans two pages.

The mapping start and length are obtained from map_private_extent_buffer,
which is heavy weight compared to what we need. We know the key size and
can find out the eb page in a simple way.  For keys spanning two pages
the fallback read_extent_buffer is used.

The temporary variables are reduced and moved to the scope of use.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/ctree.c | 43 +++++++++++++++----------------------------
 1 file changed, 15 insertions(+), 28 deletions(-)

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 6dbeb23c59ec..746dec22f250 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1668,15 +1668,8 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
 {
 	int low = 0;
 	int high = max;
-	int mid;
 	int ret;
-	struct btrfs_disk_key *tmp = NULL;
-	struct btrfs_disk_key unaligned;
-	unsigned long offset;
-	char *kaddr = NULL;
-	unsigned long map_start = 0;
-	unsigned long map_len = 0;
-	int err;
+	const int key_size = sizeof(struct btrfs_disk_key);
 
 	if (low > high) {
 		btrfs_err(eb->fs_info,
@@ -1687,32 +1680,26 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
 	}
 
 	while (low < high) {
+		unsigned long oip;
+		unsigned long offset;
+		struct btrfs_disk_key *tmp;
+		struct btrfs_disk_key unaligned;
+		int mid;
+
 		mid = (low + high) / 2;
 		offset = p + mid * item_size;
+		oip = offset_in_page(offset);
 
-		if (!kaddr || offset < map_start ||
-		    (offset + sizeof(struct btrfs_disk_key)) >
-		    map_start + map_len) {
-
-			err = map_private_extent_buffer(eb, offset,
-						sizeof(struct btrfs_disk_key),
-						&kaddr, &map_start, &map_len);
-
-			if (!err) {
-				tmp = (struct btrfs_disk_key *)(kaddr + offset -
-							map_start);
-			} else if (err == 1) {
-				read_extent_buffer(eb, &unaligned,
-						   offset, sizeof(unaligned));
-				tmp = &unaligned;
-			} else {
-				return err;
-			}
+		if (oip + key_size <= PAGE_SIZE) {
+			const unsigned long idx = offset >> PAGE_SHIFT;
+			char *kaddr = page_address(eb->pages[idx]);
 
+			tmp = (struct btrfs_disk_key *)(kaddr + oip);
 		} else {
-			tmp = (struct btrfs_disk_key *)(kaddr + offset -
-							map_start);
+			read_extent_buffer(eb, &unaligned, offset, key_size);
+			tmp = &unaligned;
 		}
+
 		ret = comp_keys(tmp, key);
 
 		if (ret < 0)
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 12/19] btrfs: remove unused map_private_extent_buffer
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (10 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 11/19] btrfs: speed up and simplify generic_bin_search David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 14:05   ` Johannes Thumshirn
  2020-05-07 20:19 ` [PATCH 13/19] btrfs: constify extent_buffer in the API functions David Sterba
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

All uses of map_private_extent_buffer have been replaced by more
effective way. The set/get helpers have their own bounds checker.
The function name was confusing since the non-private helper was removed
in a65917156e34 ("Btrfs: stop using highmem for extent_buffers") many
years ago.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/extent_io.c | 42 ------------------------------------------
 fs/btrfs/extent_io.h |  4 ----
 2 files changed, 46 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 22db0b234ffe..67ee46a0a9c8 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5685,48 +5685,6 @@ int read_extent_buffer_to_user(const struct extent_buffer *eb,
 	return ret;
 }
 
-/*
- * return 0 if the item is found within a page.
- * return 1 if the item spans two pages.
- * return -EINVAL otherwise.
- */
-int map_private_extent_buffer(const struct extent_buffer *eb,
-			      unsigned long start, unsigned long min_len,
-			      char **map, unsigned long *map_start,
-			      unsigned long *map_len)
-{
-	size_t offset;
-	char *kaddr;
-	struct page *p;
-	size_t start_offset = offset_in_page(eb->start);
-	unsigned long i = (start_offset + start) >> PAGE_SHIFT;
-	unsigned long end_i = (start_offset + start + min_len - 1) >>
-		PAGE_SHIFT;
-
-	if (start + min_len > eb->len) {
-		WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
-		       eb->start, eb->len, start, min_len);
-		return -EINVAL;
-	}
-
-	if (i != end_i)
-		return 1;
-
-	if (i == 0) {
-		offset = start_offset;
-		*map_start = 0;
-	} else {
-		offset = 0;
-		*map_start = ((u64)i << PAGE_SHIFT) - start_offset;
-	}
-
-	p = eb->pages[i];
-	kaddr = page_address(p);
-	*map = kaddr + offset;
-	*map_len = PAGE_SIZE - offset;
-	return 0;
-}
-
 int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
 			 unsigned long start, unsigned long len)
 {
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index a2842b2d9a98..9ed89c01e2da 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -271,10 +271,6 @@ bool set_extent_buffer_dirty(struct extent_buffer *eb);
 void set_extent_buffer_uptodate(struct extent_buffer *eb);
 void clear_extent_buffer_uptodate(struct extent_buffer *eb);
 int extent_buffer_under_io(struct extent_buffer *eb);
-int map_private_extent_buffer(const struct extent_buffer *eb,
-			      unsigned long offset, unsigned long min_len,
-			      char **map, unsigned long *map_start,
-			      unsigned long *map_len);
 void extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
 void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
 void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 13/19] btrfs: constify extent_buffer in the API functions
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (11 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 12/19] btrfs: remove unused map_private_extent_buffer David Sterba
@ 2020-05-07 20:19 ` David Sterba
  2020-05-08 14:07   ` Johannes Thumshirn
  2020-05-07 20:20 ` [PATCH 14/19] btrfs: drop unnecessary offset_in_page in extent buffer helpers David Sterba
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:19 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

There are many helpers around extent buffers, found in extent_io.h and
ctree.h. Most of them can be converted to take constified eb as there
are no changes to the extent buffer structure itself but rather the
pages.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/ctree.h        | 28 +++++++++++++-------------
 fs/btrfs/extent_io.c    | 44 ++++++++++++++++++++++-------------------
 fs/btrfs/extent_io.h    | 44 ++++++++++++++++++++++-------------------
 fs/btrfs/struct-funcs.c |  2 +-
 4 files changed, 63 insertions(+), 55 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fbe2f9fa9f3e..944775bef6f3 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1384,7 +1384,7 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 			    u##bits val);				\
 u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 			 const void *ptr, unsigned long off);		\
-void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,		\
+void btrfs_set_##bits(const struct extent_buffer *eb, void *ptr,	\
 		      unsigned long off, u##bits val);
 
 DECLARE_BTRFS_SETGET_BITS(8)
@@ -1399,7 +1399,7 @@ static inline u##bits btrfs_##name(const struct extent_buffer *eb,	\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
 	return btrfs_get_##bits(eb, s, offsetof(type, member));		\
 }									\
-static inline void btrfs_set_##name(struct extent_buffer *eb, type *s,	\
+static inline void btrfs_set_##name(const struct extent_buffer *eb, type *s, \
 				    u##bits val)			\
 {									\
 	BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member);	\
@@ -1425,7 +1425,7 @@ static inline u##bits btrfs_##name(const struct extent_buffer *eb)	\
 	u##bits res = le##bits##_to_cpu(p->member);			\
 	return res;							\
 }									\
-static inline void btrfs_set_##name(struct extent_buffer *eb,		\
+static inline void btrfs_set_##name(const struct extent_buffer *eb,	\
 				    u##bits val)			\
 {									\
 	type *p = page_address(eb->pages[0]);				\
@@ -1443,7 +1443,7 @@ static inline void btrfs_set_##name(type *s, u##bits val)		\
 }
 
 
-static inline u64 btrfs_device_total_bytes(struct extent_buffer *eb,
+static inline u64 btrfs_device_total_bytes(const struct extent_buffer *eb,
 					   struct btrfs_dev_item *s)
 {
 	BUILD_BUG_ON(sizeof(u64) !=
@@ -1451,7 +1451,7 @@ static inline u64 btrfs_device_total_bytes(struct extent_buffer *eb,
 	return btrfs_get_64(eb, s, offsetof(struct btrfs_dev_item,
 					    total_bytes));
 }
-static inline void btrfs_set_device_total_bytes(struct extent_buffer *eb,
+static inline void btrfs_set_device_total_bytes(const struct extent_buffer *eb,
 						struct btrfs_dev_item *s,
 						u64 val)
 {
@@ -1555,13 +1555,13 @@ static inline char *btrfs_stripe_dev_uuid_nr(struct btrfs_chunk *c, int nr)
 	return btrfs_stripe_dev_uuid(btrfs_stripe_nr(c, nr));
 }
 
-static inline u64 btrfs_stripe_offset_nr(struct extent_buffer *eb,
+static inline u64 btrfs_stripe_offset_nr(const struct extent_buffer *eb,
 					 struct btrfs_chunk *c, int nr)
 {
 	return btrfs_stripe_offset(eb, btrfs_stripe_nr(c, nr));
 }
 
-static inline u64 btrfs_stripe_devid_nr(struct extent_buffer *eb,
+static inline u64 btrfs_stripe_devid_nr(const struct extent_buffer *eb,
 					 struct btrfs_chunk *c, int nr)
 {
 	return btrfs_stripe_devid(eb, btrfs_stripe_nr(c, nr));
@@ -1658,14 +1658,14 @@ BTRFS_SETGET_FUNCS(extent_refs_v0, struct btrfs_extent_item_v0, refs, 32);
 
 BTRFS_SETGET_FUNCS(tree_block_level, struct btrfs_tree_block_info, level, 8);
 
-static inline void btrfs_tree_block_key(struct extent_buffer *eb,
+static inline void btrfs_tree_block_key(const struct extent_buffer *eb,
 					struct btrfs_tree_block_info *item,
 					struct btrfs_disk_key *key)
 {
 	read_eb_member(eb, item, struct btrfs_tree_block_info, key, key);
 }
 
-static inline void btrfs_set_tree_block_key(struct extent_buffer *eb,
+static inline void btrfs_set_tree_block_key(const struct extent_buffer *eb,
 					    struct btrfs_tree_block_info *item,
 					    struct btrfs_disk_key *key)
 {
@@ -1717,7 +1717,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_key_blockptr, struct btrfs_key_ptr,
 BTRFS_SETGET_STACK_FUNCS(stack_key_generation, struct btrfs_key_ptr,
 			 generation, 64);
 
-static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr)
+static inline u64 btrfs_node_blockptr(const struct extent_buffer *eb, int nr)
 {
 	unsigned long ptr;
 	ptr = offsetof(struct btrfs_node, ptrs) +
@@ -1725,7 +1725,7 @@ static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr)
 	return btrfs_key_blockptr(eb, (struct btrfs_key_ptr *)ptr);
 }
 
-static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
+static inline void btrfs_set_node_blockptr(const struct extent_buffer *eb,
 					   int nr, u64 val)
 {
 	unsigned long ptr;
@@ -1734,7 +1734,7 @@ static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
 	btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
 }
 
-static inline u64 btrfs_node_ptr_generation(struct extent_buffer *eb, int nr)
+static inline u64 btrfs_node_ptr_generation(const struct extent_buffer *eb, int nr)
 {
 	unsigned long ptr;
 	ptr = offsetof(struct btrfs_node, ptrs) +
@@ -1742,7 +1742,7 @@ static inline u64 btrfs_node_ptr_generation(struct extent_buffer *eb, int nr)
 	return btrfs_key_generation(eb, (struct btrfs_key_ptr *)ptr);
 }
 
-static inline void btrfs_set_node_ptr_generation(struct extent_buffer *eb,
+static inline void btrfs_set_node_ptr_generation(const struct extent_buffer *eb,
 						 int nr, u64 val)
 {
 	unsigned long ptr;
@@ -1760,7 +1760,7 @@ static inline unsigned long btrfs_node_key_ptr_offset(int nr)
 void btrfs_node_key(const struct extent_buffer *eb,
 		    struct btrfs_disk_key *disk_key, int nr);
 
-static inline void btrfs_set_node_key(struct extent_buffer *eb,
+static inline void btrfs_set_node_key(const struct extent_buffer *eb,
 				      struct btrfs_disk_key *disk_key, int nr)
 {
 	unsigned long ptr;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 67ee46a0a9c8..da6f0c1ed80c 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2333,7 +2333,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
 	return 0;
 }
 
-int btrfs_repair_eb_io_failure(struct extent_buffer *eb, int mirror_num)
+int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, int mirror_num)
 {
 	struct btrfs_fs_info *fs_info = eb->fs_info;
 	u64 start = eb->start;
@@ -4910,7 +4910,7 @@ static void __free_extent_buffer(struct extent_buffer *eb)
 	kmem_cache_free(extent_buffer_cache, eb);
 }
 
-int extent_buffer_under_io(struct extent_buffer *eb)
+int extent_buffer_under_io(const struct extent_buffer *eb)
 {
 	return (atomic_read(&eb->io_pages) ||
 		test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) ||
@@ -5018,7 +5018,7 @@ __alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start,
 	return eb;
 }
 
-struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src)
+struct extent_buffer *btrfs_clone_extent_buffer(const struct extent_buffer *src)
 {
 	int i;
 	struct page *p;
@@ -5424,7 +5424,7 @@ void free_extent_buffer_stale(struct extent_buffer *eb)
 	release_extent_buffer(eb);
 }
 
-void clear_extent_buffer_dirty(struct extent_buffer *eb)
+void clear_extent_buffer_dirty(const struct extent_buffer *eb)
 {
 	int i;
 	int num_pages;
@@ -5720,7 +5720,7 @@ int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
 	return ret;
 }
 
-void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb,
+void write_extent_buffer_chunk_tree_uuid(const struct extent_buffer *eb,
 		const void *srcv)
 {
 	char *kaddr;
@@ -5731,7 +5731,7 @@ void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb,
 			BTRFS_FSID_SIZE);
 }
 
-void write_extent_buffer_fsid(struct extent_buffer *eb, const void *srcv)
+void write_extent_buffer_fsid(const struct extent_buffer *eb, const void *srcv)
 {
 	char *kaddr;
 
@@ -5741,7 +5741,7 @@ void write_extent_buffer_fsid(struct extent_buffer *eb, const void *srcv)
 			BTRFS_FSID_SIZE);
 }
 
-void write_extent_buffer(struct extent_buffer *eb, const void *srcv,
+void write_extent_buffer(const struct extent_buffer *eb, const void *srcv,
 			 unsigned long start, unsigned long len)
 {
 	size_t cur;
@@ -5772,7 +5772,7 @@ void write_extent_buffer(struct extent_buffer *eb, const void *srcv,
 	}
 }
 
-void memzero_extent_buffer(struct extent_buffer *eb, unsigned long start,
+void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
 		unsigned long len)
 {
 	size_t cur;
@@ -5801,8 +5801,8 @@ void memzero_extent_buffer(struct extent_buffer *eb, unsigned long start,
 	}
 }
 
-void copy_extent_buffer_full(struct extent_buffer *dst,
-			     struct extent_buffer *src)
+void copy_extent_buffer_full(const struct extent_buffer *dst,
+			     const struct extent_buffer *src)
 {
 	int i;
 	int num_pages;
@@ -5815,7 +5815,8 @@ void copy_extent_buffer_full(struct extent_buffer *dst,
 				page_address(src->pages[i]));
 }
 
-void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
+void copy_extent_buffer(const struct extent_buffer *dst,
+			const struct extent_buffer *src,
 			unsigned long dst_offset, unsigned long src_offset,
 			unsigned long len)
 {
@@ -5860,7 +5861,7 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
  * This helper hides the ugliness of finding the byte in an extent buffer which
  * contains a given bit.
  */
-static inline void eb_bitmap_offset(struct extent_buffer *eb,
+static inline void eb_bitmap_offset(const struct extent_buffer *eb,
 				    unsigned long start, unsigned long nr,
 				    unsigned long *page_index,
 				    size_t *page_offset)
@@ -5886,7 +5887,7 @@ static inline void eb_bitmap_offset(struct extent_buffer *eb,
  * @start: offset of the bitmap item in the extent buffer
  * @nr: bit number to test
  */
-int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
+int extent_buffer_test_bit(const struct extent_buffer *eb, unsigned long start,
 			   unsigned long nr)
 {
 	u8 *kaddr;
@@ -5908,7 +5909,7 @@ int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
  * @pos: bit number of the first bit
  * @len: number of bits to set
  */
-void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
+void extent_buffer_bitmap_set(const struct extent_buffer *eb, unsigned long start,
 			      unsigned long pos, unsigned long len)
 {
 	u8 *kaddr;
@@ -5950,8 +5951,9 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
  * @pos: bit number of the first bit
  * @len: number of bits to clear
  */
-void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
-				unsigned long pos, unsigned long len)
+void extent_buffer_bitmap_clear(const struct extent_buffer *eb,
+				unsigned long start, unsigned long pos,
+				unsigned long len)
 {
 	u8 *kaddr;
 	struct page *page;
@@ -6012,8 +6014,9 @@ static void copy_pages(struct page *dst_page, struct page *src_page,
 		memcpy(dst_kaddr + dst_off, src_kaddr + src_off, len);
 }
 
-void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
-			   unsigned long src_offset, unsigned long len)
+void memcpy_extent_buffer(const struct extent_buffer *dst,
+			  unsigned long dst_offset, unsigned long src_offset,
+			  unsigned long len)
 {
 	struct btrfs_fs_info *fs_info = dst->fs_info;
 	size_t cur;
@@ -6057,8 +6060,9 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
 	}
 }
 
-void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
-			   unsigned long src_offset, unsigned long len)
+void memmove_extent_buffer(const struct extent_buffer *dst,
+			   unsigned long dst_offset, unsigned long src_offset,
+			   unsigned long len)
 {
 	struct btrfs_fs_info *fs_info = dst->fs_info;
 	size_t cur;
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 9ed89c01e2da..9a10681b12bf 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -213,7 +213,7 @@ struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
 						  u64 start, unsigned long len);
 struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
 						u64 start);
-struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src);
+struct extent_buffer *btrfs_clone_extent_buffer(const struct extent_buffer *src);
 struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
 					 u64 start);
 void free_extent_buffer(struct extent_buffer *eb);
@@ -231,7 +231,7 @@ static inline int num_extent_pages(const struct extent_buffer *eb)
 	       (eb->start >> PAGE_SHIFT);
 }
 
-static inline int extent_buffer_uptodate(struct extent_buffer *eb)
+static inline int extent_buffer_uptodate(const struct extent_buffer *eb)
 {
 	return test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 }
@@ -244,33 +244,37 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dst,
 int read_extent_buffer_to_user(const struct extent_buffer *eb,
 			       void __user *dst, unsigned long start,
 			       unsigned long len);
-void write_extent_buffer_fsid(struct extent_buffer *eb, const void *src);
-void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb,
+void write_extent_buffer_fsid(const struct extent_buffer *eb, const void *src);
+void write_extent_buffer_chunk_tree_uuid(const struct extent_buffer *eb,
 		const void *src);
-void write_extent_buffer(struct extent_buffer *eb, const void *src,
+void write_extent_buffer(const struct extent_buffer *eb, const void *src,
 			 unsigned long start, unsigned long len);
-void copy_extent_buffer_full(struct extent_buffer *dst,
-			     struct extent_buffer *src);
-void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
+void copy_extent_buffer_full(const struct extent_buffer *dst,
+			     const struct extent_buffer *src);
+void copy_extent_buffer(const struct extent_buffer *dst,
+			const struct extent_buffer *src,
 			unsigned long dst_offset, unsigned long src_offset,
 			unsigned long len);
-void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
-			   unsigned long src_offset, unsigned long len);
-void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
-			   unsigned long src_offset, unsigned long len);
-void memzero_extent_buffer(struct extent_buffer *eb, unsigned long start,
+void memcpy_extent_buffer(const struct extent_buffer *dst,
+			  unsigned long dst_offset, unsigned long src_offset,
+			  unsigned long len);
+void memmove_extent_buffer(const struct extent_buffer *dst,
+			   unsigned long dst_offset, unsigned long src_offset,
 			   unsigned long len);
-int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
+void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
+			   unsigned long len);
+int extent_buffer_test_bit(const struct extent_buffer *eb, unsigned long start,
 			   unsigned long pos);
-void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
+void extent_buffer_bitmap_set(const struct extent_buffer *eb, unsigned long start,
 			      unsigned long pos, unsigned long len);
-void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
-				unsigned long pos, unsigned long len);
-void clear_extent_buffer_dirty(struct extent_buffer *eb);
+void extent_buffer_bitmap_clear(const struct extent_buffer *eb,
+				unsigned long start, unsigned long pos,
+				unsigned long len);
+void clear_extent_buffer_dirty(const struct extent_buffer *eb);
 bool set_extent_buffer_dirty(struct extent_buffer *eb);
 void set_extent_buffer_uptodate(struct extent_buffer *eb);
 void clear_extent_buffer_uptodate(struct extent_buffer *eb);
-int extent_buffer_under_io(struct extent_buffer *eb);
+int extent_buffer_under_io(const struct extent_buffer *eb);
 void extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
 void extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
 void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
@@ -289,7 +293,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
 		      u64 length, u64 logical, struct page *page,
 		      unsigned int pg_offset, int mirror_num);
 void end_extent_writepage(struct page *page, int err, u64 start, u64 end);
-int btrfs_repair_eb_io_failure(struct extent_buffer *eb, int mirror_num);
+int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, int mirror_num);
 
 /*
  * When IO fails, either with EIO or csum verification fails, we
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 67dfd1287c3e..0b23aa0a32d5 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -131,7 +131,7 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 	leres = cpu_to_le##bits(val);					\
 	write_extent_buffer(token->eb, &leres, member_offset, size);	\
 }									\
-void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,		\
+void btrfs_set_##bits(const struct extent_buffer *eb, void *ptr,	\
 		      unsigned long off, u##bits val)			\
 {									\
 	const unsigned long member_offset = (unsigned long)ptr + off;	\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 14/19] btrfs: drop unnecessary offset_in_page in extent buffer helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (12 preceding siblings ...)
  2020-05-07 20:19 ` [PATCH 13/19] btrfs: constify extent_buffer in the API functions David Sterba
@ 2020-05-07 20:20 ` David Sterba
  2020-05-08 14:13   ` Johannes Thumshirn
  2020-05-07 20:20 ` [PATCH 15/19] btrfs: optimize split page read in btrfs_get_##bits David Sterba
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:20 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

Helpers that iterate over extent buffer pages set up several variables,
one of them is finding out offset of the extent buffer start within a
page. Right now we have extent buffers aligned to page sizes so this is
effectively storing zero. This makes the code harder the follow and can
be simplified.

The same change is done in all the helpers:

* remove: size_t start_offset = offset_in_page(eb->start);
* simplify code using start_offset

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/extent_io.c | 51 ++++++++++++++++++--------------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index da6f0c1ed80c..c59e07360083 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5622,8 +5622,7 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
 	struct page *page;
 	char *kaddr;
 	char *dst = (char *)dstv;
-	size_t start_offset = offset_in_page(eb->start);
-	unsigned long i = (start_offset + start) >> PAGE_SHIFT;
+	unsigned long i = start >> PAGE_SHIFT;
 
 	if (start + len > eb->len) {
 		WARN(1, KERN_ERR "btrfs bad mapping eb start %llu len %lu, wanted %lu %lu\n",
@@ -5632,7 +5631,7 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
 		return;
 	}
 
-	offset = offset_in_page(start_offset + start);
+	offset = offset_in_page(start);
 
 	while (len > 0) {
 		page = eb->pages[i];
@@ -5657,14 +5656,13 @@ int read_extent_buffer_to_user(const struct extent_buffer *eb,
 	struct page *page;
 	char *kaddr;
 	char __user *dst = (char __user *)dstv;
-	size_t start_offset = offset_in_page(eb->start);
-	unsigned long i = (start_offset + start) >> PAGE_SHIFT;
+	unsigned long i = start >> PAGE_SHIFT;
 	int ret = 0;
 
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = offset_in_page(start_offset + start);
+	offset = offset_in_page(start);
 
 	while (len > 0) {
 		page = eb->pages[i];
@@ -5693,14 +5691,13 @@ int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
 	struct page *page;
 	char *kaddr;
 	char *ptr = (char *)ptrv;
-	size_t start_offset = offset_in_page(eb->start);
-	unsigned long i = (start_offset + start) >> PAGE_SHIFT;
+	unsigned long i = start >> PAGE_SHIFT;
 	int ret = 0;
 
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = offset_in_page(start_offset + start);
+	offset = offset_in_page(start);
 
 	while (len > 0) {
 		page = eb->pages[i];
@@ -5749,13 +5746,12 @@ void write_extent_buffer(const struct extent_buffer *eb, const void *srcv,
 	struct page *page;
 	char *kaddr;
 	char *src = (char *)srcv;
-	size_t start_offset = offset_in_page(eb->start);
-	unsigned long i = (start_offset + start) >> PAGE_SHIFT;
+	unsigned long i = start >> PAGE_SHIFT;
 
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = offset_in_page(start_offset + start);
+	offset = offset_in_page(start);
 
 	while (len > 0) {
 		page = eb->pages[i];
@@ -5779,13 +5775,12 @@ void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
 	size_t offset;
 	struct page *page;
 	char *kaddr;
-	size_t start_offset = offset_in_page(eb->start);
-	unsigned long i = (start_offset + start) >> PAGE_SHIFT;
+	unsigned long i = start >> PAGE_SHIFT;
 
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = offset_in_page(start_offset + start);
+	offset = offset_in_page(start);
 
 	while (len > 0) {
 		page = eb->pages[i];
@@ -5825,12 +5820,11 @@ void copy_extent_buffer(const struct extent_buffer *dst,
 	size_t offset;
 	struct page *page;
 	char *kaddr;
-	size_t start_offset = offset_in_page(dst->start);
-	unsigned long i = (start_offset + dst_offset) >> PAGE_SHIFT;
+	unsigned long i = dst_offset >> PAGE_SHIFT;
 
 	WARN_ON(src->len != dst_len);
 
-	offset = offset_in_page(start_offset + dst_offset);
+	offset = offset_in_page(dst_offset);
 
 	while (len > 0) {
 		page = dst->pages[i];
@@ -5866,7 +5860,6 @@ static inline void eb_bitmap_offset(const struct extent_buffer *eb,
 				    unsigned long *page_index,
 				    size_t *page_offset)
 {
-	size_t start_offset = offset_in_page(eb->start);
 	size_t byte_offset = BIT_BYTE(nr);
 	size_t offset;
 
@@ -5875,7 +5868,7 @@ static inline void eb_bitmap_offset(const struct extent_buffer *eb,
 	 * the bitmap item in the extent buffer + the offset of the byte in the
 	 * bitmap item.
 	 */
-	offset = start_offset + start + byte_offset;
+	offset = start + byte_offset;
 
 	*page_index = offset >> PAGE_SHIFT;
 	*page_offset = offset_in_page(offset);
@@ -6022,7 +6015,6 @@ void memcpy_extent_buffer(const struct extent_buffer *dst,
 	size_t cur;
 	size_t dst_off_in_page;
 	size_t src_off_in_page;
-	size_t start_offset = offset_in_page(dst->start);
 	unsigned long dst_i;
 	unsigned long src_i;
 
@@ -6040,11 +6032,11 @@ void memcpy_extent_buffer(const struct extent_buffer *dst,
 	}
 
 	while (len > 0) {
-		dst_off_in_page = offset_in_page(start_offset + dst_offset);
-		src_off_in_page = offset_in_page(start_offset + src_offset);
+		dst_off_in_page = offset_in_page(dst_offset);
+		src_off_in_page = offset_in_page(src_offset);
 
-		dst_i = (start_offset + dst_offset) >> PAGE_SHIFT;
-		src_i = (start_offset + src_offset) >> PAGE_SHIFT;
+		dst_i = dst_offset >> PAGE_SHIFT;
+		src_i = src_offset >> PAGE_SHIFT;
 
 		cur = min(len, (unsigned long)(PAGE_SIZE -
 					       src_off_in_page));
@@ -6070,7 +6062,6 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
 	size_t src_off_in_page;
 	unsigned long dst_end = dst_offset + len - 1;
 	unsigned long src_end = src_offset + len - 1;
-	size_t start_offset = offset_in_page(dst->start);
 	unsigned long dst_i;
 	unsigned long src_i;
 
@@ -6091,11 +6082,11 @@ void memmove_extent_buffer(const struct extent_buffer *dst,
 		return;
 	}
 	while (len > 0) {
-		dst_i = (start_offset + dst_end) >> PAGE_SHIFT;
-		src_i = (start_offset + src_end) >> PAGE_SHIFT;
+		dst_i = dst_end >> PAGE_SHIFT;
+		src_i = src_end >> PAGE_SHIFT;
 
-		dst_off_in_page = offset_in_page(start_offset + dst_end);
-		src_off_in_page = offset_in_page(start_offset + src_end);
+		dst_off_in_page = offset_in_page(dst_end);
+		src_off_in_page = offset_in_page(src_end);
 
 		cur = min_t(unsigned long, len, src_off_in_page + 1);
 		cur = min(cur, dst_off_in_page + 1);
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 15/19] btrfs: optimize split page read in btrfs_get_##bits
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (13 preceding siblings ...)
  2020-05-07 20:20 ` [PATCH 14/19] btrfs: drop unnecessary offset_in_page in extent buffer helpers David Sterba
@ 2020-05-07 20:20 ` David Sterba
  2020-05-08 14:17   ` Johannes Thumshirn
  2020-05-07 20:20 ` [PATCH 16/19] btrfs: optimize split page read in btrfs_get_token_##bits David Sterba
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:20 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The helper read_extent_buffer is called to do read of the data spanning
two extent buffer pages. As the size is known, we can do the read
directly in two steps.  This removes one function call and compiler can
optimize memcpy as the sizes are known at compile time.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 0b23aa0a32d5..46a7269bee07 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -90,17 +90,20 @@ u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 {									\
 	const unsigned long member_offset = (unsigned long)ptr + off;	\
 	const unsigned long oip = offset_in_page(member_offset);	\
+	const unsigned long idx = member_offset >> PAGE_SHIFT;		\
+	char *kaddr = page_address(eb->pages[idx]);			\
 	const int size = sizeof(u##bits);				\
-	__le##bits leres;						\
+	const int part = PAGE_SIZE - oip;				\
+	u8 lebytes[sizeof(u##bits)];					\
 									\
 	ASSERT(check_setget_bounds(eb, ptr, off, size));		\
-	if (oip + size <= PAGE_SIZE) {					\
-		const unsigned long idx = member_offset >> PAGE_SHIFT;	\
-		const char *kaddr = page_address(eb->pages[idx]);	\
+	if (oip + size <= PAGE_SIZE)					\
 		return get_unaligned_le##bits(kaddr + oip);		\
-	}								\
-	read_extent_buffer(eb, &leres, member_offset, size);		\
-	return le##bits##_to_cpu(leres);				\
+									\
+	memcpy(lebytes, kaddr + oip, part);				\
+	kaddr = page_address(eb->pages[idx + 1]);			\
+	memcpy(lebytes + part, kaddr, size - part);			\
+	return get_unaligned_le##bits(lebytes);				\
 }									\
 void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 			    const void *ptr, unsigned long off,		\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 16/19] btrfs: optimize split page read in btrfs_get_token_##bits
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (14 preceding siblings ...)
  2020-05-07 20:20 ` [PATCH 15/19] btrfs: optimize split page read in btrfs_get_##bits David Sterba
@ 2020-05-07 20:20 ` David Sterba
  2020-05-08 14:18   ` Johannes Thumshirn
  2020-05-07 20:20 ` [PATCH 17/19] btrfs: optimize split page write in btrfs_set_##bits David Sterba
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:20 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The fallback path calls helper read_extent_buffer to do read of the data
spanning two extent buffer pages. As the size is known, we can do the
read directly in two steps.  This removes one function call and compiler
can optimize memcpy as the sizes are known at compile time. The cached
token address is set to the second page.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 46a7269bee07..63cab91507f8 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -66,7 +66,8 @@ u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
 	const unsigned long idx = member_offset >> PAGE_SHIFT;		\
 	const unsigned long oip = offset_in_page(member_offset);	\
 	const int size = sizeof(u##bits);				\
-	__le##bits leres;						\
+	u8 lebytes[sizeof(u##bits)];					\
+	const int part = PAGE_SIZE - oip;				\
 									\
 	ASSERT(token);							\
 	ASSERT(token->kaddr);						\
@@ -75,15 +76,16 @@ u##bits btrfs_get_token_##bits(struct btrfs_map_token *token,		\
 	    member_offset + size <= token->offset + PAGE_SIZE) {	\
 		return get_unaligned_le##bits(token->kaddr + oip);	\
 	}								\
-	if (oip + size <= PAGE_SIZE) {					\
-		token->kaddr = page_address(token->eb->pages[idx]);	\
-		token->offset = idx << PAGE_SHIFT;			\
+	token->kaddr = page_address(token->eb->pages[idx]);		\
+	token->offset = idx << PAGE_SHIFT;				\
+	if (oip + size <= PAGE_SIZE)					\
 		return get_unaligned_le##bits(token->kaddr + oip);	\
-	}								\
+									\
+	memcpy(lebytes, token->kaddr + oip, part);			\
 	token->kaddr = page_address(token->eb->pages[idx + 1]);		\
 	token->offset = (idx + 1) << PAGE_SHIFT;			\
-	read_extent_buffer(token->eb, &leres, member_offset, size);	\
-	return le##bits##_to_cpu(leres);				\
+	memcpy(lebytes + part, token->kaddr, size - part);		\
+	return get_unaligned_le##bits(lebytes);				\
 }									\
 u##bits btrfs_get_##bits(const struct extent_buffer *eb,		\
 			 const void *ptr, unsigned long off)		\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 17/19] btrfs: optimize split page write in btrfs_set_##bits
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (15 preceding siblings ...)
  2020-05-07 20:20 ` [PATCH 16/19] btrfs: optimize split page read in btrfs_get_token_##bits David Sterba
@ 2020-05-07 20:20 ` David Sterba
  2020-05-08 14:20   ` Johannes Thumshirn
  2020-05-07 20:20 ` [PATCH 18/19] btrfs: optimize split page write in btrfs_set_token_##bits David Sterba
  2020-05-07 20:20 ` [PATCH 19/19] btrfs: update documentation of set/get helpers David Sterba
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:20 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The helper write_extent_buffer is called to do write of the data
spanning two extent buffer pages. As the size is known, we can do the
write directly in two steps.  This removes one function call and
compiler can optimize memcpy as the sizes are known at compile time.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 63cab91507f8..7987d3910660 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -141,18 +141,22 @@ void btrfs_set_##bits(const struct extent_buffer *eb, void *ptr,	\
 {									\
 	const unsigned long member_offset = (unsigned long)ptr + off;	\
 	const unsigned long oip = offset_in_page(member_offset);	\
+	const unsigned long idx = member_offset >> PAGE_SHIFT;		\
+	char *kaddr = page_address(eb->pages[idx]);			\
 	const int size = sizeof(u##bits);				\
-	__le##bits leres;						\
+	const int part = PAGE_SIZE - oip;				\
+	u8 lebytes[sizeof(u##bits)];					\
 									\
 	ASSERT(check_setget_bounds(eb, ptr, off, size));		\
 	if (oip + size <= PAGE_SIZE) {					\
-		const unsigned long idx = member_offset >> PAGE_SHIFT;	\
-		char *kaddr = page_address(eb->pages[idx]);		\
 		put_unaligned_le##bits(val, kaddr + oip);		\
 		return;							\
 	}								\
-	leres = cpu_to_le##bits(val);					\
-	write_extent_buffer(eb, &leres, member_offset, size);		\
+									\
+	put_unaligned_le##bits(val, lebytes);				\
+	memcpy(kaddr + oip, lebytes, part);				\
+	kaddr = page_address(eb->pages[idx + 1]);			\
+	memcpy(kaddr, lebytes + part, size - part);			\
 }
 
 DEFINE_BTRFS_SETGET_BITS(8)
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 18/19] btrfs: optimize split page write in btrfs_set_token_##bits
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (16 preceding siblings ...)
  2020-05-07 20:20 ` [PATCH 17/19] btrfs: optimize split page write in btrfs_set_##bits David Sterba
@ 2020-05-07 20:20 ` David Sterba
  2020-05-08 14:21   ` Johannes Thumshirn
  2020-05-07 20:20 ` [PATCH 19/19] btrfs: update documentation of set/get helpers David Sterba
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:20 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

The fallback path calls helper write_extent_buffer to do write of the
data spanning two extent buffer pages. As the size is known, we can do
the write directly in two steps.  This removes one function call and
compiler can optimize memcpy as the sizes are known at compile time. The
cached token address is set to the second page.

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 7987d3910660..225ef6d7e949 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -115,7 +115,8 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 	const unsigned long idx = member_offset >> PAGE_SHIFT;		\
 	const unsigned long oip = offset_in_page(member_offset);	\
 	const int size = sizeof(u##bits);				\
-	__le##bits leres;						\
+	u8 lebytes[sizeof(u##bits)];					\
+	const int part = PAGE_SIZE - oip;				\
 									\
 	ASSERT(token);							\
 	ASSERT(token->kaddr);						\
@@ -125,16 +126,17 @@ void btrfs_set_token_##bits(struct btrfs_map_token *token,		\
 		put_unaligned_le##bits(val, token->kaddr + oip);	\
 		return;							\
 	}								\
+	token->kaddr = page_address(token->eb->pages[idx]);		\
+	token->offset = idx << PAGE_SHIFT;				\
 	if (oip + size <= PAGE_SIZE) {					\
-		token->kaddr = page_address(token->eb->pages[idx]);	\
-		token->offset = idx << PAGE_SHIFT;			\
 		put_unaligned_le##bits(val, token->kaddr + oip);	\
 		return;							\
 	}								\
+	put_unaligned_le##bits(val, lebytes);				\
+	memcpy(token->kaddr + oip, lebytes, part);			\
 	token->kaddr = page_address(token->eb->pages[idx + 1]);		\
 	token->offset = (idx + 1) << PAGE_SHIFT;			\
-	leres = cpu_to_le##bits(val);					\
-	write_extent_buffer(token->eb, &leres, member_offset, size);	\
+	memcpy(token->kaddr, lebytes + part, size - part);		\
 }									\
 void btrfs_set_##bits(const struct extent_buffer *eb, void *ptr,	\
 		      unsigned long off, u##bits val)			\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 19/19] btrfs: update documentation of set/get helpers
  2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
                   ` (17 preceding siblings ...)
  2020-05-07 20:20 ` [PATCH 18/19] btrfs: optimize split page write in btrfs_set_token_##bits David Sterba
@ 2020-05-07 20:20 ` David Sterba
  2020-05-07 21:33   ` Nikolay Borisov
  18 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-07 20:20 UTC (permalink / raw)
  To: linux-btrfs; +Cc: David Sterba

Signed-off-by: David Sterba <dsterba@suse.com>
---
 fs/btrfs/struct-funcs.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 225ef6d7e949..1021b80f70db 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -39,23 +39,26 @@ static bool check_setget_bounds(const struct extent_buffer *eb,
 }
 
 /*
- * this is some deeply nasty code.
+ * Macro templates that define helpers to read/write extent buffer data of a
+ * given size, that are also used via ctree.h for access to item members via
+ * specialized helpers.
  *
- * The end result is that anyone who #includes ctree.h gets a
- * declaration for the btrfs_set_foo functions and btrfs_foo functions,
- * which are wrappers of btrfs_set_token_#bits functions and
- * btrfs_get_token_#bits functions, which are defined in this file.
+ * Generic helpers:
+ * - btrfs_set_8 (for 8/16/32/64)
+ * - btrfs_get_8 (for 8/16/32/64)
  *
- * These setget functions do all the extent_buffer related mapping
- * required to efficiently read and write specific fields in the extent
- * buffers.  Every pointer to metadata items in btrfs is really just
- * an unsigned long offset into the extent buffer which has been
- * cast to a specific type.  This gives us all the gcc type checking.
+ * Generic helpes with a token, caching last page address:
+ * - btrfs_set_token_8 (for 8/16/32/64)
+ * - btrfs_get_token_8 (for 8/16/32/64)
  *
- * The extent buffer api is used to do the page spanning work required to
- * have a metadata blocksize different from the page size.
+ * The set/get functions handle data spanning two pages transparently, in case
+ * metadata block size is larger than page.  Every pointer to metadata items is
+ * an offset into the extent buffer page array, cast to a specific type.  This
+ * gives us all the type checking.
  *
- * There are 2 variants defined, one with a token pointer and one without.
+ * The extent buffer pages stored in the array pages do not form a contiguous
+ * range, but the API functions assume the linear offset to the range from
+ * 0 to metadata node size.
  */
 
 #define DEFINE_BTRFS_SETGET_BITS(bits)					\
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 19/19] btrfs: update documentation of set/get helpers
  2020-05-07 20:20 ` [PATCH 19/19] btrfs: update documentation of set/get helpers David Sterba
@ 2020-05-07 21:33   ` Nikolay Borisov
  2020-05-11 13:10     ` David Sterba
  0 siblings, 1 reply; 44+ messages in thread
From: Nikolay Borisov @ 2020-05-07 21:33 UTC (permalink / raw)
  To: David Sterba, linux-btrfs



On 7.05.20 г. 23:20 ч., David Sterba wrote:
> Signed-off-by: David Sterba <dsterba@suse.com>
> ---
>  fs/btrfs/struct-funcs.c | 29 ++++++++++++++++-------------
>  1 file changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
> index 225ef6d7e949..1021b80f70db 100644
> --- a/fs/btrfs/struct-funcs.c
> +++ b/fs/btrfs/struct-funcs.c
> @@ -39,23 +39,26 @@ static bool check_setget_bounds(const struct extent_buffer *eb,
>  }
>  
>  /*
> - * this is some deeply nasty code.
> + * Macro templates that define helpers to read/write extent buffer data of a
> + * given size, that are also used via ctree.h for access to item members via
> + * specialized helpers.
>   *
> - * The end result is that anyone who #includes ctree.h gets a
> - * declaration for the btrfs_set_foo functions and btrfs_foo functions,
> - * which are wrappers of btrfs_set_token_#bits functions and
> - * btrfs_get_token_#bits functions, which are defined in this file.
> + * Generic helpers:
> + * - btrfs_set_8 (for 8/16/32/64)
> + * - btrfs_get_8 (for 8/16/32/64)
>   *
> - * These setget functions do all the extent_buffer related mapping
> - * required to efficiently read and write specific fields in the extent
> - * buffers.  Every pointer to metadata items in btrfs is really just
> - * an unsigned long offset into the extent buffer which has been
> - * cast to a specific type.  This gives us all the gcc type checking.
> + * Generic helpes with a token, caching last page address:

nit: missing 'r' in 'helpers'. Without having looked into the code It's
not obvious what a "token" is in this context, is it worth it perhaps
documenting? ( I will take a look later and see if it's self-evident).

> + * - btrfs_set_token_8 (for 8/16/32/64)
> + * - btrfs_get_token_8 (for 8/16/32/64)
>   *
> - * The extent buffer api is used to do the page spanning work required to
> - * have a metadata blocksize different from the page size.
> + * The set/get functions handle data spanning two pages transparently, in case
> + * metadata block size is larger than page.  Every pointer to metadata items is
       ^^^^^
nit: s/metadata/btree/?

> + * an offset into the extent buffer page array, cast to a specific type.  This
> + * gives us all the type checking.
>   *
> - * There are 2 variants defined, one with a token pointer and one without.
> + * The extent buffer pages stored in the array pages do not form a contiguous
> + * range, but the API functions assume the linear offset to the range from

nit: "contiguous physical range"

> + * 0 to metadata node size.
>   */
>  
>  #define DEFINE_BTRFS_SETGET_BITS(bits)					\
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 01/19] btrfs: use the token::eb for all set/get helpers
  2020-05-07 20:19 ` [PATCH 01/19] btrfs: use the token::eb for all set/get helpers David Sterba
@ 2020-05-08 12:05   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 12:05 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers
  2020-05-07 20:19 ` [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers David Sterba
@ 2020-05-08 12:09   ` Johannes Thumshirn
  2020-05-11 13:02     ` David Sterba
  0 siblings, 1 reply; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 12:09 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

On 07/05/2020 22:20, David Sterba wrote:
> +		push_space = push_space - btrfs_token_item_size(&token, item);

Nit: push_space -= btrfs_token_item_size(&token, item);

Anayways,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 03/19] btrfs: don't use set/get token for single assignment in overwrite_item
  2020-05-07 20:19 ` [PATCH 03/19] btrfs: don't use set/get token for single assignment in overwrite_item David Sterba
@ 2020-05-08 13:25   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:25 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/19] btrfs: don't use set/get token in leaf_space_used
  2020-05-07 20:19 ` [PATCH 04/19] btrfs: don't use set/get token in leaf_space_used David Sterba
@ 2020-05-08 13:27   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:27 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

On 07/05/2020 22:20, David Sterba wrote:
> +	data_len = data_len - btrfs_item_offset(l, end_item);

Nit: Could again be data_len -= btrfs_item_offset(l, end_item);
Otherwise,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 05/19] btrfs: preset set/get token with first page and drop condition
  2020-05-07 20:19 ` [PATCH 05/19] btrfs: preset set/get token with first page and drop condition David Sterba
@ 2020-05-08 13:37   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:37 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 06/19] btrfs: add separate bounds checker for set/get helpers
  2020-05-07 20:19 ` [PATCH 06/19] btrfs: add separate bounds checker for set/get helpers David Sterba
@ 2020-05-08 13:39   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:39 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/19] btrfs: speed up btrfs_get_##bits helpers
  2020-05-07 20:19 ` [PATCH 07/19] btrfs: speed up btrfs_get_##bits helpers David Sterba
@ 2020-05-08 13:42   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:42 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 08/19] btrfs: speed up btrfs_get_token_##bits helpers
  2020-05-07 20:19 ` [PATCH 08/19] btrfs: speed up btrfs_get_token_##bits helpers David Sterba
@ 2020-05-08 13:46   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:46 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/19] btrfs: speed up btrfs_set_##bits helpers
  2020-05-07 20:19 ` [PATCH 09/19] btrfs: speed up btrfs_set_##bits helpers David Sterba
@ 2020-05-08 13:48   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:48 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

On 07/05/2020 22:21, David Sterba wrote:
> This is all wasteful. We know the number of bytes to read, 1/2/4/8 and
                                                 write? ~^

Otherwise,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers
  2020-05-07 20:19 ` [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers David Sterba
@ 2020-05-08 13:50   ` Johannes Thumshirn
  2020-05-11 13:17     ` David Sterba
  0 siblings, 1 reply; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 13:50 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

On 07/05/2020 22:21, David Sterba wrote:
> This is all wasteful. We know the number of bytes to read, 1/2/4/8 and

Same question, s/read/write/?

Otherwise,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 11/19] btrfs: speed up and simplify generic_bin_search
  2020-05-07 20:19 ` [PATCH 11/19] btrfs: speed up and simplify generic_bin_search David Sterba
@ 2020-05-08 14:04   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:04 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Nice simplification,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

but one unrelated question, generic_bin_search() sounds so, well 
generic. Maybe we should rename it to __btrfs_bin_search(), given it's 
only called by btrfs_bin_search().

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 12/19] btrfs: remove unused map_private_extent_buffer
  2020-05-07 20:19 ` [PATCH 12/19] btrfs: remove unused map_private_extent_buffer David Sterba
@ 2020-05-08 14:05   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:05 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

So long and thanks for all the fish ;-)
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 13/19] btrfs: constify extent_buffer in the API functions
  2020-05-07 20:19 ` [PATCH 13/19] btrfs: constify extent_buffer in the API functions David Sterba
@ 2020-05-08 14:07   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:07 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 14/19] btrfs: drop unnecessary offset_in_page in extent buffer helpers
  2020-05-07 20:20 ` [PATCH 14/19] btrfs: drop unnecessary offset_in_page in extent buffer helpers David Sterba
@ 2020-05-08 14:13   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:13 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 15/19] btrfs: optimize split page read in btrfs_get_##bits
  2020-05-07 20:20 ` [PATCH 15/19] btrfs: optimize split page read in btrfs_get_##bits David Sterba
@ 2020-05-08 14:17   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:17 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 16/19] btrfs: optimize split page read in btrfs_get_token_##bits
  2020-05-07 20:20 ` [PATCH 16/19] btrfs: optimize split page read in btrfs_get_token_##bits David Sterba
@ 2020-05-08 14:18   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:18 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 17/19] btrfs: optimize split page write in btrfs_set_##bits
  2020-05-07 20:20 ` [PATCH 17/19] btrfs: optimize split page write in btrfs_set_##bits David Sterba
@ 2020-05-08 14:20   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:20 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 18/19] btrfs: optimize split page write in btrfs_set_token_##bits
  2020-05-07 20:20 ` [PATCH 18/19] btrfs: optimize split page write in btrfs_set_token_##bits David Sterba
@ 2020-05-08 14:21   ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-08 14:21 UTC (permalink / raw)
  To: David Sterba, linux-btrfs

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers
  2020-05-08 12:09   ` Johannes Thumshirn
@ 2020-05-11 13:02     ` David Sterba
  2020-05-11 14:41       ` Johannes Thumshirn
  0 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-11 13:02 UTC (permalink / raw)
  To: Johannes Thumshirn; +Cc: David Sterba, linux-btrfs

On Fri, May 08, 2020 at 12:09:15PM +0000, Johannes Thumshirn wrote:
> On 07/05/2020 22:20, David Sterba wrote:
> > +		push_space = push_space - btrfs_token_item_size(&token, item);
> 
> Nit: push_space -= btrfs_token_item_size(&token, item);

Yeah it could be done that way but I'd rather avoid mixing such small
fixups to a patch that's otherwise a mechanical change.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 19/19] btrfs: update documentation of set/get helpers
  2020-05-07 21:33   ` Nikolay Borisov
@ 2020-05-11 13:10     ` David Sterba
  2020-05-11 14:16       ` Nikolay Borisov
  0 siblings, 1 reply; 44+ messages in thread
From: David Sterba @ 2020-05-11 13:10 UTC (permalink / raw)
  To: Nikolay Borisov; +Cc: David Sterba, linux-btrfs

On Fri, May 08, 2020 at 12:33:08AM +0300, Nikolay Borisov wrote:
> On 7.05.20 г. 23:20 ч., David Sterba wrote:
> > Signed-off-by: David Sterba <dsterba@suse.com>
> > ---
> >  fs/btrfs/struct-funcs.c | 29 ++++++++++++++++-------------
> >  1 file changed, 16 insertions(+), 13 deletions(-)
> > 
> > diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
> > index 225ef6d7e949..1021b80f70db 100644
> > --- a/fs/btrfs/struct-funcs.c
> > +++ b/fs/btrfs/struct-funcs.c
> > @@ -39,23 +39,26 @@ static bool check_setget_bounds(const struct extent_buffer *eb,
> >  }
> >  
> >  /*
> > - * this is some deeply nasty code.
> > + * Macro templates that define helpers to read/write extent buffer data of a
> > + * given size, that are also used via ctree.h for access to item members via
> > + * specialized helpers.
> >   *
> > - * The end result is that anyone who #includes ctree.h gets a
> > - * declaration for the btrfs_set_foo functions and btrfs_foo functions,
> > - * which are wrappers of btrfs_set_token_#bits functions and
> > - * btrfs_get_token_#bits functions, which are defined in this file.
> > + * Generic helpers:
> > + * - btrfs_set_8 (for 8/16/32/64)
> > + * - btrfs_get_8 (for 8/16/32/64)
> >   *
> > - * These setget functions do all the extent_buffer related mapping
> > - * required to efficiently read and write specific fields in the extent
> > - * buffers.  Every pointer to metadata items in btrfs is really just
> > - * an unsigned long offset into the extent buffer which has been
> > - * cast to a specific type.  This gives us all the gcc type checking.
> > + * Generic helpes with a token, caching last page address:
> 
> nit: missing 'r' in 'helpers'. Without having looked into the code It's
> not obvious what a "token" is in this context, is it worth it perhaps
> documenting? ( I will take a look later and see if it's self-evident).

I could write it as

"Generic helpers with a token (a structure caching the address of most
recently accessed page)"

The use of 'last' is confusing as it's not the last as in the array.

> > + * - btrfs_set_token_8 (for 8/16/32/64)
> > + * - btrfs_get_token_8 (for 8/16/32/64)
> >   *
> > - * The extent buffer api is used to do the page spanning work required to
> > - * have a metadata blocksize different from the page size.
> > + * The set/get functions handle data spanning two pages transparently, in case
> > + * metadata block size is larger than page.  Every pointer to metadata items is
>        ^^^^^
> nit: s/metadata/btree/?

The terms should be interchangeable, but in the previous sentence it's 'metadata'
and this one continues, so I wonder how would 'btree' fit here.

All the structures here are on the higher level, so metadata etc, while
b-tree node is the storage.

> > + * an offset into the extent buffer page array, cast to a specific type.  This
> > + * gives us all the type checking.
> >   *
> > - * There are 2 variants defined, one with a token pointer and one without.
> > + * The extent buffer pages stored in the array pages do not form a contiguous
> > + * range, but the API functions assume the linear offset to the range from
> 
> nit: "contiguous physical range"

Ok.

> > + * 0 to metadata node size.
> >   */
> >  
> >  #define DEFINE_BTRFS_SETGET_BITS(bits)					\
> > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers
  2020-05-08 13:50   ` Johannes Thumshirn
@ 2020-05-11 13:17     ` David Sterba
  0 siblings, 0 replies; 44+ messages in thread
From: David Sterba @ 2020-05-11 13:17 UTC (permalink / raw)
  To: Johannes Thumshirn; +Cc: David Sterba, linux-btrfs

On Fri, May 08, 2020 at 01:50:52PM +0000, Johannes Thumshirn wrote:
> On 07/05/2020 22:21, David Sterba wrote:
> > This is all wasteful. We know the number of bytes to read, 1/2/4/8 and
> 
> Same question, s/read/write/?

Yes, fixed, thanks.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 19/19] btrfs: update documentation of set/get helpers
  2020-05-11 13:10     ` David Sterba
@ 2020-05-11 14:16       ` Nikolay Borisov
  0 siblings, 0 replies; 44+ messages in thread
From: Nikolay Borisov @ 2020-05-11 14:16 UTC (permalink / raw)
  To: dsterba, David Sterba, linux-btrfs



On 11.05.20 г. 16:10 ч., David Sterba wrote:
> On Fri, May 08, 2020 at 12:33:08AM +0300, Nikolay Borisov wrote:
>> On 7.05.20 г. 23:20 ч., David Sterba wrote:
>>> Signed-off-by: David Sterba <dsterba@suse.com>
>>> ---
>>>  fs/btrfs/struct-funcs.c | 29 ++++++++++++++++-------------
>>>  1 file changed, 16 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
>>> index 225ef6d7e949..1021b80f70db 100644
>>> --- a/fs/btrfs/struct-funcs.c
>>> +++ b/fs/btrfs/struct-funcs.c
>>> @@ -39,23 +39,26 @@ static bool check_setget_bounds(const struct extent_buffer *eb,
>>>  }
>>>  
>>>  /*
>>> - * this is some deeply nasty code.
>>> + * Macro templates that define helpers to read/write extent buffer data of a
>>> + * given size, that are also used via ctree.h for access to item members via
>>> + * specialized helpers.
>>>   *
>>> - * The end result is that anyone who #includes ctree.h gets a
>>> - * declaration for the btrfs_set_foo functions and btrfs_foo functions,
>>> - * which are wrappers of btrfs_set_token_#bits functions and
>>> - * btrfs_get_token_#bits functions, which are defined in this file.
>>> + * Generic helpers:
>>> + * - btrfs_set_8 (for 8/16/32/64)
>>> + * - btrfs_get_8 (for 8/16/32/64)
>>>   *
>>> - * These setget functions do all the extent_buffer related mapping
>>> - * required to efficiently read and write specific fields in the extent
>>> - * buffers.  Every pointer to metadata items in btrfs is really just
>>> - * an unsigned long offset into the extent buffer which has been
>>> - * cast to a specific type.  This gives us all the gcc type checking.
>>> + * Generic helpes with a token, caching last page address:
>>
>> nit: missing 'r' in 'helpers'. Without having looked into the code It's
>> not obvious what a "token" is in this context, is it worth it perhaps
>> documenting? ( I will take a look later and see if it's self-evident).
> 
> I could write it as
> 
> "Generic helpers with a token (a structure caching the address of most
> recently accessed page)"

Much better.

> 
> The use of 'last' is confusing as it's not the last as in the array.
> 
>>> + * - btrfs_set_token_8 (for 8/16/32/64)
>>> + * - btrfs_get_token_8 (for 8/16/32/64)
>>>   *
>>> - * The extent buffer api is used to do the page spanning work required to
>>> - * have a metadata blocksize different from the page size.
>>> + * The set/get functions handle data spanning two pages transparently, in case
>>> + * metadata block size is larger than page.  Every pointer to metadata items is
>>        ^^^^^
>> nit: s/metadata/btree/?
> 
> The terms should be interchangeable, but in the previous sentence it's 'metadata'
> and this one continues, so I wonder how would 'btree' fit here.
> 
> All the structures here are on the higher level, so metadata etc, while
> b-tree node is the storage.

Fair enough, I reread the section and it's ok.

> 
>>> + * an offset into the extent buffer page array, cast to a specific type.  This
>>> + * gives us all the type checking.
>>>   *
>>> - * There are 2 variants defined, one with a token pointer and one without.
>>> + * The extent buffer pages stored in the array pages do not form a contiguous
>>> + * range, but the API functions assume the linear offset to the range from
>>
>> nit: "contiguous physical range"
> 
> Ok.
> 
>>> + * 0 to metadata node size.
>>>   */
>>>  
>>>  #define DEFINE_BTRFS_SETGET_BITS(bits)					\
>>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers
  2020-05-11 13:02     ` David Sterba
@ 2020-05-11 14:41       ` Johannes Thumshirn
  0 siblings, 0 replies; 44+ messages in thread
From: Johannes Thumshirn @ 2020-05-11 14:41 UTC (permalink / raw)
  To: dsterba; +Cc: David Sterba, linux-btrfs

On 11/05/2020 15:03, David Sterba wrote:
> On Fri, May 08, 2020 at 12:09:15PM +0000, Johannes Thumshirn wrote:
>> On 07/05/2020 22:20, David Sterba wrote:
>>> +		push_space = push_space - btrfs_token_item_size(&token, item);
>>
>> Nit: push_space -= btrfs_token_item_size(&token, item);
> 
> Yeah it could be done that way but I'd rather avoid mixing such small
> fixups to a patch that's otherwise a mechanical change.
> 

Fair enough

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2020-05-11 14:41 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-07 20:19 [PATCH 00/19] Set/get helpers speedups and cleanups David Sterba
2020-05-07 20:19 ` [PATCH 01/19] btrfs: use the token::eb for all set/get helpers David Sterba
2020-05-08 12:05   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 02/19] btrfs: drop eb parameter from set/get token helpers David Sterba
2020-05-08 12:09   ` Johannes Thumshirn
2020-05-11 13:02     ` David Sterba
2020-05-11 14:41       ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 03/19] btrfs: don't use set/get token for single assignment in overwrite_item David Sterba
2020-05-08 13:25   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 04/19] btrfs: don't use set/get token in leaf_space_used David Sterba
2020-05-08 13:27   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 05/19] btrfs: preset set/get token with first page and drop condition David Sterba
2020-05-08 13:37   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 06/19] btrfs: add separate bounds checker for set/get helpers David Sterba
2020-05-08 13:39   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 07/19] btrfs: speed up btrfs_get_##bits helpers David Sterba
2020-05-08 13:42   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 08/19] btrfs: speed up btrfs_get_token_##bits helpers David Sterba
2020-05-08 13:46   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 09/19] btrfs: speed up btrfs_set_##bits helpers David Sterba
2020-05-08 13:48   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 10/19] btrfs: speed up btrfs_set_token_##bits helpers David Sterba
2020-05-08 13:50   ` Johannes Thumshirn
2020-05-11 13:17     ` David Sterba
2020-05-07 20:19 ` [PATCH 11/19] btrfs: speed up and simplify generic_bin_search David Sterba
2020-05-08 14:04   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 12/19] btrfs: remove unused map_private_extent_buffer David Sterba
2020-05-08 14:05   ` Johannes Thumshirn
2020-05-07 20:19 ` [PATCH 13/19] btrfs: constify extent_buffer in the API functions David Sterba
2020-05-08 14:07   ` Johannes Thumshirn
2020-05-07 20:20 ` [PATCH 14/19] btrfs: drop unnecessary offset_in_page in extent buffer helpers David Sterba
2020-05-08 14:13   ` Johannes Thumshirn
2020-05-07 20:20 ` [PATCH 15/19] btrfs: optimize split page read in btrfs_get_##bits David Sterba
2020-05-08 14:17   ` Johannes Thumshirn
2020-05-07 20:20 ` [PATCH 16/19] btrfs: optimize split page read in btrfs_get_token_##bits David Sterba
2020-05-08 14:18   ` Johannes Thumshirn
2020-05-07 20:20 ` [PATCH 17/19] btrfs: optimize split page write in btrfs_set_##bits David Sterba
2020-05-08 14:20   ` Johannes Thumshirn
2020-05-07 20:20 ` [PATCH 18/19] btrfs: optimize split page write in btrfs_set_token_##bits David Sterba
2020-05-08 14:21   ` Johannes Thumshirn
2020-05-07 20:20 ` [PATCH 19/19] btrfs: update documentation of set/get helpers David Sterba
2020-05-07 21:33   ` Nikolay Borisov
2020-05-11 13:10     ` David Sterba
2020-05-11 14:16       ` Nikolay Borisov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.