summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-02-03 00:22:47 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2017-01-18 21:38:26 -0900
commitf0e5fe448e8fd34a881fb0f081122c44004b2ef2 (patch)
tree552324787b364397013a5c98af30bf591f3cb099
parent4c78450d3785a4fca3e15b35316745c0f0916407 (diff)
bcachefs: verify i_size/i_size_dirty in various places
-rw-r--r--drivers/md/bcache/fs-io.c52
-rw-r--r--drivers/md/bcache/fs-io.h3
2 files changed, 50 insertions, 5 deletions
diff --git a/drivers/md/bcache/fs-io.c b/drivers/md/bcache/fs-io.c
index 282d58897321..ba92857f3056 100644
--- a/drivers/md/bcache/fs-io.c
+++ b/drivers/md/bcache/fs-io.c
@@ -204,6 +204,10 @@ static void i_sectors_hook_fn(struct btree_insert_hook *hook,
struct i_sectors_hook *h = container_of(hook,
struct i_sectors_hook, hook);
+ EBUG_ON(h->ei->vfs_inode.i_ino != insert->k.p.inode);
+ EBUG_ON(!(h->ei->i_flags & BCH_INODE_I_SECTORS_DIRTY));
+ EBUG_ON(!atomic_long_read(&h->ei->i_sectors_dirty_count));
+
if (k.k) {
if (!bkey_extent_is_allocation(k.k))
return;
@@ -229,6 +233,22 @@ static void i_sectors_hook_fn(struct btree_insert_hook *hook,
if (!bkey_extent_is_allocation(&insert->k))
return;
+#ifdef CONFIG_BCACHE_DEBUG
+ if (!(insert->k.type == BCH_RESERVATION)) {
+ struct bch_inode_info *ei = h->ei;
+ unsigned seq;
+ bool bad_write;
+
+ do {
+ seq = read_seqcount_begin(&ei->shadow_i_size_lock);
+ bad_write = !(ei->i_flags & BCH_INODE_I_SIZE_DIRTY) &&
+ insert->k.p.offset >
+ (round_up(ei->i_size, PAGE_SIZE) >> 9);
+ } while (read_seqcount_retry(&ei->shadow_i_size_lock, seq));
+
+ BUG_ON(bad_write);
+ }
+#endif
h->sectors += insert->k.size;
}
}
@@ -298,6 +318,9 @@ static int __must_check i_sectors_dirty_get(struct bch_inode_info *ei,
h->hook.fn = i_sectors_hook_fn;
h->sectors = 0;
+#ifdef CONFIG_BCACHE_DEBUG
+ h->ei = ei;
+#endif
if (atomic_long_inc_not_zero(&ei->i_sectors_dirty_count))
return 0;
@@ -484,6 +507,25 @@ int bch_set_page_dirty(struct page *page)
{
struct bch_page_state old, new;
+#ifdef CONFIG_BCACHE_DEBUG
+ {
+ struct bch_inode_info *ei = to_bch_ei(page->mapping->host);
+ unsigned seq, i_flags;
+ u64 i_size;
+
+ do {
+ seq = read_seqcount_begin(&ei->shadow_i_size_lock);
+ i_size = ei->i_size;
+ i_flags = ei->i_flags;
+ } while (read_seqcount_retry(&ei->shadow_i_size_lock, seq));
+
+ BUG_ON(((page_offset(page) + PAGE_SIZE) >
+ round_up(i_size, PAGE_SIZE)) &&
+ !(i_flags & BCH_INODE_I_SIZE_DIRTY) &&
+ !atomic_long_read(&ei->i_size_dirty_count));
+ }
+#endif
+
old = page_state_cmpxchg(page_state(page), new,
new.dirty_sectors = PAGE_SECTORS - new.sectors;
);
@@ -1132,11 +1174,6 @@ int bch_write_end(struct file *filp, struct address_space *mapping,
goto out;
}
- if (!PageUptodate(page))
- SetPageUptodate(page);
- if (!PageDirty(page))
- set_page_dirty(page);
-
if (pos + copied > inode->i_size) {
struct bch_page_state old, new;
struct i_size_update *u;
@@ -1172,6 +1209,11 @@ int bch_write_end(struct file *filp, struct address_space *mapping,
bch_i_size_write(inode, pos + copied);
mutex_unlock(&ei->update_lock);
}
+
+ if (!PageUptodate(page))
+ SetPageUptodate(page);
+ if (!PageDirty(page))
+ set_page_dirty(page);
out:
unlock_page(page);
put_page(page);
diff --git a/drivers/md/bcache/fs-io.h b/drivers/md/bcache/fs-io.h
index f7b9b7b57e88..28fc4a64132b 100644
--- a/drivers/md/bcache/fs-io.h
+++ b/drivers/md/bcache/fs-io.h
@@ -35,6 +35,9 @@ int bch_migrate_page(struct address_space *, struct page *,
struct i_sectors_hook {
struct btree_insert_hook hook;
s64 sectors;
+#ifdef CONFIG_BCACHE_DEBUG
+ struct bch_inode_info *ei;
+#endif
};
struct bch_writepage_io {