Blame view

block/blk-flush.c 6.7 KB
86db1e297   Jens Axboe   block: continue l...
1
  /*
4fed947cb   Tejun Heo   block: implement ...
2
   * Functions to sequence FLUSH and FUA writes.
86db1e297   Jens Axboe   block: continue l...
3
4
5
6
7
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/bio.h>
  #include <linux/blkdev.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/gfp.h>
86db1e297   Jens Axboe   block: continue l...
9
10
  
  #include "blk.h"
4fed947cb   Tejun Heo   block: implement ...
11
12
13
14
15
16
17
18
  /* FLUSH/FUA sequences */
  enum {
  	QUEUE_FSEQ_STARTED	= (1 << 0), /* flushing in progress */
  	QUEUE_FSEQ_PREFLUSH	= (1 << 1), /* pre-flushing in progress */
  	QUEUE_FSEQ_DATA		= (1 << 2), /* data write in progress */
  	QUEUE_FSEQ_POSTFLUSH	= (1 << 3), /* post-flushing in progress */
  	QUEUE_FSEQ_DONE		= (1 << 4),
  };
dd4c133f3   Tejun Heo   block: rename bar...
19
  static struct request *queue_next_fseq(struct request_queue *q);
28e7d1845   Tejun Heo   block: drop barri...
20

dd4c133f3   Tejun Heo   block: rename bar...
21
  unsigned blk_flush_cur_seq(struct request_queue *q)
86db1e297   Jens Axboe   block: continue l...
22
  {
dd4c133f3   Tejun Heo   block: rename bar...
23
  	if (!q->flush_seq)
86db1e297   Jens Axboe   block: continue l...
24
  		return 0;
dd4c133f3   Tejun Heo   block: rename bar...
25
  	return 1 << ffz(q->flush_seq);
86db1e297   Jens Axboe   block: continue l...
26
  }
dd4c133f3   Tejun Heo   block: rename bar...
27
28
  static struct request *blk_flush_complete_seq(struct request_queue *q,
  					      unsigned seq, int error)
86db1e297   Jens Axboe   block: continue l...
29
  {
28e7d1845   Tejun Heo   block: drop barri...
30
  	struct request *next_rq = NULL;
86db1e297   Jens Axboe   block: continue l...
31

dd4c133f3   Tejun Heo   block: rename bar...
32
33
  	if (error && !q->flush_err)
  		q->flush_err = error;
86db1e297   Jens Axboe   block: continue l...
34

dd4c133f3   Tejun Heo   block: rename bar...
35
36
  	BUG_ON(q->flush_seq & seq);
  	q->flush_seq |= seq;
86db1e297   Jens Axboe   block: continue l...
37

dd4c133f3   Tejun Heo   block: rename bar...
38
39
40
  	if (blk_flush_cur_seq(q) != QUEUE_FSEQ_DONE) {
  		/* not complete yet, queue the next flush sequence */
  		next_rq = queue_next_fseq(q);
28e7d1845   Tejun Heo   block: drop barri...
41
  	} else {
dd4c133f3   Tejun Heo   block: rename bar...
42
43
44
45
46
47
48
49
  		/* complete this flush request */
  		__blk_end_request_all(q->orig_flush_rq, q->flush_err);
  		q->orig_flush_rq = NULL;
  		q->flush_seq = 0;
  
  		/* dispatch the next flush if there's one */
  		if (!list_empty(&q->pending_flushes)) {
  			next_rq = list_entry_rq(q->pending_flushes.next);
28e7d1845   Tejun Heo   block: drop barri...
50
51
52
53
  			list_move(&next_rq->queuelist, &q->queue_head);
  		}
  	}
  	return next_rq;
86db1e297   Jens Axboe   block: continue l...
54
  }
47f70d5a6   Tejun Heo   block: kick queue...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  static void blk_flush_complete_seq_end_io(struct request_queue *q,
  					  unsigned seq, int error)
  {
  	bool was_empty = elv_queue_empty(q);
  	struct request *next_rq;
  
  	next_rq = blk_flush_complete_seq(q, seq, error);
  
  	/*
  	 * Moving a request silently to empty queue_head may stall the
  	 * queue.  Kick the queue in those cases.
  	 */
  	if (was_empty && next_rq)
  		__blk_run_queue(q);
  }
86db1e297   Jens Axboe   block: continue l...
70
71
72
  static void pre_flush_end_io(struct request *rq, int error)
  {
  	elv_completed_request(rq->q, rq);
47f70d5a6   Tejun Heo   block: kick queue...
73
  	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_PREFLUSH, error);
86db1e297   Jens Axboe   block: continue l...
74
  }
dd4c133f3   Tejun Heo   block: rename bar...
75
  static void flush_data_end_io(struct request *rq, int error)
86db1e297   Jens Axboe   block: continue l...
76
77
  {
  	elv_completed_request(rq->q, rq);
47f70d5a6   Tejun Heo   block: kick queue...
78
  	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_DATA, error);
86db1e297   Jens Axboe   block: continue l...
79
80
81
82
83
  }
  
  static void post_flush_end_io(struct request *rq, int error)
  {
  	elv_completed_request(rq->q, rq);
47f70d5a6   Tejun Heo   block: kick queue...
84
  	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_POSTFLUSH, error);
86db1e297   Jens Axboe   block: continue l...
85
  }
cde4c406d   Christoph Hellwig   block: simplify q...
86
  static void init_flush_request(struct request *rq, struct gendisk *disk)
86db1e297   Jens Axboe   block: continue l...
87
  {
28e18d018   FUJITA Tomonori   block: set REQ_TY...
88
  	rq->cmd_type = REQ_TYPE_FS;
337238be1   Tejun Heo   block: initialize...
89
  	rq->cmd_flags = WRITE_FLUSH;
cde4c406d   Christoph Hellwig   block: simplify q...
90
  	rq->rq_disk = disk;
86db1e297   Jens Axboe   block: continue l...
91
  }
dd4c133f3   Tejun Heo   block: rename bar...
92
  static struct request *queue_next_fseq(struct request_queue *q)
86db1e297   Jens Axboe   block: continue l...
93
  {
4fed947cb   Tejun Heo   block: implement ...
94
  	struct request *orig_rq = q->orig_flush_rq;
dd4c133f3   Tejun Heo   block: rename bar...
95
  	struct request *rq = &q->flush_rq;
86db1e297   Jens Axboe   block: continue l...
96

cde4c406d   Christoph Hellwig   block: simplify q...
97
  	blk_rq_init(q, rq);
dd4c133f3   Tejun Heo   block: rename bar...
98
99
  	switch (blk_flush_cur_seq(q)) {
  	case QUEUE_FSEQ_PREFLUSH:
cde4c406d   Christoph Hellwig   block: simplify q...
100
101
  		init_flush_request(rq, orig_rq->rq_disk);
  		rq->end_io = pre_flush_end_io;
28e7d1845   Tejun Heo   block: drop barri...
102
  		break;
dd4c133f3   Tejun Heo   block: rename bar...
103
  	case QUEUE_FSEQ_DATA:
4fed947cb   Tejun Heo   block: implement ...
104
  		init_request_from_bio(rq, orig_rq->bio);
09d60c701   Tejun Heo   block: make sure ...
105
106
107
108
109
110
111
  		/*
  		 * orig_rq->rq_disk may be different from
  		 * bio->bi_bdev->bd_disk if orig_rq got here through
  		 * remapping drivers.  Make sure rq->rq_disk points
  		 * to the same one as orig_rq.
  		 */
  		rq->rq_disk = orig_rq->rq_disk;
4fed947cb   Tejun Heo   block: implement ...
112
113
  		rq->cmd_flags &= ~(REQ_FLUSH | REQ_FUA);
  		rq->cmd_flags |= orig_rq->cmd_flags & (REQ_FLUSH | REQ_FUA);
dd4c133f3   Tejun Heo   block: rename bar...
114
  		rq->end_io = flush_data_end_io;
28e7d1845   Tejun Heo   block: drop barri...
115
  		break;
dd4c133f3   Tejun Heo   block: rename bar...
116
  	case QUEUE_FSEQ_POSTFLUSH:
cde4c406d   Christoph Hellwig   block: simplify q...
117
118
  		init_flush_request(rq, orig_rq->rq_disk);
  		rq->end_io = post_flush_end_io;
28e7d1845   Tejun Heo   block: drop barri...
119
  		break;
28e7d1845   Tejun Heo   block: drop barri...
120
121
122
  	default:
  		BUG();
  	}
cde4c406d   Christoph Hellwig   block: simplify q...
123
124
  
  	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
dd831006d   Tejun Heo   block: misc clean...
125
  	return rq;
86db1e297   Jens Axboe   block: continue l...
126
  }
dd4c133f3   Tejun Heo   block: rename bar...
127
  struct request *blk_do_flush(struct request_queue *q, struct request *rq)
86db1e297   Jens Axboe   block: continue l...
128
  {
4fed947cb   Tejun Heo   block: implement ...
129
130
131
132
  	unsigned int fflags = q->flush_flags; /* may change, cache it */
  	bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA;
  	bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH);
  	bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA);
28e7d1845   Tejun Heo   block: drop barri...
133
  	unsigned skip = 0;
4fed947cb   Tejun Heo   block: implement ...
134
135
136
137
138
139
140
141
142
143
144
145
146
  	/*
  	 * Special case.  If there's data but flush is not necessary,
  	 * the request can be issued directly.
  	 *
  	 * Flush w/o data should be able to be issued directly too but
  	 * currently some drivers assume that rq->bio contains
  	 * non-zero data if it isn't NULL and empty FLUSH requests
  	 * getting here usually have bio's without data.
  	 */
  	if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) {
  		rq->cmd_flags &= ~REQ_FLUSH;
  		if (!has_fua)
  			rq->cmd_flags &= ~REQ_FUA;
28e7d1845   Tejun Heo   block: drop barri...
147
  		return rq;
4fed947cb   Tejun Heo   block: implement ...
148
  	}
28e7d1845   Tejun Heo   block: drop barri...
149

4fed947cb   Tejun Heo   block: implement ...
150
151
152
153
154
  	/*
  	 * Sequenced flushes can't be processed in parallel.  If
  	 * another one is already in progress, queue for later
  	 * processing.
  	 */
dd4c133f3   Tejun Heo   block: rename bar...
155
  	if (q->flush_seq) {
dd4c133f3   Tejun Heo   block: rename bar...
156
  		list_move_tail(&rq->queuelist, &q->pending_flushes);
28e7d1845   Tejun Heo   block: drop barri...
157
158
  		return NULL;
  	}
86db1e297   Jens Axboe   block: continue l...
159
  	/*
dd4c133f3   Tejun Heo   block: rename bar...
160
  	 * Start a new flush sequence
86db1e297   Jens Axboe   block: continue l...
161
  	 */
dd4c133f3   Tejun Heo   block: rename bar...
162
  	q->flush_err = 0;
dd4c133f3   Tejun Heo   block: rename bar...
163
  	q->flush_seq |= QUEUE_FSEQ_STARTED;
86db1e297   Jens Axboe   block: continue l...
164

4fed947cb   Tejun Heo   block: implement ...
165
166
167
168
  	/* adjust FLUSH/FUA of the original request and stash it away */
  	rq->cmd_flags &= ~REQ_FLUSH;
  	if (!has_fua)
  		rq->cmd_flags &= ~REQ_FUA;
28e7d1845   Tejun Heo   block: drop barri...
169
  	blk_dequeue_request(rq);
dd4c133f3   Tejun Heo   block: rename bar...
170
  	q->orig_flush_rq = rq;
86db1e297   Jens Axboe   block: continue l...
171

4fed947cb   Tejun Heo   block: implement ...
172
173
  	/* skip unneded sequences and return the first one */
  	if (!do_preflush)
dd4c133f3   Tejun Heo   block: rename bar...
174
  		skip |= QUEUE_FSEQ_PREFLUSH;
4fed947cb   Tejun Heo   block: implement ...
175
  	if (!blk_rq_sectors(rq))
dd4c133f3   Tejun Heo   block: rename bar...
176
  		skip |= QUEUE_FSEQ_DATA;
4fed947cb   Tejun Heo   block: implement ...
177
  	if (!do_postflush)
dd4c133f3   Tejun Heo   block: rename bar...
178
  		skip |= QUEUE_FSEQ_POSTFLUSH;
dd4c133f3   Tejun Heo   block: rename bar...
179
  	return blk_flush_complete_seq(q, skip, 0);
86db1e297   Jens Axboe   block: continue l...
180
  }
d391a2dda   Tejun Heo   block: use REQ_FL...
181
  static void bio_end_flush(struct bio *bio, int err)
86db1e297   Jens Axboe   block: continue l...
182
  {
d391a2dda   Tejun Heo   block: use REQ_FL...
183
  	if (err)
86db1e297   Jens Axboe   block: continue l...
184
  		clear_bit(BIO_UPTODATE, &bio->bi_flags);
f17e232e9   Dmitry Monakhov   blkdev: allow asy...
185
186
187
  	if (bio->bi_private)
  		complete(bio->bi_private);
  	bio_put(bio);
86db1e297   Jens Axboe   block: continue l...
188
189
190
191
192
  }
  
  /**
   * blkdev_issue_flush - queue a flush
   * @bdev:	blockdev to issue flush for
fbd9b09a1   Dmitry Monakhov   blkdev: generaliz...
193
   * @gfp_mask:	memory allocation flags (for bio_alloc)
86db1e297   Jens Axboe   block: continue l...
194
195
196
197
198
   * @error_sector:	error sector
   *
   * Description:
   *    Issue a flush for the block device in question. Caller can supply
   *    room for storing the error offset in case of a flush error, if they
f17e232e9   Dmitry Monakhov   blkdev: allow asy...
199
200
   *    wish to. If WAIT flag is not passed then caller may check only what
   *    request was pushed in some internal queue for later handling.
86db1e297   Jens Axboe   block: continue l...
201
   */
fbd9b09a1   Dmitry Monakhov   blkdev: generaliz...
202
  int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
dd3932edd   Christoph Hellwig   block: remove BLK...
203
  		sector_t *error_sector)
86db1e297   Jens Axboe   block: continue l...
204
205
206
207
  {
  	DECLARE_COMPLETION_ONSTACK(wait);
  	struct request_queue *q;
  	struct bio *bio;
fbd9b09a1   Dmitry Monakhov   blkdev: generaliz...
208
  	int ret = 0;
86db1e297   Jens Axboe   block: continue l...
209
210
211
212
213
214
215
  
  	if (bdev->bd_disk == NULL)
  		return -ENXIO;
  
  	q = bdev_get_queue(bdev);
  	if (!q)
  		return -ENXIO;
f10d9f617   Dave Chinner   blkdev: check for...
216
217
218
219
  	/*
  	 * some block devices may not have their queue correctly set up here
  	 * (e.g. loop device without a backing file) and so issuing a flush
  	 * here will panic. Ensure there is a request function before issuing
d391a2dda   Tejun Heo   block: use REQ_FL...
220
  	 * the flush.
f10d9f617   Dave Chinner   blkdev: check for...
221
222
223
  	 */
  	if (!q->make_request_fn)
  		return -ENXIO;
fbd9b09a1   Dmitry Monakhov   blkdev: generaliz...
224
  	bio = bio_alloc(gfp_mask, 0);
d391a2dda   Tejun Heo   block: use REQ_FL...
225
  	bio->bi_end_io = bio_end_flush;
86db1e297   Jens Axboe   block: continue l...
226
  	bio->bi_bdev = bdev;
dd3932edd   Christoph Hellwig   block: remove BLK...
227
  	bio->bi_private = &wait;
86db1e297   Jens Axboe   block: continue l...
228

f17e232e9   Dmitry Monakhov   blkdev: allow asy...
229
  	bio_get(bio);
d391a2dda   Tejun Heo   block: use REQ_FL...
230
  	submit_bio(WRITE_FLUSH, bio);
dd3932edd   Christoph Hellwig   block: remove BLK...
231
232
233
234
235
236
237
238
239
  	wait_for_completion(&wait);
  
  	/*
  	 * The driver must store the error location in ->bi_sector, if
  	 * it supports it. For non-stacked drivers, this should be
  	 * copied from blk_rq_pos(rq).
  	 */
  	if (error_sector)
                 *error_sector = bio->bi_sector;
86db1e297   Jens Axboe   block: continue l...
240

d391a2dda   Tejun Heo   block: use REQ_FL...
241
  	if (!bio_flagged(bio, BIO_UPTODATE))
86db1e297   Jens Axboe   block: continue l...
242
243
244
245
246
  		ret = -EIO;
  
  	bio_put(bio);
  	return ret;
  }
86db1e297   Jens Axboe   block: continue l...
247
  EXPORT_SYMBOL(blkdev_issue_flush);