提交 9c8ff4f4 编写于 作者: L 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.
......@@ -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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册