diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-27 17:21:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-27 17:21:19 -0500 |
commit | 9c8ff4f4dac189e4111238d54c2b12e7837f4818 (patch) | |
tree | 70bd1b82721b56e17ebdbb11b618c47864146061 | |
parent | 86e67a07d4dc8cd40454698f2abb972fced06910 (diff) | |
parent | 645a8d94629fd812a220d54876339a1ddafd9bc2 (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block:
scatterlist: add more safeguards
Revert "ll_rw_blk: temporarily enable max_segments tweaking"
mmc: Add missing sg_init_table() call
block: Fix memory leak in alloc_disk_node()
alpha: fix sg_page breakage
blktrace: Make sure BLKTRACETEARDOWN does the full cleanup.
-rw-r--r-- | arch/alpha/kernel/pci-noop.c | 14 | ||||
-rw-r--r-- | block/blktrace.c | 9 | ||||
-rw-r--r-- | block/genhd.c | 1 | ||||
-rw-r--r-- | block/ll_rw_blk.c | 23 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 3 | ||||
-rw-r--r-- | include/linux/scatterlist.h | 37 |
6 files changed, 44 insertions, 43 deletions
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c index 174b729c504b..468b76ce66a1 100644 --- a/arch/alpha/kernel/pci-noop.c +++ b/arch/alpha/kernel/pci-noop.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
15 | #include <linux/scatterlist.h> | ||
15 | 16 | ||
16 | #include "proto.h" | 17 | #include "proto.h" |
17 | 18 | ||
@@ -172,18 +173,19 @@ dma_alloc_coherent(struct device *dev, size_t size, | |||
172 | EXPORT_SYMBOL(dma_alloc_coherent); | 173 | EXPORT_SYMBOL(dma_alloc_coherent); |
173 | 174 | ||
174 | int | 175 | int |
175 | dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 176 | dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents, |
176 | enum dma_data_direction direction) | 177 | enum dma_data_direction direction) |
177 | { | 178 | { |
178 | int i; | 179 | int i; |
180 | struct scatterlist *sg; | ||
179 | 181 | ||
180 | for (i = 0; i < nents; i++ ) { | 182 | for_each_sg(sgl, sg, nents, i) { |
181 | void *va; | 183 | void *va; |
182 | 184 | ||
183 | BUG_ON(!sg[i].page); | 185 | BUG_ON(!sg_page(sg)); |
184 | va = page_address(sg[i].page) + sg[i].offset; | 186 | va = sg_virt(sg); |
185 | sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va); | 187 | sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va); |
186 | sg_dma_len(sg + i) = sg[i].length; | 188 | sg_dma_len(sg) = sg->length; |
187 | } | 189 | } |
188 | 190 | ||
189 | return nents; | 191 | return nents; |
diff --git a/block/blktrace.c b/block/blktrace.c index d00ac3993c18..498a0a54a6aa 100644 --- a/block/blktrace.c +++ b/block/blktrace.c | |||
@@ -202,6 +202,7 @@ static void blk_remove_tree(struct dentry *dir) | |||
202 | static struct dentry *blk_create_tree(const char *blk_name) | 202 | static struct dentry *blk_create_tree(const char *blk_name) |
203 | { | 203 | { |
204 | struct dentry *dir = NULL; | 204 | struct dentry *dir = NULL; |
205 | int created = 0; | ||
205 | 206 | ||
206 | mutex_lock(&blk_tree_mutex); | 207 | mutex_lock(&blk_tree_mutex); |
207 | 208 | ||
@@ -209,13 +210,17 @@ static struct dentry *blk_create_tree(const char *blk_name) | |||
209 | blk_tree_root = debugfs_create_dir("block", NULL); | 210 | blk_tree_root = debugfs_create_dir("block", NULL); |
210 | if (!blk_tree_root) | 211 | if (!blk_tree_root) |
211 | goto err; | 212 | goto err; |
213 | created = 1; | ||
212 | } | 214 | } |
213 | 215 | ||
214 | dir = debugfs_create_dir(blk_name, blk_tree_root); | 216 | dir = debugfs_create_dir(blk_name, blk_tree_root); |
215 | if (dir) | 217 | if (dir) |
216 | root_users++; | 218 | root_users++; |
217 | else | 219 | else { |
218 | blk_remove_root(); | 220 | /* Delete root only if we created it */ |
221 | if (created) | ||
222 | blk_remove_root(); | ||
223 | } | ||
219 | 224 | ||
220 | err: | 225 | err: |
221 | mutex_unlock(&blk_tree_mutex); | 226 | mutex_unlock(&blk_tree_mutex); |
diff --git a/block/genhd.c b/block/genhd.c index e609996f2e76..f2ac914160d1 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -715,6 +715,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id) | |||
715 | disk->part = kmalloc_node(size, | 715 | disk->part = kmalloc_node(size, |
716 | GFP_KERNEL | __GFP_ZERO, node_id); | 716 | GFP_KERNEL | __GFP_ZERO, node_id); |
717 | if (!disk->part) { | 717 | if (!disk->part) { |
718 | free_disk_stats(disk); | ||
718 | kfree(disk); | 719 | kfree(disk); |
719 | return NULL; | 720 | return NULL; |
720 | } | 721 | } |
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 3b927be03850..8b919940b2ab 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
@@ -4080,23 +4080,7 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) | |||
4080 | return queue_var_show(max_hw_sectors_kb, (page)); | 4080 | return queue_var_show(max_hw_sectors_kb, (page)); |
4081 | } | 4081 | } |
4082 | 4082 | ||
4083 | static ssize_t queue_max_segments_show(struct request_queue *q, char *page) | ||
4084 | { | ||
4085 | return queue_var_show(q->max_phys_segments, page); | ||
4086 | } | ||
4087 | |||
4088 | static ssize_t queue_max_segments_store(struct request_queue *q, | ||
4089 | const char *page, size_t count) | ||
4090 | { | ||
4091 | unsigned long segments; | ||
4092 | ssize_t ret = queue_var_store(&segments, page, count); | ||
4093 | 4083 | ||
4094 | spin_lock_irq(q->queue_lock); | ||
4095 | q->max_phys_segments = segments; | ||
4096 | spin_unlock_irq(q->queue_lock); | ||
4097 | |||
4098 | return ret; | ||
4099 | } | ||
4100 | static struct queue_sysfs_entry queue_requests_entry = { | 4084 | static struct queue_sysfs_entry queue_requests_entry = { |
4101 | .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, | 4085 | .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, |
4102 | .show = queue_requests_show, | 4086 | .show = queue_requests_show, |
@@ -4120,12 +4104,6 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = { | |||
4120 | .show = queue_max_hw_sectors_show, | 4104 | .show = queue_max_hw_sectors_show, |
4121 | }; | 4105 | }; |
4122 | 4106 | ||
4123 | static struct queue_sysfs_entry queue_max_segments_entry = { | ||
4124 | .attr = {.name = "max_segments", .mode = S_IRUGO | S_IWUSR }, | ||
4125 | .show = queue_max_segments_show, | ||
4126 | .store = queue_max_segments_store, | ||
4127 | }; | ||
4128 | |||
4129 | static struct queue_sysfs_entry queue_iosched_entry = { | 4107 | static struct queue_sysfs_entry queue_iosched_entry = { |
4130 | .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, | 4108 | .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, |
4131 | .show = elv_iosched_show, | 4109 | .show = elv_iosched_show, |
@@ -4137,7 +4115,6 @@ static struct attribute *default_attrs[] = { | |||
4137 | &queue_ra_entry.attr, | 4115 | &queue_ra_entry.attr, |
4138 | &queue_max_hw_sectors_entry.attr, | 4116 | &queue_max_hw_sectors_entry.attr, |
4139 | &queue_max_sectors_entry.attr, | 4117 | &queue_max_sectors_entry.attr, |
4140 | &queue_max_segments_entry.attr, | ||
4141 | &queue_iosched_entry.attr, | 4118 | &queue_iosched_entry.attr, |
4142 | NULL, | 4119 | NULL, |
4143 | }; | 4120 | }; |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 1b9c9b6da5b7..30cd13b13ac3 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -180,12 +180,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
180 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); | 180 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); |
181 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); | 181 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); |
182 | 182 | ||
183 | mq->sg = kzalloc(sizeof(struct scatterlist) * | 183 | mq->sg = kmalloc(sizeof(struct scatterlist) * |
184 | host->max_phys_segs, GFP_KERNEL); | 184 | host->max_phys_segs, GFP_KERNEL); |
185 | if (!mq->sg) { | 185 | if (!mq->sg) { |
186 | ret = -ENOMEM; | 186 | ret = -ENOMEM; |
187 | goto cleanup_queue; | 187 | goto cleanup_queue; |
188 | } | 188 | } |
189 | sg_init_table(mq->sg, host->max_phys_segs); | ||
189 | } | 190 | } |
190 | 191 | ||
191 | init_MUTEX(&mq->thread_sem); | 192 | init_MUTEX(&mq->thread_sem); |
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 259735044148..416e000dfe81 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
@@ -26,6 +26,16 @@ | |||
26 | 26 | ||
27 | #define SG_MAGIC 0x87654321 | 27 | #define SG_MAGIC 0x87654321 |
28 | 28 | ||
29 | /* | ||
30 | * We overload the LSB of the page pointer to indicate whether it's | ||
31 | * a valid sg entry, or whether it points to the start of a new scatterlist. | ||
32 | * Those low bits are there for everyone! (thanks mason :-) | ||
33 | */ | ||
34 | #define sg_is_chain(sg) ((sg)->page_link & 0x01) | ||
35 | #define sg_is_last(sg) ((sg)->page_link & 0x02) | ||
36 | #define sg_chain_ptr(sg) \ | ||
37 | ((struct scatterlist *) ((sg)->page_link & ~0x03)) | ||
38 | |||
29 | /** | 39 | /** |
30 | * sg_assign_page - Assign a given page to an SG entry | 40 | * sg_assign_page - Assign a given page to an SG entry |
31 | * @sg: SG entry | 41 | * @sg: SG entry |
@@ -47,6 +57,7 @@ static inline void sg_assign_page(struct scatterlist *sg, struct page *page) | |||
47 | BUG_ON((unsigned long) page & 0x03); | 57 | BUG_ON((unsigned long) page & 0x03); |
48 | #ifdef CONFIG_DEBUG_SG | 58 | #ifdef CONFIG_DEBUG_SG |
49 | BUG_ON(sg->sg_magic != SG_MAGIC); | 59 | BUG_ON(sg->sg_magic != SG_MAGIC); |
60 | BUG_ON(sg_is_chain(sg)); | ||
50 | #endif | 61 | #endif |
51 | sg->page_link = page_link | (unsigned long) page; | 62 | sg->page_link = page_link | (unsigned long) page; |
52 | } | 63 | } |
@@ -73,7 +84,14 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page, | |||
73 | sg->length = len; | 84 | sg->length = len; |
74 | } | 85 | } |
75 | 86 | ||
76 | #define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) | 87 | static inline struct page *sg_page(struct scatterlist *sg) |
88 | { | ||
89 | #ifdef CONFIG_DEBUG_SG | ||
90 | BUG_ON(sg->sg_magic != SG_MAGIC); | ||
91 | BUG_ON(sg_is_chain(sg)); | ||
92 | #endif | ||
93 | return (struct page *)((sg)->page_link & ~0x3); | ||
94 | } | ||
77 | 95 | ||
78 | /** | 96 | /** |
79 | * sg_set_buf - Set sg entry to point at given data | 97 | * sg_set_buf - Set sg entry to point at given data |
@@ -88,16 +106,6 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, | |||
88 | sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); | 106 | sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); |
89 | } | 107 | } |
90 | 108 | ||
91 | /* | ||
92 | * We overload the LSB of the page pointer to indicate whether it's | ||
93 | * a valid sg entry, or whether it points to the start of a new scatterlist. | ||
94 | * Those low bits are there for everyone! (thanks mason :-) | ||
95 | */ | ||
96 | #define sg_is_chain(sg) ((sg)->page_link & 0x01) | ||
97 | #define sg_is_last(sg) ((sg)->page_link & 0x02) | ||
98 | #define sg_chain_ptr(sg) \ | ||
99 | ((struct scatterlist *) ((sg)->page_link & ~0x03)) | ||
100 | |||
101 | /** | 109 | /** |
102 | * sg_next - return the next scatterlist entry in a list | 110 | * sg_next - return the next scatterlist entry in a list |
103 | * @sg: The current sg entry | 111 | * @sg: The current sg entry |
@@ -179,6 +187,13 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, | |||
179 | #ifndef ARCH_HAS_SG_CHAIN | 187 | #ifndef ARCH_HAS_SG_CHAIN |
180 | BUG(); | 188 | BUG(); |
181 | #endif | 189 | #endif |
190 | |||
191 | /* | ||
192 | * offset and length are unused for chain entry. Clear them. | ||
193 | */ | ||
194 | prv->offset = 0; | ||
195 | prv->length = 0; | ||
196 | |||
182 | /* | 197 | /* |
183 | * Set lowest bit to indicate a link pointer, and make sure to clear | 198 | * Set lowest bit to indicate a link pointer, and make sure to clear |
184 | * the termination bit if it happens to be set. | 199 | * the termination bit if it happens to be set. |