David Sterba
2013-Apr-30 14:29 UTC
[PATCH] btrfs: add debug check for extent_io range alignment
The ''end'' value must exactly cover the end of the interval,
which means
one byte less than the expected block alignment, or in case of a file
smaller than one block, one byte less than the inode size.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
fs/btrfs/extent_io.c | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index c4949f1..6f6beda 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -76,10 +76,29 @@ void btrfs_leak_debug_check(void)
kmem_cache_free(extent_buffer_cache, eb);
}
}
+
+#define btrfs_debug_check_extent_io_range(inode, start, end) \
+ __btrfs_debug_check_extent_io_range(__func__, (inode), (start), (end))
+static inline void __btrfs_debug_check_extent_io_range(const char *caller,
+ struct inode *inode, u64 start, u64 end)
+{
+ u64 isize = i_size_read(inode);
+
+ if (end >= PAGE_SIZE && (end % 2) == 0 && end != isize - 1)
{
+ printk_ratelimited(KERN_DEBUG
+ "btrfs: %s: ino %llu isize %llu odd range [%llu,%llu)\n",
+ caller,
+ (unsigned long long)btrfs_ino(inode),
+ (unsigned long long)isize,
+ (unsigned long long)start,
+ (unsigned long long)end);
+ }
+}
#else
#define btrfs_leak_debug_add(new, head) do {} while (0)
#define btrfs_leak_debug_del(entry) do {} while (0)
#define btrfs_leak_debug_check() do {} while (0)
+#define btrfs_debug_check_extent_io_range(c, s, e) do {} while (0)
#endif
#define BUFFER_LRU_MAX 64
@@ -509,6 +528,8 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start,
u64 end,
int err;
int clear = 0;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
if (delete)
bits |= ~EXTENT_CTLBITS;
bits |= EXTENT_FIRST_DELALLOC;
@@ -664,6 +685,8 @@ static void wait_extent_bit(struct extent_io_tree *tree, u64
start, u64 end,
struct extent_state *state;
struct rb_node *node;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
spin_lock(&tree->lock);
again:
while (1) {
@@ -756,6 +779,8 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64
end,
u64 last_start;
u64 last_end;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
bits |= EXTENT_FIRST_DELALLOC;
again:
if (!prealloc && (mask & __GFP_WAIT)) {
@@ -976,6 +1001,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64
start, u64 end,
u64 last_start;
u64 last_end;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
again:
if (!prealloc && (mask & __GFP_WAIT)) {
prealloc = alloc_extent_state(mask);
--
1.7.9
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Hugo Mills
2013-Apr-30 14:35 UTC
Re: [PATCH] btrfs: add debug check for extent_io range alignment
On Tue, Apr 30, 2013 at 04:29:44PM +0200, David Sterba wrote:> The ''end'' value must exactly cover the end of the interval, which means > one byte less than the expected block alignment, or in case of a file > smaller than one block, one byte less than the inode size.If that''s actually the case, then the error message needs to use "]" not ")" to close the interval. Using ")" would imply that the end value is one past the end of the interval in question. Hugo.> Signed-off-by: David Sterba <dsterba@suse.cz> > --- > fs/btrfs/extent_io.c | 27 +++++++++++++++++++++++++++ > 1 files changed, 27 insertions(+), 0 deletions(-) > > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > index c4949f1..6f6beda 100644 > --- a/fs/btrfs/extent_io.c > +++ b/fs/btrfs/extent_io.c > @@ -76,10 +76,29 @@ void btrfs_leak_debug_check(void) > kmem_cache_free(extent_buffer_cache, eb); > } > } > + > +#define btrfs_debug_check_extent_io_range(inode, start, end) \ > + __btrfs_debug_check_extent_io_range(__func__, (inode), (start), (end)) > +static inline void __btrfs_debug_check_extent_io_range(const char *caller, > + struct inode *inode, u64 start, u64 end) > +{ > + u64 isize = i_size_read(inode); > + > + if (end >= PAGE_SIZE && (end % 2) == 0 && end != isize - 1) { > + printk_ratelimited(KERN_DEBUG > + "btrfs: %s: ino %llu isize %llu odd range [%llu,%llu)\n", > + caller, > + (unsigned long long)btrfs_ino(inode), > + (unsigned long long)isize, > + (unsigned long long)start, > + (unsigned long long)end); > + } > +} > #else > #define btrfs_leak_debug_add(new, head) do {} while (0) > #define btrfs_leak_debug_del(entry) do {} while (0) > #define btrfs_leak_debug_check() do {} while (0) > +#define btrfs_debug_check_extent_io_range(c, s, e) do {} while (0) > #endif > > #define BUFFER_LRU_MAX 64 > @@ -509,6 +528,8 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, > int err; > int clear = 0; > > + btrfs_debug_check_extent_io_range(tree->mapping->host, start, end); > + > if (delete) > bits |= ~EXTENT_CTLBITS; > bits |= EXTENT_FIRST_DELALLOC; > @@ -664,6 +685,8 @@ static void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, > struct extent_state *state; > struct rb_node *node; > > + btrfs_debug_check_extent_io_range(tree->mapping->host, start, end); > + > spin_lock(&tree->lock); > again: > while (1) { > @@ -756,6 +779,8 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, > u64 last_start; > u64 last_end; > > + btrfs_debug_check_extent_io_range(tree->mapping->host, start, end); > + > bits |= EXTENT_FIRST_DELALLOC; > again: > if (!prealloc && (mask & __GFP_WAIT)) { > @@ -976,6 +1001,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, > u64 last_start; > u64 last_end; > > + btrfs_debug_check_extent_io_range(tree->mapping->host, start, end); > + > again: > if (!prealloc && (mask & __GFP_WAIT)) { > prealloc = alloc_extent_state(mask);-- === Hugo Mills: hugo@... carfax.org.uk | darksatanic.net | lug.org.uk == PGP key: 65E74AC0 from wwwkeys.eu.pgp.net or http://www.carfax.org.uk --- Is it true that "last known good" on Windows XP --- boots into CP/M?
David Sterba
2013-Apr-30 15:22 UTC
[PATCH v2] btrfs: add debug check for extent_io range alignment
The ''end'' value must exactly cover the end of the interval,
which means
one byte less than the expected block alignment, or in case of a file
smaller than one block, one byte less than the inode size.
Signed-off-by: David Sterba <dsterba@suse.cz>
---
v1->v2: denote that range is inclusive [...]
fs/btrfs/extent_io.c | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index c4949f1..6f6beda 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -76,10 +76,29 @@ void btrfs_leak_debug_check(void)
kmem_cache_free(extent_buffer_cache, eb);
}
}
+
+#define btrfs_debug_check_extent_io_range(inode, start, end) \
+ __btrfs_debug_check_extent_io_range(__func__, (inode), (start), (end))
+static inline void __btrfs_debug_check_extent_io_range(const char *caller,
+ struct inode *inode, u64 start, u64 end)
+{
+ u64 isize = i_size_read(inode);
+
+ if (end >= PAGE_SIZE && (end % 2) == 0 && end != isize - 1)
{
+ printk_ratelimited(KERN_DEBUG
+ "btrfs: %s: ino %llu isize %llu odd range [%llu,%llu]\n",
+ caller,
+ (unsigned long long)btrfs_ino(inode),
+ (unsigned long long)isize,
+ (unsigned long long)start,
+ (unsigned long long)end);
+ }
+}
#else
#define btrfs_leak_debug_add(new, head) do {} while (0)
#define btrfs_leak_debug_del(entry) do {} while (0)
#define btrfs_leak_debug_check() do {} while (0)
+#define btrfs_debug_check_extent_io_range(c, s, e) do {} while (0)
#endif
#define BUFFER_LRU_MAX 64
@@ -509,6 +528,8 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start,
u64 end,
int err;
int clear = 0;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
if (delete)
bits |= ~EXTENT_CTLBITS;
bits |= EXTENT_FIRST_DELALLOC;
@@ -664,6 +685,8 @@ static void wait_extent_bit(struct extent_io_tree *tree, u64
start, u64 end,
struct extent_state *state;
struct rb_node *node;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
spin_lock(&tree->lock);
again:
while (1) {
@@ -756,6 +779,8 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64
end,
u64 last_start;
u64 last_end;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
bits |= EXTENT_FIRST_DELALLOC;
again:
if (!prealloc && (mask & __GFP_WAIT)) {
@@ -976,6 +1001,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64
start, u64 end,
u64 last_start;
u64 last_end;
+ btrfs_debug_check_extent_io_range(tree->mapping->host, start, end);
+
again:
if (!prealloc && (mask & __GFP_WAIT)) {
prealloc = alloc_extent_state(mask);
--
1.7.9
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html