1 ext4: add callback support for bio read completion
3 From: Make Halcrow <mhalcrow@google.com>
5 Adds callback support for bio read completion. This supports data
6 transformation such as encryption.
8 This change deliberately targets only file systems that use struct
9 bio, including ext4. A more invasive change would be required for
10 other file systems such as NFS.
12 Signed-off-by: Michael Halcrow <mhalcrow@google.com>
13 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
15 fs/buffer.c | 46 +++++++++++++++++++++++++++++++++++++++------
16 include/linux/blk_types.h | 4 ++++
17 include/linux/buffer_head.h | 8 ++++++++
18 3 files changed, 52 insertions(+), 6 deletions(-)
20 diff --git a/fs/buffer.c b/fs/buffer.c
21 index eba6e4f..a5527c5 100644
24 @@ -296,7 +296,7 @@ static void free_more_memory(void)
25 * I/O completion handler for block_read_full_page() - pages
26 * which come unlocked at the end of I/O.
28 -static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
29 +void end_buffer_async_read(struct buffer_head *bh, int uptodate)
32 struct buffer_head *first;
33 @@ -339,6 +339,13 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
34 bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
35 local_irq_restore(flags);
37 + if (bh->b_private) {
38 + struct bio *bio = (struct bio *)bh->b_private;
39 + BUG_ON(!bio->bi_cb);
40 + if (!bio->bi_cb(bio, !(page_uptodate && !PageError(page))))
45 * If none of the buffers had errors and they are all
46 * uptodate then we can set the page uptodate.
47 @@ -346,6 +353,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
48 if (page_uptodate && !PageError(page))
49 SetPageUptodate(page);
55 @@ -353,6 +361,7 @@ still_busy:
56 local_irq_restore(flags);
59 +EXPORT_SYMBOL_GPL(end_buffer_async_read);
62 * Completion handler for block_write_full_page() - pages which are unlocked
63 @@ -431,11 +440,12 @@ EXPORT_SYMBOL(end_buffer_async_write);
64 * PageLocked prevents anyone from starting writeback of a page which is
65 * under read I/O (PageWriteback is only ever set against a locked page).
67 -static void mark_buffer_async_read(struct buffer_head *bh)
68 +void mark_buffer_async_read(struct buffer_head *bh)
70 bh->b_end_io = end_buffer_async_read;
71 set_buffer_async_read(bh);
73 +EXPORT_SYMBOL_GPL(mark_buffer_async_read);
75 static void mark_buffer_async_write_endio(struct buffer_head *bh,
77 @@ -1654,14 +1664,17 @@ static inline int block_size_bits(unsigned int blocksize)
78 return ilog2(blocksize);
81 -static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
82 +struct buffer_head *create_page_buffers(struct page *page, struct inode *inode,
83 + unsigned int b_state)
85 BUG_ON(!PageLocked(page));
87 if (!page_has_buffers(page))
88 - create_empty_buffers(page, 1 << ACCESS_ONCE(inode->i_blkbits), b_state);
89 + create_empty_buffers(page, 1 << ACCESS_ONCE(inode->i_blkbits),
91 return page_buffers(page);
93 +EXPORT_SYMBOL_GPL(create_page_buffers);
96 * NOTE! All mapped/uptodate combinations are valid:
97 @@ -3009,7 +3022,8 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
101 -int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
102 +int _submit_bh_cb(int rw, struct buffer_head *bh, unsigned long bio_flags,
103 + bio_completion_cb_t *cb, void *cb_ctx)
107 @@ -3043,6 +3057,8 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
109 bio->bi_end_io = end_bio_bh_io_sync;
110 bio->bi_private = bh;
112 + bio->bi_cb_ctx = cb_ctx;
113 bio->bi_flags |= bio_flags;
115 /* Take care of bh's that straddle the end of the device */
116 @@ -3054,6 +3070,12 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
122 + BUG_ON(bh->b_private);
123 + bh->b_private = bio;
128 if (bio_flagged(bio, BIO_EOPNOTSUPP))
129 @@ -3062,14 +3084,26 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
134 +int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
136 + return _submit_bh_cb(rw, bh, bio_flags, NULL, NULL);
138 EXPORT_SYMBOL_GPL(_submit_bh);
140 int submit_bh(int rw, struct buffer_head *bh)
142 - return _submit_bh(rw, bh, 0);
143 + return submit_bh_cb(rw, bh, NULL, NULL);
145 EXPORT_SYMBOL(submit_bh);
147 +int submit_bh_cb(int rw, struct buffer_head *bh, bio_completion_cb_t *cb,
150 + return _submit_bh_cb(rw, bh, 0, cb, cb_ctx);
152 +EXPORT_SYMBOL_GPL(submit_bh_cb);
155 * ll_rw_block: low-level access to block devices (DEPRECATED)
156 * @rw: whether to %READ or %WRITE or maybe %READA (readahead)
157 diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
158 index 66c2167..06102df 100644
159 --- a/include/linux/blk_types.h
160 +++ b/include/linux/blk_types.h
161 @@ -16,6 +16,7 @@ struct io_context;
162 struct cgroup_subsys_state;
163 typedef void (bio_end_io_t) (struct bio *, int);
164 typedef void (bio_destructor_t) (struct bio *);
165 +typedef int (bio_completion_cb_t) (struct bio *, int);
168 * was unsigned short, but we might as well be ready for > 64kB I/O pages
169 @@ -96,6 +97,9 @@ struct bio {
171 struct bio_set *bi_pool;
173 + bio_completion_cb_t *bi_cb; /* completion callback */
174 + void *bi_cb_ctx; /* callback context */
177 * We can inline a number of vecs at the end of the bio, to avoid
178 * double allocations for a small number of bio_vecs. This member
179 diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
180 index 324329c..24ea03a 100644
181 --- a/include/linux/buffer_head.h
182 +++ b/include/linux/buffer_head.h
183 @@ -160,7 +160,9 @@ void create_empty_buffers(struct page *, unsigned long,
184 unsigned long b_state);
185 void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
186 void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
187 +void end_buffer_async_read(struct buffer_head *bh, int uptodate);
188 void end_buffer_async_write(struct buffer_head *bh, int uptodate);
189 +void mark_buffer_async_read(struct buffer_head *bh);
191 /* Things to do with buffers at mapping->private_list */
192 void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
193 @@ -169,6 +171,8 @@ void invalidate_inode_buffers(struct inode *);
194 int remove_inode_buffers(struct inode *inode);
195 int sync_mapping_buffers(struct address_space *mapping);
196 void unmap_underlying_metadata(struct block_device *bdev, sector_t block);
197 +struct buffer_head *create_page_buffers(struct page *page, struct inode *inode,
198 + unsigned int b_state);
200 void mark_buffer_async_write(struct buffer_head *bh);
201 void __wait_on_buffer(struct buffer_head *);
202 @@ -191,7 +195,11 @@ int sync_dirty_buffer(struct buffer_head *bh);
203 int __sync_dirty_buffer(struct buffer_head *bh, int rw);
204 void write_dirty_buffer(struct buffer_head *bh, int rw);
205 int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags);
206 +int _submit_bh_cb(int rw, struct buffer_head *bh, unsigned long bio_flags,
207 + bio_completion_cb_t *cb, void *cb_ctx);
208 int submit_bh(int, struct buffer_head *);
209 +int submit_bh_cb(int rw, struct buffer_head *bh, bio_completion_cb_t *cb,
211 void write_boundary_block(struct block_device *bdev,
212 sector_t bblock, unsigned blocksize);
213 int bh_uptodate_or_lock(struct buffer_head *bh);
215 2.1.0.rc2.206.gedb03e5