Commit d1c8fac1 authored by James Simmons's avatar James Simmons

Merge bk://linux.bkbits.net/linux-2.5

into maxwell.earthlink.net:/usr/src/linus-2.5
parents 7999a2d4 6a839d30
...@@ -30,6 +30,10 @@ static struct file_operations raw_ctl_fops; ...@@ -30,6 +30,10 @@ static struct file_operations raw_ctl_fops;
/* /*
* Open/close code for raw IO. * Open/close code for raw IO.
* *
* We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to
* point at the blockdev's address_space and set the file handle to use
* O_DIRECT.
*
* Set the device's soft blocksize to the minimum possible. This gives the * Set the device's soft blocksize to the minimum possible. This gives the
* finest possible alignment and has no adverse impact on performance. * finest possible alignment and has no adverse impact on performance.
*/ */
...@@ -56,7 +60,12 @@ static int raw_open(struct inode *inode, struct file *filp) ...@@ -56,7 +60,12 @@ static int raw_open(struct inode *inode, struct file *filp)
err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
if (!err) { if (!err) {
err = set_blocksize(bdev, bdev_hardsect_size(bdev)); err = set_blocksize(bdev, bdev_hardsect_size(bdev));
if (err == 0) {
raw_devices[minor].inuse++; raw_devices[minor].inuse++;
filp->f_dentry->d_inode->i_mapping =
bdev->bd_inode->i_mapping;
filp->f_flags |= O_DIRECT;
}
} }
} }
up(&raw_mutex); up(&raw_mutex);
...@@ -200,72 +209,22 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp, ...@@ -200,72 +209,22 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
return err; return err;
} }
static ssize_t static ssize_t raw_file_write(struct file *file, const char *buf,
rw_raw_dev(int rw, struct file *filp, const struct iovec *iov, unsigned long nr_segs, loff_t *offp) size_t count, loff_t *ppos)
{ {
const int minor = minor(filp->f_dentry->d_inode->i_rdev); struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
struct block_device *bdev = raw_devices[minor].binding;
struct inode *inode = bdev->bd_inode;
size_t count = iov_length(iov, nr_segs);
ssize_t ret = 0;
if (count == 0)
goto out;
if ((ssize_t)count < 0)
return -EINVAL;
if (*offp >= inode->i_size)
return -ENXIO;
if (count + *offp > inode->i_size) { return generic_file_write_nolock(file, &local_iov, 1, ppos);
count = inode->i_size - *offp;
nr_segs = iov_shorten((struct iovec *)iov, nr_segs, count);
}
ret = generic_file_direct_IO(rw, filp, iov, *offp, nr_segs);
if (ret > 0)
*offp += ret;
out:
return ret;
}
static ssize_t
raw_read(struct file *filp, char *buf, size_t size, loff_t *offp)
{
struct iovec local_iov = { .iov_base = buf, .iov_len = size};
return rw_raw_dev(READ, filp, &local_iov, 1, offp);
}
static ssize_t
raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp)
{
struct iovec local_iov = { .iov_base = (char *)buf, .iov_len = size};
return rw_raw_dev(WRITE, filp, &local_iov, 1, offp);
}
static ssize_t
raw_readv(struct file *filp, const struct iovec *iov, unsigned long nr_segs, loff_t *offp)
{
return rw_raw_dev(READ, filp, iov, nr_segs, offp);
}
static ssize_t
raw_writev(struct file *filp, const struct iovec *iov, unsigned long nr_segs, loff_t *offp)
{
return rw_raw_dev(WRITE, filp, iov, nr_segs, offp);
} }
static struct file_operations raw_fops = { static struct file_operations raw_fops = {
.read = raw_read, .read = generic_file_read,
.write = raw_write, .write = raw_file_write,
.open = raw_open, .open = raw_open,
.release= raw_release, .release= raw_release,
.ioctl = raw_ioctl, .ioctl = raw_ioctl,
.readv = raw_readv, .readv = generic_file_readv,
.writev = raw_writev, .writev = generic_file_writev,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -1434,9 +1434,10 @@ int journal_stop(handle_t *handle) ...@@ -1434,9 +1434,10 @@ int journal_stop(handle_t *handle)
* by 30x or more... * by 30x or more...
*/ */
if (handle->h_sync) { if (handle->h_sync) {
set_current_state(TASK_RUNNING);
do { do {
old_handle_count = transaction->t_handle_count; old_handle_count = transaction->t_handle_count;
yield(); schedule();
} while (old_handle_count != transaction->t_handle_count); } while (old_handle_count != transaction->t_handle_count);
} }
......
...@@ -316,7 +316,7 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -316,7 +316,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
size_t tot_len; size_t tot_len;
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov=iovstack; struct iovec *iov=iovstack;
ssize_t ret = -EINVAL; ssize_t ret;
int seg; int seg;
io_fn_t fn; io_fn_t fn;
iov_fn_t fnv; iov_fn_t fnv;
...@@ -325,8 +325,9 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -325,8 +325,9 @@ static ssize_t do_readv_writev(int type, struct file *file,
/* /*
* SuS says "The readv() function *may* fail if the iovcnt argument * SuS says "The readv() function *may* fail if the iovcnt argument
* was less than or equal to 0, or greater than {IOV_MAX}. Linux has * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
* traditionally returned -EINVAL for zero segments, so... * traditionally returned zero for zero segments, so...
*/ */
ret = 0;
if (nr_segs == 0) if (nr_segs == 0)
goto out; goto out;
...@@ -334,6 +335,7 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -334,6 +335,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
* First get the "struct iovec" from user memory and * First get the "struct iovec" from user memory and
* verify all the pointers * verify all the pointers
*/ */
ret = -EINVAL;
if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0)) if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
goto out; goto out;
if (!file->f_op) if (!file->f_op)
......
...@@ -259,12 +259,21 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ...@@ -259,12 +259,21 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
#define pte_offset_kernel(dir, address) \ #define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address)) ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
#if defined(CONFIG_HIGHPTE)
#define pte_offset_map(dir, address) \ #define pte_offset_map(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address)) ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
#define pte_offset_map_nested(dir, address) \ #define pte_offset_map_nested(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address)) ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
#else
#define pte_offset_map(dir, address) \
((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
#endif
#if defined(CONFIG_HIGHPTE) && defined(CONFIG_HIGHMEM4G) #if defined(CONFIG_HIGHPTE) && defined(CONFIG_HIGHMEM4G)
typedef u32 pte_addr_t; typedef u32 pte_addr_t;
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
struct radix_tree_node; struct radix_tree_node;
#define RADIX_TREE_SLOT_RESERVED ((void *)~0UL)
struct radix_tree_root { struct radix_tree_root {
unsigned int height; unsigned int height;
int gfp_mask; int gfp_mask;
...@@ -41,7 +39,6 @@ do { \ ...@@ -41,7 +39,6 @@ do { \
(root)->rnode = NULL; \ (root)->rnode = NULL; \
} while (0) } while (0)
extern int radix_tree_reserve(struct radix_tree_root *, unsigned long, void ***);
extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long); extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
extern int radix_tree_delete(struct radix_tree_root *, unsigned long); extern int radix_tree_delete(struct radix_tree_root *, unsigned long);
......
...@@ -266,29 +266,31 @@ int del_timer(timer_t *timer) ...@@ -266,29 +266,31 @@ int del_timer(timer_t *timer)
int del_timer_sync(timer_t *timer) int del_timer_sync(timer_t *timer)
{ {
tvec_base_t *base = tvec_bases; tvec_base_t *base = tvec_bases;
int i, ret; int i, ret = 0;
ret = del_timer(timer); del_again:
ret += del_timer(timer);
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++, base++) {
if (!cpu_online(i)) if (!cpu_online(i))
continue; continue;
if (base->running_timer == timer) { if (base->running_timer == timer) {
while (base->running_timer == timer) { while (base->running_timer == timer) {
cpu_relax(); cpu_relax();
preempt_disable(); preempt_check_resched();
preempt_enable();
} }
break; break;
} }
base++;
} }
if (timer_pending(timer))
goto del_again;
return ret; return ret;
} }
#endif #endif
static void cascade(tvec_base_t *base, tvec_t *tv) static int cascade(tvec_base_t *base, tvec_t *tv)
{ {
/* cascade all the timers from tv up one level */ /* cascade all the timers from tv up one level */
struct list_head *head, *curr, *next; struct list_head *head, *curr, *next;
...@@ -310,7 +312,8 @@ static void cascade(tvec_base_t *base, tvec_t *tv) ...@@ -310,7 +312,8 @@ static void cascade(tvec_base_t *base, tvec_t *tv)
curr = next; curr = next;
} }
INIT_LIST_HEAD(head); INIT_LIST_HEAD(head);
tv->index = (tv->index + 1) & TVN_MASK;
return tv->index = (tv->index + 1) & TVN_MASK;
} }
/*** /***
...@@ -322,26 +325,18 @@ static void cascade(tvec_base_t *base, tvec_t *tv) ...@@ -322,26 +325,18 @@ static void cascade(tvec_base_t *base, tvec_t *tv)
*/ */
static inline void __run_timers(tvec_base_t *base) static inline void __run_timers(tvec_base_t *base)
{ {
unsigned long flags; spin_lock_irq(&base->lock);
spin_lock_irqsave(&base->lock, flags);
while ((long)(jiffies - base->timer_jiffies) >= 0) { while ((long)(jiffies - base->timer_jiffies) >= 0) {
struct list_head *head, *curr; struct list_head *head, *curr;
/* /*
* Cascade timers: * Cascade timers:
*/ */
if (!base->tv1.index) { if (!base->tv1.index &&
cascade(base, &base->tv2); (cascade(base, &base->tv2) == 1) &&
if (base->tv2.index == 1) { (cascade(base, &base->tv3) == 1) &&
cascade(base, &base->tv3); cascade(base, &base->tv4) == 1)
if (base->tv3.index == 1) {
cascade(base, &base->tv4);
if (base->tv4.index == 1)
cascade(base, &base->tv5); cascade(base, &base->tv5);
}
}
}
repeat: repeat:
head = base->tv1.vec + base->tv1.index; head = base->tv1.vec + base->tv1.index;
curr = head->next; curr = head->next;
...@@ -360,6 +355,9 @@ static inline void __run_timers(tvec_base_t *base) ...@@ -360,6 +355,9 @@ static inline void __run_timers(tvec_base_t *base)
base->running_timer = timer; base->running_timer = timer;
#endif #endif
spin_unlock_irq(&base->lock); spin_unlock_irq(&base->lock);
if (!fn)
printk("Bad: timer %p has NULL fn. (data: %08lx)\n", timer, data);
else
fn(data); fn(data);
spin_lock_irq(&base->lock); spin_lock_irq(&base->lock);
goto repeat; goto repeat;
...@@ -370,7 +368,7 @@ static inline void __run_timers(tvec_base_t *base) ...@@ -370,7 +368,7 @@ static inline void __run_timers(tvec_base_t *base)
#if CONFIG_SMP #if CONFIG_SMP
base->running_timer = NULL; base->running_timer = NULL;
#endif #endif
spin_unlock_irqrestore(&base->lock, flags); spin_unlock_irq(&base->lock);
} }
/******************************************************************/ /******************************************************************/
......
...@@ -77,7 +77,6 @@ static inline unsigned long radix_tree_maxindex(unsigned int height) ...@@ -77,7 +77,6 @@ static inline unsigned long radix_tree_maxindex(unsigned int height)
return index; return index;
} }
/* /*
* Extend a radix tree so it can store key @index. * Extend a radix tree so it can store key @index.
*/ */
...@@ -109,16 +108,15 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) ...@@ -109,16 +108,15 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
return 0; return 0;
} }
/** /**
* radix_tree_reserve - reserve space in a radix tree * radix_tree_insert - insert into a radix tree
* @root: radix tree root * @root: radix tree root
* @index: index key * @index: index key
* @pslot: pointer to reserved slot * @item: item to insert
* *
* Reserve a slot in a radix tree for the key @index. * Insert an item into the radix tree at position @index.
*/ */
int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void ***pslot) int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
{ {
struct radix_tree_node *node = NULL, *tmp, **slot; struct radix_tree_node *node = NULL, *tmp, **slot;
unsigned int height, shift; unsigned int height, shift;
...@@ -158,36 +156,11 @@ int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void * ...@@ -158,36 +156,11 @@ int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void *
if (node) if (node)
node->count++; node->count++;
*pslot = (void **)slot;
**pslot = RADIX_TREE_SLOT_RESERVED;
return 0;
}
EXPORT_SYMBOL(radix_tree_reserve);
/**
* radix_tree_insert - insert into a radix tree
* @root: radix tree root
* @index: index key
* @item: item to insert
*
* Insert an item into the radix tree at position @index.
*/
int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
{
void **slot;
int error;
error = radix_tree_reserve(root, index, &slot);
if (!error)
*slot = item; *slot = item;
return error; return 0;
} }
EXPORT_SYMBOL(radix_tree_insert); EXPORT_SYMBOL(radix_tree_insert);
/** /**
* radix_tree_lookup - perform lookup operation on a radix tree * radix_tree_lookup - perform lookup operation on a radix tree
* @root: radix tree root * @root: radix tree root
...@@ -267,8 +240,8 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index, ...@@ -267,8 +240,8 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index,
out: out:
*next_index = index; *next_index = index;
return nr_found; return nr_found;
} }
/** /**
* radix_tree_gang_lookup - perform multiple lookup on a radix tree * radix_tree_gang_lookup - perform multiple lookup on a radix tree
* @root: radix tree root * @root: radix tree root
...@@ -371,7 +344,6 @@ int radix_tree_delete(struct radix_tree_root *root, unsigned long index) ...@@ -371,7 +344,6 @@ int radix_tree_delete(struct radix_tree_root *root, unsigned long index)
return 0; return 0;
} }
EXPORT_SYMBOL(radix_tree_delete); EXPORT_SYMBOL(radix_tree_delete);
static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags) static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
......
...@@ -194,7 +194,8 @@ static inline unsigned long move_vma(struct vm_area_struct * vma, ...@@ -194,7 +194,8 @@ static inline unsigned long move_vma(struct vm_area_struct * vma,
prev->vm_end = next->vm_end; prev->vm_end = next->vm_end;
__vma_unlink(mm, next, prev); __vma_unlink(mm, next, prev);
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
if (vma == next)
vma = prev;
mm->map_count--; mm->map_count--;
kmem_cache_free(vm_area_cachep, next); kmem_cache_free(vm_area_cachep, next);
} }
......
...@@ -199,16 +199,14 @@ void delete_from_swap_cache(struct page *page) ...@@ -199,16 +199,14 @@ void delete_from_swap_cache(struct page *page)
int move_to_swap_cache(struct page *page, swp_entry_t entry) int move_to_swap_cache(struct page *page, swp_entry_t entry)
{ {
struct address_space *mapping = page->mapping; struct address_space *mapping = page->mapping;
void **pslot;
int err; int err;
write_lock(&swapper_space.page_lock); write_lock(&swapper_space.page_lock);
write_lock(&mapping->page_lock); write_lock(&mapping->page_lock);
err = radix_tree_reserve(&swapper_space.page_tree, entry.val, &pslot); err = radix_tree_insert(&swapper_space.page_tree, entry.val, page);
if (!err) { if (!err) {
__remove_from_page_cache(page); __remove_from_page_cache(page);
*pslot = page;
___add_to_page_cache(page, &swapper_space, entry.val); ___add_to_page_cache(page, &swapper_space, entry.val);
} }
...@@ -231,7 +229,6 @@ int move_from_swap_cache(struct page *page, unsigned long index, ...@@ -231,7 +229,6 @@ int move_from_swap_cache(struct page *page, unsigned long index,
struct address_space *mapping) struct address_space *mapping)
{ {
swp_entry_t entry; swp_entry_t entry;
void **pslot;
int err; int err;
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
...@@ -243,10 +240,9 @@ int move_from_swap_cache(struct page *page, unsigned long index, ...@@ -243,10 +240,9 @@ int move_from_swap_cache(struct page *page, unsigned long index,
write_lock(&swapper_space.page_lock); write_lock(&swapper_space.page_lock);
write_lock(&mapping->page_lock); write_lock(&mapping->page_lock);
err = radix_tree_reserve(&mapping->page_tree, index, &pslot); err = radix_tree_insert(&mapping->page_tree, index, page);
if (!err) { if (!err) {
__delete_from_swap_cache(page); __delete_from_swap_cache(page);
*pslot = page;
___add_to_page_cache(page, mapping, index); ___add_to_page_cache(page, mapping, index);
} }
......
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