Commit 9c8ff4f4 authored by Linus Torvalds's avatar Linus Torvalds

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.
parents 86e67a07 645a8d94
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include "proto.h" #include "proto.h"
...@@ -172,18 +173,19 @@ dma_alloc_coherent(struct device *dev, size_t size, ...@@ -172,18 +173,19 @@ dma_alloc_coherent(struct device *dev, size_t size,
EXPORT_SYMBOL(dma_alloc_coherent); EXPORT_SYMBOL(dma_alloc_coherent);
int int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
enum dma_data_direction direction) enum dma_data_direction direction)
{ {
int i; int i;
struct scatterlist *sg;
for (i = 0; i < nents; i++ ) { for_each_sg(sgl, sg, nents, i) {
void *va; void *va;
BUG_ON(!sg[i].page); BUG_ON(!sg_page(sg));
va = page_address(sg[i].page) + sg[i].offset; va = sg_virt(sg);
sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va); sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va);
sg_dma_len(sg + i) = sg[i].length; sg_dma_len(sg) = sg->length;
} }
return nents; return nents;
......
...@@ -202,6 +202,7 @@ static void blk_remove_tree(struct dentry *dir) ...@@ -202,6 +202,7 @@ static void blk_remove_tree(struct dentry *dir)
static struct dentry *blk_create_tree(const char *blk_name) static struct dentry *blk_create_tree(const char *blk_name)
{ {
struct dentry *dir = NULL; struct dentry *dir = NULL;
int created = 0;
mutex_lock(&blk_tree_mutex); mutex_lock(&blk_tree_mutex);
...@@ -209,13 +210,17 @@ static struct dentry *blk_create_tree(const char *blk_name) ...@@ -209,13 +210,17 @@ static struct dentry *blk_create_tree(const char *blk_name)
blk_tree_root = debugfs_create_dir("block", NULL); blk_tree_root = debugfs_create_dir("block", NULL);
if (!blk_tree_root) if (!blk_tree_root)
goto err; goto err;
created = 1;
} }
dir = debugfs_create_dir(blk_name, blk_tree_root); dir = debugfs_create_dir(blk_name, blk_tree_root);
if (dir) if (dir)
root_users++; root_users++;
else else {
blk_remove_root(); /* Delete root only if we created it */
if (created)
blk_remove_root();
}
err: err:
mutex_unlock(&blk_tree_mutex); mutex_unlock(&blk_tree_mutex);
......
...@@ -715,6 +715,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id) ...@@ -715,6 +715,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
disk->part = kmalloc_node(size, disk->part = kmalloc_node(size,
GFP_KERNEL | __GFP_ZERO, node_id); GFP_KERNEL | __GFP_ZERO, node_id);
if (!disk->part) { if (!disk->part) {
free_disk_stats(disk);
kfree(disk); kfree(disk);
return NULL; return NULL;
} }
......
...@@ -4080,23 +4080,7 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) ...@@ -4080,23 +4080,7 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
return queue_var_show(max_hw_sectors_kb, (page)); return queue_var_show(max_hw_sectors_kb, (page));
} }
static ssize_t queue_max_segments_show(struct request_queue *q, char *page)
{
return queue_var_show(q->max_phys_segments, page);
}
static ssize_t queue_max_segments_store(struct request_queue *q,
const char *page, size_t count)
{
unsigned long segments;
ssize_t ret = queue_var_store(&segments, page, count);
spin_lock_irq(q->queue_lock);
q->max_phys_segments = segments;
spin_unlock_irq(q->queue_lock);
return ret;
}
static struct queue_sysfs_entry queue_requests_entry = { static struct queue_sysfs_entry queue_requests_entry = {
.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
.show = queue_requests_show, .show = queue_requests_show,
...@@ -4120,12 +4104,6 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = { ...@@ -4120,12 +4104,6 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
.show = queue_max_hw_sectors_show, .show = queue_max_hw_sectors_show,
}; };
static struct queue_sysfs_entry queue_max_segments_entry = {
.attr = {.name = "max_segments", .mode = S_IRUGO | S_IWUSR },
.show = queue_max_segments_show,
.store = queue_max_segments_store,
};
static struct queue_sysfs_entry queue_iosched_entry = { static struct queue_sysfs_entry queue_iosched_entry = {
.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
.show = elv_iosched_show, .show = elv_iosched_show,
...@@ -4137,7 +4115,6 @@ static struct attribute *default_attrs[] = { ...@@ -4137,7 +4115,6 @@ static struct attribute *default_attrs[] = {
&queue_ra_entry.attr, &queue_ra_entry.attr,
&queue_max_hw_sectors_entry.attr, &queue_max_hw_sectors_entry.attr,
&queue_max_sectors_entry.attr, &queue_max_sectors_entry.attr,
&queue_max_segments_entry.attr,
&queue_iosched_entry.attr, &queue_iosched_entry.attr,
NULL, NULL,
}; };
......
...@@ -180,12 +180,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock ...@@ -180,12 +180,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size); blk_queue_max_segment_size(mq->queue, host->max_seg_size);
mq->sg = kzalloc(sizeof(struct scatterlist) * mq->sg = kmalloc(sizeof(struct scatterlist) *
host->max_phys_segs, GFP_KERNEL); host->max_phys_segs, GFP_KERNEL);
if (!mq->sg) { if (!mq->sg) {
ret = -ENOMEM; ret = -ENOMEM;
goto cleanup_queue; goto cleanup_queue;
} }
sg_init_table(mq->sg, host->max_phys_segs);
} }
init_MUTEX(&mq->thread_sem); init_MUTEX(&mq->thread_sem);
......
...@@ -26,6 +26,16 @@ ...@@ -26,6 +26,16 @@
#define SG_MAGIC 0x87654321 #define SG_MAGIC 0x87654321
/*
* We overload the LSB of the page pointer to indicate whether it's
* a valid sg entry, or whether it points to the start of a new scatterlist.
* Those low bits are there for everyone! (thanks mason :-)
*/
#define sg_is_chain(sg) ((sg)->page_link & 0x01)
#define sg_is_last(sg) ((sg)->page_link & 0x02)
#define sg_chain_ptr(sg) \
((struct scatterlist *) ((sg)->page_link & ~0x03))
/** /**
* sg_assign_page - Assign a given page to an SG entry * sg_assign_page - Assign a given page to an SG entry
* @sg: SG entry * @sg: SG entry
...@@ -47,6 +57,7 @@ static inline void sg_assign_page(struct scatterlist *sg, struct page *page) ...@@ -47,6 +57,7 @@ static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
BUG_ON((unsigned long) page & 0x03); BUG_ON((unsigned long) page & 0x03);
#ifdef CONFIG_DEBUG_SG #ifdef CONFIG_DEBUG_SG
BUG_ON(sg->sg_magic != SG_MAGIC); BUG_ON(sg->sg_magic != SG_MAGIC);
BUG_ON(sg_is_chain(sg));
#endif #endif
sg->page_link = page_link | (unsigned long) page; sg->page_link = page_link | (unsigned long) page;
} }
...@@ -73,7 +84,14 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page, ...@@ -73,7 +84,14 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page,
sg->length = len; sg->length = len;
} }
#define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) static inline struct page *sg_page(struct scatterlist *sg)
{
#ifdef CONFIG_DEBUG_SG
BUG_ON(sg->sg_magic != SG_MAGIC);
BUG_ON(sg_is_chain(sg));
#endif
return (struct page *)((sg)->page_link & ~0x3);
}
/** /**
* sg_set_buf - Set sg entry to point at given data * 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,16 +106,6 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
} }
/*
* We overload the LSB of the page pointer to indicate whether it's
* a valid sg entry, or whether it points to the start of a new scatterlist.
* Those low bits are there for everyone! (thanks mason :-)
*/
#define sg_is_chain(sg) ((sg)->page_link & 0x01)
#define sg_is_last(sg) ((sg)->page_link & 0x02)
#define sg_chain_ptr(sg) \
((struct scatterlist *) ((sg)->page_link & ~0x03))
/** /**
* sg_next - return the next scatterlist entry in a list * sg_next - return the next scatterlist entry in a list
* @sg: The current sg entry * @sg: The current sg entry
...@@ -179,6 +187,13 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, ...@@ -179,6 +187,13 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
#ifndef ARCH_HAS_SG_CHAIN #ifndef ARCH_HAS_SG_CHAIN
BUG(); BUG();
#endif #endif
/*
* offset and length are unused for chain entry. Clear them.
*/
prv->offset = 0;
prv->length = 0;
/* /*
* Set lowest bit to indicate a link pointer, and make sure to clear * Set lowest bit to indicate a link pointer, and make sure to clear
* the termination bit if it happens to be set. * the termination bit if it happens to be set.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment