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.
This commit is contained in:
Коммит
9c8ff4f4da
|
@ -12,6 +12,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
|
@ -172,18 +173,19 @@ dma_alloc_coherent(struct device *dev, size_t size,
|
|||
EXPORT_SYMBOL(dma_alloc_coherent);
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
struct scatterlist *sg;
|
||||
|
||||
for (i = 0; i < nents; i++ ) {
|
||||
for_each_sg(sgl, sg, nents, i) {
|
||||
void *va;
|
||||
|
||||
BUG_ON(!sg[i].page);
|
||||
va = page_address(sg[i].page) + sg[i].offset;
|
||||
sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va);
|
||||
sg_dma_len(sg + i) = sg[i].length;
|
||||
BUG_ON(!sg_page(sg));
|
||||
va = sg_virt(sg);
|
||||
sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va);
|
||||
sg_dma_len(sg) = sg->length;
|
||||
}
|
||||
|
||||
return nents;
|
||||
|
|
|
@ -202,6 +202,7 @@ static void blk_remove_tree(struct dentry *dir)
|
|||
static struct dentry *blk_create_tree(const char *blk_name)
|
||||
{
|
||||
struct dentry *dir = NULL;
|
||||
int created = 0;
|
||||
|
||||
mutex_lock(&blk_tree_mutex);
|
||||
|
||||
|
@ -209,13 +210,17 @@ static struct dentry *blk_create_tree(const char *blk_name)
|
|||
blk_tree_root = debugfs_create_dir("block", NULL);
|
||||
if (!blk_tree_root)
|
||||
goto err;
|
||||
created = 1;
|
||||
}
|
||||
|
||||
dir = debugfs_create_dir(blk_name, blk_tree_root);
|
||||
if (dir)
|
||||
root_users++;
|
||||
else
|
||||
blk_remove_root();
|
||||
else {
|
||||
/* Delete root only if we created it */
|
||||
if (created)
|
||||
blk_remove_root();
|
||||
}
|
||||
|
||||
err:
|
||||
mutex_unlock(&blk_tree_mutex);
|
||||
|
|
|
@ -715,6 +715,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
|
|||
disk->part = kmalloc_node(size,
|
||||
GFP_KERNEL | __GFP_ZERO, node_id);
|
||||
if (!disk->part) {
|
||||
free_disk_stats(disk);
|
||||
kfree(disk);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
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 = {
|
||||
.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
|
||||
.show = queue_requests_show,
|
||||
|
@ -4120,12 +4104,6 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
|
|||
.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 = {
|
||||
.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
|
||||
.show = elv_iosched_show,
|
||||
|
@ -4137,7 +4115,6 @@ static struct attribute *default_attrs[] = {
|
|||
&queue_ra_entry.attr,
|
||||
&queue_max_hw_sectors_entry.attr,
|
||||
&queue_max_sectors_entry.attr,
|
||||
&queue_max_segments_entry.attr,
|
||||
&queue_iosched_entry.attr,
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -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_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);
|
||||
if (!mq->sg) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup_queue;
|
||||
}
|
||||
sg_init_table(mq->sg, host->max_phys_segs);
|
||||
}
|
||||
|
||||
init_MUTEX(&mq->thread_sem);
|
||||
|
|
|
@ -26,6 +26,16 @@
|
|||
|
||||
#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: SG entry
|
||||
|
@ -47,6 +57,7 @@ static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
|
|||
BUG_ON((unsigned long) page & 0x03);
|
||||
#ifdef CONFIG_DEBUG_SG
|
||||
BUG_ON(sg->sg_magic != SG_MAGIC);
|
||||
BUG_ON(sg_is_chain(sg));
|
||||
#endif
|
||||
sg->page_link = page_link | (unsigned long) page;
|
||||
}
|
||||
|
@ -73,7 +84,14 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page,
|
|||
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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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: The current sg entry
|
||||
|
@ -179,6 +187,13 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
|
|||
#ifndef ARCH_HAS_SG_CHAIN
|
||||
BUG();
|
||||
#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
|
||||
* the termination bit if it happens to be set.
|
||||
|
|
Загрузка…
Ссылка в новой задаче