Blame view

block/blk-lib.c 4.27 KB
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  /*
   * Functions related to generic helpers functions
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/bio.h>
  #include <linux/blkdev.h>
  #include <linux/scatterlist.h>
  
  #include "blk.h"
  
  static void blkdev_discard_end_io(struct bio *bio, int err)
  {
  	if (err) {
  		if (err == -EOPNOTSUPP)
  			set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
  		clear_bit(BIO_UPTODATE, &bio->bi_flags);
  	}
  
  	if (bio->bi_private)
  		complete(bio->bi_private);
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  
  	bio_put(bio);
  }
  
  /**
   * blkdev_issue_discard - queue a discard
   * @bdev:	blockdev to issue discard for
   * @sector:	start sector
   * @nr_sects:	number of sectors to discard
   * @gfp_mask:	memory allocation flags (for bio_alloc)
   * @flags:	BLKDEV_IFL_* flags to control behaviour
   *
   * Description:
   *    Issue a discard request for the sectors in question.
   */
  int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
  		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
  {
  	DECLARE_COMPLETION_ONSTACK(wait);
  	struct request_queue *q = bdev_get_queue(bdev);
8c5553678   Christoph Hellwig   block: remove the...
42
  	int type = REQ_WRITE | REQ_DISCARD;
10d1f9e2c   Jens Axboe   block: fix proble...
43
  	unsigned int max_discard_sectors;
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
44
  	struct bio *bio;
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
45
46
47
48
49
50
51
  	int ret = 0;
  
  	if (!q)
  		return -ENXIO;
  
  	if (!blk_queue_discard(q))
  		return -EOPNOTSUPP;
10d1f9e2c   Jens Axboe   block: fix proble...
52
53
54
55
56
57
58
59
60
61
  	/*
  	 * Ensure that max_discard_sectors is of the proper
  	 * granularity
  	 */
  	max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
  	if (q->limits.discard_granularity) {
  		unsigned int disc_sects = q->limits.discard_granularity >> 9;
  
  		max_discard_sectors &= ~(disc_sects - 1);
  	}
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
62

dd3932edd   Christoph Hellwig   block: remove BLK...
63
  	if (flags & BLKDEV_DISCARD_SECURE) {
8d57a98cc   Adrian Hunter   block: add secure...
64
65
  		if (!blk_queue_secdiscard(q))
  			return -EOPNOTSUPP;
8c5553678   Christoph Hellwig   block: remove the...
66
  		type |= REQ_SECURE;
8d57a98cc   Adrian Hunter   block: add secure...
67
  	}
10d1f9e2c   Jens Axboe   block: fix proble...
68
  	while (nr_sects && !ret) {
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
69
  		bio = bio_alloc(gfp_mask, 1);
66ac02801   Christoph Hellwig   block: don't allo...
70
71
72
73
  		if (!bio) {
  			ret = -ENOMEM;
  			break;
  		}
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
74
75
76
  		bio->bi_sector = sector;
  		bio->bi_end_io = blkdev_discard_end_io;
  		bio->bi_bdev = bdev;
dd3932edd   Christoph Hellwig   block: remove BLK...
77
  		bio->bi_private = &wait;
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
78

f31e7e402   Dmitry Monakhov   blkdev: move blkd...
79
80
81
82
83
84
85
86
87
88
89
  		if (nr_sects > max_discard_sectors) {
  			bio->bi_size = max_discard_sectors << 9;
  			nr_sects -= max_discard_sectors;
  			sector += max_discard_sectors;
  		} else {
  			bio->bi_size = nr_sects << 9;
  			nr_sects = 0;
  		}
  
  		bio_get(bio);
  		submit_bio(type, bio);
dd3932edd   Christoph Hellwig   block: remove BLK...
90
  		wait_for_completion(&wait);
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
91
92
93
94
95
96
97
  
  		if (bio_flagged(bio, BIO_EOPNOTSUPP))
  			ret = -EOPNOTSUPP;
  		else if (!bio_flagged(bio, BIO_UPTODATE))
  			ret = -EIO;
  		bio_put(bio);
  	}
66ac02801   Christoph Hellwig   block: don't allo...
98

f31e7e402   Dmitry Monakhov   blkdev: move blkd...
99
  	return ret;
f31e7e402   Dmitry Monakhov   blkdev: move blkd...
100
101
  }
  EXPORT_SYMBOL(blkdev_issue_discard);
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
102
103
104
105
106
107
  
  struct bio_batch
  {
  	atomic_t 		done;
  	unsigned long 		flags;
  	struct completion 	*wait;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
108
109
110
111
112
  };
  
  static void bio_batch_end_io(struct bio *bio, int err)
  {
  	struct bio_batch *bb = bio->bi_private;
0341aafb7   Jens Axboe   block: fix bad us...
113

3f14d792f   Dmitry Monakhov   blkdev: add blkde...
114
115
116
117
118
119
  	if (err) {
  		if (err == -EOPNOTSUPP)
  			set_bit(BIO_EOPNOTSUPP, &bb->flags);
  		else
  			clear_bit(BIO_UPTODATE, &bb->flags);
  	}
0aeea1896   Lukas Czerner   block: fix mis-sy...
120
121
122
  	if (bb)
  		if (atomic_dec_and_test(&bb->done))
  			complete(bb->wait);
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
123
124
125
126
  	bio_put(bio);
  }
  
  /**
291d24f6d   Ben Hutchings   block: fix kernel...
127
   * blkdev_issue_zeroout - generate number of zero filed write bios
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
128
129
130
131
   * @bdev:	blockdev to issue
   * @sector:	start sector
   * @nr_sects:	number of sectors to write
   * @gfp_mask:	memory allocation flags (for bio_alloc)
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
132
133
134
   *
   * Description:
   *  Generate and issue number of bios with zerofiled pages.
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
135
136
137
   */
  
  int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
dd3932edd   Christoph Hellwig   block: remove BLK...
138
  			sector_t nr_sects, gfp_t gfp_mask)
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
139
  {
18edc8eaa   Dmitry Monakhov   blkdev: fix blkde...
140
  	int ret;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
141
142
  	struct bio *bio;
  	struct bio_batch bb;
0aeea1896   Lukas Czerner   block: fix mis-sy...
143
  	unsigned int sz;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
144
  	DECLARE_COMPLETION_ONSTACK(wait);
0aeea1896   Lukas Czerner   block: fix mis-sy...
145
  	atomic_set(&bb.done, 1);
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
146
147
  	bb.flags = 1 << BIO_UPTODATE;
  	bb.wait = &wait;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
148

3f14d792f   Dmitry Monakhov   blkdev: add blkde...
149
  submit:
18edc8eaa   Dmitry Monakhov   blkdev: fix blkde...
150
  	ret = 0;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
151
152
153
  	while (nr_sects != 0) {
  		bio = bio_alloc(gfp_mask,
  				min(nr_sects, (sector_t)BIO_MAX_PAGES));
18edc8eaa   Dmitry Monakhov   blkdev: fix blkde...
154
155
  		if (!bio) {
  			ret = -ENOMEM;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
156
  			break;
18edc8eaa   Dmitry Monakhov   blkdev: fix blkde...
157
  		}
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
158
159
160
161
  
  		bio->bi_sector = sector;
  		bio->bi_bdev   = bdev;
  		bio->bi_end_io = bio_batch_end_io;
dd3932edd   Christoph Hellwig   block: remove BLK...
162
  		bio->bi_private = &bb;
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
163

0341aafb7   Jens Axboe   block: fix bad us...
164
165
  		while (nr_sects != 0) {
  			sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
166
167
168
169
170
171
172
173
174
  			if (sz == 0)
  				/* bio has maximum size possible */
  				break;
  			ret = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0);
  			nr_sects -= ret >> 9;
  			sector += ret >> 9;
  			if (ret < (sz << 9))
  				break;
  		}
18edc8eaa   Dmitry Monakhov   blkdev: fix blkde...
175
  		ret = 0;
0aeea1896   Lukas Czerner   block: fix mis-sy...
176
  		atomic_inc(&bb.done);
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
177
178
  		submit_bio(WRITE, bio);
  	}
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
179

dd3932edd   Christoph Hellwig   block: remove BLK...
180
  	/* Wait for bios in-flight */
0aeea1896   Lukas Czerner   block: fix mis-sy...
181
  	if (!atomic_dec_and_test(&bb.done))
dd3932edd   Christoph Hellwig   block: remove BLK...
182
  		wait_for_completion(&wait);
3f14d792f   Dmitry Monakhov   blkdev: add blkde...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  
  	if (!test_bit(BIO_UPTODATE, &bb.flags))
  		/* One of bios in the batch was completed with error.*/
  		ret = -EIO;
  
  	if (ret)
  		goto out;
  
  	if (test_bit(BIO_EOPNOTSUPP, &bb.flags)) {
  		ret = -EOPNOTSUPP;
  		goto out;
  	}
  	if (nr_sects != 0)
  		goto submit;
  out:
  	return ret;
  }
  EXPORT_SYMBOL(blkdev_issue_zeroout);