add patch delete-useless-comments-about-ext4_move_extents
[ext4-patch-queue.git] / add-callback-support-for-bio-read-completion
blobe0367d58acf9fcb0a416f50afa658218c643ac0f
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>
14 ---
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
22 --- a/fs/buffer.c
23 +++ b/fs/buffer.c
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.
27   */
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)
30  {
31         unsigned long flags;
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))))
41 +                       goto out;
42 +       }
44         /*
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);
50         unlock_page(page);
51 +out:
52         return;
54  still_busy:
55 @@ -353,6 +361,7 @@ still_busy:
56         local_irq_restore(flags);
57         return;
58  }
59 +EXPORT_SYMBOL_GPL(end_buffer_async_read);
61  /*
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).
66   */
67 -static void mark_buffer_async_read(struct buffer_head *bh)
68 +void mark_buffer_async_read(struct buffer_head *bh)
69  {
70         bh->b_end_io = end_buffer_async_read;
71         set_buffer_async_read(bh);
72  }
73 +EXPORT_SYMBOL_GPL(mark_buffer_async_read);
75  static void mark_buffer_async_write_endio(struct buffer_head *bh,
76                                           bh_end_io_t *handler)
77 @@ -1654,14 +1664,17 @@ static inline int block_size_bits(unsigned int blocksize)
78         return ilog2(blocksize);
79  }
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)
84  {
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),
90 +                                    b_state);
91         return page_buffers(page);
92  }
93 +EXPORT_SYMBOL_GPL(create_page_buffers);
95  /*
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)
98         }
99  }
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)
105         struct bio *bio;
106         int ret = 0;
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;
111 +       bio->bi_cb = cb;
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)
117                 rw |= REQ_PRIO;
119         bio_get(bio);
121 +       if (bio->bi_cb) {
122 +               BUG_ON(bh->b_private);
123 +               bh->b_private = bio;
124 +       }
126         submit_bio(rw, 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)
130         bio_put(bio);
131         return ret;
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,
148 +                void *cb_ctx)
150 +       return _submit_bh_cb(rw, bh, 0, cb, cb_ctx);
152 +EXPORT_SYMBOL_GPL(submit_bh_cb);
154  /**
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);
167  /*
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 */
176         /*
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,
210 +                void *cb_ctx);
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);
214 -- 
215 2.1.0.rc2.206.gedb03e5