Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
71660e15
Commit
71660e15
authored
Oct 13, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
31c96625
2dcb8ff9
Changes
33
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
271 additions
and
906 deletions
+271
-906
arch/cris/drivers/examples/kiobuftest.c
arch/cris/drivers/examples/kiobuftest.c
+0
-111
arch/i386/mm/discontig.c
arch/i386/mm/discontig.c
+1
-0
drivers/block/Config.in
drivers/block/Config.in
+1
-2
drivers/block/ll_rw_blk.c
drivers/block/ll_rw_blk.c
+1
-1
drivers/media/video/bttv-risc.c
drivers/media/video/bttv-risc.c
+0
-1
drivers/media/video/bttvp.h
drivers/media/video/bttvp.h
+0
-1
drivers/media/video/video-buf.c
drivers/media/video/video-buf.c
+72
-37
drivers/media/video/video-buf.h
drivers/media/video/video-buf.h
+5
-3
fs/Makefile
fs/Makefile
+1
-1
fs/aio.c
fs/aio.c
+1
-6
fs/bio.c
fs/bio.c
+1
-124
fs/block_dev.c
fs/block_dev.c
+0
-1
fs/buffer.c
fs/buffer.c
+0
-60
fs/dcache.c
fs/dcache.c
+20
-30
fs/dquot.c
fs/dquot.c
+20
-8
fs/fcntl.c
fs/fcntl.c
+0
-1
fs/file_table.c
fs/file_table.c
+0
-1
fs/inode.c
fs/inode.c
+25
-24
fs/iobuf.c
fs/iobuf.c
+0
-125
fs/open.c
fs/open.c
+0
-1
fs/xfs/linux/xfs_aops.c
fs/xfs/linux/xfs_aops.c
+0
-1
fs/xfs/linux/xfs_ioctl.c
fs/xfs/linux/xfs_ioctl.c
+1
-1
include/linux/buffer_head.h
include/linux/buffer_head.h
+0
-1
include/linux/dcache.h
include/linux/dcache.h
+0
-11
include/linux/iobuf.h
include/linux/iobuf.h
+0
-88
include/linux/mm.h
include/linux/mm.h
+23
-0
init/main.c
init/main.c
+0
-1
kernel/ksyms.c
kernel/ksyms.c
+2
-14
mm/filemap.c
mm/filemap.c
+0
-1
mm/memory.c
mm/memory.c
+1
-220
mm/msync.c
mm/msync.c
+5
-0
mm/page_alloc.c
mm/page_alloc.c
+2
-0
mm/vmscan.c
mm/vmscan.c
+89
-30
No files found.
arch/cris/drivers/examples/kiobuftest.c
deleted
100644 → 0
View file @
31c96625
/*
* Example showing how to pin down a range of virtual pages from user-space
* to be able to do for example DMA directly into them.
*
* It is necessary because the pages the virtual pointers reference, might
* not exist in memory (could be mapped to the zero-page, filemapped etc)
* and DMA cannot trigger the MMU to force them in (and would have time
* contraints making it impossible to wait for it anyway).
*
* Author: Bjorn Wesen
*
* $Log: kiobuftest.c,v $
* Revision 1.1.1.1 2001/12/17 13:59:27 bjornw
* Import of Linux 2.5.1
*
* Revision 1.2 2001/02/27 13:52:50 bjornw
* malloc.h -> slab.h
*
* Revision 1.1 2001/01/19 15:57:49 bjornw
* Example of how to do direct HW -> user-mode DMA
*
*
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/iobuf.h>
#define KIOBUFTEST_MAJOR 124
/* in the local range, experimental */
static
ssize_t
kiobuf_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
{
struct
kiobuf
*
iobuf
;
int
res
,
i
;
/* Make a kiobuf that maps the entire length the reader has given
* us
*/
res
=
alloc_kiovec
(
1
,
&
iobuf
);
if
(
res
)
return
res
;
if
((
res
=
map_user_kiobuf
(
READ
,
iobuf
,
(
unsigned
long
)
buf
,
len
)))
{
printk
(
"map_user_kiobuf failed, return %d
\n
"
,
res
);
return
res
;
}
/* At this point, the virtual area buf[0] -> buf[len-1] will
* have corresponding pages mapped in physical memory and locked
* until we unmap the kiobuf. They cannot be swapped out or moved
* around.
*/
printk
(
"nr_pages == %d
\n
offset == %d
\n
length == %d
\n
"
,
iobuf
->
nr_pages
,
iobuf
->
offset
,
iobuf
->
length
);
for
(
i
=
0
;
i
<
iobuf
->
nr_pages
;
i
++
)
{
printk
(
"page_add(maplist[%d]) == 0x%x
\n
"
,
i
,
page_address
(
iobuf
->
maplist
[
i
]));
}
/* This is the place to create the necessary scatter-gather vector
* for the DMA using the iobuf->maplist array and page_address
* (don't forget __pa if the DMA needs the actual physical DRAM address)
* and run it.
*/
/* Release the mapping and exit */
unmap_kiobuf
(
iobuf
);
/* The unlock_kiobuf is implicit here */
return
len
;
}
static
struct
file_operations
kiobuf_fops
=
{
owner:
THIS_MODULE
,
read:
kiobuf_read
};
static
int
__init
kiobuftest_init
(
void
)
{
int
res
;
/* register char device */
res
=
register_chrdev
(
KIOBUFTEST_MAJOR
,
"kiobuftest"
,
&
kiobuf_fops
);
if
(
res
<
0
)
{
printk
(
KERN_ERR
"kiobuftest: couldn't get a major number.
\n
"
);
return
res
;
}
printk
(
"Initializing kiobuf-test device
\n
"
);
}
module_init
(
kiobuftest_init
);
arch/i386/mm/discontig.c
View file @
71660e15
...
...
@@ -70,6 +70,7 @@ static void __init allocate_pgdat(int nid)
node_datasz
=
PFN_UP
(
sizeof
(
struct
pglist_data
));
NODE_DATA
(
nid
)
=
(
pg_data_t
*
)(
__va
(
min_low_pfn
<<
PAGE_SHIFT
));
min_low_pfn
+=
node_datasz
;
memset
(
NODE_DATA
(
nid
),
0
,
sizeof
(
struct
pglist_data
));
}
/*
...
...
drivers/block/Config.in
View file @
71660e15
...
...
@@ -49,7 +49,6 @@ fi
dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
if [ "$CONFIG_X86" = "y" -o "$CONFIG_PPC32" = "y" ]; then
# bool 'Support for Large Block Devices' CONFIG_LBD
define_bool CONFIG_LBD y
bool 'Support for Large Block Devices' CONFIG_LBD
fi
endmenu
drivers/block/ll_rw_blk.c
View file @
71660e15
...
...
@@ -1878,7 +1878,7 @@ void generic_make_request(struct bio *bio)
*/
int
submit_bio
(
int
rw
,
struct
bio
*
bio
)
{
int
count
=
bio_sectors
(
bio
)
>>
1
;
int
count
=
bio_sectors
(
bio
);
BUG_ON
(
!
bio
->
bi_end_io
);
BIO_BUG_ON
(
!
bio
->
bi_size
);
...
...
drivers/media/video/bttv-risc.c
View file @
71660e15
...
...
@@ -29,7 +29,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/iobuf.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <asm/page.h>
...
...
drivers/media/video/bttvp.h
View file @
71660e15
...
...
@@ -31,7 +31,6 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/videodev.h>
#include <linux/iobuf.h>
#include <linux/pci.h>
#include <asm/scatterlist.h>
...
...
drivers/media/video/video-buf.c
View file @
71660e15
...
...
@@ -18,8 +18,8 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/iobuf.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
...
...
@@ -65,32 +65,31 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
return
NULL
;
}
struct
scatterlist
*
videobuf_
iobuf_to_sg
(
struct
kiobuf
*
iobuf
)
struct
scatterlist
*
videobuf_
pages_to_sg
(
struct
page
**
pages
,
int
nr_pages
,
int
offset
)
{
struct
scatterlist
*
sglist
;
int
i
=
0
;
sglist
=
kmalloc
(
sizeof
(
struct
scatterlist
)
*
iobuf
->
nr_pages
,
GFP_KERNEL
);
if
(
NULL
==
pages
[
0
])
return
NULL
;
sglist
=
kmalloc
(
sizeof
(
*
sglist
)
*
nr_pages
,
GFP_KERNEL
);
if
(
NULL
==
sglist
)
return
NULL
;
memset
(
sglist
,
0
,
sizeof
(
struct
scatterlist
)
*
iobuf
->
nr_pages
);
memset
(
sglist
,
0
,
sizeof
(
*
sglist
)
*
nr_pages
);
if
(
NULL
==
iobuf
->
maplist
[
0
])
goto
err
;
if
(
PageHighMem
(
iobuf
->
maplist
[
0
]))
if
(
PageHighMem
(
pages
[
0
]))
/* DMA to highmem pages might not work */
goto
err
;
sglist
[
0
].
page
=
iobuf
->
maplist
[
0
];
sglist
[
0
].
offset
=
iobuf
->
offset
;
sglist
[
0
].
length
=
PAGE_SIZE
-
iobuf
->
offset
;
for
(
i
=
1
;
i
<
iobuf
->
nr_pages
;
i
++
)
{
if
(
NULL
==
iobuf
->
maplist
[
i
])
sglist
[
0
].
page
=
pages
[
0
];
sglist
[
0
].
offset
=
offset
;
sglist
[
0
].
length
=
PAGE_SIZE
-
offset
;
for
(
i
=
1
;
i
<
nr_pages
;
i
++
)
{
if
(
NULL
==
pages
[
i
])
goto
err
;
if
(
PageHighMem
(
iobuf
->
maplist
[
i
]))
if
(
PageHighMem
(
pages
[
i
]))
goto
err
;
sglist
[
i
].
page
=
iobuf
->
maplist
[
i
];
sglist
[
i
].
page
=
pages
[
i
];
sglist
[
i
].
length
=
PAGE_SIZE
;
}
return
sglist
;
...
...
@@ -100,6 +99,30 @@ videobuf_iobuf_to_sg(struct kiobuf *iobuf)
return
NULL
;
}
int
videobuf_lock
(
struct
page
**
pages
,
int
nr_pages
)
{
int
i
;
for
(
i
=
0
;
i
<
nr_pages
;
i
++
)
if
(
TestSetPageLocked
(
pages
[
i
]))
goto
err
;
return
0
;
err:
while
(
i
>
0
)
unlock_page
(
pages
[
--
i
]);
return
-
EINVAL
;
}
int
videobuf_unlock
(
struct
page
**
pages
,
int
nr_pages
)
{
int
i
;
for
(
i
=
0
;
i
<
nr_pages
;
i
++
)
unlock_page
(
pages
[
i
]);
return
0
;
}
/* --------------------------------------------------------------------- */
int
videobuf_dma_init_user
(
struct
videobuf_dmabuf
*
dma
,
int
direction
,
...
...
@@ -113,14 +136,21 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
case
PCI_DMA_TODEVICE
:
rw
=
WRITE
;
break
;
default:
BUG
();
}
if
(
0
!=
(
err
=
alloc_kiovec
(
1
,
&
dma
->
iobuf
)))
return
err
;
if
(
0
!=
(
err
=
map_user_kiobuf
(
rw
,
dma
->
iobuf
,
data
,
size
)))
{
dprintk
(
1
,
"map_user_kiobuf: %d
\n
"
,
err
);
return
err
;
}
dma
->
nr_pages
=
dma
->
iobuf
->
nr_pages
;
return
0
;
dma
->
offset
=
data
&
PAGE_MASK
;
dma
->
nr_pages
=
((((
data
+
size
)
&
~
PAGE_MASK
)
-
(
data
&
~
PAGE_MASK
))
>>
PAGE_SHIFT
)
+
1
;
dma
->
pages
=
kmalloc
(
dma
->
nr_pages
*
sizeof
(
struct
page
*
),
GFP_KERNEL
);
if
(
NULL
==
dma
->
pages
)
return
-
ENOMEM
;
down_read
(
&
current
->
mm
->
mmap_sem
);
err
=
get_user_pages
(
current
,
current
->
mm
,
data
,
dma
->
nr_pages
,
rw
==
READ
,
0
,
/* don't force */
dma
->
pages
,
NULL
);
up_read
(
&
current
->
mm
->
mmap_sem
);
return
err
;
}
int
videobuf_dma_init_kernel
(
struct
videobuf_dmabuf
*
dma
,
int
direction
,
...
...
@@ -144,13 +174,15 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
if
(
0
==
dma
->
nr_pages
)
BUG
();
if
(
dma
->
iobuf
)
{
if
(
0
!=
(
err
=
lock_kiovec
(
1
,
&
dma
->
iobuf
,
1
)))
{
dprintk
(
1
,
"
lock_kiovec
: %d
\n
"
,
err
);
if
(
dma
->
pages
)
{
if
(
0
!=
(
err
=
videobuf_lock
(
dma
->
pages
,
dma
->
nr_pages
)))
{
dprintk
(
1
,
"
videobuf_lock_pages
: %d
\n
"
,
err
);
return
err
;
}
dma
->
sglist
=
videobuf_iobuf_to_sg
(
dma
->
iobuf
);
dma
->
sglist
=
videobuf_pages_to_sg
(
dma
->
pages
,
dma
->
nr_pages
,
dma
->
offset
);
}
if
(
dma
->
vmalloc
)
{
dma
->
sglist
=
videobuf_vmalloc_to_sg
(
dma
->
vmalloc
,
dma
->
nr_pages
);
...
...
@@ -160,7 +192,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
return
-
ENOMEM
;
}
dma
->
sglen
=
pci_map_sg
(
dev
,
dma
->
sglist
,
dma
->
nr_pages
,
dma
->
direction
);
dma
->
direction
);
return
0
;
}
...
...
@@ -182,8 +214,8 @@ int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma)
kfree
(
dma
->
sglist
);
dma
->
sglist
=
NULL
;
dma
->
sglen
=
0
;
if
(
dma
->
iobuf
)
unlock_kiovec
(
1
,
&
dma
->
iobuf
);
if
(
dma
->
pages
)
videobuf_lock
(
dma
->
pages
,
dma
->
nr_pages
);
return
0
;
}
...
...
@@ -192,11 +224,14 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
if
(
dma
->
sglen
)
BUG
();
if
(
dma
->
iobuf
)
{
unmap_kiobuf
(
dma
->
iobuf
);
free_kiovec
(
1
,
&
dma
->
iobuf
);
dma
->
iobuf
=
NULL
;
if
(
dma
->
pages
)
{
int
i
;
for
(
i
=
0
;
i
<
dma
->
nr_pages
;
i
++
)
page_cache_release
(
dma
->
pages
[
i
]);
kfree
(
dma
->
pages
);
dma
->
pages
=
NULL
;
}
if
(
dma
->
vmalloc
)
{
vfree
(
dma
->
vmalloc
);
dma
->
vmalloc
=
NULL
;
...
...
@@ -959,6 +994,7 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma,
map
->
q
=
q
;
vma
->
vm_ops
=
&
videobuf_vm_ops
;
vma
->
vm_flags
|=
VM_DONTEXPAND
;
vma
->
vm_flags
&=
~
VM_IO
;
/* using shared anonymous pages */
vma
->
vm_private_data
=
map
;
dprintk
(
1
,
"mmap %p: %08lx-%08lx pgoff %08lx bufs %d-%d
\n
"
,
map
,
vma
->
vm_start
,
vma
->
vm_end
,
vma
->
vm_pgoff
,
first
,
last
);
...
...
@@ -972,7 +1008,6 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma,
/* --------------------------------------------------------------------- */
EXPORT_SYMBOL_GPL
(
videobuf_vmalloc_to_sg
);
EXPORT_SYMBOL_GPL
(
videobuf_iobuf_to_sg
);
EXPORT_SYMBOL_GPL
(
videobuf_dma_init_user
);
EXPORT_SYMBOL_GPL
(
videobuf_dma_init_kernel
);
...
...
drivers/media/video/video-buf.h
View file @
71660e15
...
...
@@ -28,11 +28,12 @@
struct
scatterlist
*
videobuf_vmalloc_to_sg
(
unsigned
char
*
virt
,
int
nr_pages
);
/*
* Return a scatterlist for a
locked iobuf
(NULL on errors). Memory
* Return a scatterlist for a
an array of userpages
(NULL on errors). Memory
* for the scatterlist is allocated using kmalloc. The caller must
* free the memory.
*/
struct
scatterlist
*
videobuf_iobuf_to_sg
(
struct
kiobuf
*
iobuf
);
struct
scatterlist
*
videobuf_pages_to_sg
(
struct
page
**
pages
,
int
nr_pages
,
int
offset
);
/* --------------------------------------------------------------------- */
...
...
@@ -57,7 +58,8 @@ struct scatterlist* videobuf_iobuf_to_sg(struct kiobuf *iobuf);
struct
videobuf_dmabuf
{
/* for userland buffer */
struct
kiobuf
*
iobuf
;
struct
page
**
pages
;
int
offset
;
/* for kernel buffers */
void
*
vmalloc
;
...
...
fs/Makefile
View file @
71660e15
...
...
@@ -11,7 +11,7 @@ export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \
obj-y
:=
open.o read_write.o devices.o file_table.o buffer.o
\
bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o
\
namei.o fcntl.o ioctl.o readdir.o
select
.o fifo.o locks.o
\
dcache.o inode.o attr.o bad_inode.o file.o
iobuf.o
dnotify.o
\
dcache.o inode.o attr.o bad_inode.o file.o dnotify.o
\
filesystems.o namespace.o seq_file.o xattr.o libfs.o
\
fs-writeback.o mpage.o direct-io.o aio.o
...
...
fs/aio.c
View file @
71660e15
...
...
@@ -9,6 +9,7 @@
* See ../COPYING for licensing terms.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/aio_abi.h>
...
...
@@ -21,15 +22,9 @@
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vmalloc.h>
#include <linux/iobuf.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/brlock.h>
#include <linux/aio.h>
#include <linux/smp_lock.h>
#include <linux/compiler.h>
#include <linux/brlock.h>
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
...
...
fs/bio.c
View file @
71660e15
...
...
@@ -20,7 +20,7 @@
#include <linux/bio.h>
#include <linux/blk.h>
#include <linux/slab.h>
#include <linux/i
obuf
.h>
#include <linux/i
nit
.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mempool.h>
...
...
@@ -438,128 +438,6 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
return
0
;
}
static
int
bio_end_io_kio
(
struct
bio
*
bio
,
unsigned
int
bytes_done
,
int
error
)
{
struct
kiobuf
*
kio
=
(
struct
kiobuf
*
)
bio
->
bi_private
;
if
(
bio
->
bi_size
)
return
1
;
end_kio_request
(
kio
,
error
);
bio_put
(
bio
);
return
0
;
}
/**
* ll_rw_kio - submit a &struct kiobuf for I/O
* @rw: %READ or %WRITE
* @kio: the kiobuf to do I/O on
* @bdev: target device
* @sector: start location on disk
*
* Description:
* ll_rw_kio will map the page list inside the &struct kiobuf to
* &struct bio and queue them for I/O. The kiobuf given must describe
* a continous range of data, and must be fully prepared for I/O.
**/
void
ll_rw_kio
(
int
rw
,
struct
kiobuf
*
kio
,
struct
block_device
*
bdev
,
sector_t
sector
)
{
int
i
,
offset
,
size
,
err
,
map_i
,
total_nr_pages
,
nr_pages
;
struct
bio
*
bio
;
err
=
0
;
if
((
rw
&
WRITE
)
&&
bdev_read_only
(
bdev
))
{
printk
(
"ll_rw_bio: WRITE to ro device %s
\n
"
,
bdevname
(
bdev
));
err
=
-
EPERM
;
goto
out
;
}
if
(
!
kio
->
nr_pages
)
{
err
=
-
EINVAL
;
goto
out
;
}
/*
* maybe kio is bigger than the max we can easily map into a bio.
* if so, split it up in appropriately sized chunks.
*/
total_nr_pages
=
kio
->
nr_pages
;
offset
=
kio
->
offset
&
~
PAGE_MASK
;
size
=
kio
->
length
;
atomic_set
(
&
kio
->
io_count
,
1
);
map_i
=
0
;
next_chunk:
nr_pages
=
BIO_MAX_PAGES
;
if
(
nr_pages
>
total_nr_pages
)
nr_pages
=
total_nr_pages
;
atomic_inc
(
&
kio
->
io_count
);
/*
* allocate bio and do initial setup
*/
if
((
bio
=
bio_alloc
(
GFP_NOIO
,
nr_pages
))
==
NULL
)
{
err
=
-
ENOMEM
;
goto
out
;
}
bio
->
bi_sector
=
sector
;
bio
->
bi_bdev
=
bdev
;
bio
->
bi_idx
=
0
;
bio
->
bi_end_io
=
bio_end_io_kio
;
bio
->
bi_private
=
kio
;
for
(
i
=
0
;
i
<
nr_pages
;
i
++
,
map_i
++
)
{
int
nbytes
=
PAGE_SIZE
-
offset
;
if
(
nbytes
>
size
)
nbytes
=
size
;
BUG_ON
(
kio
->
maplist
[
map_i
]
==
NULL
);
/*
* if we can't add this page to the bio, submit for i/o
* and alloc a new one if needed
*/
if
(
bio_add_page
(
bio
,
kio
->
maplist
[
map_i
],
nbytes
,
offset
))
break
;
/*
* kiobuf only has an offset into the first page
*/
offset
=
0
;
sector
+=
nbytes
>>
9
;
size
-=
nbytes
;
total_nr_pages
--
;
kio
->
offset
+=
nbytes
;
}
submit_bio
(
rw
,
bio
);
if
(
total_nr_pages
)
goto
next_chunk
;
if
(
size
)
{
printk
(
"ll_rw_kio: size %d left (kio %d)
\n
"
,
size
,
kio
->
length
);
BUG
();
}
out:
if
(
err
)
kio
->
errno
=
err
;
/*
* final atomic_dec of io_count to match our initial setting of 1.
* I/O may or may not have completed at this point, final completion
* handler is only run on last decrement.
*/
end_kio_request
(
kio
,
!
err
);
}
/**
* bio_endio - end I/O on a bio
* @bio: bio
...
...
@@ -662,7 +540,6 @@ module_init(init_bio);
EXPORT_SYMBOL
(
bio_alloc
);
EXPORT_SYMBOL
(
bio_put
);
EXPORT_SYMBOL
(
ll_rw_kio
);
EXPORT_SYMBOL
(
bio_endio
);
EXPORT_SYMBOL
(
bio_init
);
EXPORT_SYMBOL
(
bio_copy
);
...
...
fs/block_dev.c
View file @
71660e15
...
...
@@ -14,7 +14,6 @@
#include <linux/major.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/smp_lock.h>
#include <linux/iobuf.h>
#include <linux/highmem.h>
#include <linux/blkdev.h>
#include <linux/module.h>
...
...
fs/buffer.c
View file @
71660e15
...
...
@@ -28,7 +28,6 @@
#include <linux/blkdev.h>
#include <linux/file.h>
#include <linux/quotaops.h>
#include <linux/iobuf.h>
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/writeback.h>
...
...
@@ -2300,65 +2299,6 @@ sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
return
tmp
.
b_blocknr
;
}
/*
* Start I/O on a physical range of kernel memory, defined by a vector
* of kiobuf structs (much like a user-space iovec list).
*
* The kiobuf must already be locked for IO. IO is submitted
* asynchronously: you need to check page->locked and page->uptodate.
*
* It is up to the caller to make sure that there are enough blocks
* passed in to completely map the iobufs to disk.
*/
int
brw_kiovec
(
int
rw
,
int
nr
,
struct
kiobuf
*
iovec
[],
struct
block_device
*
bdev
,
sector_t
b
[],
int
size
)
{
int
transferred
;
int
i
;
int
err
;
struct
kiobuf
*
iobuf
;
if
(
!
nr
)
return
0
;
/*
* First, do some alignment and validity checks
*/
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
iovec
[
i
];
if
((
iobuf
->
offset
&
(
size
-
1
))
||
(
iobuf
->
length
&
(
size
-
1
)))
return
-
EINVAL
;
if
(
!
iobuf
->
nr_pages
)
panic
(
"brw_kiovec: iobuf not initialised"
);
}
/*
* OK to walk down the iovec doing page IO on each page we find.
*/
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
iovec
[
i
];
iobuf
->
errno
=
0
;
ll_rw_kio
(
rw
,
iobuf
,
bdev
,
b
[
i
]
*
(
size
>>
9
));
}
/*
* now they are all submitted, wait for completion
*/
transferred
=
0
;
err
=
0
;
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
iovec
[
i
];
kiobuf_wait_for_io
(
iobuf
);
if
(
iobuf
->
errno
&&
!
err
)
err
=
iobuf
->
errno
;
if
(
!
err
)
transferred
+=
iobuf
->
length
;
}
return
err
?
err
:
transferred
;
}
static
int
end_bio_bh_io_sync
(
struct
bio
*
bio
,
unsigned
int
bytes_done
,
int
err
)
{
struct
buffer_head
*
bh
=
bio
->
bi_private
;
...
...
fs/dcache.c
View file @
71660e15
...
...
@@ -328,7 +328,7 @@ static inline void prune_one_dentry(struct dentry * dentry)
* all the dentries are in use.
*/
void
prune_dcache
(
int
count
)
static
void
prune_dcache
(
int
count
)
{
spin_lock
(
&
dcache_lock
);
for
(;
count
;
count
--
)
{
...
...
@@ -572,25 +572,24 @@ void shrink_dcache_anon(struct list_head *head)
* This is called from kswapd when we think we need some
* more memory.
*/
int
shrink_dcache_memory
(
int
ratio
,
unsigned
int
gfp_mask
)
static
int
shrink_dcache_memory
(
int
nr
,
unsigned
int
gfp_mask
)
{
int
entries
=
dentry_stat
.
nr_dentry
/
ratio
+
1
;
/*
* Nasty deadlock avoidance.
*
* ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache->
* prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->
* put_inode->ext2_discard_prealloc->ext2_free_blocks->lock_super->
* DEADLOCK.
*
* We should make sure we don't hold the superblock lock over
* block allocations, but for now:
*/
if
(
!
(
gfp_mask
&
__GFP_FS
))
return
0
;
prune_dcache
(
entries
);
return
entries
;
if
(
nr
)
{
/*
* Nasty deadlock avoidance.
*
* ext2_new_block->getblk->GFP->shrink_dcache_memory->
* prune_dcache->prune_one_dentry->dput->dentry_iput->iput->
* inode->i_sb->s_op->put_inode->ext2_discard_prealloc->
* ext2_free_blocks->lock_super->DEADLOCK.
*
* We should make sure we don't hold the superblock lock over
* block allocations, but for now:
*/
if
(
gfp_mask
&
__GFP_FS
)
prune_dcache
(
nr
);
}
return
dentry_stat
.
nr_dentry
;
}
#define NAME_ALLOC_LEN(len) ((len+16) & ~15)
...
...
@@ -1330,6 +1329,8 @@ static void __init dcache_init(unsigned long mempages)
NULL
,
NULL
);
if
(
!
dentry_cache
)
panic
(
"Cannot create dentry cache"
);
set_shrinker
(
DEFAULT_SEEKS
,
shrink_dcache_memory
);
#if PAGE_SHIFT < 13
mempages
>>=
(
13
-
PAGE_SHIFT
);
...
...
@@ -1375,9 +1376,6 @@ kmem_cache_t *names_cachep;
/* SLAB cache for file structures */
kmem_cache_t
*
filp_cachep
;
/* SLAB cache for dquot structures */
kmem_cache_t
*
dquot_cachep
;
EXPORT_SYMBOL
(
d_genocide
);
extern
void
bdev_cache_init
(
void
);
...
...
@@ -1397,14 +1395,6 @@ void __init vfs_caches_init(unsigned long mempages)
if
(
!
filp_cachep
)
panic
(
"Cannot create filp SLAB cache"
);
#if defined (CONFIG_QUOTA)
dquot_cachep
=
kmem_cache_create
(
"dquot"
,
sizeof
(
struct
dquot
),
sizeof
(
unsigned
long
)
*
4
,
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
if
(
!
dquot_cachep
)
panic
(
"Cannot create dquot SLAB cache"
);
#endif
dcache_init
(
mempages
);
inode_init
(
mempages
);
files_init
(
mempages
);
...
...
fs/dquot.c
View file @
71660e15
...
...
@@ -55,6 +55,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/time.h>
#include <linux/types.h>
#include <linux/string.h>
...
...
@@ -481,14 +482,14 @@ static void prune_dqcache(int count)
* more memory
*/
int
shrink_dqcache_memory
(
int
ratio
,
unsigned
int
gfp_mask
)
static
int
shrink_dqcache_memory
(
int
nr
,
unsigned
int
gfp_mask
)
{
i
nt
entries
=
dqstats
.
allocated_dquots
/
ratio
+
1
;
lock_kernel
(
);
prune_dqcache
(
entries
);
unlock_kernel
();
return
entrie
s
;
i
f
(
nr
)
{
lock_kernel
();
prune_dqcache
(
nr
);
unlock_kernel
(
);
}
return
dqstats
.
allocated_dquot
s
;
}
/*
...
...
@@ -1490,6 +1491,9 @@ static ctl_table sys_table[] = {
{},
};
/* SLAB cache for dquot structures */
kmem_cache_t
*
dquot_cachep
;
static
int
__init
dquot_init
(
void
)
{
int
i
;
...
...
@@ -1499,9 +1503,17 @@ static int __init dquot_init(void)
INIT_LIST_HEAD
(
dquot_hash
+
i
);
printk
(
KERN_NOTICE
"VFS: Disk quotas v%s
\n
"
,
__DQUOT_VERSION__
);
dquot_cachep
=
kmem_cache_create
(
"dquot"
,
sizeof
(
struct
dquot
),
sizeof
(
unsigned
long
)
*
4
,
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
if
(
!
dquot_cachep
)
panic
(
"Cannot create dquot SLAB cache"
);
set_shrinker
(
DEFAULT_SEEKS
,
shrink_dqcache_memory
);
return
0
;
}
__initcall
(
dquot_init
);
module_init
(
dquot_init
);
EXPORT_SYMBOL
(
register_quota_format
);
EXPORT_SYMBOL
(
unregister_quota_format
);
...
...
fs/fcntl.c
View file @
71660e15
...
...
@@ -10,7 +10,6 @@
#include <linux/dnotify.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/iobuf.h>
#include <linux/module.h>
#include <linux/security.h>
...
...
fs/file_table.c
View file @
71660e15
...
...
@@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/iobuf.h>
#include <linux/fs.h>
#include <linux/security.h>
...
...
fs/inode.c
View file @
71660e15
...
...
@@ -243,22 +243,25 @@ void clear_inode(struct inode *inode)
* Dispose-list gets a local list with local inodes in it, so it doesn't
* need to worry about list corruption and SMP locks.
*/
static
void
dispose_list
(
struct
list_head
*
head
)
static
void
dispose_list
(
struct
list_head
*
head
)
{
struct
list_head
*
inode_entry
;
struct
inode
*
inode
;
int
nr_disposed
=
0
;
while
(
!
list_empty
(
head
))
{
struct
inode
*
inode
;
while
((
inode_entry
=
head
->
next
)
!=
head
)
{
list_del
(
inode_entry
);
inode
=
list_entry
(
head
->
next
,
struct
inode
,
i_list
);
list_del
(
&
inode
->
i_list
);
inode
=
list_entry
(
inode_entry
,
struct
inode
,
i_list
);
if
(
inode
->
i_data
.
nrpages
)
truncate_inode_pages
(
&
inode
->
i_data
,
0
);
clear_inode
(
inode
);
destroy_inode
(
inode
);
inodes_stat
.
nr_inodes
--
;
nr_disposed
++
;
}
spin_lock
(
&
inode_lock
);
inodes_stat
.
nr_inodes
-=
nr_disposed
;
spin_unlock
(
&
inode_lock
);
}
/*
...
...
@@ -377,7 +380,7 @@ int invalidate_device(kdev_t dev, int do_sync)
!inode_has_buffers(inode))
#define INODE(entry) (list_entry(entry, struct inode, i_list))
void
prune_icache
(
int
goal
)
static
inline
void
prune_icache
(
int
goal
)
{
LIST_HEAD
(
list
);
struct
list_head
*
entry
,
*
freeable
=
&
list
;
...
...
@@ -417,23 +420,19 @@ void prune_icache(int goal)
* This is called from kswapd when we think we need some
* more memory.
*/
int
shrink_icache_memory
(
int
ratio
,
unsigned
int
gfp_mask
)
static
int
shrink_icache_memory
(
int
nr
,
unsigned
int
gfp_mask
)
{
int
entries
=
inodes_stat
.
nr_inodes
/
ratio
+
1
;
/*
* Nasty deadlock avoidance..
*
* We may hold various FS locks, and we don't
* want to recurse into the FS that called us
* in clear_inode() and friends..
*/
if
(
!
(
gfp_mask
&
__GFP_FS
))
return
0
;
prune_icache
(
entries
);
return
entries
;
if
(
nr
)
{
/*
* Nasty deadlock avoidance. We may hold various FS locks,
* and we don't want to recurse into the FS that called us
* in clear_inode() and friends..
*/
if
(
gfp_mask
&
__GFP_FS
)
prune_icache
(
nr
);
}
return
inodes_stat
.
nr_inodes
;
}
EXPORT_SYMBOL
(
shrink_icache_memory
);
/*
* Called with the inode lock held.
...
...
@@ -1226,4 +1225,6 @@ void __init inode_init(unsigned long mempages)
NULL
);
if
(
!
inode_cachep
)
panic
(
"cannot create inode slab cache"
);
set_shrinker
(
DEFAULT_SEEKS
,
shrink_icache_memory
);
}
fs/iobuf.c
deleted
100644 → 0
View file @
31c96625
/*
* iobuf.c
*
* Keep track of the general-purpose IO-buffer structures used to track
* abstract kernel-space io buffers.
*
*/
#include <linux/iobuf.h>
#include <linux/slab.h>
int
end_kio_request
(
struct
kiobuf
*
kiobuf
,
int
uptodate
)
{
int
ret
=
1
;
if
((
!
uptodate
)
&&
!
kiobuf
->
errno
)
kiobuf
->
errno
=
-
EIO
;
if
(
atomic_dec_and_test
(
&
kiobuf
->
io_count
))
{
ret
=
0
;
if
(
kiobuf
->
end_io
)
kiobuf
->
end_io
(
kiobuf
);
wake_up
(
&
kiobuf
->
wait_queue
);
}
return
ret
;
}
static
void
kiobuf_init
(
struct
kiobuf
*
iobuf
)
{
init_waitqueue_head
(
&
iobuf
->
wait_queue
);
atomic_set
(
&
iobuf
->
io_count
,
0
);
iobuf
->
array_len
=
KIO_STATIC_PAGES
;
iobuf
->
maplist
=
iobuf
->
map_array
;
iobuf
->
nr_pages
=
0
;
iobuf
->
locked
=
0
;
iobuf
->
io_count
.
counter
=
0
;
iobuf
->
end_io
=
NULL
;
}
int
alloc_kiovec
(
int
nr
,
struct
kiobuf
**
bufp
)
{
int
i
;
struct
kiobuf
*
iobuf
;
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
kmalloc
(
sizeof
(
struct
kiobuf
),
GFP_KERNEL
);
if
(
!
iobuf
)
{
free_kiovec
(
i
,
bufp
);
return
-
ENOMEM
;
}
kiobuf_init
(
iobuf
);
bufp
[
i
]
=
iobuf
;
}
return
0
;
}
void
free_kiovec
(
int
nr
,
struct
kiobuf
**
bufp
)
{
int
i
;
struct
kiobuf
*
iobuf
;
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
bufp
[
i
];
if
(
iobuf
->
locked
)
unlock_kiovec
(
1
,
&
iobuf
);
if
(
iobuf
->
array_len
>
KIO_STATIC_PAGES
)
kfree
(
iobuf
->
maplist
);
kfree
(
bufp
[
i
]);
}
}
int
expand_kiobuf
(
struct
kiobuf
*
iobuf
,
int
wanted
)
{
struct
page
**
maplist
;
if
(
iobuf
->
array_len
>=
wanted
)
return
0
;
maplist
=
(
struct
page
**
)
kmalloc
(
wanted
*
sizeof
(
struct
page
**
),
GFP_KERNEL
);
if
(
!
maplist
)
return
-
ENOMEM
;
/* Did it grow while we waited? */
if
(
iobuf
->
array_len
>=
wanted
)
{
kfree
(
maplist
);
return
0
;
}
memcpy
(
maplist
,
iobuf
->
maplist
,
iobuf
->
array_len
*
sizeof
(
struct
page
**
));
if
(
iobuf
->
array_len
>
KIO_STATIC_PAGES
)
kfree
(
iobuf
->
maplist
);
iobuf
->
maplist
=
maplist
;
iobuf
->
array_len
=
wanted
;
return
0
;
}
void
kiobuf_wait_for_io
(
struct
kiobuf
*
kiobuf
)
{
struct
task_struct
*
tsk
=
current
;
DECLARE_WAITQUEUE
(
wait
,
tsk
);
if
(
atomic_read
(
&
kiobuf
->
io_count
)
==
0
)
return
;
add_wait_queue
(
&
kiobuf
->
wait_queue
,
&
wait
);
repeat:
set_task_state
(
tsk
,
TASK_UNINTERRUPTIBLE
);
if
(
atomic_read
(
&
kiobuf
->
io_count
)
!=
0
)
{
blk_run_queues
();
schedule
();
if
(
atomic_read
(
&
kiobuf
->
io_count
)
!=
0
)
goto
repeat
;
}
tsk
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
kiobuf
->
wait_queue
,
&
wait
);
}
fs/open.c
View file @
71660e15
...
...
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/iobuf.h>
#include <linux/namei.h>
#include <linux/backing-dev.h>
#include <linux/security.h>
...
...
fs/xfs/linux/xfs_aops.c
View file @
71660e15
...
...
@@ -34,7 +34,6 @@
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/mpage.h>
#include <linux/iobuf.h>
STATIC
int
delalloc_convert
(
struct
inode
*
,
struct
page
*
,
int
,
int
);
...
...
fs/xfs/linux/xfs_ioctl.c
View file @
71660e15
...
...
@@ -35,7 +35,6 @@
#include <xfs_dfrag.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/iobuf.h>
extern
int
xfs_change_file_space
(
bhv_desc_t
*
,
int
,
...
...
@@ -605,6 +604,7 @@ xfs_ioctl(
* it is set to the file system block size to
* avoid having to do block zeroing on short writes.
*/
#define KIO_MAX_ATOMIC_IO 512
/* FIXME: what do we really want here? */
da
.
d_maxiosz
=
XFS_FSB_TO_B
(
mp
,
XFS_B_TO_FSBT
(
mp
,
KIO_MAX_ATOMIC_IO
<<
10
));
...
...
include/linux/buffer_head.h
View file @
71660e15
...
...
@@ -32,7 +32,6 @@ enum bh_state_bits {
#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
struct
page
;
struct
kiobuf
;
struct
buffer_head
;
struct
address_space
;
typedef
void
(
bh_end_io_t
)(
struct
buffer_head
*
bh
,
int
uptodate
);
...
...
include/linux/dcache.h
View file @
71660e15
...
...
@@ -180,17 +180,6 @@ extern void shrink_dcache_parent(struct dentry *);
extern
void
shrink_dcache_anon
(
struct
list_head
*
);
extern
int
d_invalidate
(
struct
dentry
*
);
/* dcache memory management */
extern
int
shrink_dcache_memory
(
int
,
unsigned
int
);
extern
void
prune_dcache
(
int
);
/* icache memory management (defined in linux/fs/inode.c) */
extern
int
shrink_icache_memory
(
int
,
unsigned
int
);
extern
void
prune_icache
(
int
);
/* quota cache memory management (defined in linux/fs/dquot.c) */
extern
int
shrink_dqcache_memory
(
int
,
unsigned
int
);
/* only used at mount-time */
extern
struct
dentry
*
d_alloc_root
(
struct
inode
*
);
...
...
include/linux/iobuf.h
deleted
100644 → 0
View file @
31c96625
/*
* iobuf.h
*
* Defines the structures used to track abstract kernel-space io buffers.
*
*/
#ifndef __LINUX_IOBUF_H
#define __LINUX_IOBUF_H
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <asm/atomic.h>
/*
* The kiobuf structure describes a physical set of pages reserved
* locked for IO. The reference counts on each page will have been
* incremented, and the flags field will indicate whether or not we have
* pre-locked all of the pages for IO.
*
* kiobufs may be passed in arrays to form a kiovec, but we must
* preserve the property that no page is present more than once over the
* entire iovec.
*/
#define KIO_MAX_ATOMIC_IO 512
/* in kb */
#define KIO_STATIC_PAGES (KIO_MAX_ATOMIC_IO / (PAGE_SIZE >> 10) + 1)
#define KIO_MAX_SECTORS (KIO_MAX_ATOMIC_IO * 2)
/* The main kiobuf struct */
struct
kiobuf
{
int
nr_pages
;
/* Pages actually referenced */
int
array_len
;
/* Space in the allocated lists */
int
offset
;
/* Offset to start of valid data */
int
length
;
/* Number of valid bytes of data */
/* Keep separate track of the physical addresses and page
* structs involved. If we do IO to a memory-mapped device
* region, there won't necessarily be page structs defined for
* every address. */
struct
page
**
maplist
;
unsigned
int
locked
:
1
;
/* If set, pages has been locked */
/* Always embed enough struct pages for atomic IO */
struct
page
*
map_array
[
KIO_STATIC_PAGES
];
sector_t
blocks
[
KIO_MAX_SECTORS
];
/* Dynamic state for IO completion: */
atomic_t
io_count
;
/* IOs still in progress */
int
errno
;
/* Status of completed IO */
void
(
*
end_io
)
(
struct
kiobuf
*
);
/* Completion callback */
wait_queue_head_t
wait_queue
;
};
/* mm/memory.c */
int
map_user_kiobuf
(
int
rw
,
struct
kiobuf
*
,
unsigned
long
va
,
size_t
len
);
void
unmap_kiobuf
(
struct
kiobuf
*
iobuf
);
int
lock_kiovec
(
int
nr
,
struct
kiobuf
*
iovec
[],
int
wait
);
int
unlock_kiovec
(
int
nr
,
struct
kiobuf
*
iovec
[]);
void
mark_dirty_kiobuf
(
struct
kiobuf
*
iobuf
,
int
bytes
);
/* fs/iobuf.c */
int
end_kio_request
(
struct
kiobuf
*
,
int
);
void
simple_wakeup_kiobuf
(
struct
kiobuf
*
);
int
alloc_kiovec
(
int
nr
,
struct
kiobuf
**
);
void
free_kiovec
(
int
nr
,
struct
kiobuf
**
);
int
expand_kiobuf
(
struct
kiobuf
*
,
int
);
void
kiobuf_wait_for_io
(
struct
kiobuf
*
);
extern
int
alloc_kiobuf_bhs
(
struct
kiobuf
*
);
extern
void
free_kiobuf_bhs
(
struct
kiobuf
*
);
/* fs/buffer.c */
int
brw_kiovec
(
int
rw
,
int
nr
,
struct
kiobuf
*
iovec
[],
struct
block_device
*
bdev
,
sector_t
[],
int
size
);
/* fs/bio.c */
void
ll_rw_kio
(
int
rw
,
struct
kiobuf
*
kio
,
struct
block_device
*
bdev
,
sector_t
block
);
#endif
/* __LINUX_IOBUF_H */
include/linux/mm.h
View file @
71660e15
...
...
@@ -391,6 +391,29 @@ extern int free_hugepages(struct vm_area_struct *);
#endif
/*
* Prototype to add a shrinker callback for ageable caches.
*
* These functions are passed a count `nr_to_scan' and a gfpmask. They should
* scan `nr_to_scan' objects, attempting to free them.
*
* The callback must the number of objects which remain in the cache.
*
* The callback will be passes nr_to_scan == 0 when the VM is querying the
* cache size, so a fastpath for that case is appropriate.
*/
typedef
int
(
*
shrinker_t
)(
int
nr_to_scan
,
unsigned
int
gfp_mask
);
/*
* Add an aging callback. The int is the number of 'seeks' it takes
* to recreate one of the objects that these functions age.
*/
#define DEFAULT_SEEKS 2
struct
shrinker
;
extern
struct
shrinker
*
set_shrinker
(
int
,
shrinker_t
);
extern
void
remove_shrinker
(
struct
shrinker
*
shrinker
);
/*
* If the mapping doesn't provide a set_page_dirty a_op, then
* just fall through and assume that it wants buffer_heads.
...
...
init/main.c
View file @
71660e15
...
...
@@ -24,7 +24,6 @@
#include <linux/smp_lock.h>
#include <linux/blk.h>
#include <linux/hdreg.h>
#include <linux/iobuf.h>
#include <linux/bootmem.h>
#include <linux/tty.h>
#include <linux/percpu.h>
...
...
kernel/ksyms.c
View file @
71660e15
...
...
@@ -33,7 +33,6 @@
#include <linux/swap.h>
#include <linux/ctype.h>
#include <linux/file.h>
#include <linux/iobuf.h>
#include <linux/console.h>
#include <linux/poll.h>
#include <linux/mmzone.h>
...
...
@@ -103,6 +102,8 @@ EXPORT_SYMBOL(kmem_cache_shrink);
EXPORT_SYMBOL
(
kmem_cache_alloc
);
EXPORT_SYMBOL
(
kmem_cache_free
);
EXPORT_SYMBOL
(
kmem_cache_size
);
EXPORT_SYMBOL
(
set_shrinker
);
EXPORT_SYMBOL
(
remove_shrinker
);
EXPORT_SYMBOL
(
kmalloc
);
EXPORT_SYMBOL
(
kfree
);
EXPORT_SYMBOL
(
vfree
);
...
...
@@ -246,7 +247,6 @@ EXPORT_SYMBOL(dput);
EXPORT_SYMBOL
(
have_submounts
);
EXPORT_SYMBOL
(
d_find_alias
);
EXPORT_SYMBOL
(
d_prune_aliases
);
EXPORT_SYMBOL
(
prune_dcache
);
EXPORT_SYMBOL
(
shrink_dcache_sb
);
EXPORT_SYMBOL
(
shrink_dcache_parent
);
EXPORT_SYMBOL
(
shrink_dcache_anon
);
...
...
@@ -438,18 +438,6 @@ EXPORT_SYMBOL(__br_write_lock);
EXPORT_SYMBOL
(
__br_write_unlock
);
#endif
/* Kiobufs */
EXPORT_SYMBOL
(
alloc_kiovec
);
EXPORT_SYMBOL
(
free_kiovec
);
EXPORT_SYMBOL
(
expand_kiobuf
);
EXPORT_SYMBOL
(
map_user_kiobuf
);
EXPORT_SYMBOL
(
unmap_kiobuf
);
EXPORT_SYMBOL
(
lock_kiovec
);
EXPORT_SYMBOL
(
unlock_kiovec
);
EXPORT_SYMBOL
(
brw_kiovec
);
EXPORT_SYMBOL
(
kiobuf_wait_for_io
);
#ifdef HAVE_DISABLE_HLT
EXPORT_SYMBOL
(
disable_hlt
);
EXPORT_SYMBOL
(
enable_hlt
);
...
...
mm/filemap.c
View file @
71660e15
...
...
@@ -20,7 +20,6 @@
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/uio.h>
#include <linux/iobuf.h>
#include <linux/hash.h>
#include <linux/writeback.h>
#include <linux/pagevec.h>
...
...
mm/memory.c
View file @
71660e15
...
...
@@ -40,7 +40,6 @@
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/swap.h>
#include <linux/iobuf.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/vcache.h>
...
...
@@ -504,7 +503,7 @@ follow_page(struct mm_struct *mm, unsigned long address, int write)
/*
* Given a physical address, is there a useful struct page pointing to
* it? This may become more complex in the future if we start dealing
* with IO-aperture pages
in kiobufs
.
* with IO-aperture pages
for direct-IO
.
*/
static
inline
struct
page
*
get_page_map
(
struct
page
*
page
)
...
...
@@ -589,224 +588,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
return
i
;
}
/*
* Force in an entire range of pages from the current process's user VA,
* and pin them in physical memory.
*/
#define dprintk(x...)
int
map_user_kiobuf
(
int
rw
,
struct
kiobuf
*
iobuf
,
unsigned
long
va
,
size_t
len
)
{
int
pgcount
,
err
;
struct
mm_struct
*
mm
;
/* Make sure the iobuf is not already mapped somewhere. */
if
(
iobuf
->
nr_pages
)
return
-
EINVAL
;
mm
=
current
->
mm
;
dprintk
(
"map_user_kiobuf: begin
\n
"
);
pgcount
=
(
va
+
len
+
PAGE_SIZE
-
1
)
/
PAGE_SIZE
-
va
/
PAGE_SIZE
;
/* mapping 0 bytes is not permitted */
if
(
!
pgcount
)
BUG
();
err
=
expand_kiobuf
(
iobuf
,
pgcount
);
if
(
err
)
return
err
;
iobuf
->
locked
=
0
;
iobuf
->
offset
=
va
&
(
PAGE_SIZE
-
1
);
iobuf
->
length
=
len
;
/* Try to fault in all of the necessary pages */
down_read
(
&
mm
->
mmap_sem
);
/* rw==READ means read from disk, write into memory area */
err
=
get_user_pages
(
current
,
mm
,
va
,
pgcount
,
(
rw
==
READ
),
0
,
iobuf
->
maplist
,
NULL
);
up_read
(
&
mm
->
mmap_sem
);
if
(
err
<
0
)
{
unmap_kiobuf
(
iobuf
);
dprintk
(
"map_user_kiobuf: end %d
\n
"
,
err
);
return
err
;
}
iobuf
->
nr_pages
=
err
;
while
(
pgcount
--
)
{
/* FIXME: flush superflous for rw==READ,
* probably wrong function for rw==WRITE
*/
flush_dcache_page
(
iobuf
->
maplist
[
pgcount
]);
}
dprintk
(
"map_user_kiobuf: end OK
\n
"
);
return
0
;
}
/*
* Mark all of the pages in a kiobuf as dirty
*
* We need to be able to deal with short reads from disk: if an IO error
* occurs, the number of bytes read into memory may be less than the
* size of the kiobuf, so we have to stop marking pages dirty once the
* requested byte count has been reached.
*/
void
mark_dirty_kiobuf
(
struct
kiobuf
*
iobuf
,
int
bytes
)
{
int
index
,
offset
,
remaining
;
struct
page
*
page
;
index
=
iobuf
->
offset
>>
PAGE_SHIFT
;
offset
=
iobuf
->
offset
&
~
PAGE_MASK
;
remaining
=
bytes
;
if
(
remaining
>
iobuf
->
length
)
remaining
=
iobuf
->
length
;
while
(
remaining
>
0
&&
index
<
iobuf
->
nr_pages
)
{
page
=
iobuf
->
maplist
[
index
];
if
(
!
PageReserved
(
page
))
set_page_dirty
(
page
);
remaining
-=
(
PAGE_SIZE
-
offset
);
offset
=
0
;
index
++
;
}
}
/*
* Unmap all of the pages referenced by a kiobuf. We release the pages,
* and unlock them if they were locked.
*/
void
unmap_kiobuf
(
struct
kiobuf
*
iobuf
)
{
int
i
;
struct
page
*
map
;
for
(
i
=
0
;
i
<
iobuf
->
nr_pages
;
i
++
)
{
map
=
iobuf
->
maplist
[
i
];
if
(
map
)
{
if
(
iobuf
->
locked
)
unlock_page
(
map
);
/* FIXME: cache flush missing for rw==READ
* FIXME: call the correct reference counting function
*/
page_cache_release
(
map
);
}
}
iobuf
->
nr_pages
=
0
;
iobuf
->
locked
=
0
;
}
/*
* Lock down all of the pages of a kiovec for IO.
*
* If any page is mapped twice in the kiovec, we return the error -EINVAL.
*
* The optional wait parameter causes the lock call to block until all
* pages can be locked if set. If wait==0, the lock operation is
* aborted if any locked pages are found and -EAGAIN is returned.
*/
int
lock_kiovec
(
int
nr
,
struct
kiobuf
*
iovec
[],
int
wait
)
{
struct
kiobuf
*
iobuf
;
int
i
,
j
;
struct
page
*
page
,
**
ppage
;
int
doublepage
=
0
;
int
repeat
=
0
;
repeat:
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
iovec
[
i
];
if
(
iobuf
->
locked
)
continue
;
ppage
=
iobuf
->
maplist
;
for
(
j
=
0
;
j
<
iobuf
->
nr_pages
;
ppage
++
,
j
++
)
{
page
=
*
ppage
;
if
(
!
page
)
continue
;
if
(
TestSetPageLocked
(
page
))
{
while
(
j
--
)
{
struct
page
*
tmp
=
*--
ppage
;
if
(
tmp
)
unlock_page
(
tmp
);
}
goto
retry
;
}
}
iobuf
->
locked
=
1
;
}
return
0
;
retry:
/*
* We couldn't lock one of the pages. Undo the locking so far,
* wait on the page we got to, and try again.
*/
unlock_kiovec
(
nr
,
iovec
);
if
(
!
wait
)
return
-
EAGAIN
;
/*
* Did the release also unlock the page we got stuck on?
*/
if
(
!
PageLocked
(
page
))
{
/*
* If so, we may well have the page mapped twice
* in the IO address range. Bad news. Of
* course, it _might_ just be a coincidence,
* but if it happens more than once, chances
* are we have a double-mapped page.
*/
if
(
++
doublepage
>=
3
)
return
-
EINVAL
;
/* Try again... */
wait_on_page_locked
(
page
);
}
if
(
++
repeat
<
16
)
goto
repeat
;
return
-
EAGAIN
;
}
/*
* Unlock all of the pages of a kiovec after IO.
*/
int
unlock_kiovec
(
int
nr
,
struct
kiobuf
*
iovec
[])
{
struct
kiobuf
*
iobuf
;
int
i
,
j
;
struct
page
*
page
,
**
ppage
;
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
iobuf
=
iovec
[
i
];
if
(
!
iobuf
->
locked
)
continue
;
iobuf
->
locked
=
0
;
ppage
=
iobuf
->
maplist
;
for
(
j
=
0
;
j
<
iobuf
->
nr_pages
;
ppage
++
,
j
++
)
{
page
=
*
ppage
;
if
(
!
page
)
continue
;
unlock_page
(
page
);
}
}
return
0
;
}
static
inline
void
zeromap_pte_range
(
pte_t
*
pte
,
unsigned
long
address
,
unsigned
long
size
,
pgprot_t
prot
)
{
...
...
mm/msync.c
View file @
71660e15
...
...
@@ -137,6 +137,9 @@ static int msync_interval(struct vm_area_struct * vma,
int
ret
=
0
;
struct
file
*
file
=
vma
->
vm_file
;
if
((
flags
&
MS_INVALIDATE
)
&&
(
vma
->
vm_flags
&
VM_LOCKED
))
return
-
EBUSY
;
if
(
file
&&
(
vma
->
vm_flags
&
VM_SHARED
))
{
ret
=
filemap_sync
(
vma
,
start
,
end
-
start
,
flags
);
...
...
@@ -173,6 +176,8 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
goto
out
;
if
(
start
&
~
PAGE_MASK
)
goto
out
;
if
((
flags
&
MS_ASYNC
)
&&
(
flags
&
MS_SYNC
))
goto
out
;
error
=
-
ENOMEM
;
len
=
(
len
+
~
PAGE_MASK
)
&
PAGE_MASK
;
end
=
start
+
len
;
...
...
mm/page_alloc.c
View file @
71660e15
...
...
@@ -1147,6 +1147,8 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos)
if
(
!
ps
)
return
ERR_PTR
(
-
ENOMEM
);
get_full_page_state
(
ps
);
ps
->
pgpgin
/=
2
;
/* sectors -> kbytes */
ps
->
pgpgout
/=
2
;
return
(
unsigned
long
*
)
ps
+
*
pos
;
}
...
...
mm/vmscan.c
View file @
71660e15
...
...
@@ -77,9 +77,94 @@ static long total_memory;
#define prefetchw_prev_lru_page(_page, _base, _field) do { } while (0)
#endif
#ifndef CONFIG_QUOTA
#define shrink_dqcache_memory(ratio, gfp_mask) do { } while (0)
#endif
/*
* The list of shrinker callbacks used by to apply pressure to
* ageable caches.
*/
struct
shrinker
{
shrinker_t
shrinker
;
struct
list_head
list
;
int
seeks
;
/* seeks to recreate an obj */
int
nr
;
/* objs pending delete */
};
static
LIST_HEAD
(
shrinker_list
);
static
DECLARE_MUTEX
(
shrinker_sem
);
/*
* Add a shrinker callback to be called from the vm
*/
struct
shrinker
*
set_shrinker
(
int
seeks
,
shrinker_t
theshrinker
)
{
struct
shrinker
*
shrinker
;
shrinker
=
kmalloc
(
sizeof
(
*
shrinker
),
GFP_KERNEL
);
if
(
shrinker
)
{
shrinker
->
shrinker
=
theshrinker
;
shrinker
->
seeks
=
seeks
;
shrinker
->
nr
=
0
;
down
(
&
shrinker_sem
);
list_add
(
&
shrinker
->
list
,
&
shrinker_list
);
up
(
&
shrinker_sem
);
}
return
shrinker
;
}
/*
* Remove one
*/
void
remove_shrinker
(
struct
shrinker
*
shrinker
)
{
down
(
&
shrinker_sem
);
list_del
(
&
shrinker
->
list
);
up
(
&
shrinker_sem
);
kfree
(
shrinker
);
}
#define SHRINK_BATCH 32
/*
* Call the shrink functions to age shrinkable caches
*
* Here we assume it costs one seek to replace a lru page and that it also
* takes a seek to recreate a cache object. With this in mind we age equal
* percentages of the lru and ageable caches. This should balance the seeks
* generated by these structures.
*
* If the vm encounted mapped pages on the LRU it increase the pressure on
* slab to avoid swapping.
*
* FIXME: do not do for zone highmem
*/
static
int
shrink_slab
(
int
scanned
,
unsigned
int
gfp_mask
)
{
struct
list_head
*
lh
;
int
pages
;
if
(
down_trylock
(
&
shrinker_sem
))
return
0
;
pages
=
nr_used_zone_pages
();
list_for_each
(
lh
,
&
shrinker_list
)
{
struct
shrinker
*
shrinker
;
int
entries
;
unsigned
long
delta
;
shrinker
=
list_entry
(
lh
,
struct
shrinker
,
list
);
entries
=
(
*
shrinker
->
shrinker
)(
0
,
gfp_mask
);
if
(
!
entries
)
continue
;
delta
=
scanned
*
shrinker
->
seeks
*
entries
;
shrinker
->
nr
+=
delta
/
(
pages
+
1
);
if
(
shrinker
->
nr
>
SHRINK_BATCH
)
{
int
nr
=
shrinker
->
nr
;
shrinker
->
nr
=
0
;
(
*
shrinker
->
shrinker
)(
nr
,
gfp_mask
);
}
}
up
(
&
shrinker_sem
);
return
0
;
}
/* Must be called with page's pte_chain_lock held. */
static
inline
int
page_mapping_inuse
(
struct
page
*
page
)
...
...
@@ -626,32 +711,6 @@ shrink_zone(struct zone *zone, int max_scan, unsigned int gfp_mask,
max_scan
,
nr_mapped
);
}
/*
* FIXME: don't do this for ZONE_HIGHMEM
*/
/*
* Here we assume it costs one seek to replace a lru page and that it also
* takes a seek to recreate a cache object. With this in mind we age equal
* percentages of the lru and ageable caches. This should balance the seeks
* generated by these structures.
*
* NOTE: for now I do this for all zones. If we find this is too aggressive
* on large boxes we may want to exclude ZONE_HIGHMEM.
*
* If we're encountering mapped pages on the LRU then increase the pressure on
* slab to avoid swapping.
*/
static
void
shrink_slab
(
int
total_scanned
,
int
gfp_mask
)
{
int
shrink_ratio
;
int
pages
=
nr_used_zone_pages
();
shrink_ratio
=
(
pages
/
(
total_scanned
+
1
))
+
1
;
shrink_dcache_memory
(
shrink_ratio
,
gfp_mask
);
shrink_icache_memory
(
shrink_ratio
,
gfp_mask
);
shrink_dqcache_memory
(
shrink_ratio
,
gfp_mask
);
}
/*
* This is the direct reclaim path, for page-allocating processes. We only
* try to reclaim pages from zones which will satisfy the caller's allocation
...
...
@@ -695,7 +754,7 @@ shrink_caches(struct zone *classzone, int priority, int *total_scanned,
}
return
ret
;
}
/*
* This is the main entry point to direct page reclaim.
*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment