diff options
-rw-r--r-- | drivers/scsi/scsi_lib.c | 16 | ||||
-rw-r--r-- | include/linux/scatterlist.h | 6 | ||||
-rw-r--r-- | lib/scatterlist.c | 25 |
3 files changed, 27 insertions, 20 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8723abeb018e..bbd7a0a08692 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -564,6 +564,11 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) | |||
564 | return mempool_alloc(sgp->pool, gfp_mask); | 564 | return mempool_alloc(sgp->pool, gfp_mask); |
565 | } | 565 | } |
566 | 566 | ||
567 | static void scsi_free_sgtable(struct scsi_data_buffer *sdb) | ||
568 | { | ||
569 | __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, false, scsi_sg_free); | ||
570 | } | ||
571 | |||
567 | static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, | 572 | static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, |
568 | gfp_t gfp_mask) | 573 | gfp_t gfp_mask) |
569 | { | 574 | { |
@@ -572,19 +577,12 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, | |||
572 | BUG_ON(!nents); | 577 | BUG_ON(!nents); |
573 | 578 | ||
574 | ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, | 579 | ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, |
575 | gfp_mask, scsi_sg_alloc); | 580 | NULL, gfp_mask, scsi_sg_alloc); |
576 | if (unlikely(ret)) | 581 | if (unlikely(ret)) |
577 | __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, | 582 | scsi_free_sgtable(sdb); |
578 | scsi_sg_free); | ||
579 | |||
580 | return ret; | 583 | return ret; |
581 | } | 584 | } |
582 | 585 | ||
583 | static void scsi_free_sgtable(struct scsi_data_buffer *sdb) | ||
584 | { | ||
585 | __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free); | ||
586 | } | ||
587 | |||
588 | /* | 586 | /* |
589 | * Function: scsi_release_buffers() | 587 | * Function: scsi_release_buffers() |
590 | * | 588 | * |
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index a964f7285600..f4ec8bbcb372 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
@@ -229,10 +229,10 @@ void sg_init_one(struct scatterlist *, const void *, unsigned int); | |||
229 | typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); | 229 | typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); |
230 | typedef void (sg_free_fn)(struct scatterlist *, unsigned int); | 230 | typedef void (sg_free_fn)(struct scatterlist *, unsigned int); |
231 | 231 | ||
232 | void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *); | 232 | void __sg_free_table(struct sg_table *, unsigned int, bool, sg_free_fn *); |
233 | void sg_free_table(struct sg_table *); | 233 | void sg_free_table(struct sg_table *); |
234 | int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, | 234 | int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, |
235 | sg_alloc_fn *); | 235 | struct scatterlist *, gfp_t, sg_alloc_fn *); |
236 | int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); | 236 | int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); |
237 | int sg_alloc_table_from_pages(struct sg_table *sgt, | 237 | int sg_alloc_table_from_pages(struct sg_table *sgt, |
238 | struct page **pages, unsigned int n_pages, | 238 | struct page **pages, unsigned int n_pages, |
diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 3a8e8e8fb2a5..b4415fceb7e7 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c | |||
@@ -165,6 +165,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents) | |||
165 | * __sg_free_table - Free a previously mapped sg table | 165 | * __sg_free_table - Free a previously mapped sg table |
166 | * @table: The sg table header to use | 166 | * @table: The sg table header to use |
167 | * @max_ents: The maximum number of entries per single scatterlist | 167 | * @max_ents: The maximum number of entries per single scatterlist |
168 | * @skip_first_chunk: don't free the (preallocated) first scatterlist chunk | ||
168 | * @free_fn: Free function | 169 | * @free_fn: Free function |
169 | * | 170 | * |
170 | * Description: | 171 | * Description: |
@@ -174,7 +175,7 @@ static void sg_kfree(struct scatterlist *sg, unsigned int nents) | |||
174 | * | 175 | * |
175 | **/ | 176 | **/ |
176 | void __sg_free_table(struct sg_table *table, unsigned int max_ents, | 177 | void __sg_free_table(struct sg_table *table, unsigned int max_ents, |
177 | sg_free_fn *free_fn) | 178 | bool skip_first_chunk, sg_free_fn *free_fn) |
178 | { | 179 | { |
179 | struct scatterlist *sgl, *next; | 180 | struct scatterlist *sgl, *next; |
180 | 181 | ||
@@ -202,7 +203,10 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents, | |||
202 | } | 203 | } |
203 | 204 | ||
204 | table->orig_nents -= sg_size; | 205 | table->orig_nents -= sg_size; |
205 | free_fn(sgl, alloc_size); | 206 | if (!skip_first_chunk) { |
207 | free_fn(sgl, alloc_size); | ||
208 | skip_first_chunk = false; | ||
209 | } | ||
206 | sgl = next; | 210 | sgl = next; |
207 | } | 211 | } |
208 | 212 | ||
@@ -217,7 +221,7 @@ EXPORT_SYMBOL(__sg_free_table); | |||
217 | **/ | 221 | **/ |
218 | void sg_free_table(struct sg_table *table) | 222 | void sg_free_table(struct sg_table *table) |
219 | { | 223 | { |
220 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree); | 224 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree); |
221 | } | 225 | } |
222 | EXPORT_SYMBOL(sg_free_table); | 226 | EXPORT_SYMBOL(sg_free_table); |
223 | 227 | ||
@@ -241,8 +245,8 @@ EXPORT_SYMBOL(sg_free_table); | |||
241 | * | 245 | * |
242 | **/ | 246 | **/ |
243 | int __sg_alloc_table(struct sg_table *table, unsigned int nents, | 247 | int __sg_alloc_table(struct sg_table *table, unsigned int nents, |
244 | unsigned int max_ents, gfp_t gfp_mask, | 248 | unsigned int max_ents, struct scatterlist *first_chunk, |
245 | sg_alloc_fn *alloc_fn) | 249 | gfp_t gfp_mask, sg_alloc_fn *alloc_fn) |
246 | { | 250 | { |
247 | struct scatterlist *sg, *prv; | 251 | struct scatterlist *sg, *prv; |
248 | unsigned int left; | 252 | unsigned int left; |
@@ -269,7 +273,12 @@ int __sg_alloc_table(struct sg_table *table, unsigned int nents, | |||
269 | 273 | ||
270 | left -= sg_size; | 274 | left -= sg_size; |
271 | 275 | ||
272 | sg = alloc_fn(alloc_size, gfp_mask); | 276 | if (first_chunk) { |
277 | sg = first_chunk; | ||
278 | first_chunk = NULL; | ||
279 | } else { | ||
280 | sg = alloc_fn(alloc_size, gfp_mask); | ||
281 | } | ||
273 | if (unlikely(!sg)) { | 282 | if (unlikely(!sg)) { |
274 | /* | 283 | /* |
275 | * Adjust entry count to reflect that the last | 284 | * Adjust entry count to reflect that the last |
@@ -324,9 +333,9 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) | |||
324 | int ret; | 333 | int ret; |
325 | 334 | ||
326 | ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC, | 335 | ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC, |
327 | gfp_mask, sg_kmalloc); | 336 | NULL, gfp_mask, sg_kmalloc); |
328 | if (unlikely(ret)) | 337 | if (unlikely(ret)) |
329 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree); | 338 | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, false, sg_kfree); |
330 | 339 | ||
331 | return ret; | 340 | return ret; |
332 | } | 341 | } |