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
nexedi
linux
Commits
531fc7be
Commit
531fc7be
authored
Oct 09, 2002
by
Benjamin LaHaise
Browse files
Options
Browse Files
Download
Plain Diff
Merge toomuch.toronto.redhat.com:/md0/linus-2.5
into toomuch.toronto.redhat.com:/md0/aio-2.5
parents
e38e1e7f
040ffec6
Changes
12
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
767 additions
and
188 deletions
+767
-188
drivers/net/ns83820.c
drivers/net/ns83820.c
+515
-119
fs/Makefile
fs/Makefile
+1
-1
fs/aio.c
fs/aio.c
+129
-32
fs/exec.c
fs/exec.c
+4
-7
fs/ext2/file.c
fs/ext2/file.c
+2
-0
fs/ext3/file.c
fs/ext3/file.c
+7
-4
fs/nfs/file.c
fs/nfs/file.c
+14
-12
fs/read_write.c
fs/read_write.c
+41
-4
include/linux/aio.h
include/linux/aio.h
+37
-6
include/linux/fs.h
include/linux/fs.h
+5
-1
include/linux/kernel.h
include/linux/kernel.h
+3
-0
mm/filemap.c
mm/filemap.c
+9
-2
No files found.
drivers/net/ns83820.c
View file @
531fc7be
This diff is collapsed.
Click to expand it.
fs/Makefile
View file @
531fc7be
...
...
@@ -6,7 +6,7 @@
#
export-objs
:=
open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o
\
fcntl.o
fcntl.o
read_write.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
\
...
...
fs/aio.c
View file @
531fc7be
...
...
@@ -35,6 +35,7 @@
#include <asm/kmap_types.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#if DEBUG > 1
#define dprintk printk
...
...
@@ -59,6 +60,8 @@ static DECLARE_WORK(fput_work, aio_fput_routine, NULL);
static
spinlock_t
fput_lock
=
SPIN_LOCK_UNLOCKED
;
LIST_HEAD
(
fput_head
);
static
void
aio_kick_handler
(
void
*
);
/* aio_setup
* Creates the slab caches used by the aio routines, panic on
* failure as this is done early during the boot sequence.
...
...
@@ -175,31 +178,28 @@ static int aio_setup_ring(struct kioctx *ctx)
return
0
;
}
/* aio_ring_event: returns a pointer to the event at the given index from
* kmap_atomic(, km). Release the pointer with put_aio_ring_event();
*/
static
inline
struct
io_event
*
aio_ring_event
(
struct
aio_ring_info
*
info
,
int
nr
,
enum
km_type
km
)
{
struct
io_event
*
events
;
#define AIO_EVENTS_PER_PAGE (PAGE_SIZE / sizeof(struct io_event))
#define AIO_EVENTS_FIRST_PAGE ((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
if
(
nr
<
AIO_EVENTS_FIRST_PAGE
)
{
struct
aio_ring
*
ring
;
ring
=
kmap_atomic
(
info
->
ring_pages
[
0
],
km
);
return
&
ring
->
io_events
[
nr
];
}
nr
-=
AIO_EVENTS_FIRST_PAGE
;
events
=
kmap_atomic
(
info
->
ring_pages
[
1
+
nr
/
AIO_EVENTS_PER_PAGE
],
km
);
return
events
+
(
nr
%
AIO_EVENTS_PER_PAGE
);
}
static
inline
void
put_aio_ring_event
(
struct
io_event
*
event
,
enum
km_type
km
)
{
kunmap_atomic
((
void
*
)((
unsigned
long
)
event
&
PAGE_MASK
),
km
);
}
#define AIO_EVENTS_OFFSET (AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)
#define aio_ring_event(info, nr, km) ({ \
unsigned pos = (nr) + AIO_EVENTS_OFFSET; \
struct io_event *__event; \
__event = kmap_atomic( \
(info)->ring_pages[pos / AIO_EVENTS_PER_PAGE], km); \
__event += pos % AIO_EVENTS_PER_PAGE; \
__event; \
})
#define put_aio_ring_event(event, km) do { \
struct io_event *__event = (event); \
(void)__event; \
kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK), km); \
} while(0)
/* ioctx_alloc
* Allocates and initializes an ioctx. Returns an ERR_PTR if it failed.
...
...
@@ -234,14 +234,18 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
init_waitqueue_head
(
&
ctx
->
wait
);
INIT_LIST_HEAD
(
&
ctx
->
active_reqs
);
INIT_LIST_HEAD
(
&
ctx
->
run_list
);
INIT_WORK
(
&
ctx
->
wq
,
aio_kick_handler
,
ctx
);
if
(
aio_setup_ring
(
ctx
)
<
0
)
goto
out_freectx
;
/*
now link into global list. kludge. FIXME
*/
/*
limit the number of system wide aios
*/
atomic_add
(
ctx
->
max_reqs
,
&
aio_nr
);
/* undone by __put_ioctx */
if
(
unlikely
(
atomic_read
(
&
aio_nr
)
>
aio_max_nr
))
goto
out_cleanup
;
/* now link into global list. kludge. FIXME */
write_lock
(
&
mm
->
ioctx_list_lock
);
ctx
->
next
=
mm
->
ioctx_list
;
mm
->
ioctx_list
=
ctx
;
...
...
@@ -383,17 +387,26 @@ static struct kiocb *__aio_get_req(struct kioctx *ctx)
{
struct
kiocb
*
req
=
NULL
;
struct
aio_ring
*
ring
;
int
okay
=
0
;
req
=
kmem_cache_alloc
(
kiocb_cachep
,
GFP_KERNEL
);
if
(
unlikely
(
!
req
))
return
NULL
;
req
->
ki_flags
=
1
<<
KIF_LOCKED
;
req
->
ki_users
=
1
;
req
->
ki_key
=
0
;
req
->
ki_ctx
=
ctx
;
req
->
ki_cancel
=
NULL
;
req
->
ki_retry
=
NULL
;
req
->
ki_user_obj
=
NULL
;
/* Check if the completion queue has enough free space to
* accept an event from this io.
*/
spin_lock_irq
(
&
ctx
->
ctx_lock
);
ring
=
kmap_atomic
(
ctx
->
ring_info
.
ring_pages
[
0
],
KM_USER0
);
if
(
likely
(
ctx
->
reqs_active
<
aio_ring_avail
(
&
ctx
->
ring_info
,
ring
)
))
{
if
(
ctx
->
reqs_active
<
aio_ring_avail
(
&
ctx
->
ring_info
,
ring
))
{
list_add
(
&
req
->
ki_list
,
&
ctx
->
active_reqs
);
get_ioctx
(
ctx
);
ctx
->
reqs_active
++
;
...
...
@@ -402,11 +415,16 @@ static struct kiocb *__aio_get_req(struct kioctx *ctx)
req
->
ki_users
=
1
;
}
else
{
kmem_cache_free
(
kiocb_cachep
,
req
);
req
=
NULL
;
okay
=
1
;
}
kunmap_atomic
(
ring
,
KM_USER0
);
spin_unlock_irq
(
&
ctx
->
ctx_lock
);
if
(
!
okay
)
{
kmem_cache_free
(
kiocb_cachep
,
req
);
req
=
NULL
;
}
return
req
;
}
...
...
@@ -476,6 +494,7 @@ static inline int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
return
0
;
list_del
(
&
req
->
ki_list
);
/* remove from active_reqs */
req
->
ki_cancel
=
NULL
;
req
->
ki_retry
=
NULL
;
/* Must be done under the lock to serialise against cancellation.
* Call this aio_fput as it duplicates fput via the fput_work.
...
...
@@ -527,6 +546,82 @@ static inline struct kioctx *lookup_ioctx(unsigned long ctx_id)
return
ioctx
;
}
static
void
use_mm
(
struct
mm_struct
*
mm
)
{
struct
mm_struct
*
active_mm
=
current
->
active_mm
;
atomic_inc
(
&
mm
->
mm_count
);
current
->
mm
=
mm
;
if
(
mm
!=
active_mm
)
{
current
->
active_mm
=
mm
;
activate_mm
(
active_mm
,
mm
);
}
mmdrop
(
active_mm
);
}
static
void
unuse_mm
(
struct
mm_struct
*
mm
)
{
current
->
mm
=
NULL
;
/* active_mm is still 'mm' */
enter_lazy_tlb
(
mm
,
current
,
smp_processor_id
());
}
/* Run on kevent's context. FIXME: needs to be per-cpu and warn if an
* operation blocks.
*/
static
void
aio_kick_handler
(
void
*
data
)
{
struct
kioctx
*
ctx
=
data
;
use_mm
(
ctx
->
mm
);
spin_lock_irq
(
&
ctx
->
ctx_lock
);
while
(
!
list_empty
(
&
ctx
->
run_list
))
{
struct
kiocb
*
iocb
;
long
ret
;
iocb
=
list_entry
(
ctx
->
run_list
.
next
,
struct
kiocb
,
ki_run_list
);
list_del
(
&
iocb
->
ki_run_list
);
iocb
->
ki_users
++
;
spin_unlock_irq
(
&
ctx
->
ctx_lock
);
kiocbClearKicked
(
iocb
);
ret
=
iocb
->
ki_retry
(
iocb
);
if
(
-
EIOCBQUEUED
!=
ret
)
{
aio_complete
(
iocb
,
ret
,
0
);
iocb
=
NULL
;
}
spin_lock_irq
(
&
ctx
->
ctx_lock
);
if
(
NULL
!=
iocb
)
__aio_put_req
(
ctx
,
iocb
);
}
spin_unlock_irq
(
&
ctx
->
ctx_lock
);
unuse_mm
(
ctx
->
mm
);
}
void
kick_iocb
(
struct
kiocb
*
iocb
)
{
struct
kioctx
*
ctx
=
iocb
->
ki_ctx
;
/* sync iocbs are easy: they can only ever be executing from a
* single context. */
if
(
is_sync_kiocb
(
iocb
))
{
kiocbSetKicked
(
iocb
);
wake_up_process
(
iocb
->
ki_user_obj
);
return
;
}
if
(
!
kiocbTryKick
(
iocb
))
{
long
flags
;
spin_lock_irqsave
(
&
ctx
->
ctx_lock
,
flags
);
list_add_tail
(
&
iocb
->
ki_run_list
,
&
ctx
->
run_list
);
spin_unlock_irqrestore
(
&
ctx
->
ctx_lock
,
flags
);
schedule_work
(
&
ctx
->
wq
);
}
}
/* aio_complete
* Called when the io request on the given iocb is complete.
* Returns true if this is the last user of the request. The
...
...
@@ -548,7 +643,7 @@ int aio_complete(struct kiocb *iocb, long res, long res2)
* case the usage count checks will have to move under ctx_lock
* for all cases.
*/
if
(
ctx
==
&
ctx
->
mm
->
default_kioctx
)
{
if
(
is_sync_kiocb
(
iocb
)
)
{
int
ret
;
iocb
->
ki_user_data
=
res
;
...
...
@@ -560,7 +655,10 @@ int aio_complete(struct kiocb *iocb, long res, long res2)
iocb
->
ki_users
--
;
ret
=
(
0
==
iocb
->
ki_users
);
spin_unlock_irq
(
&
ctx
->
ctx_lock
);
return
0
;
/* sync iocbs put the task here for us */
wake_up_process
(
iocb
->
ki_user_obj
);
return
ret
;
}
info
=
&
ctx
->
ring_info
;
...
...
@@ -940,6 +1038,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
req
->
ki_user_obj
=
user_iocb
;
req
->
ki_user_data
=
iocb
->
aio_data
;
req
->
ki_pos
=
iocb
->
aio_offset
;
buf
=
(
char
*
)(
unsigned
long
)
iocb
->
aio_buf
;
...
...
@@ -954,7 +1053,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret
=
-
EINVAL
;
if
(
file
->
f_op
->
aio_read
)
ret
=
file
->
f_op
->
aio_read
(
req
,
buf
,
iocb
->
aio_nbytes
,
iocb
->
aio_offset
);
iocb
->
aio_nbytes
,
req
->
ki_pos
);
break
;
case
IOCB_CMD_PWRITE
:
ret
=
-
EBADF
;
...
...
@@ -966,7 +1065,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret
=
-
EINVAL
;
if
(
file
->
f_op
->
aio_write
)
ret
=
file
->
f_op
->
aio_write
(
req
,
buf
,
iocb
->
aio_nbytes
,
iocb
->
aio_offset
);
iocb
->
aio_nbytes
,
req
->
ki_pos
);
break
;
case
IOCB_CMD_FDSYNC
:
ret
=
-
EINVAL
;
...
...
@@ -983,12 +1082,10 @@ static int io_submit_one(struct kioctx *ctx, struct iocb *user_iocb,
ret
=
-
EINVAL
;
}
if
(
likely
(
EIOCBQUEUED
==
ret
))
if
(
likely
(
-
EIOCBQUEUED
==
ret
))
return
0
;
if
(
ret
>=
0
)
{
aio_complete
(
req
,
ret
,
0
);
return
0
;
}
out_put_req:
aio_put_req
(
req
);
...
...
fs/exec.c
View file @
531fc7be
...
...
@@ -131,7 +131,7 @@ asmlinkage long sys_uselib(const char * library)
goto
out
;
error
=
-
ENOEXEC
;
if
(
file
->
f_op
&&
file
->
f_op
->
read
)
{
if
(
file
->
f_op
)
{
struct
linux_binfmt
*
fmt
;
read_lock
(
&
binfmt_lock
);
...
...
@@ -453,19 +453,16 @@ struct file *open_exec(const char *name)
}
int
kernel_read
(
struct
file
*
file
,
unsigned
long
offset
,
char
*
addr
,
unsigned
long
count
)
char
*
addr
,
unsigned
long
count
)
{
mm_segment_t
old_fs
;
loff_t
pos
=
offset
;
int
result
=
-
ENOSYS
;
int
result
;
if
(
!
file
->
f_op
->
read
)
goto
fail
;
old_fs
=
get_fs
();
set_fs
(
get_ds
());
result
=
file
->
f_op
->
read
(
file
,
addr
,
count
,
&
pos
);
result
=
vfs_
read
(
file
,
addr
,
count
,
&
pos
);
set_fs
(
old_fs
);
fail:
return
result
;
}
...
...
fs/ext2/file.c
View file @
531fc7be
...
...
@@ -41,6 +41,8 @@ struct file_operations ext2_file_operations = {
.
llseek
=
generic_file_llseek
,
.
read
=
generic_file_read
,
.
write
=
generic_file_write
,
.
aio_read
=
generic_file_aio_read
,
.
aio_write
=
generic_file_aio_write
,
.
ioctl
=
ext2_ioctl
,
.
mmap
=
generic_file_mmap
,
.
open
=
generic_file_open
,
...
...
fs/ext3/file.c
View file @
531fc7be
...
...
@@ -61,8 +61,9 @@ static int ext3_open_file (struct inode * inode, struct file * filp)
*/
static
ssize_t
ext3_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
p
pos
)
ext3_file_write
(
struct
kiocb
*
iocb
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
struct
file
*
file
=
iocb
->
ki_filp
;
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
/*
...
...
@@ -75,13 +76,15 @@ ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if
(
IS_SYNC
(
inode
)
||
(
file
->
f_flags
&
O_SYNC
))
mark_inode_dirty
(
inode
);
return
generic_file_
write
(
file
,
buf
,
count
,
p
pos
);
return
generic_file_
aio_write
(
iocb
,
buf
,
count
,
pos
);
}
struct
file_operations
ext3_file_operations
=
{
.
llseek
=
generic_file_llseek
,
.
read
=
generic_file_read
,
.
write
=
ext3_file_write
,
.
read
=
do_sync_read
,
.
write
=
do_sync_write
,
.
aio_read
=
generic_file_aio_read
,
.
aio_write
=
ext3_file_write
,
.
readv
=
generic_file_readv
,
.
writev
=
generic_file_writev
,
.
ioctl
=
ext3_ioctl
,
...
...
fs/nfs/file.c
View file @
531fc7be
...
...
@@ -35,15 +35,17 @@
#define NFSDBG_FACILITY NFSDBG_FILE
static
int
nfs_file_mmap
(
struct
file
*
,
struct
vm_area_struct
*
);
static
ssize_t
nfs_file_read
(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
static
ssize_t
nfs_file_write
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
static
ssize_t
nfs_file_read
(
struct
kiocb
*
,
char
*
,
size_t
,
loff_t
);
static
ssize_t
nfs_file_write
(
struct
kiocb
*
,
const
char
*
,
size_t
,
loff_t
);
static
int
nfs_file_flush
(
struct
file
*
);
static
int
nfs_fsync
(
struct
file
*
,
struct
dentry
*
dentry
,
int
datasync
);
struct
file_operations
nfs_file_operations
=
{
.
llseek
=
remote_llseek
,
.
read
=
nfs_file_read
,
.
write
=
nfs_file_write
,
.
read
=
do_sync_read
,
.
write
=
do_sync_write
,
.
aio_read
=
nfs_file_read
,
.
aio_write
=
nfs_file_write
,
.
mmap
=
nfs_file_mmap
,
.
open
=
nfs_open
,
.
flush
=
nfs_file_flush
,
...
...
@@ -89,19 +91,19 @@ nfs_file_flush(struct file *file)
}
static
ssize_t
nfs_file_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
p
pos
)
nfs_file_read
(
struct
kiocb
*
iocb
,
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
dentry
*
dentry
=
iocb
->
ki_filp
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
ssize_t
result
;
dfprintk
(
VFS
,
"nfs: read(%s/%s, %lu@%lu)
\n
"
,
dentry
->
d_parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
(
unsigned
long
)
count
,
(
unsigned
long
)
*
p
pos
);
(
unsigned
long
)
count
,
(
unsigned
long
)
pos
);
result
=
nfs_revalidate_inode
(
NFS_SERVER
(
inode
),
inode
);
if
(
!
result
)
result
=
generic_file_
read
(
file
,
buf
,
count
,
p
pos
);
result
=
generic_file_
aio_read
(
iocb
,
buf
,
count
,
pos
);
return
result
;
}
...
...
@@ -209,15 +211,15 @@ struct address_space_operations nfs_file_aops = {
* Write to a file (through the page cache).
*/
static
ssize_t
nfs_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
p
pos
)
nfs_file_write
(
struct
kiocb
*
iocb
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
dentry
*
dentry
=
iocb
->
ki_filp
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
ssize_t
result
;
dfprintk
(
VFS
,
"nfs: write(%s/%s(%ld), %lu@%lu)
\n
"
,
dentry
->
d_parent
->
d_name
.
name
,
dentry
->
d_name
.
name
,
inode
->
i_ino
,
(
unsigned
long
)
count
,
(
unsigned
long
)
*
p
pos
);
inode
->
i_ino
,
(
unsigned
long
)
count
,
(
unsigned
long
)
pos
);
result
=
-
EBUSY
;
if
(
IS_SWAPFILE
(
inode
))
...
...
@@ -230,7 +232,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if
(
!
count
)
goto
out
;
result
=
generic_file_
write
(
file
,
buf
,
count
,
p
pos
);
result
=
generic_file_
aio_write
(
iocb
,
buf
,
count
,
pos
);
out:
return
result
;
...
...
fs/read_write.c
View file @
531fc7be
...
...
@@ -176,6 +176,20 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
}
#endif
ssize_t
do_sync_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
{
struct
kiocb
kiocb
;
ssize_t
ret
;
init_sync_kiocb
(
&
kiocb
,
filp
);
kiocb
.
ki_pos
=
*
ppos
;
ret
=
filp
->
f_op
->
aio_read
(
&
kiocb
,
buf
,
len
,
kiocb
.
ki_pos
);
if
(
-
EIOCBQUEUED
==
ret
)
ret
=
wait_on_sync_kiocb
(
&
kiocb
);
*
ppos
=
kiocb
.
ki_pos
;
return
ret
;
}
ssize_t
vfs_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
pos
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
...
...
@@ -183,14 +197,17 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
return
-
EBADF
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
read
)
if
(
!
file
->
f_op
||
(
!
file
->
f_op
->
read
&&
!
file
->
f_op
->
aio_read
)
)
return
-
EINVAL
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_READ
,
inode
,
file
,
*
pos
,
count
);
if
(
!
ret
)
{
ret
=
security_ops
->
file_permission
(
file
,
MAY_READ
);
if
(
!
ret
)
{
if
(
file
->
f_op
->
read
)
ret
=
file
->
f_op
->
read
(
file
,
buf
,
count
,
pos
);
else
ret
=
do_sync_read
(
file
,
buf
,
count
,
pos
);
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_ACCESS
);
}
...
...
@@ -199,6 +216,20 @@ ssize_t vfs_read(struct file *file, char *buf, size_t count, loff_t *pos)
return
ret
;
}
ssize_t
do_sync_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
{
struct
kiocb
kiocb
;
ssize_t
ret
;
init_sync_kiocb
(
&
kiocb
,
filp
);
kiocb
.
ki_pos
=
*
ppos
;
ret
=
filp
->
f_op
->
aio_write
(
&
kiocb
,
buf
,
len
,
kiocb
.
ki_pos
);
if
(
-
EIOCBQUEUED
==
ret
)
ret
=
wait_on_sync_kiocb
(
&
kiocb
);
*
ppos
=
kiocb
.
ki_pos
;
return
ret
;
}
ssize_t
vfs_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
pos
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
...
...
@@ -206,14 +237,17 @@ ssize_t vfs_write(struct file *file, const char *buf, size_t count, loff_t *pos)
if
(
!
(
file
->
f_mode
&
FMODE_WRITE
))
return
-
EBADF
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
write
)
if
(
!
file
->
f_op
||
(
!
file
->
f_op
->
write
&&
!
file
->
f_op
->
aio_write
)
)
return
-
EINVAL
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_WRITE
,
inode
,
file
,
*
pos
,
count
);
if
(
!
ret
)
{
ret
=
security_ops
->
file_permission
(
file
,
MAY_WRITE
);
if
(
!
ret
)
{
if
(
file
->
f_op
->
write
)
ret
=
file
->
f_op
->
write
(
file
,
buf
,
count
,
pos
);
else
ret
=
do_sync_write
(
file
,
buf
,
count
,
pos
);
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_MODIFY
);
}
...
...
@@ -580,3 +614,6 @@ asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t
return
do_sendfile
(
out_fd
,
in_fd
,
NULL
,
count
,
0
);
}
EXPORT_SYMBOL
(
do_sync_read
);
EXPORT_SYMBOL
(
do_sync_write
);
include/linux/aio.h
View file @
531fc7be
...
...
@@ -2,10 +2,11 @@
#define __LINUX__AIO_H
#include <linux/list.h>
#include <asm/atomic.h>
#include <linux/workqueue.h>
#include <linux/aio_abi.h>
#include <asm/atomic.h>
#define AIO_MAXSEGS 4
#define AIO_KIOGRP_NR_ATOMIC 8
...
...
@@ -22,28 +23,54 @@ struct kioctx;
#define KIOCB_SYNC_KEY (~0U)
#define KIOCB_PRIVATE_SIZE (16 * sizeof(long))
#define KIOCB_PRIVATE_SIZE (24 * sizeof(long))
/* ki_flags bits */
#define KIF_LOCKED 0
#define KIF_KICKED 1
#define KIF_CANCELLED 2
#define kiocbTryLock(iocb) test_and_set_bit(KIF_LOCKED, &(iocb)->ki_flags)
#define kiocbTryKick(iocb) test_and_set_bit(KIF_KICKED, &(iocb)->ki_flags)
#define kiocbSetLocked(iocb) set_bit(KIF_LOCKED, &(iocb)->ki_flags)
#define kiocbSetKicked(iocb) set_bit(KIF_KICKED, &(iocb)->ki_flags)
#define kiocbSetCancelled(iocb) set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
#define kiocbClearLocked(iocb) set_bit(KIF_LOCKED, &(iocb)->ki_flags)
#define kiocbClearKicked(iocb) set_bit(KIF_KICKED, &(iocb)->ki_flags)
#define kiocbClearCancelled(iocb) set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
#define kiocbIsLocked(iocb) test_bit(0, &(iocb)->ki_flags)
#define kiocbIsKicked(iocb) test_bit(1, &(iocb)->ki_flags)
#define kiocbIsCancelled(iocb) test_bit(2, &(iocb)->ki_flags)
struct
kiocb
{
struct
list_head
ki_run_list
;
long
ki_flags
;
int
ki_users
;
unsigned
ki_key
;
/* id of this request */
struct
file
*
ki_filp
;
struct
kioctx
*
ki_ctx
;
/* may be NULL for sync ops */
int
(
*
ki_cancel
)(
struct
kiocb
*
,
struct
io_event
*
);
long
(
*
ki_retry
)(
struct
kiocb
*
);
struct
list_head
ki_list
;
struct
list_head
ki_list
;
/* the aio core uses this
* for cancellation */
void
*
ki_data
;
/* for use by the the file */
void
*
ki_user_obj
;
/* pointer to userland's iocb */
__u64
ki_user_data
;
/* user's data for completion */
loff_t
ki_pos
;
long
private
[
KIOCB_PRIVATE_SIZE
/
sizeof
(
long
)
];
char
private
[
KIOCB_PRIVATE_SIZE
];
};
#define is_sync_kiocb(iocb) ((iocb)->ki_key == KIOCB_SYNC_KEY)
#define init_sync_kiocb(x, filp) \
do { \
struct task_struct *tsk = current; \
(x)->ki_flags = 0; \
(x)->ki_users = 1; \
(x)->ki_key = KIOCB_SYNC_KEY; \
(x)->ki_filp = (filp); \
...
...
@@ -101,10 +128,13 @@ struct kioctx {
int
reqs_active
;
struct
list_head
active_reqs
;
/* used for cancellation */
struct
list_head
run_list
;
/* used for kicked reqs */
unsigned
max_reqs
;
struct
aio_ring_info
ring_info
;
struct
work_struct
wq
;
};
/* prototypes */
...
...
@@ -112,6 +142,7 @@ extern unsigned aio_max_size;
extern
ssize_t
FASTCALL
(
wait_on_sync_kiocb
(
struct
kiocb
*
iocb
));
extern
int
FASTCALL
(
aio_put_req
(
struct
kiocb
*
iocb
));
extern
void
FASTCALL
(
kick_iocb
(
struct
kiocb
*
iocb
));
extern
int
FASTCALL
(
aio_complete
(
struct
kiocb
*
iocb
,
long
res
,
long
res2
));
extern
void
FASTCALL
(
__put_ioctx
(
struct
kioctx
*
ctx
));
struct
mm_struct
;
...
...
include/linux/fs.h
View file @
531fc7be
...
...
@@ -746,7 +746,7 @@ struct file_operations {
ssize_t
(
*
read
)
(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
ssize_t
(
*
aio_read
)
(
struct
kiocb
*
,
char
*
,
size_t
,
loff_t
);
ssize_t
(
*
write
)
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
ssize_t
(
*
aio_write
)
(
struct
kiocb
*
,
char
*
,
size_t
,
loff_t
);
ssize_t
(
*
aio_write
)
(
struct
kiocb
*
,
c
onst
c
har
*
,
size_t
,
loff_t
);
int
(
*
readdir
)
(
struct
file
*
,
void
*
,
filldir_t
);
unsigned
int
(
*
poll
)
(
struct
file
*
,
struct
poll_table_struct
*
);
int
(
*
ioctl
)
(
struct
inode
*
,
struct
file
*
,
unsigned
int
,
unsigned
long
);
...
...
@@ -1238,6 +1238,10 @@ extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern
int
file_read_actor
(
read_descriptor_t
*
desc
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
size
);
extern
ssize_t
generic_file_read
(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
extern
ssize_t
generic_file_write
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
extern
ssize_t
generic_file_aio_read
(
struct
kiocb
*
,
char
*
,
size_t
,
loff_t
);
extern
ssize_t
generic_file_aio_write
(
struct
kiocb
*
,
const
char
*
,
size_t
,
loff_t
);
extern
ssize_t
do_sync_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
);
extern
ssize_t
do_sync_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
len
,
loff_t
*
ppos
);
ssize_t
generic_file_write_nolock
(
struct
file
*
file
,
const
struct
iovec
*
iov
,
unsigned
long
nr_segs
,
loff_t
*
ppos
);
extern
ssize_t
generic_file_sendfile
(
struct
file
*
,
struct
file
*
,
loff_t
*
,
size_t
);
...
...
include/linux/kernel.h
View file @
531fc7be
...
...
@@ -201,6 +201,9 @@ struct sysinfo {
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
extern
void
BUILD_BUG
(
void
);
#define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
/* Trap pasters of __FUNCTION__ at compile-time */
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 95
#define __FUNCTION__ (__func__)
...
...
mm/filemap.c
View file @
531fc7be
...
...
@@ -885,11 +885,12 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
}
ssize_t
generic_file_aio_read
(
struct
kiocb
*
iocb
,
char
*
buf
,
size_t
count
,
loff_t
*
p
pos
)
generic_file_aio_read
(
struct
kiocb
*
iocb
,
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
struct
iovec
local_iov
=
{
.
iov_base
=
buf
,
.
iov_len
=
count
};
return
__generic_file_aio_read
(
iocb
,
&
local_iov
,
1
,
ppos
);
BUG_ON
(
iocb
->
ki_pos
!=
pos
);
return
__generic_file_aio_read
(
iocb
,
&
local_iov
,
1
,
&
iocb
->
ki_pos
);
}
ssize_t
...
...
@@ -1645,6 +1646,12 @@ generic_file_write_nolock(struct file *file, const struct iovec *iov,
return
err
;
}
ssize_t
generic_file_aio_write
(
struct
kiocb
*
iocb
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
return
generic_file_write
(
iocb
->
ki_filp
,
buf
,
count
,
&
iocb
->
ki_pos
);
}
ssize_t
generic_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
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